延迟着色和背景颜色

时间:2012-09-29 14:06:09

标签: opengl-4

我实现了一个简化的延迟着色(我不计算点光源的边界) 在填充g-buffer之后我只使用全屏quad来计算照明。我用 在第二阶段混合(glBlendFunc(GL_ONE,GL_ONE))以处理多个灯光。 然后glClearColor中的rgb值应设置为0,以获得正确的结果。填充g-buffer时 glClearColor可以是任何颜色(某些颜色可能仅改变最终图像中的背景颜色)。 现在我想知道如何在最终图像中设置背景颜色。一种方法来做到这一点 在填充g-buffer期间使用glClearColor(0,0,0),然后在片段着色器中使用if-if语句:

if((normal.x == 0.0) && (normal.y == 0.0) && (normal.z == 0.0))
{
    fragColor = vec4(1, 0, 0, 1); // here we can set a background color
}
else
{
    fragColor = computeLighting(worldPos, normal, diffM, specM, specMS);
} 

它工作正常,但if语句可能会导致一些性能损失。这是设置的唯一方法吗? 背景颜色?

1 个答案:

答案 0 :(得分:3)

不确定我是否理解问题所在,但这里有一些有很多假设的想法。

您正在考虑做这样的事情? :

  • 使用您想要的背景颜色清除gbuffer中的漫反射附件(Howevery ..你不想用这个值清除其他纹理,例如法线!)
  • 填充gbuffer后,几何体未覆盖的任何内容仍应具有背景颜色(在漫反射附件中)
  • 如果没有为片段定义法线,则在最后一个阶段手动编写硬编码颜色。

我认为渲染器正在执行以下操作:

  • 填充gbuffer(带有多个附件的FBO中的漫反射,法线,深度等)
  • 对于每个灯光,您将全屏四边形添加剂混合到单独的FBO(光累积缓冲区)。
  • 然后最后将gbuffer中的漫反射附件与光线累积缓冲区结合使用,将最终结果渲染到屏幕上。

你的着色器真的没有理由像这样编写背景颜色。我实际上也会渲染背景中的内容并始终使用0值清除gbuffer。我想在最后阶段将漫反射和光线结合起来时会出现问题,因此可能更容易进行下面进一步解释的模板方法。我个人将材质索引存储在漫反射颜色的alpha通道中,然后上传纹理中的所有材质属性。

在我的材料中,我有两个标量(以及更多......):

  • AmbientWeight
  • 轻质

组合漫反射缓冲区和光缓冲区时(大大简化):

FinalColor = Diffuse * AmbientWeight + Diffuse * Light * LightWeight

如果您的背景使用材质0且AmbientWeight = 1且LightWeight = 0,则FinalColor将始终为漫反射缓冲区中的原始值。

许多简单的延迟渲染器只是以这种方式计算最终结果:

FinalColor = Diffuse * Light(来自光缓冲区的漫反射缓冲区*片段的碎片)

在您的情况下,这当然会导致您的背景颜色消失,因为这些碎片永远不会被点亮。 (Diffuse * 0始终是结果)您可以将漫反射缓冲区中的Alpha通道用作AmbientWeight以获得一些快速结果。

FinalColor = Diffuse * Diffuse.a + Diffuse * Light

谈到表现:

这真的很难预测。在着色器中跳过最终的光计算可能会给你一些东西,但是在你到达这个阶段之前你已经完成了所有的gbuffer读取和解包。无论着色器返回什么,您最终都会使用混合操作影响整个光缓冲区,并且每个光源都会读取整个gbuffer。检查正常缓冲区中的所有组件是否为0将仅触发没有几何体的区域。当每个灯使用全屏四边形时,你会遇到很多瓶颈。

从读取位置缓冲区(或从深度缓冲区重建位置)开始,然后确定点光源是否无法到达片段并在执行任何其他操作之前丢弃它可能会有所帮助。对于较小的灯光,您不会最终读取每个片段的gbuffer中的所有内容。这实际上取决于你的gbuffer有多胖,渲染的内容,灯光的大小以及你渲染的灯光数量。

动态分支也可以扼杀性能,但有时可能是“较小的邪恶”。我尽可能地避免它。

额外:

说到“背景颜色”,我个人使用模板缓冲区用天空盒或类似物填充背景。在编写漫反射缓冲区时构建模板蒙版,使用反向蒙板渲染背景时,只会影响背景片段(无深度测试或深度写入)。如果我的整个场景都被几何体覆盖,那么就不会写出碎片。这假设您正在将最终结果写入使用与gbuffer相同深度附件的第3个FBO。 (Depth24 + Stencil8缓冲区)

您可以使用带有光信息的UBO发送数组,而不是使用全屏四边形(使用混合)绘制每个灯光。然后使用一个全屏四边形绘制所有点光源。您最终会进行相同数量的光计算,但读写的数量始终是不变的。 (但是UBO仍然有尺寸限制)

您可能还会发现感兴趣的Tiled Deferreed Shading是潜在的下一步: http://www.cse.chalmers.se/~olaolss/main_frame.php?contents=publication&id=tiled_shading (你只从gbuffer中读取一次,只为光通道写一个片段)

论文:http://www.cse.chalmers.se/~uffe/tiled_shading_preprint.pdf