在 OpenGL 中处理 FBO 的最佳方法是啥?

Posted

技术标签:

【中文标题】在 OpenGL 中处理 FBO 的最佳方法是啥?【英文标题】:What is the best way to handle FBOs in OpenGL?在 OpenGL 中处理 FBO 的最佳方法是什么? 【发布时间】:2011-01-13 00:02:47 【问题描述】:

长期以来,我一直想知道处理 OpenGL 帧缓冲区对象 (FBO) 的最佳方式是什么。 切换 FBO 的成本可能很高,但也会定义新的附件。

你是怎么做到的快速

我在这三个之间犹豫:

1 FBO 适用于所有内容,更改附件但不要在 FBO 之间切换

为渲染路径中的每个渲染目标(大小 + 格式)提供 1 个 FBO。这意味着我将为类似的渲染目标重用相同的 FBO。但这种方式自定义模糊将花费 4+ FBO。

每个渲染目标1个FBO,只设置一次附件,然后在FBO之间切换

另外,我是否应该尽量减少 FBO 开关的数量(就像我尽量减少纹理绑定的数量一样)?

【问题讨论】:

首先...什么是 FBO?如果您要多次使用首字母缩写词,建议第一次使用未展开的缩写词。 FBO = 帧缓冲对象 很好的问题。但是下面给出的答案的第一部分与“OpenGL Insights”一书中所说的相矛盾。该书指出,在多个 FBO 之间切换是昂贵的,并且是提高性能的最佳方法正在对同一个 FBO 使用多个附件。 这就是为什么他说“为了提高性能”。 【参考方案1】:

更新的参考资料:

NVIDIA 2016 (?):使用多个 FBO intel 2016:使用多个 FBO

NVIDIA 2005(可能已经过时): 我所知道的 NVIDIA 上一次官方性能推荐已经快五年了。在他的GDC presentation 中,Simon Green 推荐了以下内容(幻灯片 29):

按照性能提高的顺序:

    多个 FBO 为您要渲染到的每个纹理创建一个单独的 FBO 使用BindFramebuffer()切换 在测试版 NVIDIA 驱动程序中可以比 wglMakeCurrent() 快 2 倍 单个 FBO,多个纹理附件 纹理应具有相同的格式和尺寸 使用FramebufferTexture()在纹理之间切换 单个 FBO,多个纹理附件 将纹理附加到不同颜色的附件 使用glDrawBuffer() 切换渲染到不同颜色的附件

根据我的经验,第二种情况确实比第一种更快(ATI Radeon HD4850、Geforce 8800GT)。我没有尝试过第三种情况,因为它会使我的代码复杂化。

【讨论】:

GDC presentation here 提到不要切换附件,因为这显然会导致性能下降。所以它与这个性能顺序相矛盾。 请注意,我提到的演示文稿是 2005 年的,而我的结果是 2009 年的。如果过去十年的表现顺序发生变化,我不会感到惊讶。 我还要添加这个link,它提到了切换 FBO(#1)而不是切换附件(#2 和 #3)的更好性能。更新这个问题的答案是个好主意。 感谢 Deathicon,我刚刚更新了答案,包括您的链接【参考方案2】:

作为哲学问题,修改对象状态需要重新验证。相反,对于驱动程序 [1],只需更改对象绑定(从前一帧开始就已经有效)应该更快。

所以作为第一个实现,我会为每个渲染目标选择 1 个 FBO(或者更准确地说,渲染目标 set。您通常一次渲染到多个缓冲区)。

也就是说,没有什么比针对多个实现对您的应用进行基准测试更好的了。

[1] 我提到了驱动程序,因为 FBO 更改可能会强制刷新 GPU,具体取决于架构。在大多数情况下,它会引入气泡。所以这绝对是你不想经常做的事情。这比优化纹理绑定更重要,例如

【讨论】:

以上是关于在 OpenGL 中处理 FBO 的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

用openGL绘制频谱图的最佳方法是啥

使用 OpenGL / LibGDX 的后处理问题 - 黑屏(FBO、着色器、四边形)

在 CUDA 中修改 OpenGL FBO 纹理附件

OpenGL:一次只有一个 FBO 工作

OpenGL 渲染到 FBO

将绑定到 FBO 的纹理复制到另一个 OpenGL 上下文