PDA

View Full Version : Pixel-perfect drawing



halo
02-08-2005, 08:44 PM
I'm having a lot of problems drawing lines without getting little 1-pixel inaccuracies. I tried offsetting the view by (0.375,0.375) but it had no effect. How can I get pixel-perfect drawing? This is for an editor, so it has to be PERFECT.

I am using glOrtho(0,pixelwidth,pixelheight,0), so the viewport is exactly as large as the pixel area.

halo
02-08-2005, 08:58 PM
If GL just isn't designed this way, I can still do my own lines and stuff if I can get a Plot(x,y) method that is ALWAYS accurate.

Relic
02-08-2005, 10:29 PM
Copied and slightly edited my answer from here:
http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=2;t=017931

The correct thing to do for pixel aligned rendering of rectangluar primitives is to setup a 2D ortho projection which is exactly from the bottom left corner of the bottom left pixel on screen to the top right corner of the upper right pixel on the screen.

Then all pixel aligned filled rectangle drawing needs to be done on the pixel's corner coordinates fully covering the pixels you want to draw.
All line and point drawing must happen on pixel centers. Use floats and offset the integer coordinates of line and points, which would be on the corner of a pixel, by (+0.5, +0.5) to start in the center.

halo
02-09-2005, 06:07 AM
Does it matter that it be from the bottom-left? Screen/image style coordinates (x increases to the right, y increases going down) are easiest for me to visualize and work with.

halo
02-09-2005, 06:14 AM
I also found when drawing a cross, the line would be one pixel short, so I had to add or subtract 1 to the line of each second vertex:

glBegin GL_LINES
glVertex2f cx+sw,cy+sw
glVertex2f cx-sw-1,cy-sw-1
glVertex2f cx+sw,cy-sw
glVertex2f cx-sw-1,cy+sw+1
glEnd

VikingCoder
02-09-2005, 06:25 AM
My advice - make a class that has the exact interface that you want. Use it all over the place in your code. Implement that class with the appropriate OpenGL calls. I know this sounds like a "duh," but I think you might be amazed by how many people just chose to "live with" adding 0.5 to X and Y, and all of the other inconveniences that you'll probably run into. There's no honor in having to fix all of your code because of an off-by-one error you discovered at the last minute. Encapsulate it all, so you can (hopefully) fix it in one place.

halo
02-09-2005, 07:35 AM
Not sure what you mean. I have one DrawViewportOverlay() function which handles everything.

Relic
02-09-2005, 10:34 PM
Line drawing in OpenGL follows the diamond exit rule. A line might not draw the last point if it doesn't leave the diamond inside the last pixel, but the next line starting there will, and this is a must if you want to touch every pixel only once in a rasterizer. Otherwise XOR, blending, stencil algorithm etc. would not produce correct results.
This is also the reason why drawing a line from A to B is not the same as drawing it from B to A in OpenGL. If you ever erase lines with an overdraw you must use the exact same coordinates and ordering.

The glOrtho y-axis direction is your choice. But I prefer the OpenGL standard bottom-left, which is mathematically more intuitive.

arekkusu
02-10-2005, 11:05 AM
In general, you can not guarantee pixel perfect rendering in OpenGL, because you are at the mercy of the hardware and driver implementation. There's lots of different hardware out there, and lots of driver bugs.

If you only need aliased, 1 pixel wide lines, you can probably get repeatable results on most hardware as others have already described (ortho2D, 0.5px offsets.) But, some renderers fail the diamond exit rule, so even this simple case isn't guarantee-able.

If you need antialiasing or lines wider than 1 px, just forget about it. Implement your own line primitives using quads.

michagl
02-27-2005, 04:52 PM
just wanted to say that i found this thread very imformative... for my custom gui system i've practicly given up on pixel perfect rendering... though with my drivers it is usually not a problem unless scaling is envolved, but alas my system alows for infinite scaling.

i've basicly been dissapointed with opengl in this respect... i read somewhere in some specifications that pixel perfect rendering was basicly an impossibility with opengl. and i agree with the last poster in that it is a driver/hardware dependant matter, but i really think opengl should do something to address this finally for gui type systems.

i could find nothing about pixel behavior, or make head or tail of what was really going on. i'm grateful for the advice here though. when i get back to working with the gui system, which is really a quite amazing project, i intend to encapsulate the primitive rendering system and try to offer end users as many different modes as possible where hardware and drivers diverge.

if anyone knows of any particular pixel lighting techniques utilized by various drivers i would be very interested in hearing them.

sincerely,

michael