I want to access the depth buffer value at the currently processed pixel in a pixel shader.
How can we achieve this goal? Basically, there seems to be two options:
The depth is found by using the near and far values set in the projection matrix. Simply multiply by the difference between near and far and add the near value to get your original value ( ((far - near) * Depth) + near).
The depth buffer is automatically created by the windowing system and stores its depth values as 16 , 24 or 32 bit floats. In most systems you'll see a depth buffer with a precision of 24 bits. When depth testing is enabled, OpenGL tests the depth value of a fragment against the content of the depth buffer.
gl_FragCoord. z is generated by the following process, assuming the usual transforms: Camera-space to clip-space transform, via projection matrix multiplication in the vertex shader. clip. z = (projectionMatrix * cameraPosition).
To linearize the sampled depth-buffer value, we can multiply the native device coordinates (ndc) vector by the inverse projection matrix and divide the result by the w coordinate (as the result is a homogenous vector).
On question 1: You can't directly read from the depth buffer in the fragment shader (unless there are recent extensions I'm not familiar with). You need to render to a Frame Buffer Object (FBO). Typical steps:
glGenFramebuffers
and glBindFramebuffer
if you have not used FBOs before.GL_COLOR_ATTACHMENT0
attachment point of your FBO with glFramebufferTexture2D
or glFramebufferRenderbuffer
. If you only care about the depth from this rendering pass, you can skip this and render without a color buffer.GL_DEPTH_ATTACHMENT
attachment point of the FBO.glBindFramebuffer
to switch back to the default framebuffer.On question 2: gl_FragCoord.z
is the depth value of the fragment that your shader is operating on, not the current value of the depth buffer at the fragment position.
gl_FragCoord.z
is the window-space depth value of the current fragment. It has nothing to do with the value stored in the depth buffer. The value may later be written to the depth buffer, if the fragment is not discard
ed and it passes a stencil/depth test.
Technically there are some hardware optimizations that will write/test the depth early, but for all intents and purposes gl_FragCoord.z
is not the value stored in the depth buffer.
Unless you render in multiple passes, you cannot read and write to the depth buffer in a fragment shader. That is to say, you cannot use a depth texture to read the depth and then turn around and write a new depth. This is akin to trying to implement blending in the fragment shader, unless you do something exotic with DX11 class hardware and image load/store, it just is not going to work.
If you only need the depth of the final drawn scene for something like shadow mapping, then you can do a depth-only pre-pass to fill the depth buffer. In the second pass, you would read the depth buffer but not write to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With