OpenGl ES:使用许多FBO



我需要有任意数量的过程,其中每个过程渲染到某种缓冲区,然后用作下一个过程的输入纹理。

目前,每个缓冲区都是由一个FBO实现的,其纹理附加到COLOR0。首先,我用创建FBO(以及里面的纹理)

glGenTextures(1, texIds, 0);
glBindTexture(GL_TEXTURE_2D, texIds[0]);
// ... here goes the usual glTexParameterf stuff ...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
glGenFramebuffers(1, fboIds, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fboIds[0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texIds[0], 0);

然后每当我需要渲染到缓冲区时,我都会调用

glBindFramebuffer(GL_FRAMEBUFFER, fboIds[0]);

每当我需要将Buffer的内容设置为下一次传递的输入时,我都会进行

glBindTexture(GL_TEXTURE_2D, texIds[0]);

一切正常。

问题是,我在许多来源中读到BindFramebuffer调用非常慢(刷新整个管道),尤其是在我使用的OpenGL ES目标上。例如,SongHo-Ahn明确指出

"(…)切换帧缓冲区可连接的图像比FBO之间的切换。">

(http://www.songho.ca/opengl/gl_fbo.html)

因此,我正在考虑切换到只有1个帧缓冲区和许多纹理的设计;每次我需要渲染到Buffer时,我只会将给定的纹理附加到唯一Framebuffer的COLOR0。

你认为这是个好主意吗?或者,也许一些完全不同的设计在这里会是最好的——RenderBuffers呢?

根据NVIDIA的演示(第65页),您不应该在单个FBO:上交换附件

"不要创建一个FBO,然后交换其上的附件在驱动程序中导致大量验证,进而导致较差表演">

这是因为当您将新纹理附加到FBO的颜色附件时,OpenGL驱动程序必须检查附件是否正确以及FBO是否完整,如果经常这样做,可能会非常昂贵。

也有可能同时渲染为多种颜色的附件,但这仅在OpenGL ES 3.0+中可用。

但总的来说,您的问题的答案是。你应该坚持使用多个FBO,而不是更改其上的附件。

除了MarGenDo链接的英伟达演示文稿之外(还有一点矛盾),这里有一个OpenGL.org官方文档的链接,该文档似乎(部分)相反:

每次制作1个FBO并将纹理绑定到它更好吗需要渲染到纹理?FBO本身不需要太多内存。它是一个状态向量对象。就性能而言,每次绑定时,驱动程序需要验证状态,这需要花费CPU时间。从逻辑上讲,每个Render_to_Texture最好有1个FBO(RTT)。然而,研究发现,如果你纹理大小相同,并且使用1个FBO。如果你有1064x64的纹理和512x64的10个纹理构成2个FBO。每组一个FBO。

Leszek的评论必须纳入上下文才能完成当前接受的答案。

如果使用<Opengl es 3.0,最好保持FBO附件不变并更改FBO。而改变FBO成本高昂;没有必要逃避它。更改基础资源只会导致更多的额外工作。除了帧缓冲区的完整性之外,驱动程序还必须验证新纹理的渲染能力。

使用3.0+,可以附加多个纹理/渲染缓冲区,并有效地使用draw_buffer_attach以最小的状态开销进行渲染。FBO或GL_COLOR_BUFFER_ATTACHMENT根本不需要更改。

最新更新