I am doing a GL multi-pass rendering app for iOS. The first pass renders to a depth buffer texture. The second pass uses the values in the depth buffer to control the application of a fragment shader. I want to rescale the values in the depth buffer to something useful but before I can do that I need to know the depth value range of the depth buffer values. How do I do this?
2 Answers
The range of the values written to the depth buffer are whatever you want them to be. Typically they fall in the 0-to-1 range. The actual value that is written in to the depth buffer is computed during the viewport transformation, based on the Z value of vertex in NDC space (after the perspective divide by w in clip space).
The NDC depth value (Z, after the perspective divide by W) is scaled by depth portion of the viewport transformation (which brings your X and Y coordinates into a coordinate space you'd associate with pixels in the window), and then scaled by (2^n-1)
-- that's meant to be read as "two to the power of n
" -- n
is the bit precision of the depth buffer. The resulting value is written to the depth buffer.
OpenGL splits definition of the viewport transformation matrix into glViewport and glDepthRange calls. glDepthRange is what controls the scale factor responsible for determining the depth range you are asking about. You can call glGetFloatv with the GL_DEPTH_RANGE
selector to recover the current range. This will allow you to make use of the range without assuming it's 0 to 1 (although 99.9% of the time, in practice, nobody ever changes it).
Further reading, if you want some insight on how to reconstruct the math to follow the Z value all the way from eye space to the depth buffer.
-
\$\begingroup\$ I'll give this one to Josh for all the studly additional reference material and tip about triangle planar-ness. I am inclined to do a hack where are position near/far clip planes to exactly match the z-extent of the geometry I am rendering so that the depthmap has nice values. What am I up to? I want to create interesting location specific blur effects during pass #2 based on what ever is in pass #1 depth map. \$\endgroup\$– duglaFeb 3, 2011 at 19:52
Values in depth buffer are always in range between 0-1. Zero is that rendered fragment is in depth of near plane and 1 is that fragment is in depth of far plane. And everything between it.
If you want to know real depth in world space it is easy to compute it from depth buffer.
depth = nearPlane + ( farPlane - nearPlane ) * depthBufferValue;
And thats why you specify the near and far planes in your projection matri, to gain more accuracy of depth buffer.
Also be aware of difference between depth and distance when using depth buffer values.
-
\$\begingroup\$ @notebene. Almost there. I want to rescale the range of values in the depthbuffer be be exactly 0 -> 1. So if the rendered min/max depthvalues are .25/.75 I want (depthvalue - .25)/(.75 - .25). So, is there a way to discover the min/max of the depthbuffer following pass 1 and use that to rescale during pass 2. \$\endgroup\$– duglaFeb 3, 2011 at 16:10
-
1\$\begingroup\$ @dugla: since you are rendering triangles, which are planar, then perforce the minimum and maximum depth values will be associated with the minimum and maximum vertices in the scene. If you know these two, you can manually transform them all the way through the pipeline and you'll know the minimum and maximum values you'd be writing to the depth buffer. This is possibly easier than rendering, then reading back the whole depth buffer and iterating it. \$\endgroup\$– user1430Feb 3, 2011 at 16:38