绑定Framebuffer还是设置ReadBuffer?
Bind Framebuffer or set ReadBuffer?
我创建了一个帧缓冲区:
glBindFramebuffer(GL.GL_FRAMEBUFFER, &fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
正在通过
从帧缓冲区读取像素
glBindFramebuffer(GL_FRAMEBUFFER, &fbo);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data);
相当于
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data);
?
这不是等价的,读取 GL_COLOR_ATTACHMENT0
将从当前绑定的帧缓冲区中获取数据,这可能与您创建的完全不同。
所以基本上你需要通过调用
来保证你有你的帧缓冲区绑定
glBindFramebuffer(GL_FRAMEBUFFER, &fbo);
在使用它的任何操作之前。
GL_COLOR_ATTACHMENT0只是Frame buffer对象的一个属性,与具体的frame buffer无关。通过使用另一个帧缓冲区绑定调用它,您将读取它的数据,这不是您想要的。
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data);
这里的数据将从当前有界帧缓冲区中读取,这不会等同于
glBindFramebuffer(GL_FRAMEBUFFER, &fbo);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data); (如果在第一种情况下帧缓冲区未绑定到相应的 fbo)
我认为这就是为什么提供 glNamedFramebufferReadBuffer API 的原因,直接从作为第一个参数提到的帧缓冲区读取数据。
这些是完全不同的调用。让我提供一些关于 FBO 真正含义的背景知识,希望能让这一切变得更加清晰。
帧缓冲区对象(又名 FBO)只是状态的集合。以下调用更改当前绑定的 FBO 中跟踪的状态:
glFramebufferTexture2D()
glFramebufferRenderbuffer()
glDrawBuffers()
glReadBuffer()
- (以及类似调用的其他一些变体)
这意味着无论何时您进行这些调用之一,当前绑定的 FBO 中跟踪的状态都会更新以反映调用的变化。例如,如果您调用 glDrawBuffers()
,则更新当前绑定的 FBO 中的绘制缓冲区列表。
然后,任何时候绑定 FBO,FBO 中跟踪的状态将再次变为活动状态。因此,如果您之前在绑定 FBO foo
时调用了 glDrawBuffers()
,之后又再次绑定了 foo
,则之前调用的绘制缓冲区设置将再次激活。
请注意,FBO 不拥有附属于它的 renderbuffers/textures。 FBO 仅包含有关 哪个 渲染缓冲区在给定连接点连接到 FBO 的信息。在您的代码中,FBO foo
存储渲染缓冲区 rbo
附加到附着点 GL_COLOR_ATTACHMENT0
的事实。例如,将同一个 renderbuffer 附加到多个 FBO 是完全合法的。
现在,更具体地介绍您的代码:
glBindFramebuffer()
调用的参数类型错误:
glBindFramebuffer(GL.GL_FRAMEBUFFER, &fbo);
第二个参数是 FBO 的名称 (id),而不是地址。所以调用是:
glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
这个调用什么都不做:
glReadBuffer(GL_COLOR_ATTACHMENT0);
GL_COLOR_ATTACHMENT0
是 FBO 的默认读取缓冲区。因此,除非您之前将其设置为不同的值,否则此调用是多余的,并且只会设置与默认值相同的值。正如命名所暗示的那样,FBO 可以有多个附件,如果您将 renderbuffer/texture 附加到 ATTACHMENT0
以外的附件,并且想从该附件中读取,则可以使用 glReadBuffer()
。
只要您只是为 FBO 使用一个附件,您真正需要做的唯一一件事就是绑定您想要阅读的 FBO:
glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
glReadPixels(...);
glReadPixels()
总是从当前绑定的 FBO 中读取,所以没有办法解决这个问题。
我创建了一个帧缓冲区:
glBindFramebuffer(GL.GL_FRAMEBUFFER, &fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
正在通过
从帧缓冲区读取像素glBindFramebuffer(GL_FRAMEBUFFER, &fbo);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data);
相当于
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data);
?
这不是等价的,读取 GL_COLOR_ATTACHMENT0
将从当前绑定的帧缓冲区中获取数据,这可能与您创建的完全不同。
所以基本上你需要通过调用
来保证你有你的帧缓冲区绑定glBindFramebuffer(GL_FRAMEBUFFER, &fbo);
在使用它的任何操作之前。
GL_COLOR_ATTACHMENT0只是Frame buffer对象的一个属性,与具体的frame buffer无关。通过使用另一个帧缓冲区绑定调用它,您将读取它的数据,这不是您想要的。
glReadBuffer(GL_COLOR_ATTACHMENT0); glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data);
这里的数据将从当前有界帧缓冲区中读取,这不会等同于
glBindFramebuffer(GL_FRAMEBUFFER, &fbo); glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, &data); (如果在第一种情况下帧缓冲区未绑定到相应的 fbo)
我认为这就是为什么提供 glNamedFramebufferReadBuffer API 的原因,直接从作为第一个参数提到的帧缓冲区读取数据。
这些是完全不同的调用。让我提供一些关于 FBO 真正含义的背景知识,希望能让这一切变得更加清晰。
帧缓冲区对象(又名 FBO)只是状态的集合。以下调用更改当前绑定的 FBO 中跟踪的状态:
glFramebufferTexture2D()
glFramebufferRenderbuffer()
glDrawBuffers()
glReadBuffer()
- (以及类似调用的其他一些变体)
这意味着无论何时您进行这些调用之一,当前绑定的 FBO 中跟踪的状态都会更新以反映调用的变化。例如,如果您调用 glDrawBuffers()
,则更新当前绑定的 FBO 中的绘制缓冲区列表。
然后,任何时候绑定 FBO,FBO 中跟踪的状态将再次变为活动状态。因此,如果您之前在绑定 FBO foo
时调用了 glDrawBuffers()
,之后又再次绑定了 foo
,则之前调用的绘制缓冲区设置将再次激活。
请注意,FBO 不拥有附属于它的 renderbuffers/textures。 FBO 仅包含有关 哪个 渲染缓冲区在给定连接点连接到 FBO 的信息。在您的代码中,FBO foo
存储渲染缓冲区 rbo
附加到附着点 GL_COLOR_ATTACHMENT0
的事实。例如,将同一个 renderbuffer 附加到多个 FBO 是完全合法的。
现在,更具体地介绍您的代码:
glBindFramebuffer()
调用的参数类型错误:glBindFramebuffer(GL.GL_FRAMEBUFFER, &fbo);
第二个参数是 FBO 的名称 (id),而不是地址。所以调用是:
glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
这个调用什么都不做:
glReadBuffer(GL_COLOR_ATTACHMENT0);
GL_COLOR_ATTACHMENT0
是 FBO 的默认读取缓冲区。因此,除非您之前将其设置为不同的值,否则此调用是多余的,并且只会设置与默认值相同的值。正如命名所暗示的那样,FBO 可以有多个附件,如果您将 renderbuffer/texture 附加到ATTACHMENT0
以外的附件,并且想从该附件中读取,则可以使用glReadBuffer()
。
只要您只是为 FBO 使用一个附件,您真正需要做的唯一一件事就是绑定您想要阅读的 FBO:
glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
glReadPixels(...);
glReadPixels()
总是从当前绑定的 FBO 中读取,所以没有办法解决这个问题。