View Full Version : Problems with line drawing
Hi,
I'm writing a window manager that uses OpenGL as the rasteriser. Bizarrly, I have a problem with straight lines.
I set the screen up so that the x,y dimensions coorespond to the pixel width / height of the video mode.
int GLRasteriser::Set2DLinearMode()
{
float matrix[16];
int x,y,bpp;
GB_GetScreenDimensions(&x,&y,&bpp);
glDisable(GL_NORMALIZE);
glDisable(GL_LINE_SMOOTH);
glViewport(0,0,x,y);
glMatrixMode(GL_PROJECTION); // set up projection transform
glLoadIdentity();
gluOrtho2D(0,(double)x,(double)y,0); // Top left = 0,0 screen origin
glMatrixMode(GL_MODELVIEW); // now change to modelview
glLoadIdentity();
return TRUE;
}
When I try an draw a line (glBegin(GL_LINES))that is approx. 75% of the screen away from the origin it is draw at 1 pixel less than the specified coordinate. What makes it really strange is that calls to glBegin(GL_QUADS), for filling the windows, and glDrawPixels get the correct coordinate.
Any ideas?
Leo
Fredy
03-05-2001, 10:44 AM
This is just a guess, but if you have the starting coordinates 0,0 then the ending coordinates should be x-1, y-1.
eg. 0,0-----------\
| |
\----------x-1,y-1
http://www.opengl.org/discussion_boards/ubb/rolleyes.gif
danoon
03-05-2001, 11:39 AM
I'm also using OpenGl as a 2D rasterizer and I also had the same problem. I ended up just using GL_QUADS to draw my lines because GL_LINES seemed inexact. It wasn't always one pixel off otherwise I would have just added a constant. Instead it was off by one pixel depending on where in the window it was drawing.
I would be very curious for someone to explane this too.
Relic
03-05-2001, 11:30 PM
Have a look at the "diamond exit rule" used in OpenGL to decide which pixels are touched while rendering primitives. Pictures are in the OpenGL specs.
Also remember that pixels are not infinitely small points but have an area. If you want to hit a pixel exactly in the center you have to shift all 2D screen coordinates by 0.5.
That is, don't draw from (0, 0) to (x, y) but from (0.0 + 0.5, 0.0 + 0.5) to (x + 0.5, y + 0.5). This should fulfill the diamond exit rule conditions for both start and end points.
Thanks all,
stumbled across the GL_QUADS method before reading this post. Used a width of 1.1f for the quads as single pixel width was creating new atifacts. Will have a look at the +/-0.5f line method later
cheers
Leo
Tried both methods. QUADS worked nicely until I noticed that very infrequently it would drop pixels in the middle of a line! Some kind of odd sliver problems there.
LINES method didn't work with an offset of 0.5, (as I'm using straight lines I only added the offset on the princliple axis). Played around with it and used 0.4f offset. That works.
#define USELINES
int GLRasteriser::iDrawVline(int an_XPos, int an_Ypos, int an_Len, COLOUR a_Colour)
{
if ( mn_RasterMode != RM_2DLINEAR ) Set2DLinearMode();
#ifdef USELINES
glBegin(GL_LINES);
glColor3ub((GLubyte)GETRED(a_Colour),(GLubyte)GETG REEN(a_Colour),(GLubyte)GETBLUE(a_Colour));
glVertex2f((float)an_XPos+0.4f, an_Ypos);
glVertex2f((float)an_XPos+0.4f, an_Ypos + an_Len);
glEnd();
#else
glBegin(GL_QUADS);
glColor3ub((GLubyte)GETRED(a_Colour),(GLubyte)GETG REEN(a_Colour),(GLubyte)GETBLUE(a_Colour));
glVertex2d((double)an_XPos-0.4f, (double) (an_Ypos) );
glVertex2d((double)an_XPos+1.4f, (double) (an_Ypos) );
glVertex2d((double)an_XPos-0.4f, (double)(an_Ypos + an_Len));
glVertex2d((double)an_XPos+1.4f, (double)(an_Ypos + an_Len));
glEnd();
#endif
return TRUE;
}
int GLRasteriser::iDrawHline(int an_XPos, int an_Ypos, int an_Len, COLOUR a_Colour)
{
if ( mn_RasterMode != RM_2DLINEAR ) Set2DLinearMode();
#ifdef USELINES
glBegin(GL_LINES);
glColor3ub((GLubyte)GETRED(a_Colour),(GLubyte)GETG REEN(a_Colour),(GLubyte)GETBLUE(a_Colour));
glVertex2f((float)an_XPos, (float)an_Ypos + 0.4f);
glVertex2f((float)(an_XPos + an_Len), (float)an_Ypos + 0.4f);
glEnd();
#else
glBegin(GL_QUADS);
glColor3ub((GLubyte)GETRED(a_Colour),(GLubyte)GETG REEN(a_Colour),(GLubyte)GETBLUE(a_Colour));
glVertex2d((double)an_XPos, (double)an_Ypos-0.45f);
glVertex2d((double)(an_XPos + an_Len), (double)an_Ypos-0.45f);
glVertex2d((double)(an_XPos + an_Len), (double)an_Ypos+1.45f);
glVertex2d((double)an_XPos, (double)an_Ypos+1.45f);
glEnd();
#endif
return TRUE;
}
#undef USELINES
Powered by vBulletin® Version 4.2.0 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.