【问题标题】:Accessing the Depth Buffer from a fragment shader从片段着色器访问深度缓冲区
【发布时间】:2014-03-21 20:02:15
【问题描述】:

我有一个关于雾的想法,我想在 OpenGL 中实现:渲染场景后,在整个视口上渲染一个四边形。在片段着色器中,这个四边形对那个位置的深度缓冲区进行采样并改变它的颜色/alpha,以使那个像素像需要的那样模糊。

现在我知道我可以使用链接到纹理的深度缓冲区来渲染场景,正常渲染场景,然后渲染雾,将纹理传递给它,但这种渲染太多了。我希望能够

  • 直接从片段着色器访问当前深度缓冲区
  • 能够将场景渲染一次,既可以渲染到正常的深度缓冲区/屏幕,也可以渲染到雾的纹理。

这可能吗?

【问题讨论】:

标签: opengl fragment-shader


【解决方案1】:

您的想法(访问目标帧缓冲区以进行输入)会导致一个被禁止的反馈循环。

(...),但这个渲染太多了。

你为什么这么认为?您不必重新渲染整个场景,只需在其顶部叠加雾。

我希望能够

  • 从片段着色器直接访问当前深度缓冲区

如果您只想访问新渲染片段的深度,只需使用 gl_FragCoord.z,此变量(仅应读取以保持性能)保存新片段将具有的深度缓冲区值。

请参阅 GLSL 规范:

变量 gl_FragCoord 可用作片段着色器中的输入变量 它保存片段的窗口相对坐标 (x, y, z, 1/w) 值。 如果是多重采样,这个值可以是像素内的任何位置,或者是其中一个 片段样本。使用 centroid in 并没有进一步限制这个值是 在当前原语中。该值是固定功能的结果 在顶点处理后插入图元以生成片段。 z 分量 如果不包含着色器,是用于片段深度的深度值 对 gl_FragDepth 的任何写入。 如果着色器有条件,这对于不变性很有用 计算 gl_FragDepth 但需要固定的功能片段深度。

  • 能够将场景渲染一次,既可以渲染到正常的深度缓冲区/屏幕,也可以渲染到雾的纹理。

首先正常渲染场景有什么问题,深度进入单独的深度纹理附件,然后渲染雾,最后合成它们。计算复杂度不会因此而增加。只是因为它的步骤更多,它并没有在您想象的解决方案中做更多的工作,因为各个步骤变得更简单。

【讨论】:

  • gl_FragDepth 是一个输出变量,详细解释一下在这个正在进行的片段传递之后如何访问新渲染的片段深度? gl_FragDepth 只是针对固定管道功能的输出
【解决方案2】:

距离相机像素:

float z = gl_FragCoord.z / gl_FragCoord.w;

您认为的解决方案是一种常见的解决方案,但不需要使用四边形进行补充采样,如果启用了深度缓冲区,一切都已经存在,可以一次性计算雾:

here is a an implementation

const float LOG2 = 1.442695;
float z = gl_FragCoord.z / gl_FragCoord.w;
float fogFactor = exp2( -gl_Fog.density * 
                   gl_Fog.density * 
                   z * 
                   z * 
                   LOG2 );
fogFactor = clamp(fogFactor, 0.0, 1.0);

gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 2016-11-27
    • 2014-02-18
    相关资源
    最近更新 更多