我想在OpenGl中实现雾的想法:渲染场景后,在整个视口上渲染四边形。在片段着色器中,此四边形对该位置的深度缓冲区进行采样并更改其颜色/ alpha,以便根据需要使该像素变得模糊。
现在我知道我可以使用链接到纹理的深度缓冲区渲染场景,正常渲染场景然后渲染雾,传递它的纹理,但这是渲染太多。我希望能够
这可能吗?
答案 0 :(得分:3)
距离相机 - 像素:
float z = gl_FragCoord.z / gl_FragCoord.w;
您认为解决方案是一种常见的解决方案,但不需要使用四元组的补充采样,如果启用深度缓冲区,则一次性计算雾就已经存在:
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,但另外想要固定功能片段深度。
- 能够渲染场景一次,既可以渲染到正常的深度缓冲区/屏幕,也可以渲染到雾的纹理。
首先正常渲染场景会出现什么问题,深度会进入单独的深度纹理附件,然后渲染雾,最后合成它们。由此计算复杂性不会增加。仅仅因为它是更多的步骤,它在你想象的解决方案中没有做更多的工作,因为各个步骤变得更简单。