OpenGL Differences between iPhone Sim and Real iPhone

Member
Posts: 48
Joined: 2011.03
Post: #1
Hello again. I'm trying to get my 2D drawing functions working consistently between iPhone simulator and real iPhone. I'm finding that I can now draw lines consistently on both, but shading rectangular regions is another matter.

The code below draws a line around the edges of the screen and fills in a rectangular region inside the line. What I'm finding is this:
- Simulator: Filled rectangle is drawn one pixel too far right and one pixel too far down (top left start is one pixel too far right and one pixel too far down)
- Real iPhone: Filled rectangle is drawn one pixel too far down (top left start is one pixel too far down)

I get the same problem in 480x320 and 960x640 resolutions.

I know I can hack around this by subtracting 1 and doing #if TARGET_SIMULATOR etc but I'd like to know why my drawing isn't working as I expect it to.

Can somebody please help? Here's my code below. I'm drawing in landscape mode.

Code:
glViewport( 0, 0, g_ScreenHeight, g_ScreenWidth );
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();              
  glRotatef( -90, 0, 0, 1 );  
  glOrthof( 0.0f, g_ScreenWidth, g_ScreenHeight, 0.0f, -1.0f, 1.0f );
  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity();
  glTranslatef(0.5, 0.5, 0);
...
void DrawLine( int x1, int y1, int x2, int y2 )
{
  GLfloat  avLine[ 6 ];
  GLfloat *p = avLine;
  
  p = AddVertex3( p, (float) x1, (float) y1 );
  p = AddVertex3( p, (float) x2, (float) y2 );
  
  glEnableClientState( GL_VERTEX_ARRAY );
  glVertexPointer( 3, GL_FLOAT, 0, avLine );    
  glDrawArrays( GL_LINES, 0, 2 );
  glDisableClientState( GL_VERTEX_ARRAY );
}

void DrawLineRectangle( int nLeft, int nTop, int nWidth, int nHeight )
{
  int nRight  = nLeft + nWidth  - 1;
  int nBottom = nTop  + nHeight - 1;

  DrawLine( nLeft,  nTop,    nRight, nTop );
  DrawLine( nRight, nTop,    nRight, nBottom + 1 );
  DrawLine( nRight, nBottom, nLeft,  nBottom );
  DrawLine( nLeft,  nBottom, nLeft,  nTop );
}

void DrawFilledRectangle( int nLeft, int nTop, int nWidth, int nHeight )
{
  int nRight  = nLeft + nWidth;
  int nBottom = nTop  + nHeight;

  GLfloat avRect[ 18 ];
  GLfloat *p = avRect;    
  
  p = AddVertex3( p, nLeft,  nTop );
  p = AddVertex3( p, nRight, nTop );
  p = AddVertex3( p, nRight, nBottom );
  
  p = AddVertex3( p, nLeft,  nTop );
  p = AddVertex3( p, nLeft,  nBottom );
  p = AddVertex3( p, nRight, nBottom );
  
  glEnableClientState( GL_VERTEX_ARRAY );
  glEnableClientState( GL_NORMAL_ARRAY );
  glVertexPointer( 3, GL_FLOAT, 0, avRect );
  glDrawArrays( GL_TRIANGLES, 0, 6 );
  glDisableClientState( GL_VERTEX_ARRAY );
}

...
  SelectColor( COLOR_GREEN );
  DrawLineRectangle( 0, 0, g_ScreenWidth, g_ScreenHeight );
  SelectColor( COLOR_RED );
  DrawFilledRectangle( 1, 1, g_ScreenWidth-2, g_ScreenHeight-2 );
...
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #2
You're specifying your line vertices on pixel cracks, not pixel centers. So what you're seeing is the difference between rounding 0.5 to 0, or to 1.

When a filled primitive (triangle) is rasterized, it will light up pixels inside the region described by the vertices.

However when a point or line is rasterized, there isn't a region. Rather there is an infinitely small point or an infinitely thin line. If the line width is 1, then the area covered by the line is 0.5 pixels outwards on either side of that infinitely thin line.

So, add 0.5 to all of your line coordinates.
Quote this message in a reply
Member
Posts: 48
Joined: 2011.03
Post: #3
(Apr 13, 2011 09:17 AM)arekkusu Wrote:  So, add 0.5 to all of your line coordinates.

Isn't that what my glTranslatef(0.5, 0.5, 0); is supposed to do?

I just tried adding 0.5 to all of my top left coords and thats made the gap even bigger - my line appears on pixel x=0, but now the filled rectangle starts on x=2, so I'm afraid that hasn't worked.
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #4
Oop, yes. So your line drawing is already on pixel centers.

But then your filled rectangle is also on pixel centers, which makes that region rounding-dependent, which is wrong.

You only want the translate for point and line primitives, not triangles.
Quote this message in a reply
Member
Posts: 48
Joined: 2011.03
Post: #5
(Apr 13, 2011 11:17 AM)arekkusu Wrote:  You only want the translate for point and line primitives, not triangles.

Oh, I see. I'll give that a try now.. once my iPhone will let me. Its started giving me "program received signal sigabrt" crashes and I don't know why. The simulator is working fine, other apps download and run on the iPhone fine, but my OpenGL app has went funny - it was working before I went to bed, so goodness knows whats happened overnight. :-(


Well on the simulator, what you've suggested seems to work.

For DrawLines():
glLoadIdentity();
glTranslatef(0.5, 0.5, 0);

And for drawing filled regions (DrawFilledRectangle() ):
glLoadIdentity(); // This undoes the glTranslatef( 0.5, 0.5, 0 );

Now I just need to sort out this annoying sigabrt problem so I can test it on the iPhone itself..
Quote this message in a reply
Member
Posts: 48
Joined: 2011.03
Post: #6
A reboot of my iPhone fixed the sigabrt problem.. It looks as though the drawing problem has been fixed, arekkusu. Thanks.
Quote this message in a reply
Post Reply