depthBuffer, non linear values !!

Hi,
I am trying to get the depth of some pixels in my screen. for this I use glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&pixel);

it is good for the first and last plan (0.0 and 1.0), rigth values!

but for intermidiate values I am having some troubles…

for exemple:
I put a lookat at (1000,0,0,0,0,0,0,0,1)
I put three triangles perpenducular to X axis. the first at (x=0) the 2nd at (x=100) and the 3rd at (x=200). and I get the depth of three pixels each one inside one of the triangles.

when I multiplie by scale, add bias and map to the range…etc. I shoud have the depth equal to the x coord of the point.

I don’t have this and more (depth pt1 + depth pt3)/2 isn’t equal to depth2.

this means that the values are not linear !!??

here is the code:


glViewport(0,0,500,500);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90,1.,800,2000);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1200,0,0,0,0,0,0,0,1);

//for the 1 point I draw this triangle
glBegin(GL_TRIANGLES);
glVertex3f(0, 0 , 50);
glVertex3f(0, 25,-25);
glVertex3f(0,-25,-25);
glEnd();

//for the 2 point I draw this triangle
glBegin(GL_TRIANGLES);
glVertex3f(100, 0 , 50);
glVertex3f(100, 25,-25);
glVertex3f(100,-25,-25);
glEnd();

//for the 3 point I draw this triangle
glBegin(GL_TRIANGLES);
glVertex3f(200, 0 , 50);
glVertex3f(200, 25,-25);
glVertex3f(200,-25,-25);
glEnd();

(of course one triangle each time,and I get the depht of the point that match (y==0 and z==0)

//then I use this to get the depth
glReadPixels(xc, yc, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pixel);

//I tried with GL_INSIGNED_INT and is the same!!!

please help !!!

think you

this is simply because opengl doesnt use a linear z-buffer. if you take a look at a perspective projection matrix you will realize, that the z value of a transformed vertex is something like 1/z. a linear z buffer cant be realized by using linear matrix math and thus i guess it wont get implemented in opengl anytime soon (btw the nonlinearity of the zbuffer is also quite useful, since it makes the ztest more accurate for models that are close to the viewer and less for those that are far away)

Depth buufer precision isn’t linear throughout the buffer, so I wouldn’t be surprised if returned depth values arn’t linear.
In games you usally notice that objects that are further are z-fighting, though ones that are close arn’t. Check specs for reading DEPTH.

ok, I see …
anyway is there any way to get the x initial value of the point from the depth buffer.

in my program I need to know the true distance between the eye and the intersection of a line and the first object.

if I can’t do this with gluPerspective() can I do it otherway…??

think you

I’ve done linear z in perpective view with a couple of means.
You can read about it and download a glut example
http://www.geocities.com/vmelkon/zprecision.html

there is something that i do not understand yet !!!
1: what is w ???
2: when I see the 3rd line of the matrix projection is like this: (0 0 a b) then the new z value of the vertex is something like a*z + b. and not 1/z.
so I havn’t seen yet the devision by z!!!

could you please help ??!!

think you

uhm well thats not really an advanced questions… try to find a tutorial on homogenous coordinates (those are used in opengl to realize perspective projections… the x y and z coordinate are divided by the w coordinate. thus if the z value az + b is divided by w (which is -z because of the perspective matrix) you get (az+b)/-z…)

[This message has been edited by Chuck0 (edited 02-24-2004).]

ok I see and it work !!! good !!!
now from the depht buffer I can calculate the real distance between the eye and the object that I see in the screen. (I do the calculating inverse of OpenGL to get the real distance).

now I will tell you the project that I am working in

I am doing a ray-casting viewer of 3D objects. (because of the quality I have chosen this rendering method).
but the probleme with the ray-casting method is the time of rendering, too slow
because you have to find the intersection of your ray and the first obstacl in the sceen witch takes you a lot of time in calculating…

the idea is to use the opengl rendering (without really rendering anything) only for getting the famous distance. and then I would know the intersection of my ray with the first object in the sceen.

so my questions are:
1 - can I do this ?? )
2 - what is the fastest way to do it ?
3 - how can I draw my sceen without showing any thing on the window (just to get the z-buffer)

think you guys for your help

These are beginnners question but I will answer them anyway. The moderators may move this thread if they wish.

  1. yes, but the depth is in 0.0 - 1.0 range when you readback.
  2. It depends on your code and the hw
  3. What do you mean? You can make a hidden GL window and use p-buffer

The intersection test can be very expensive so there are some raytracers that use hw to render the first scene.

I thought you’d need a main window anyways for a pbuffer to get a DC, but I may be wrong.

You could also request a double buffered window and draw to the backbuffer, that’s the easiest way to draw stuff without showing it.

V-Man, I’m interested in the other method on your page (messing with the projection matrix), have you made any further experiments with it? Are the values really linear? I wish I’d know if it works on all HW.

-Ilkka