What's up with glOrtho and drawing primitives? I'm having all sorts of weird off-by-one errors in the 2D section of my rendering loop. They're all easily correctable but I'd prefer to know
WHY and not just adjust them as they happen.
See at first I noticed this when I was drawing borders around a few objects on my screen using LINE_LOOP. What would happen is it would draw everything fine except the very upper-left corner would not get plotted. Well for the longest time I thought it wasn't plotting the first pixel for some reason. It was kind of annoying but I was just ignoring it for the time being by patching it up with a GL_POINT.
Well then last night I was working on a new piece of the project (some window drawing code) which required drawing lots of 2D lines and rectangles and such and they all had to be pixel-perfect precision to match exactly the template I had in Photoshop. Well that's when I figured out that LINE_LOOP was screwing up because as I went around the square clockwise from the upper left corner, the lower-left corner was drawn one pixel to the left of the upper-left corner, so that even though I was using the exact same X coordinate for each of them, the left side of the square showed up 1 pixel to the left of the X.
It does it on other 2D primitives too, but lines are the really weird ones.
They have no appear pattern that I could figure out as to when one or the other endpoint will be inclusive and when it will not be. I did get my window drawing code to work properly but the way I did it was to experiment with the different shapes when drawn very small (2x2 or less) so that I could easily see when there was an error. Doing this I was able to develop the following set of macros which draws the lines "properly". I was hoping someone would be able to explain why the values in there are the way they are because to me they're just "magic numbers".
When I say "properly" know that I come from 2D graphics libraries. i.e., the upper-left corner of the screen is (0,0), a line drawn from (1,1)-(2,1) is a horizontal line 2 pixels in width, offset 1x1 pixel from the upper-left corner.
These macros do have blackslashes on the end of every line but I took them out because it was screwing up the forum.
#define glfLineH(X1,Y1,X2) {
glBegin(GL_LINES);
glVertex2i((X1), (Y1)+1);
glVertex2i((X2)+1, (Y1)+1);
glEnd();
}
#define glfLineV(X1,Y1,Y2) {
glBegin(GL_LINES);
glVertex2i((X1)+1, (Y1));
glVertex2i((X1)+1, (Y2)+1);
glEnd();
}
#define glfSquare(X1,Y1,X2,Y2) {
glBegin(GL_LINE_LOOP);
glVertex2i((X1), (Y1)+1);
glVertex2i((X2)+1, (Y1)+1);
glVertex2i((X2)+1, (Y2)+1);
glVertex2i((X1)+1, (Y2)+1);
glEnd();
}
#define glfBox(X1,Y1,X2,Y2) {
glBegin(GL_QUADS);
glVertex2i((X1), (Y1));
glVertex2i((X2)+1, (Y1));
glVertex2i((X2)+1, (Y2)+1);
glVertex2i((X1), (Y2)+1);
glEnd();
}
#define glfPoint(X1,Y1) {
glBegin(GL_POINTS);
glVertex2i((X1), (Y1)+1);
glEnd();
}
I think it's pretty clear from their names and the code what they are supposed to do (and they do work, I just don't know why). You'll notice that the one to draw a filled box out of a QUAD makes sort-of sense, presumably gl is considering the endpoints to be exclusive. However when I draw the exact same shape with a LINE_LOOP I have to use different coordinates, and a lot of them are startpoints, except for the first X coordinate which is not for some reason.
For reference here is my function to enter 2D orthographic mode. The "game.renders" test is for making a smaller message-console window when the program is running as a dedicated multiplayer server (in the case I'm dealing with game.renders is 1). It's not that though, I know it's the first thing I homed in on but I tried commenting it out both ways and it did not change anything. I also thought maybe I was declaring the screen size one pixel too big and it was scaling everything but this is apparently not the case because the primitives appear in exactly the same way no matter where they are on the screen, and because I tried adding +1 and -1 on SCREEN_WIDTH and SCREEN_HEIGHT and it did not fix it.
void rend_Enter_2D(void)
{
// to 2D drawing mode
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
if (!game.renders)
glOrtho(0,window_width,window_height,0,-1,1);
else
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
}
One more conundrum on top of all this; is that when I turn on GL_LINE_STIPPLE, the rules change and my "glf" macros no longer work. I did not fully investigate the behavior while LINE_STIPPLE is on but it appears that everything works "normally" with the endpoints of the lines except that anything I draw is offset by 1x1 pixels, so [0x0] is actually one pixel right and down from the top of the screen. Whereas with LINE_STIPPLE off I can not draw anything at [0x0] because it is one pixel past the top of the screen.
[wow]
Obviously something is Not Right here and it's probably either my code or my understanding of the API, so does anybody have a better version of either?