Opengl - glDrawBuffers修改存储在FBO中吗?没有?

时间:2015-06-22 13:00:50

标签: opengl state-machine render-to-texture

我尝试创建一个附有2个纹理的FrameBuffer(Multi Render Targets)。然后在每个时间步骤中,清除和绘制两个纹理,如下面的代码。 (某些部分将被替换为伪代码,以缩短它。)

版本1

//beginning of the 1st time step
initialize(framebufferID12)
//^ I quite sure it is done correctly, 
//^ Note : there is no glDrawBuffers()  calling

loop , do once every time step {
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID12);  
    //(#1#) a line will be add here in version 2 (see belowed) <------------
    glClearColor (0.5f, 0.0f, 0.5f, 0.0f);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    //  paint a lot of object here , using glsl (Shader .frag, .vert)
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  
}

所有对象都正确绘制到两个纹理,但每帧清除第一个纹理(ATTACHMENT0),这是错误的。

版本2

我尝试插入一行代码......

glDrawBuffers({ATTACHMENT0,ATTACHMENT1}) ;  

at(#1#)并按预期工作,即清除所有两个纹理。

(图片http://s13.postimg.org/66k9lr5av/gl_Draw_Buffer.jpg

版本3

从版本2开始,我移动那个 glDrawBuffers()语句就像这样在帧缓冲区初始化中

initialize(int framebufferID12){
    int nameFBO = glGenFramebuffersEXT();
    int nameTexture0=glGenTextures();
    int nameTexture1=glGenTextures();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,nameFBO);
      glBindTexture(nameTexture0);
      glTexImage2D( .... ); glTexParameteri(...);
      glFramebufferTexture2DEXT( ATTACHMENT0, nameTexture0);
      glBindTexture(nameTexture1);
      glTexImage2D( .... ); glTexParameteri(...);
      glFramebufferTexture2DEXT( ATTACHMENT0, nameTexture1);
      glDrawBuffers({ATTACHMENT0,ATTACHMENT1}) ;  //<--- moved here ---
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
    return nameFBO ;
}

它不再起作用(症状如版本1),为什么?

opengl手册说“对上下文状态的更改将存储在这个对象中”,所以从 glDrawBuffers()的状态修改将存储在“framebufferID12”中吗?那么,为什么我必须每次都调用它(或每次我改变FBO)

我可能会误解一些opengl的概念,请有人启发我。

编辑1 :感谢j-p。我同意这是有意义的,但是不应该将状态记录在FBO中吗?

编辑2(接受回答):Reto Koradi的回答是正确的!我使用的是一个名为LWJGL的不太标准的库。

1 个答案:

答案 0 :(得分:6)

是的,绘制缓冲区设置是帧缓冲区状态的一部分。例如,如果您查看OpenGL 3.3规范文档,它将在第299页的表6.23中列出,标题为&#34; Framebuffer(每帧缓冲对象的状态)&#34;。

FBO的默认值是单个绘制缓冲区,即GL_COLOR_ATTACHMENT0。从同一规范,第214页:

  

对于帧缓冲对象,在初始状态下,片段颜色为零的绘制缓冲区为COLOR_ATTACHMENT0。对于默认的帧缓冲区和帧缓冲区对象,除零之外的碎片颜色的初始绘制缓冲区状态为NONE。

因此,如果您有多个绘制缓冲区,则需要显式glDrawBuffers()调用。

现在,如果你作为FBO设置的一部分进行glDrawBuffers()调用,它为什么似乎不适合你,这有点神秘。我在您的代码中注意到的一件事是您正在使用FBO调用的EXT形式。我怀疑这可能与你的问题有关。

自3.0版以来,FBO已成为标准OpenGL的一部分。如果您有任何方式可以使用OpenGL 3.0或更高版本,我强烈建议您使用标准入口点。虽然扩展通常在功能已成为标准之后仍然有效,但我总是怀疑它们如何与其他功能交互。特别是,在3.0之前有多个FBO功能扩展,具有不同的行为。如果与标准FBO功能相比,其中一些与其他OpenGL调用的交互方式不同,我不会感到惊讶。

因此,请尝试使用标准入口点(名称中没有EXT的入口点)。这有望解决您的问题。