PDA

View Full Version : depth buffer values

thelamberto
07-22-2002, 06:03 AM
Hi,

I'm reading the depth buffer to enable me to calculate the range to any pixel in the screen. I'm want to ajust the z values from [0,1] to real-world depths. I can then multiply these by the corresponding precomputed scale factor to give the range. Can anyone tell me how these depth buffer values could be adjusted to real-world depths? Am I right to assume that 0.0 is coincident with the near clipping plane and 1.0 with the far clipping plane - thus I simply need to multiply by (far-near)?

// read the depth map from the framebuffer normalizing on the way
glPixelTransferf(GL_DEPTH_SCALE, 1.0);
glPixelTransferf(GL_DEPTH_BIAS, 0.0);
glClearDepth(1.0);
glReadPixels(x, y, dx, dy, GL_DEPTH_COMPONENT, GL_FLOAT, depthMap);

Cheers for any pointers.

[This message has been edited by thelamberto (edited 07-22-2002).]

rhmazza
07-22-2002, 10:36 AM
I'm pretty sure that's the way it works.

john
07-22-2002, 07:26 PM
Hello,

no, that's not how it works. the depth map is _exponential_, not linear.

ie, the values from near to far are stored like

z' <- (z-n)/(f-n)

so, z` becomes 0 when z == n and it becomes 1 when z==f, but it doesn't become 0.5 when z=(f+n)/2

you'll need to compute the reverse of the projection matrix (found in the back of the red book), or use gluUnProject (which does this for you).

cheers,
John

Jambolo
07-22-2002, 09:24 PM
Originally posted by john:
... the values from near to far are stored like

z' <- (z-n)/(f-n)

so, z` becomes 0 when z == n and it becomes 1 when z==f, but it doesn't become 0.5 when z=(f+n)/2
...

Hmmm, you'd better go back and relearn algebra. If z = (f+n)/2 and z' = (z-n)/(f-n), then z' = 0.5

john
07-22-2002, 10:34 PM
hey
you're right.

hmm. maybe i was thinking of something else, then, without thinking it through properly

oops

john
07-22-2002, 10:40 PM
aha!
you're right about the poorly thought out analogy. but, then it clicked. z' is divided by w' when stored in the depth buffer, yes? Maybe it isn't. I'm pretty sure it is, in which case:

octave:1> f=10
f = 10
octave:2> n=10
n = 10
octave:3> f=100
f = 100
octave:4> z=55
z = 55
octave:5> za=-(f*n)/(f-n)-(2.0*f*n)/(f-n)
za = -33.333
octave:6> zb=-z
zb = -55
octave:7> za/zb
ans = 0.60606

thelamberto
07-23-2002, 12:12 AM
Hi Guys,

I think I've nailed it - the transformation is not linear. Many thanks to Kevin Dennen for pointing this out.

By Kevin Dennen
Taken from "The Hidden Charms of Z-buffer" by Kurt Akeley, IRIS Universe ( 11 )

dcp = FarClip - NearClip
scp = FarClip + NearClip
a = -1.0 * ( FarClip * NearClip / dcp )
b = scp/ ( 2.0 * dcp ) + 0.5

ans = a / ( zval - b )

Depending on your far and near clip values, you may not see a big change until the 0.9## decimal values as this transformation is not linear. For example:
for Near Clip = 10 and Far Clip = 10000, zval =0.9 range = 99.1
zval =0.99 range = 909
zval = 0.999 range = 5002

http://www.opengl.org/discussion_boards/ubb/biggrin.gif

[This message has been edited by thelamberto (edited 07-23-2002).]

thelamberto
07-24-2002, 03:45 AM
Also got this:

From "ABCs of th Z-Buffer", published Jan/Feb 1991, Pipeline Volume 2, Number 1, Revision 1.1.

When the projection matrix is defined by

perspective (fovy, aspect, near, far);

and the z viewport transformation is defined by

lsetdepth (near ,far );
vp vp

then z and z are related by the following:
eye screen

far near(far - near )
vp vp
------------------------
far - near
z = ------------------------------------------------------------------
eye (far + near) (far - near ) far + near
vp vp vp vp
z - ----------------------------- - --------------
screen 2 (far - near) 2

Most of the time far_vp and near_vp are 1 and 0 respectively so equation simplifies to that posted above. Remember z is negative into the screen and this is "corrected" in the previous post.

EDIT: Equation got messed up - sorted.

[This message has been edited by thelamberto (edited 07-24-2002).]