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

问题描述 投票:0回答:3

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

如何才能实现这个目标?基本上,似乎有两个选择:

  1. 渲染纹理的深度。我们怎样才能做到这一点以及权衡是什么?
  2. 使用 gl_FragCoord.z 提供的值 - 但是:这是正确的值吗?
opengl glsl shader fragment-shader
3个回答
33
投票

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

  1. 创建并绑定FBO。如果您以前没有使用过 FBO,请查找诸如
    glGenFramebuffers
    glBindFramebuffer
    之类的电话。
  2. 创建一个纹理或渲染缓冲区用作颜色缓冲区,并使用
    GL_COLOR_ATTACHMENT0
    glFramebufferTexture2D
    将其附加到 FBO 的
    glFramebufferRenderbuffer
    附加点。如果您只关心此渲染通道的深度,则可以跳过此步骤并在没有颜色缓冲区的情况下进行渲染。
  3. 创建深度纹理,并将其附加到 FBO 的
    GL_DEPTH_ATTACHMENT
    附加点。
  4. 进行渲染以创建您想要使用的深度。
  5. 使用
    glBindFramebuffer
    切换回默认帧缓冲区。
  6. 将深度纹理绑定到片段着色器使用的采样器。
  7. 您的片段着色器现在可以从深度纹理中采样。

关于问题2:

gl_FragCoord.z
是着色器正在操作的片段的深度值,不是片段位置处深度缓冲区的当前值。


9
投票

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

从技术上讲,有一些硬件优化可以尽早写入/测试深度,但出于所有意图和目的,

gl_FragCoord.z
不是存储在深度缓冲区中的值。

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

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


0
投票

如果有人最近读到这篇文章,Andon 谈到的“异国情调”加载/存储可以使用扩展名:

#extension GL_ARB_shader_image_load_store: require

特别是它允许使用具有单个附件的帧缓冲区,即深度缓冲区(无渲染缓冲区),其中深度测试在片段着色器之前完成,并允许写入相同的深度缓冲区,例如就我而言,我需要这样做:

if(!gl_FrontFacing) depth = 0.0;
    else depth = gl_FragCoord.z;
© www.soinside.com 2019 - 2024. All rights reserved.