Getting worldspace coordinate out of z-value

Hi there

I´m not so good at this math-stuff, therefore i couldn´t quite get the solution to this problem myself.

All i need, is to calculate the worldspace-position of a pixel. As information i have the z-value and the modelview and projection-matrix (and maybe their inverse).

Oh, almost forgot: Of course the screenspace-coordinates are available, too.

AFAIK it is possible to do that, but i don´t know how.

Thanks in advance,

I have no idea what kind of algorithms are needed to write your own function that does that,but you can always use gluUnProject.

Na, i have to be able to do it in a fragment program.

Thanks, though.

This explains how gluUnProject works(quite simple,suprisingly):

Great. Thanks.

Now the only question remaining is, how i get the inverse of model*proj. Since this is certainly not an orthogonal matrix, i assume i cannot simply take the transpose, can i ?


Jan, here’s another way to do it:

Since this is certainly not an orthogonal matrix, i assume i cannot simply take the transpose, can i ?

You can only do the transpose trick with an orthonormal basis.

-replaced sz with z
-changed variable names to clarify a few things

Cool, that´s a really great formula !
I didn´t have the time to try it, yet, but i will as soon as possible.

eyePos and eyeLeft, etc. are in worldspace, no ?

Thanks again.

Jan, that’s affirm on the world space, for all the eye* vecs.

Originally posted by Portal:
[b]Vector deproject( float sx, float sy, float z ){

float aspect = height / width;
float proj = tan( fieldOfViewX );
float x = -z*(2.0sx/width-1.0)proj;
float y = -z
sy/height-1.0)proj aspect;

return eyePos + eyeLeftx + eyeUpy + eyeForwardz;
You are aware that the z-value is in the range [0,1],right?I don’t think eyeForward
z will give the result you’re expecting.Personally,i find it a little strange to be able to unproject a z-value in range[0,1] without having to use the Modelview and Projection matrices.

mikeman, the z is an eye space z, not a screen space z. Also, I am using the projection and model view matrices, just not in a familiar matrix form. All I’m doing is reversing the projection process, in place of an explicit matrix inversion.


another thought: If you are using a fragment program, put the world vertex position from your vertex program into a tex coord, and use the lerped value in your fragment program, or did I misunderstand your question. The code I gave above assumes screen space, not homogeneous projection space. That too is doable, you just need to reverse that setup.

For the model view projection setup:
P = ProjMat * ModelView * Pw

You need to solve for Pw, the world position

invert(ProjMat * ModelMat) * P = Pw


invert(ModelMat) * invert(ProjMat) * P = Pw
(reverse order law of inversion)

All this says is (reading right to left): First undo the homogeneous projection, then undo the eye space projection.

Here’s the invert(ProjMat) right out of the red book:
[(r-l)/(2n) 0 0 (r+l)/(2n) ]
[ 0 (t-b)/(2n) 0 (t+b)/(2n) ]
[ 0 0 0 -1 ]
[ 0 0 -(f-n)/(2fn) (f+n)/(2fn)]

Multiply this matrix with P to get your eye space position,

Pe = invert(ProjMat) * P.

Then proceed as before

Pw = eyePos + eyeLefteyeX + eyeUpeyeY + eyeForward*eyeZ

Hope this makes some sense. :slight_smile:

I want to save the depth-value (meaning 1/z) into a texture. Later on i want to reconstruct the worldspace-coordinate by using the screenspace-position (ie. x=1…1024, y=1…768) of the pixel and the depth-value.

This is for deferred shading. By only saving the depth-value i want to save memory, instead of saving x,y,z i only want to save z (or better 1/z).

But as far as i understood you, that formula should be exactly what i need.


If you want that formula to work,you have to save the eye-space z-coordinate,not (1/z) or the value of the depth buffer.

It’s a trivial matter going from a z-value in eye space to a z-value in projection or screen space:

projZ = -(f+n)/(f-n) * eyeZ - 2fn/(f-n)

this is from the red book - just the eye column vector with the 3rd row of the projection matrix.

screenZ = projZ / -eyeZ

eyeZ here is just the eye column vector with the 4th row of the projection matrix [0 0 -1 0], essentially a division by w.

I left all this out of my code simply because I just don’t use the normalized z in my work, and I though it would confuse the issue.