From clipping coordinates, back to eye coordinates

Started by
4 comments, last by Maximus32 15 years, 2 months ago
Hi Everyone, I'm not sure if this question belongs here or in "Graphics Programming and Theory", so correct me if I'm wrong. I'm using a projection matrix to go from eye coordinates to clipping coordinates. In clip space fragments are clipped and new vertices are created. These new vertices do not have a Z value in eye coordinates. But I need that Z value for the deph buffer and perspective correct textures. I already tried lots of things like: a = (zFar - zNear) / 2; b = (zFar + zNear) / 2; ze = a * znd + b; How can I get the Z value from clip space (or normalized device space) back to eye space?
Advertisement
The z dpeth is the percent in between 0 to 1 that gives the depth to the back clipping from the front so its really:

(zfar - znear) * zdepth = z depth in field of view.

You can take the wvp matrix, invert it and throw the cordinate back out into world space though fairly easy but then lack the speed of this op. Or the z part of xyz.
I Just tried it and it's still looking bad. I think znear needs to added to get the correct value, but that also doesn't work.

Perhaps my clipping / normalized device values are messed up? I know the eye coordinates are good, so perhaps my projection matrix is wrong?

This is how I setup my Projection matrix, it should be exactly as in the OpenGL spec:

void
CAGLESMatrixF::glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
{
GLfloat m[16];

GLfloat idw = 1.0f / (right - left);
GLfloat idh = 1.0f / (top - bottom);
GLfloat idz = 1.0f / (zFar - zNear);

m[0*4+0] = (2.0f * zNear) * idw;
m[0*4+1] = 0.0f;
m[0*4+2] = (right + left) * idw;
m[0*4+3] = 0.0f;

m[1*4+0] = 0.0f;
m[1*4+1] = (2.0f * zNear) * idh;
m[1*4+2] = (top + bottom) * idh;
m[1*4+3] = 0.0f;

m[2*4+0] = 0.0f;
m[2*4+1] = 0.0f;
m[2*4+2] = -((zFar + zNear) * idz);
m[2*4+3] = -((2.0f * zFar * zNear) * idz);

m[3*4+0] = 0.0f;
m[3*4+1] = 0.0f;
m[3*4+2] = -1.0f;
m[3*4+3] = 0.0f;

*pCurrentMatrix_ *= m;
}

EDIT: After lots of debugging it looks like the Z value in normalized device space is NOT linear?! It does have a range from 0(near) to 1(far).

[Edited by - Maximus32 on January 26, 2009 3:25:28 PM]
Quote:EDIT: After lots of debugging it looks like the Z value in normalized device space is NOT linear?! It does have a range from 0(near) to 1(far).


Distance from eye = Z*(Zf-Zn) + Zn

As you can tell from this equation, Z does not change linearly with distance, but 1/Z does. An inverse linear function like this is actually faster than exponential.
Transform by the inverse of the projection matrix will convert from clip space to eye space.
I finally figured out a fast way to get the eye coordinates, from the normalized device coordinates. Turns out z is already 1/z after the perspective division (from clipping-space to normalized-device-space). The formula for getting 1 / eye-z is:

ze = a * znd + b;

So that's the same I had all along, only difference is: I now get 1/ze instead of ze. Which is even better, because it saves me a division.

a = -0.5f * (1.0f / zNear_ - 1.0f / zFar_)
b = 0.5f * (1.0f / zNear_);

I don't really know what I'm doing here, matrix math is really complex. So if someone can tell me how I got 1/z without a division, I'd love to know.

But I do know it works, and it's fast! :-)

This topic is closed to new replies.

Advertisement