OpenGL - 如何访问深度缓冲区值? - 或者:gl_FragCoord.z与渲染深度到纹理

时间:2014-04-29 10:29:29

标签: opengl glsl shader fragment-shader

我想访问像素着色器中当前处理过的像素的深度缓冲区值。

我们如何实现这一目标?基本上,似乎有两种选择:

  1. 渲染纹理的深度。我们怎样才能做到这一点以及权衡什么呢?
  2. 使用gl_FragCoord.z提供的值 - 但是:这是正确的值吗?

2 个答案:

答案 0 :(得分:24)

问题1:您无法直接从片段着色器中的深度缓冲区读取(除非我最近不熟悉的扩展名)。您需要渲染到帧缓冲对象(FBO)。典型步骤:

  1. 创建并绑定FBO。如果您之前没有使用过FBO,请查找glGenFramebuffersglBindFramebuffer等来电。
  2. 创建纹理或渲染缓冲区以用作颜色缓冲区,并使用GL_COLOR_ATTACHMENT0glFramebufferTexture2D将其附加到FBO的glFramebufferRenderbuffer附着点。如果您只关心此渲染过程的深度,则可以跳过此过程并在没有颜色缓冲区的情况下进行渲染。
  3. 创建深度纹理,并将其附加到FBO的GL_DEPTH_ATTACHMENT附着点。
  4. 您的渲染会创建您想要使用的深度。
  5. 使用glBindFramebuffer切换回默认的帧缓冲区。
  6. 将深度纹理绑定到片段着色器使用的采样器。
  7. 您的片段着色器现在可以从深度纹理中进行采样。
  8. 问题2:gl_FragCoord.z是着色器正在操作的片段的深度值,片段位置深度缓冲区的当前值。

答案 1 :(得分:5)

gl_FragCoord.z是当前片段的窗口空间深度值。它与存储在深度缓冲区中的值无关。如果片段不是discard并且它通过模板/深度测试,则 以后 可以将值写入深度缓冲区。

从技术上讲,有一些硬件优化可以尽早编写/测试深度,但是对于所有意图和目的,gl_FragCoord.z不是存储在深度缓冲区中的值。

除非您在多次传递中渲染,否则无法在片段着色器中读取和写入深度缓冲区。也就是说,您不能使用深度纹理来读取深度,然后转身并写入新的深度。这类似于尝试在片段着色器中实现混合,除非您使用DX11类硬件和图像加载/存储做一些奇特的事情,它只是不起作用。

如果您只需要阴影贴图等最终绘制场景的深度,那么您可以执行仅深度预传递来填充深度缓冲区。在第二遍中,您将读取深度缓冲区但不写入它。