Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL es 2.0 Read depth buffer

As far as i know, we can't read the Z(depth) value in OpenGL ES 2.0. So I am wondering how we can get the 3D world coordinates from a point on the 2D screen?

Actually I have some random thoughts might work. Since we can read the RGBA value by using glReadPixels, how about we duplicate the depth buffer and store it in a color buffer(say ColorforDepth). Of course there need to be some nice convention so that we don't lose any information of the depth buffer. And then when we need a point's world coordinates , we attach this ColorforDepth color buffer to the framebuffer and then render it. So when we use glReadPixels to read the depth information at this frame.

However, this will lead to 1 frame flash since the colorbuffer is a weird buffer translated from the depth buffer. I am still wondering if there is some standard way to get the depth in OpenGL es 2.0?

Thx in advance!:)

like image 618
Brian Avatar asked Apr 07 '10 23:04

Brian


People also ask

What is an opengl depth buffer?

The depth-buffer is a buffer that, just like the color buffer (that stores all the fragment colors: the visual output), stores information per fragment and has the same width and height as the color buffer.

How is depth buffer calculated?

z' = (2^d -1 ) * ((far + near)/(2 * (far - near) + (1 / z) * (-far * near) / (far - near) + 1/2) when d is the depth of the z-buffer (24 bits at my case) and z is the z value of the vertex.


1 Answers

Using an FBO, you can render without displaying the results. If you're in ES 2.0, your fragment shader can access the current fragment's depth (in window coordinates) as part of gl_FragCoord, so you can write that to the colour buffer, use glReadPixels to get the result back and proceed. Alternatively, you can load world-space z as a varying and write that from your fragment shader, in case that's an easier way around.

To convince yourself, try writing a quick shader that puts gl_FragCoord.z out hastily in low precision, e.g. just

gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0);

You should get a greyscale with the intensity of the colour representing depth. Because you're in window coordinates, intensity will range from 0.0 (closest possible unclipped fragment) to 1.0 (farthest possible unclipped fragment). In order not to lose quite a lot of precision, it's probably more helpful to split the value between components, as your vendor almost certainly doesn't support floating point target buffers.

like image 197
Tommy Avatar answered Oct 11 '22 07:10

Tommy