Getting the depth image of a 3D object

Hi all,

I’m currently trying to save the depth image (pixel values = depth ) of 3D models. The aim is to simulate a kinect sensor taking depth pictures of a 3D object.
After looking at some websites, I read there are three ways to achieve this: using the zbuffer, using the wbuffer or using ray casting.
Which would you advice ? What are the pros and cons ?

For now, the only thing I barely managed to do is get information from the zbuffer. But I guess I’m doing something wrong as the values I get are really strange.

glEnable(GL_DEPTH_TEST);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);

GLfloat zData = new GLfloat[window_widthwindow_height];
glReadPixels(0, window_height, window_width, window_height, GL_DEPTH_COMPONENT32, GL_FLOAT, zData);

If you have better ideas, or know of a project already doing this, I would be glad to ear about.

Thanks for your advice.

What is “really strange” about the values?

Also, you should read your depth buffer back in the format that it’s stored in. Which means that unless you did something special when creating it, it is likely stored in 24_8 format (where the 8 bits are stencil bits). You should read them back as unsigned integers.

Well, the values are all zeros while there should be a huge teapot in the middle of the scene.
According to your comment I modified the code :

GLuint zData = new GLuint[window_widthwindow_height];
glReadPixels(0, window_height, window_width, window_height, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, zData);

But I get the same result.

Here is my display function, in case the problem is there :

readDepth();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
glTranslatef(0.0f, 0.0f, -3.0f);
glutSolidTeapot(1.0f); // Render a teapot
glutSwapBuffers();

Where the readDepth() function read the zbuffer and write it to a file.

glReadPixels(0, window_height, window_width, window_height, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, zData);

This reads from outside of the screen. If you want to read the entire screen, the first two values should be 0, 0. You’re starting at the height of the screen, and then reading another screen height on top of that. That’s not going to work.

I read the origin of the image is the bottom left corner ? Am I mistaken ?
Anyway, I changed it to

glReadPixels(0, 0, window_width, window_height, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, zData);

Still, I get only zeros. Any idea ?

I think that GL_DEPTH_COMPONENT24 would raise an error.
You probably want

glReadPixels(0, 0, window_width, window_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, zData);

http://www.opengl.org/wiki/Common_Mistakes#Depth_Buffer_Precision

Using GL_DEPTH_COMPONENT24 did not raise any exception.
With V-man’s solution, the zeros are replace by a full load of 4294967295.
But it is still as if my teapot doesn’t exist.

After some testing I get results. I think the problem is because I want to save the depth buffer to a file at the beginning of the program.
I suppose the object is not rendered when I try to read the zbuffer so it is empty.
The question now is, when should I attempt to read the z buffer in order to be sure there will be usefull information in it ?

Here is my display function :

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(0.0f, 0.0f, -3.0f);

glutSolidTeapot(1.0f); // Render a teapot

glutSwapBuffers();

readDepth();

Thank you in advance.

I kept advancing, and now I can read the zbuffer data.

However, I must read it as GL_FLOAT, adversely to all that as been said in this thread. How is that ?

Moreover, I linearize the values with the following formula :
zDataLin = (2.0 * zNear) / (zFar + zNear - zData * (zFar-zNear));

But this gives me very little numbers, I have to multiply them by 50000 to get something the order of unity.

Assuming defaults, you should reverse the order, like this :

glutSolidTeapot(1.0f); // Render a teapot

readDepth();

glutSwapBuffers();

Thank you Zbuffer, I figured this out eventually.

Now, my main problem is linearization of the z buffer data.

I need to transform z buffer data into distances from camera to object. As I said before, the only formula I came across performs poorly.