使用 FBO 的 OpenGL 着色管道效率
OpenGL shading pipeline efficiency with FBOs
我一直致力于实现延迟着色,因为我希望场景中至少有 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 和颜色 = 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 哪个更有效?
嗯,大概是这样:
blit depth buffer from geometryFBO to lightingPassFBO
正如您所指出的,格式转换可能很慢。但是由于您正在为这个 blit 操作定义输入和输出缓冲区,它们可能使用相同的深度格式。所以 blitting 操作可能会进行得更快。
此外,您可能根本不应该执行此 blit。在渲染光立方之前,只需将 geometryFBO
的 depth/stencil 缓冲区附加到 lightingPassFBO
。请记住在渲染灯光后移除附件(否则你的延迟通道将有未定义的行为,假设你正在从你的延迟通道中的深度缓冲区读取)。
至于你关于 blitting 与 full-screen quad 的问题,我有一个更好的问题:为什么你在一个场景中累积 20 多个灯并且 不 使用high-dynamic范围照明?因为渲染到屏幕的最终通道也应该使用 tone-mapping 将 HDR 图像转换为 LDR 以进行显示。
但至于确切的问题,blit 操作应该不比 FSQ 慢,假设没有进行格式转换。如果发生格式转换,那么将事情带到顶点着色器可能会更有效。
我一直致力于实现延迟着色,因为我希望场景中至少有 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 和颜色 = 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 哪个更有效?
嗯,大概是这样:
blit depth buffer from geometryFBO to lightingPassFBO
正如您所指出的,格式转换可能很慢。但是由于您正在为这个 blit 操作定义输入和输出缓冲区,它们可能使用相同的深度格式。所以 blitting 操作可能会进行得更快。
此外,您可能根本不应该执行此 blit。在渲染光立方之前,只需将 geometryFBO
的 depth/stencil 缓冲区附加到 lightingPassFBO
。请记住在渲染灯光后移除附件(否则你的延迟通道将有未定义的行为,假设你正在从你的延迟通道中的深度缓冲区读取)。
至于你关于 blitting 与 full-screen quad 的问题,我有一个更好的问题:为什么你在一个场景中累积 20 多个灯并且 不 使用high-dynamic范围照明?因为渲染到屏幕的最终通道也应该使用 tone-mapping 将 HDR 图像转换为 LDR 以进行显示。
但至于确切的问题,blit 操作应该不比 FSQ 慢,假设没有进行格式转换。如果发生格式转换,那么将事情带到顶点着色器可能会更有效。