Opengl - glDrawBuffers 修改是否存储在 FBO 中?不?

Opengl - Is glDrawBuffers modification stored in a FBO? No?

我尝试创建一个附加了 2 个纹理的 FrameBuffer(多渲染目标)。然后在每个时间步中,两个纹理都被清除和绘制,如下代码所示。 (部分内容将被替换为伪代码以使其更短。)

版本 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手册说"changes to context state will be stored in this object",所以从glDrawBuffers()修改的状态会存储在"framebufferID12"对吧?然后,为什么我必须在每个时间步(或每次更改 FBO)都调用它

我可能误解了一些opengl的概念,请大神赐教

编辑 1:谢谢 j-p。我同意这是有道理的,但是状态不应该已经记录在 FBO 中了吗?

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

是的,绘制缓冲区设置是帧缓冲区状态的一部分。例如,如果您查看 OpenGL 3.3 规范文档,它列在第 299 页的 table 6.23 中,标题为 "Framebuffer (state per framebuffer object)".

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

For framebuffer objects, in the initial state the draw buffer for fragment color zero is COLOR_ATTACHMENT0. For both the default framebuffer and framebuffer objects, the initial state of draw buffers for fragment colors other then zero is NONE.

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

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

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

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