View Full Version : 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,

Jan.

mikeman

04-25-2004, 04:55 AM

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.

Jan.

mikeman

04-25-2004, 06:47 AM

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

http://www.hmug.org/man/3/gluUnProject.html

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.

plasmonster

04-25-2004, 11:26 AM

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.

edit:

-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.

plasmonster

04-26-2004, 11:35 AM

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

mikeman

04-26-2004, 12:30 PM

Originally posted by Portal:

Vector deproject( float sx, float sy, float z ){

float aspect = height / width;

float proj = tan( fieldOfViewX );

float x = -z*(2.0*sx/width-1.0)*proj;

float y = -z*(2.0*sy/height-1.0)*proj* aspect;

return eyePos + eyeLeft*x + eyeUp*y + eyeForward*z;

}

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.

plasmonster

04-26-2004, 03:28 PM

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.

plasmonster

04-26-2004, 08:26 PM

Jan,

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

or

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 + eyeLeft*eyeX + eyeUp*eyeY + eyeForward*eyeZ

Hope this makes some sense. :)

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.

Thanks,

Jan.

mikeman

04-26-2004, 10:45 PM

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.

plasmonster

04-26-2004, 11:33 PM

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.

Powered by vBulletin® Version 4.2.2 Copyright © 2014 vBulletin Solutions, Inc. All rights reserved.