13

I'm writing a software renderer which is currently working well, but I'm trying to get perspective correction of texture coordinates and that doesn't seem to be correct. I am using all the same matrix math as opengl for my renderer. To rasterise a triangle I do the following:

  1. transform the vertices using the modelview and projection matrixes, and transform into clip coordinates.

  2. for each pixel in each triangle, calculate barycentric coordinates to interpolate properties (color, texture coordinates, normals etc.)

  3. to correct for perspective I use perspective correct interpolation: (w is depth coordinate of vertex, c is texture coordinate of vertex, b is the barycentric weight of a vertex)

1/w = b0*(1/w0) + b1*(1/w1) + b2*(1/w2)
c/w = b0*(c0/w0) + b1*(c1/w1) + b2*(c2/w2)
c = (c/w)/(1/w)

This should correct for perspective, and it helps a little, but there is still an obvious perspective problem. Am I missing something here, perhaps some rounding issues (I'm using floats for all math)?

See in this image the error in the texture coordinates evident along the diagonal, this is the result having done the division by depth coordinates.

image showing incorrect perspective correction

Also, this is usually done for texture coordinates... is it necessary for other properties (e.g. normals etc.) as well?

James Edge
  • 245
  • 5
  • 12

4 Answers4

3

I cracked the code on this issue recently. You can use a homography if you plan on modifying the texture in memory prior to assigning it to the surface. That's computationally expensive and adds an additional dependency to your program. There's a nice hack that'll fix the problem for you.

OpenGL automatically applies perspective correction to the texture you are rendering. All you need to do is multiply your texture coordinates (UV - 0.0f-1.0f) by the Z component (world space depth of an XYZ position vector) of each corner of the plane and it'll "throw off" OpenGL's perspective correction.

I asked and solved this problem recently. Give this link a shot:

texture mapping a trapezoid with a square texture in OpenGL

The paper I read that fixed this issue is called, "Navigating Static Environments Using Image-Space Simplification and Morphing" - page 9 appendix A.

Hope this helps!

ct

Community
  • 1
  • 1
ct_
  • 1,189
  • 4
  • 20
  • 34
2

The only correct transformation from UV coordinates to a 3D plane is an homographic transformation.

http://en.wikipedia.org/wiki/Homography

You must have it at some point in your computations.

To find it yourself, you can write the projection of any pixel of the texture (the same as for the vertex) and invert them to get texture coordinates from screen coordinates. It will come in the form of an homographic transform.

fa.
  • 2,456
  • 16
  • 17
1

Yeah, that looks like your traditional broken-perspective dent. Your algorithm looks right though, so I'm really not sure what could be wrong. I would check that you're actually using the newly calculated value later on when you render it? This really looks like you went to the trouble of calculating the perspective-correct value, and then used the basic non-corrected value for rendering.

Paul Z
  • 872
  • 4
  • 8
  • Just looking at the numbers, the difference between the corrected and uncorrected tex coords is of the order of 1.0e-4 (tex coords in the range [0.0,1.0]). Perhaps there is a scaling issue? Am I right to be using the clip depth coordinate for the scaling? – James Edge Mar 25 '11 at 21:31
1

You need to inform OpenGL that you need perspective correction on pixels with

glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST)

What you are observing is the typical distortion of linear texture mapping. On hardware that is not capable of per-pixel perspective correction (like for example the PS1) the standard solution is just subdividing in smaller polygons to make the defect less noticeable.

6502
  • 112,025
  • 15
  • 165
  • 265
  • 2
    This is a software renderer, not opengl (think a mod added that tag)... but I am using the opengl math for all the transformations. – James Edge Mar 25 '11 at 21:33
  • Sorry... i saw the tag OpenGL and so assumed you were using OpenGL (that should switch to software rendering if the hardware is not able to provide a feature). Anyway what you are observing is the so-called "linear perspective projection" problem and happens when you compute correct UV values for vertices but the polyfiller linearly interpolate them when rendering a polygon. – 6502 Mar 25 '11 at 21:54