我实现了一个简化的延迟着色(我不计算点光源的边界) 在填充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语句可能会导致一些性能损失。这是设置的唯一方法吗? 背景颜色?
答案 0 :(得分:3)
不确定我是否理解问题所在,但这里有一些有很多假设的想法。
您正在考虑做这样的事情? :
我认为渲染器正在执行以下操作:
你的着色器真的没有理由像这样编写背景颜色。我实际上也会渲染背景中的内容并始终使用0值清除gbuffer。我想在最后阶段将漫反射和光线结合起来时会出现问题,因此可能更容易进行下面进一步解释的模板方法。我个人将材质索引存储在漫反射颜色的alpha通道中,然后上传纹理中的所有材质属性。
在我的材料中,我有两个标量(以及更多......):
组合漫反射缓冲区和光缓冲区时(大大简化):
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