我一直在努力实现延迟着色,因为我想在场景中至少有20个灯光。我在制作它足够快(并且仍然是)时遇到了问题,但后来我做了一个我认为会让它变慢的改变,但事实上我的帧速率几乎翻了一倍。
初始代码:
geometryPassFBO = createFBO(); // position texture, normal texture, colour texture and depth buffer
while (1)
{
bind geometryPassFBO.
allObjects.draw();
bind systemFBO();
for each light
send light info
draw light sphere sampling from position, normal and colour textures.
blit depth buffer from geometryFBO to systemFBO
for each light
light.draw(); // draw a cube to represent the light
2DObjects.draw(); // frame rate, etc...
}
我正在设置模板测试以仅在几何传递过程中设置像素时才进行光照传递(即背景为法线= 0,0,0且位置= 0,0,0和color = 0,0,0。
但是我无法将组合深度/模板缓冲区复制到默认深度/模板缓冲区。显然这不起作用,因为我们不知道系统深度/模板缓冲区采用什么格式。所以我读过最好设置另一个FBO,我们可以在其中指定深度/模板缓冲区格式,渲染到此,然后blit或渲染一个四边形屏幕以将其输出到屏幕。
所以在添加任何模板之前,我只是添加了新的FBO以使其有效。
我的新代码现在看起来像:
geometryPassFBO = createGeometryFBO(); // position texture, normal texture, colour texture and depth buffer
lightingPassFBO = createLightingFBO(); // colour texture and depth buffer
while (1)
{
bind geometryPassFBO.
allObjects.draw();
bind lightingPassFBO();
for each light
send light info
draw light sphere sampling from position, normal and colour textures.
blit depth buffer from geometryFBO to lightingPassFBO
for each light
light.draw(); // draw a cube to represent the light
2DObjects.draw(); // frame rate, etc...
bind systemFBO;
render screen quad sampling from colour texture.
}
这可以按预期工作。没想到的是我的帧速率从25 FPS跃升到45 FPS。
这是为什么?如何为屏幕四边形执行额外的着色器传递比不执行更有效?
快速跟进问题。使用简单的顶点和片段着色器渲染基于gl_FragCoord的纹理,或者直接将颜色附件直接渲染到系统FBO,可以更有效地渲染屏幕四边形?
答案 0 :(得分:2)
嗯,可能是这样的:
从geometryFBO到lightingPassFBO
的blit深度缓冲区
正如您所指出的,格式转换可能很慢。但是,由于您为此blit操作定义了输入和输出缓冲区,因此它们可能使用相同的深度格式。因此,blitting操作可以更快地进行。
另外,你可能根本不应该做这种事情。在渲染光立方体之前,只需将geometryFBO
的深度/模板缓冲区附加到lightingPassFBO
即可。请记住在渲染灯光后删除附件(否则,延迟传递将具有未定义的行为,假设您在延迟传递中从深度缓冲区读取)。
关于blitting与全屏四核的问题,我有一个更好的问题:为什么你在场景中累积20多个灯光而不使用高动态范围照明?因为渲染到屏幕的最后一遍也应该使用色调映射将HDR图像转换为LDR进行显示。
但是对于确切的问题,blit操作应该不比FSQ慢,假设没有进行格式转换。如果发生格式转换,那么将事物带到顶点着色器可能更有效。