OpenGL 帧缓冲绑定目标

Posted

技术标签:

【中文标题】OpenGL 帧缓冲绑定目标【英文标题】:OpenGL framebuffer bind target 【发布时间】:2015-11-08 14:17:37 【问题描述】:

当调用glBindFramebuffer(GLenum target, GLuint framebuffer); 时,我知道target 可以是GL_READ_FRAMEBUFFERGL_DRAW_FRAMEBUFFERGL_FRAMEBUFFER,两者都是。

但是,当我将纹理或 Renderbuffer 对象附加到帧缓冲区时,我还必须提供绑定目标。

我的问题是,当我通过绑定目标 target 将任何内容附加到帧缓冲区时,它是否保持不变?

这意味着当渲染缓冲区通过绑定点GL_DRAW_FRAMEBUFFER 附加到帧缓冲区时,它将始终是绘图操作的目标,如果我希望从该渲染缓冲区读取,那么我必须再次调用glFramebufferRenderbuffer(),这次将target 设置为GL_READ_FRAMEBUFFER

谁能证实这一点?我问是因为我试图将所有这些封装在 C++ 类中。

【问题讨论】:

【参考方案1】:

这意味着当渲染缓冲区通过绑定点 GL_DRAW_FRAMEBUFFER 附加到帧缓冲区时,它将始终是绘图操作的目标,如果我想从中读取该渲染缓冲区,我必须再次调用 glFramebufferRenderbuffer() 并将目标设置为这次是 GL_READ_FRAMEBUFFER。

没有。附件是每个 FBO 状态,它们与 FBO 绑定的绑定点无关。

一个对象可能绑定到语义上不同的绑定目标,但对象本身定义了它的所有状态。例如,您可以将数据加载到绑定为GL_PIXEL_UNPACK_BUFFER 的缓冲区,然后通过将其绑定为GL_VERTEX_ARRAY_BUFFER 将此数据用作顶点属性。

但是,当我将纹理或 Renderbuffer 对象附加到帧缓冲区时,我还必须提供绑定目标。

嗯,那是因为传统的 GL 使用 bind 来修改 语义。如果要操作任何对象的状态,则必须将其绑定到某个目标(当然要匹配对象类型),并且所有状态设置函数都会通过寻址目标来间接引用该对象。这并不意味着修改与绑定点有任何关系。

Bind-to-modify 一直是 OpenGL 的一个经常被批评的原则。很长一段时间以来,一些供应商已经实施了EXT_direct_state_access 扩展来解决这个问题。它提供了直接引用对象而不是间接使用绑定点的函数。在您的示例中,glNamedFramebufferRenderbufferEXT 将允许您直接附加渲染缓冲区,而无需先绑定 FBO。

最终在 OpenGL 4.5 中,直接状态访问被提升为 OpenGL 的核心功能,并创建了ARB_direct_state_access 以允许实现者为早期的 GL 版本提供最终的 API(在某些方面与 EXT 版本不同) .现在有了官方的glNamedFramebufferRenderbuffer()功能。

【讨论】:

我理解绑定修改语义,但我仍然对这些帧缓冲区对象感到困惑。当我调用glFramebufferRenderbuffer()时,我将target设置为GL_READ_FRAMEBUFFERGL_DRAW_FRAMEBUFFER都没有关系,只要是绑定的就行? (glBindFramebuffer() 好吧,GL_FRAMEBUFFER 绑定目标只是将它绑定到读取和绘制帧缓冲区的快捷方式。结果,它将绑定在两个目标上,并且通过任何万寿菊修改它都会起作用,因为引用了同一个对象。 我明白了。一个离题的小问题:似乎我可以在我的 Renderbuffer 对象附加到帧缓冲区后调用 glDeleteRenderbuffers() ,并且没有任何不好的事情发生。这是正常的吗?你会建议这样做吗? @Pilpel:是的,就是这样指定的。您只会丢失对象名称(并且对 glGen*() 函数的进一步调用可能会重用该名称),因此在删除后您不能再引用该对象。只要它仍然被某个容器对象(在本例中为 FBO)引用,对象本身就会被保留。 删除渲染缓冲区时,它会自动与当前绑定的 FBO 分离,但不会与其他 FBO 分离。在第二种情况下,您可能会遇到非常奇怪的情况,即您有多个具有相同名称的对象,因为可以在原始对象仍然存在时重用该名称。我强烈反对为您仍在使用的渲染缓冲区调用 glDeleteRenderbuffers()

以上是关于OpenGL 帧缓冲绑定目标的主要内容,如果未能解决你的问题,请参考以下文章

将模板渲染缓冲区绑定到opengl中的帧缓冲区

创建没有帧缓冲区绑定的 Opengl 渲染缓冲区

是否可以仅使用 OpenGL 确定默认帧缓冲区的大小?

OpenGL 帧缓冲区 + LibGDX

缩放 OpenGL ES 帧缓冲区的内容

用于片段着色器的 OpenGL GLSL 绑定采样器