OpenGL Maximum 2D acuracy?

Started by
14 comments, last by Kwizatz 19 years, 6 months ago
Hello, I am coding what I hope will become a multi platform, multi API GUI library, and I am writting the OpenGL portion of it. To make the story short I will just say that I need to implement some basic drawing functions such as DrawPixel, DrawLine, DrawRect and DrawFilledRect, I started implementing these for SDL, and sure enought when I do a DrawPixel(x,y) with SDL the pixel shows up at x,y, when I do DrawLine(x1,y1,x2,y2), the line goes from x1,y1 to x2,y2 inclusive, everything is fine. But now that I am implementing the same stuff on OGL, which is supposed to be easier, it isn't! when I say DrawPixel(10,10) a pixel gets drawn at 10,10, but when I say DrawLine(10,0,10,200) for example, the line gets drawn at (9,0,9,200), if I try to draw a pixel at 0,0 it doesnt show, but if I try it at 1,1 it shows and its in the spot it should be! this is driving me crazy. Now, I am getting into Ortho mode with this code:

  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  glOrtho(0,640,480,0, 0, 1);
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();  
  glLoadIdentity();
  glBlendFunc(GL_SRC_ALPHA,GL_ONE);
  glEnable(GL_BLEND);
I tried changing glOrtho(0,640,480,0, 0, 1) to glOrtho(0,639,479,0, 0, 1),glOrtho(-1,639,479,0, 0, 1) and glOrtho(-1,639,479,-1, 0, 1), no luck. Then line and pixel functions (GUIColor is a union which holds the ARGB values for a color):

void DrawPixel(Sint16 x, Sint16 y,GUIColor color)
{
  glDisable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
  glColor4ub(color.color.R,
	     color.color.G,
	     color.color.B,
	     color.color.A);
  glBegin(GL_POINTS);
  {
    glVertex2i(x, y);
  };
  glEnd();
  glEnable(GL_BLEND);
  glEnable(GL_TEXTURE_2D);
};
 
void DrawLine(Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,GUIColor color)
{
  glDisable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
  glColor4ub(color.color.R,
	     color.color.G,
	     color.color.B,
	     color.color.A);
  glBegin(GL_LINES);
  {
    glVertex2i(x1,y1);
    glVertex2i(x2,y2);
  };
  glEnd();
  glEnable(GL_BLEND);
  glEnable(GL_TEXTURE_2D);
};



Any Ideas? [Edited by - Kwizatz on September 21, 2004 8:16:43 PM]
Advertisement
theres nothing you can do
every computer renders things differently
you could use software rendering but that would be slow
i dont think it should be a problem its only one pixel off
There should be a way, I could hardcode everything, but its a GUI, the window size and resolution should be expected to be constantly changing from App to App, I do require pixel perfect rendering [sad], I guess I'll have to do implement the line algo using GL_POINTS, I wonder how much would that slow everything else.
why do you reuire pixel perfect rendering?
Not pixel perfect rendering, but I need reliable primitive drawing functions, IE a hipotetical SDL_DrawLine function should plot the same pixels as a hipotetical OGL_DrawLine Function if given the same arguments, such that later a DDraw_DrawLine or D3D_DrawLine function would also plot the same pixels.

I require this because like I said, I am coding a multi platform, multi API GUI, I need same results on different graphic APIs.

Anyway I think I found the solution:

glOrtho(0,640,479,-1, 0, 1);

Now I just need to find out if the same call (glOrtho(0,XResolution,YResolution-1,-1,0,1);) holds true for all cases.

[Edited by - Kwizatz on September 21, 2004 8:47:42 PM]
The problem is how OpenGL fills pixels. What's happening is that you're trying to draw lines abd points on the edge between adjacent pixels, and rounding errors causes wrong pixels to be filled.

You should offset the projection matrix by 0.5 to make integer coordinates end up in the center of the pixels, instead of on the edge.
glOrtho(0, window_width, window_height, 0, 0, 1);glTranslatef(0.5, 0.5, 0);
Bob's approach isn't safe either. Usually users can offset pixel centers in driver settings, too. AFAIK there is no general solution to this other than using sofware mode.
Never heard about that. Do you have an example of a driver with a setting like that?
Quote:Original post by Brother Bob
Never heard about that. Do you have an example of a driver with a setting like that?

Sure. In Windows, you just need to open advanced display settings and go to the vendor specific tabs. You'll find the settings in current Catalyst™ drivers "3D" tab by clicking the "compatibility" button. IIRC, NVidia's ForceWare™ drivers offer a similar option (cannot tell exactly where since I currently don't have my old GeForce3 installed).

I guess that these settings are available on Linux systems, too (I don't use X on my penguin-powered box so have no clue about 3D driver settings on Linux).

Cheers,
Pat
So I guess I have to search for someone with one of those drivers and have a look for myself (have a GF2 myself, and never seen anything there). To me at least, it sounds quite strange to have an option like that. Unless it was a broken feature in the past, so the user can have the option to go back to a previous broken behaviour.

But I had a look in the display properties user guide you can download at the same place you download NV-drivers, and I couldn't find anything in there about this setting.

This topic is closed to new replies.

Advertisement