绑定帧缓冲或设置ReadBuffer?

时间:2015-11-30 22:44:34

标签: opengl framebuffer

我创建了一个帧缓冲区:

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);

3 个答案:

答案 0 :(得分:3)

它不等同,阅读GL_COLOR_ATTACHMENT0会从当前绑定的帧缓冲区获取数据,这可能与您创建的帧缓冲区完全不同。

所以基本上你需要保证你通过调用

绑定你的帧缓冲区
glBindFramebuffer(GL_FRAMEBUFFER, &fbo);

在使用它之前的任何操作。

GL_COLOR_ATTACHMENT0只是Frame缓冲区对象的一个​​属性,它与任何特定的帧缓冲区无关。通过使用另一个帧缓冲区绑定它,您将读取其不是您想要的数据。

答案 1 :(得分:1)

这些是完全不同的电话。让我提供一些关于FBO真正希望如何使这一点更加清晰的背景。

帧缓冲对象(又名FBO)只是状态的集合。以下调用更改当前绑定的FBO中跟踪的状态:

  • glFramebufferTexture2D()
  • glFramebufferRenderbuffer()
  • glDrawBuffers()
  • glReadBuffer()
  • (以及类似电话的其他一些变体)

这意味着无论何时进行其中一个调用,都会更新当前绑定的FBO中跟踪的状态以反映调用的更改。例如,如果调用glDrawBuffers(),则会更新当前绑定的FBO中的绘制缓冲区列表。

然后,无论何时绑定FBO,FBO中跟踪的状态将再次变为活动状态。因此,如果您之前在绑定FBO glDrawBuffers()时调用了foo,然后再次绑定foo,则之前调用的绘制缓冲区设置将再次处于活动状态。

请注意,FBO不拥有附加到它的渲染缓冲区/纹理。 FBO仅包含的信息,其中渲染缓冲区附加到给定连接点处的FBO。在您的代码中,FBO foo存储了渲染缓冲区rbo附加到附着点GL_COLOR_ATTACHMENT0的事实。例如,将相同的渲染缓冲区附加到多个FBO是完全合法的。

现在,更具体地说,您的代码:

  • glBindFramebuffer()次调用的参数类型错误:

    glBindFramebuffer(GL.GL_FRAMEBUFFER, &fbo);
    

    第二个参数是FBO的名称(id),而不是地址。所以电话是:

    glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
    
  • 此调用不执行任何操作:

    glReadBuffer(GL_COLOR_ATTACHMENT0);
    

    GL_COLOR_ATTACHMENT0是FBO的默认读缓冲区。因此,除非您之前将其设置为不同的值,否则此调用是多余的,并且仅设置与默认值相同的值。正如命名所暗示的那样,FBO可以有多个附件,如果你将一个渲染缓冲区/纹理附加到glReadBuffer()以外的附件,并且想从那个附件中读取,你可以使用ATTACHMENT0

只要您只为FBO使用一个附件,您唯一需要做的就是绑定您想要阅读的FBO:

glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
glReadPixels(...);

glReadPixels()总是从当前绑定的FBO中读取,因此无法解决此问题。

答案 2 :(得分:0)

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,直接从作为第一个参数提到的帧缓冲区读取数据。