从片段着色器访问深度缓冲区

时间:2014-03-21 09:19:11

标签: opengl fragment-shader

我想在OpenGl中实现雾的想法:渲染场景后,在整个视口上渲染四边形。在片段着色器中,此四边形对该位置的深度缓冲区进行采样并更改其颜色/ alpha,以便根据需要使该像素变得模糊。

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

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

这可能吗?

2 个答案:

答案 0 :(得分:3)

距离相机 - 像素:

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 );

答案 1 :(得分:3)

您正在考虑(访问目标帧缓冲区以进行输入)将导致禁止反馈循环。

  

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

你为什么这么认为?您不必将整个场景渲染为新场景,只需将雾叠加在它上面。

  

我希望能够

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

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

参见GLSL规范:

  

变量gl_FragCoord可用作片段着色器中的输入变量   它保存了片段的窗口相对坐标(x,y,z,1 / w)值。   如果是多次采样,则此值可以是像素内的任何位置,也可以是其中之一   片段样本。使用质心不会进一步限制该值   在当前原语中。此值是固定功能的结果   在顶点处理之后插入基元以生成片段。 z组件   是否包含着色器时将用于片段深度的深度值   对gl_FragDepth的任何写入。如果有条件地使用着色器,这对于不变性很有用   计算gl_FragDepth,但另外想要固定功能片段深度。

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

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