Pixel perfect texture mapping problem. Nvidia vs A

edit: Ok, I found out this problem can be solved using orthographic projection but I’m not sure why. I’d really like to know though :wink:

Recently I’ve been trying to solve a problem I have with mapping a texture on screen with pixel perfect precision. It seems to work just fine on my PC and in OSX however there is some distortion on other PC’s.
The main difference I can think off that’s causing this problem is the graphics card. I’m using an ATI graphics card myself and the other PC has an nVidia card.
Before I’ll go any further I’ll show you what it looks like (with 300% zoom):
http://img521.imageshack.us/img521/6827/texturemappingproblem.png

I’m using perspective projection however the camera is moved at a distance where objects rendered at the center of the z-axis have the same size as their texture.

I experimented with texture settings a bit but it didn’t seem to make any difference.

I’ve read about texture coordinates being in the center of pixels, which meant you had to translate them half a texel to overlap pixels and texels correctly. However I’m not sure if this applies to openGL as well.

Has anyone seen this problem before or maybe any guesses what it could be? Any help is welcome ^^

In OpenGL, texture coordinate (0.0, 0.0) is the lower left corner of the lower left texel. Texture coordinate (1.0, 1.0) is the upper right corner of the upper right texel.

If you set up your ortho to match your viewport like so,
glViewport(0, 0, 640, 480)
glOrtho(0, 640, 0, 480, -1, 1)
Then vertex coordinate (0, 0) will be the lower left corner of the lower left pixel in the viewport, and (640, 480) will be the upper right corner of the upper right pixel in the viewport. Knowing this, it is easy to arrange things to that texels will be placed exactly over pixels.

E.g. with the ortho and viewport setup from above, you can draw a 32x16 texture at 1:1 texel:pixel with the lower left corner at x,y (x and y both integers) like this:

glBegin(GL_QUADS)

glTexCoord2f(0.0, 0.0)
glVertex2f(x+0, y+0)

glTexCoord2f(1.0, 0.0)
glVertex2f(x+32, y+0)

glTexCoord2f(1.0, 1.0)
glVertex2f(x+32, y+16)

glTexCoord2f(0.0, 1.0)
glVertex2f(x+0, y+16)

glEnd()

This way, vertex coordinates span exactly 32 pixels horizontally, and texture coordinates span exactly 32 texels horizontally (similar for vertical), and texel corners and pixel corners match up exactly.

You’re probably landing right on the edge of texel boundaries so some round up and some down on one implementation.

There are two solutions, move texels or move vertices but both amount to the same thing; make sure that 0,0 and 1,1 coordinates land between pixels so that pixel centers align with texel centers.

There are several mechanisms in OpenGL to do this, ortho would be one, but just tweaking your coordinates would also do it.