OpenGL - How to access depth buffer values? - Or: gl_FragCoord.z vs. Rendering depth to texture

0xb*_*00d 10 opengl shader glsl fragment-shader

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:

  1. Render depth to texture. How can we do this and what is the tradeoff?
  2. Use the value provided by gl_FragCoord.z - But: Is this the correct value?

Ret*_*adi 25

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

  1. 创建并绑定FBO.看起来像电话glGenFramebuffersglBindFramebuffer,如果你以前没有使用过宗教组织.
  2. 创建一个纹理或渲染缓冲区以用作颜色缓冲区,并GL_COLOR_ATTACHMENT0使用glFramebufferTexture2D或将其附加到FBO 的附着点glFramebufferRenderbuffer.如果您只关心此渲染过程的深度,则可以跳过此过程并在没有颜色缓冲区的情况下进行渲染.
  3. 创建深度纹理,并将其附加到GL_DEPTH_ATTACHMENTFBO 的附着点.
  4. 您的渲染是否会创建您想要使用的深度.
  5. 使用glBindFramebuffer切换回默认的帧缓冲.
  6. 将深度纹理绑定到片段着色器使用的采样器.
  7. 您的片段着色器现在可以从深度纹理中进行采样.

问题2:gl_FragCoord.z是着色器操作的片段的深度值,而不是片段位置的深度缓冲区的当前值.

  • 通过使用投影矩阵中设置的近值和远值来找到深度。只需乘以近端和远端之间的差值,然后加上近端值即可得到原始值(((远 - 近)* 深度)+ 近)。 (2认同)

And*_*man 5

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

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

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

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