Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I try to create a FrameBuffer with 2 textures attaching to it (Multi Render Targets). Then in every time step, both textures are cleared and painted, as following code. (Some part will be replaced as pseudo code to make it shorter.)

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

All objects are painted correctly to both texture, but only the first texture (ATTACHMENT0) is cleared every frame, which is wrong.

Version 2

I try to insert a line of code ...

glDrawBuffers({ATTACHMENT0,ATTACHMENT1}) ;  

at (#1#) and it works as expected i.e. clear all two textures.

(image http://s13.postimg.org/66k9lr5av/gl_Draw_Buffer.jpg)

Version 3

From version 2, I move that glDrawBuffers() statement to be inside frame buffer initialization like this

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

It is no longer work (symptom like version 1), why?

The opengl manual said that "changes to context state will be stored in this object", so the state modification from glDrawBuffers() will be stored in "framebufferID12" right? Then, why I have to call it every time step (or every time I change FBO)

I may misunderstand some opengl's concept, someone enlighten me please.

Edit 1: Thank j-p. I agree that it is make sense, but shouldn't the state be recorded in the FBO already?

Edit 2 (accept answer): Reto Koradi's answer is correct! I am using a not-so-standard library called LWJGL.

like image 982
javaLover Avatar asked Jun 22 '15 13:06

javaLover


People also ask

What are the types of framebuffers in OpenGL?

OpenGL has two kinds of framebuffers: the Default Framebuffer, which is provided by the OpenGL Context; and user-created framebuffers called Framebuffer Objects (FBOs). The buffers for default framebuffers are part of the context and usually represent a window or display device.

What does OpenGL render to?

OpenGL renders to framebuffers. By default OpenGL renders to screen, the default framebuffer that commonly contains a color and a depth buffer. This is great for many purposes where a pipeline consists of a single pass, a pass being a sequence of shaders.

How do I clear a buffer in a GL_draw_framebuffer?

This will clear a buffer in the current GL_DRAW_FRAMEBUFFER. buffer​ is either GL_COLOR, GL_DEPTH, GL_DEPTH_STENCIL, or GL_STENCIL . When clearing the GL_DEPTH buffer, you must use glClearBufferfv, and the depth value (a single float) will be clamped to [0, 1].

How to read pixel data from the color buffer in OpenGL?

Certain OpenGL operations can read pixel data from the color buffer. These operations are: Direct pixel reads. Framebuffer blits. Copies from the framebuffer to textures, which could also be during mutable storage specification. All of these operations read from the framebuffer bound to GL_READ_FRAMEBUFFER.


1 Answers

Yes, the draw buffers setting is part of the framebuffer state. If you look at for example the OpenGL 3.3 spec document, it is listed in table 6.23 on page 299, titled "Framebuffer (state per framebuffer object)".

The default value for FBOs is a single draw buffer, which is GL_COLOR_ATTACHMENT0. From the same spec, page 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.

So it's expected that if you have more than one draw buffer, you need the explicit glDrawBuffers() call.

Now, why it doesn't seem to work for you if you make the glDrawBuffers() call as part of the FBO setup, that's somewhat mysterious. One thing I notice in your code is that you're using the EXT form of the FBO calls. I suspect that this might have something to do with your problem.

FBOs have been part of standard OpenGL since version 3.0. If there's any way for you to use OpenGL 3.0 or later, I would strongly recommend that you use the standard entry points. While the extensions normally still work even after the functionality has become standard, I would always be skeptical how they interact with other features. Particularly, there were multiple extensions for FBO functionality before 3.0, with different behavior. I wouldn't be surprised if some of them interact differently with other OpenGL calls compared to the standard FBO functionality.

So, try using the standard entry points (the ones without the EXT in their name). That will hopefully solve your problem.

like image 153
Reto Koradi Avatar answered Nov 11 '22 06:11

Reto Koradi