GL EXT framebuffer object More about FBOs

From OpenGL Wiki
Jump to navigation Jump to search

Feel free to have a look at http://www.opengl.org/registry and have a look at the GL_EXT_framebuffer_object spec.
GL 3.0 makes FBO a core feature. http://www.opengl.org/documentation/specs/
RTT = render to texture

Limitations of GL_EXT_framebuffer_object

One of the limitations of GL_EXT_framebuffer_object is that when you bind a color buffer and then you bind a depth buffer, both must have the same width and height or else the state of the FBO is considered invalid (incomplete). This means if you have 1 FBO that is 64x64, another which is 512x64, another that is 1024x1024, for each of those you have to allocate a separate depth buffer (if you need depth testing of course). This obviously wastes memory.
In GL 3.0, FBO became core and that limitation was removed.
You can create 1 depth buffer that is 1024x1024 and bind them to all 3 FBOs. Notice that the depth buffer is large enough for even the smaller textures like 64x64.

1 FBO or more

Is it better to make 1 FBO and bind your texture to it each time you need to render to the texture?
An FBO itself doesn't use much memory. It is a state vector object. In terms of performance, each time you bind, the driver needs to validate the state which costs CPU time. Logically, it would be better to have 1 FBO per Render_To_Texture (RTT).
However, it has been found that you get a speed boost if your textures is the same size and you use 1 FBO for them.
If you have 10 textures that are 64x64 and 10 textures that are 512x64, make 2 FBOs. One FBO for each group.

The main framebuffer

Can you bind the main framebuffers depth buffer as a depth buffer for your FBO?
No.
Does GL 3.0 allow using the main depth buffer? Unknown.

MSAA

Are multisample Render_To_Texture (RTT) supported?
Not directly. You need GL_EXT_framebuffer_multisample and you would have to copy the contents of the AA-FBO to a standard RTT.
Note that GL_EXT_framebuffer_multisample also became core in GL 3.0
See also http://www.opengl.org/wiki/GL_EXT_framebuffer_multisample

Color texture, Depth texture

 //RGBA8 2D texture, 24 bit depth texture, 256x256
 glGenTextures(1, &color_tex);
 glBindTexture(GL_TEXTURE_2D, color_tex);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 //NULL means reserve texture memory, but texels are undefined
 //GL_BGRA and GL_UNSIGNED_BYTE are ignored since last param is NULL
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 glGenTextures(1, &depth_tex);
 glBindTexture(GL_TEXTURE_2D, depth_tex);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
 //NULL means reserve texture memory, but texels are undefined
 //GL_BGRA and GL_UNSIGNED_BYTE are ignored since last param is NULL
 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 //-------------------------
 glGenFramebuffersEXT(1, &fb);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
 //Attach 2D texture to this FBO
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0/*mipmap level*/);
 //-------------------------
 //Attach depth texture to FBO
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth_tex, 0/*mipmap level*/);
 //-------------------------
 //Does the GPU support current FBO configuration?
 GLenum status;
 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 switch(status)
 {
    case GL_FRAMEBUFFER_COMPLETE_EXT:
    cout<<"good";
 default:
    HANDLE_THE_ERROR;
 }

And in the end, cleanup

 //Delete resources
 glDeleteTextures(1, &color_tex);
 glDeleteTextures(1, &depth_tex);
 //Bind 0, which means render to back buffer, as a result, fb is unbound
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 glDeleteFramebuffersEXT(1, &fb);


Depth only

This is similar to the case above (Color texture, Depth texture) except that since there is no color buffer, call glDrawBuffer(GL_NONE) before or after calling glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb) and then render. When you are done, call glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) to render to the main framebuffer. This is important, call glDrawBuffer(GL_BACK) after. If you call before glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0), a GL error will be raised.

Color only

Simply disable depth testing (glDisable(GL_DEPTH_TEST) and set the depth mask to FALSE (glDepthMask(GL_FALSE)) before you render to your RTT.

Stencil

Talk about stencil buffer.

MRT

MRT

MRT and cubemaps

MRT and cubemaps

Mode change

On Windows, when a display mode change occurs, resources in VRAM are lost. Resources would be display lists, VBOs, shaders, FBOs. This is why drivers keep a backup in RAM so that when a change occurs, the driver receives a notification from Windows that "poof, all is gone", and the driver can reupload all the resources.
In the case of FBOs (or should we call it render to texture), when it gets lossed, will the driver reupload it?
This is unknown and not explained in the GL_EXT_framebuffer_object extension.
It is presumed that preserving would not be beneficial to performance therefore it is not preserved. In other words, you should update your render to texture (RTT) once in a while or at every frame render.