not able to read depth value correctly from zbuffer using glReadPixels

hi,

i am trying to read the depth value from the z buffer using following code in my display function.However, it returns me some wierd values,most of the times 1.

As a sort of check, I used gluProject to project realworld (0.0,0.0,0.0) on window and get its depth value.Now when I am using window x and y coordinate obtained from above function in my glReadPixels function to get the depth value, its returning me 1.

Can anyone help me out in this? Do i need to make some initializations? I am using visual C++ 6.0. Following is my code.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1, 1.0, 500.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f,0.0f,100.0f,0.0f,0.0f,40.0f,0.0f,1.0f,0.0f );
glTranslatef(offset_x,offset_y,offset_z);
glRotatef(pitch, 1.0f, 0.0f, 0.0f);
glRotatef(yaw, 0.0f, 1.0f, 0.0f);

glLightf(GL_LIGHT0 , GL_SPOT_EXPONENT, 40.0f);
glLightfv(GL_LIGHT0 , GL_AMBIENT , light_ambient);

GLdouble modelView[16];
GLdouble projection[16];
GLint viewport[4];

//real world coordinates
GLdouble sx, sy, sz;
//window coordinates
GLdouble wx,wy,wz;

glGetDoublev (GL_MODELVIEW_MATRIX, modelView);
glGetDoublev (GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);

sx=0.0f;sy=0.0f;sz=0.0f;
// a variable to hold depth value from glReadpixels

GLfloat pixel ;

gluProject(sx, sy, sz, modelView, projection, viewport, &wx, &wy, &wz);

glReadPixels((int)wx,(int)wy,1,1,GL_DEPTH_COMPONENT,GL_FLOAT , &pixel);

cout<<sx<<","<<sy<<","<<sz<<endl;

cout<<wx<<","<<wy<<","<<wz<<endl;
cout<<pixel<<endl;

NOw, ideally wz and pixel shuold be the same…but this is not the case.Plz help me.Thanks a lot

Unless you have changed the default depth clear value in OpenGL, I don’t understand why you expect to get anything other than 1.0 back from glReadPixels. You clear the depth buffer, set up matrices and lights, and then you read back the depth buffer. But you don’t draw anything so the buffer is untouched from your last clear. At least draw something if you expect something other than 1.0 back.

Thanks a lot Bob. It worked !! Thankyou very much.
HOwever I have a question. Basically what I was trying to do, was to draw a trajectory in a 3-D world depending on the mouse click on the window. To check your suggestion, I drew a terrain(Basically a huge X-Y plane(filled polygon)) in my 3-D world and then clicked on window(so that there is something drawn before i read the depth value and convert window coordinates to real world 3-D coordinates). I got reesonable values for my 3-D coordinates.
But that means that unless I have something drawn there, I can’t get depth value and can’t draw the trajectory in 3-D world with just mouse clicks without terrain.

One more question,

sometimes I was getting 0 value for depth component on mouse click (and ofcourse, then a wrong 3-D triplet for world coordinates).On again clicking at the same point, I got correct z value (and ofcourse, then a correct 3-D triplet for world coordinates.)What do you think is the reason?

Thanks.

HOwever I have a question.

Lots of text but I don’t see the question, or did I fail to read between the lines?

One more question,

This question I have no answer to. Not very much details about the problem, you basically say it works sometimes, and don’t work sometimes.

hi,

sorry about me not being clear in my question. I forgot to add “DOES”.My question was

Quote:
But “DOES” that means that unless I have something drawn there, I can’t get depth value and can’t draw the trajectory in 3-D world with just mouse clicks without terrain.

Thanks a lot.

You’re still not being overly clear in what you want to achieve. Are you trying to allow the ability to define a 3D trajectory (or something similar) by clicking in a blank window?

If so, how do you propose that Opengl could evaluate the depth at which your click relates to?

hi rgpc,

yes. you got exactly what i want to do. To draw a trajectory in a 3-D world by clicking on blank window. The trajectory itself need not be entirely 3-D…means I want to draw it in X-Z plane.

One way to do it that I can see now,is to draw a terrain in 3-D world(a huge X-Z plane) and then click on it, retriving the depth value at that place, then unproject it to get real world coordinates and then draw a trajectory joining them.

Is there any other way?

Thanks a lot.

You can do this with a ray-plane intersection:

First find out the ray where the user clicked. You can do this with gluUnProject, just use some arbitary depth, for example 0. Then you have a point on the viewing ray, together with the camera position this completes the ray equation:

p = p0 + t*v
p0 being the camera position
v being the vector from camera to the unprojected point

The plane equation is:

ax+by+c*z+d = 0
with (a,b,c) being the normal vector and d being the distance from origin

For example, the plane equation of the xz-plane running through the origin is y=0.

Putting both equations together, you get:

t = - (c0y / vy)
vy being the y-coordinate of v and c0y being the y-coordinate of the camera

Just put t into the ray equation from above and you get the point p, which is what you are looking for.

For arbitary planes the resulting equation is a bit more complex than for a plane perpendicular to an axis, but it works basically the same for any other plane equation.

I hope this helps
Overmind

EDIT: little typo in one of the equations

[This message has been edited by Overmind (edited 07-28-2003).]

Thanks overmind…I ll try that.