Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Rendering to a Framebuffer Object

The OpenGL framebuffer extension provides a mechanism for applications to render offscreen to a destination other than the usual OpenGL buffers or destinations provided by the windowing system. This destination is called a framebuffer object.

Note: Extensions are available on a per-renderer basis. Before you use the framebuffer extension you must check each renderer to make sure that it supports the extension.

A framebuffer object (FBO) contains state information for the OpenGL framebuffer and its set of images. A framebuffer object is similar to a drawable object, except that a drawable object is a window-system-specific object, whereas a framebuffer object is a window-agnostic object that's defined in the OpenGL standard, not by Apple. After drawing to a framebuffer object it is straightforward to display the content onscreen. A single command redirects all subsequent drawing back to the drawable object provided by the window system, where the FBO content can then be used as a texture.

Framebuffer objects offer a number of benefits over using pixel buffers.

Completeness is a key concept to understanding framebuffer objects. Completeness is a state that indicates whether a framebuffer object meets all the requirements for drawing. You test for this state after performing all the necessary setup work. If a framebuffer object is not complete, it cannot be used effectively as the destination for rendering operations and the source for read operations.

Completeness is dependent on many factors that are not possible to condense into one or two statements, but these factors are thoroughly defined in the OpenGL specification for the framebuffer object extension. The specification describes the requirements for internal formats of images attached to the framebuffer, how to determine if a format is color-, depth-, and stencil-renderable, as well as a number of other requirements.

Prior to using framebuffer objects, you should take a look at the OpenGL specification, which not only defines the framebuffer object API, but provides detailed definitions of all the terms necessary to understand their use and shows several code examples.

The remainder of this section provides an overview of how to use a framebuffer in the simplest case. You'll get an idea of how the setup of a framebuffer object compares to the other methods described in this chapter. To learn how powerful framebuffer objects are and to see examples of how to use them for a variety of purposes (such as for mipmaps) you'll want to read the OpenGL specification.

Similar to pixel buffers, framebuffer objects are suited for two types of drawing: textures and images. The functions used to set up textures and images are slightly different. The API for images uses the renderbuffer terminology defined in the OpenGL specification. A renderbuffer image is simply a 2D pixel image. The API for textures uses texture terminology, as you might expect. For example, one of the calls for setting up a framebuffer object for a texture is glFramebufferTexture2DEXT, whereas the call for setting up a framebuffer object for an image is glFramebufferRenderbufferEXT. You'll see how to set up a simple framebuffer object for each type of drawing, starting first with textures.

In this section:

Drawing a Texture Offscreen
Drawing a Renderbuffer Image Offscreen


Drawing a Texture Offscreen

These are the basic steps needed to set up a framebuffer object for drawing a texture offscreen:

  1. Make sure the framebuffer extension (GL_EXT_framebuffer_object) is supported on the system that your code runs on. See “Determining the OpenGL Capabilities Supported by the Hardware.”

  2. Check the renderer limits. For example, you might want to call the OpenGL function glGetIntegerv to check the maximum texture size (GL_MAX_TEXTURE_SIZE) or find out the maximum number of color buffers (GL_MAX_COLOR_ATTACHMENTS_EXT).

  3. Generate a framebuffer object name by calling the following function:

    void glGenFramebuffersEXT (GLsizei n, GLuint *ids);

    n is the number of framebuffer object names that you want to create.

    On return, *ids points to the generated names.

  4. Bind the framebuffer object name to a framebuffer target by calling the following function:

    void glBindFramebufferEXT(GLenum target, GLuint framebuffer);

    target should be the constant GL_FRAMEBUFFER_EXT.

    framebuffer is set to an unused framebuffer object name.

    On return, the framebuffer object is initialized to the state values described in the OpenGL specification for the framebuffer object extension. Each attachment point of the framebuffer is initialized to the attachment point state values described in the specification. The number of attachment points is equal to GL_MAX_COLOR_ATTACHMENTS_EXT plus 2 (for depth and stencil attachment points).

  5. Generate a texture name.

  6. Bind the texture name to a texture target.

  7. Set up the texture environment and parameters.

  8. Define the texture by calling the appropriate OpenGL function to specify the target, level of detail, internal format, dimensions, border, pixel data format, and texture data storage.

  9. Attach the texture to the framebuffer by calling the following function:

    void glFramebufferTexture2DEXT (GLenum target, GLenum attachment,
                                     GLenum textarget, GLuint texture,
                                     GLint level);

    target must be GL_FRAMEBUFFER_EXT.

    attachment must be one of the attachment points of the framebuffer: GL_STENCIL_ATTACHMENT_EXT, GL_DEPTH_ATTACHMENT_EXT, or GL_COLOR_ATTACHMENTn_EXT, where n is a number from 0 to GL_MAX_COLOR_ATTACHMENTS_EXT-1.

    textarget is the texture target.

    texture is an existing texture object.

    level is the mipmap level of the texture image to attach to the framebuffer.

  10. Check to make sure that the framebuffer is complete by calling the following function:

    GLenum glCheckFramebufferStatusEXT(GLenum target);

    target must be the constant GL_FRAMEBUFFER_EXT.

    This function returns a status constant. You must test to make sure that the constant is GL_FRAMEBUFFER_COMPLETE_EXT. If it isn't, see the OpenGL specification for the framebuffer object extension for a description of the other constants in the status enumeration.

  11. Render content to the texture. You must make sure to bind a different texture to the framebuffer object or disable texturing before you render content. That is, if you render to a framebuffer object texture attachment with that same texture currently bound and enabled, the result is undefined.

  12. To view the contents of the texture, make the window the target of all rendering commands by calling the function glBindFramebufferEXT and passing the constant GL_FRAMEBUFFER_EXT and 0. The window is always specified as 0.

  13. Use the texture attachment as a normal texture by binding it, enabling texturing, and drawing.

  14. Delete the texture.

  15. Delete the framebuffer object by calling the following function:

    void  glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers);

    n is the number of framebuffer objects to delete.

    *framebuffers points to an array that contains the framebuffer object names.

Listing 4-2 shows code that performs these tasks. This example sets up and draws to a single framebuffer object. Your application can set up more than one framebuffer object if it requires them.

Listing 4-2  Setting up a framebuffer for texturing

GLuint framebuffer, texture;
GLenum status;
glGenFramebuffersEXT(1, &framebuffer);
// Set up the FBO with one texture attachment
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXWIDE, TEXHIGH, 0,
                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                GL_TEXTURE_2D, texture, 0);
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
                // Handle error here
// Your code to draw content to the FBO
// ...
// Make the window the target
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
//Your code to use the contents of the FBO
// ...
//Tear down the FBO and texture attachment
glDeleteTextures(1, &texture);
glDeleteFramebuffersEXT(1, &framebuffer);

Drawing a Renderbuffer Image Offscreen

There is a lot of similarity between setting up a framebuffer object for drawing images and setting one up to draw textures. These are the basic steps needed to set up a framebuffer object for drawing a 2D pixel image (a renderbuffer image) offscreen:

  1. Make sure the framebuffer extension (EXT_framebuffer_object) is supported on the renderer that your code runs on. See “Determining the OpenGL Capabilities Supported by the Hardware.”

  2. Check the renderer limits. For example, you might want to call the OpenGL function glGetIntegerv to find out the maximum number of color buffers (GL_MAX_COLOR_ATTACHMENTS_EXT).

  3. Generate a framebuffer object name by calling the function glGenFramebuffersEXT. (See Step 3 in “Drawing a Texture Offscreen.”)

  4. Bind the framebuffer object name to a framebuffer target by calling the function glBindFramebufferEXT. (See Step 4 in “Drawing a Texture Offscreen.”)

  5. Generate a renderbuffer object name by calling the following function:

    void  glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers );

    n is the number of renderbuffer object names to create.

    *renderbuffers points to storage for the generated names.

  6. Bind the renderbuffer object name to a renderbuffer target by calling the following function:

    void glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);

    target must be the constant GL_RENDERBUFFER_EXT

    renderbuffer is the renderbuffer object name generated previously.

  7. Create data storage and establish the pixel format and dimensions of the renderbuffer image by calling the following function:

    void glRenderbufferStorageEXT (GLenum target, GLenum internalformat,
                                    GLsizei width, GLsizei height);

    target must be the constant GL_RENDERBUFFER_EXT.

    internalformat is the pixel format of the image. The value must be RGB, RGBA, DEPTH_COMPONENT, STENCIL_INDEX, or one of the other formats listed in the OpenGL specification.

    width is the width of the image, in pixels.

    height is the height of the image, in pixels.

  8. Attach the renderbuffer to a framebuffer target by calling the function glFramebufferRenderbufferEXT.

    void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment,
                                 GLenum renderbuffertarget, GLuint renderbuffer);

    target must be the constant GL_FRAMEBUFFER_EXT.

    attachment should be one of the attachment points of the framebuffer: GL_STENCIL_ATTACHMENT_EXT, GL_DEPTH_ATTACHMENT_EXT, or GL_COLOR_ATTACHMENTn_EXT, where n is a number from 0 to GL_MAX_COLOR_ATTACHMENTS_EXT–1.

    renderbuffertarget must be the constant GL_RENDERBUFFER_EXT.

    renderbuffer should be set to the name of the renderbuffer object that you want to attach to the framebuffer.

  9. Check to make sure that the framebuffer is complete by calling the following function:

    enum  glCheckFramebufferStatusEXT(GLenum target);

    target must be the constant GL_FRAMEBUFFER_EXT.

    This function returns a status constant. You must test to make sure that the constant is GL_FRAMEBUFFER_COMPLETE_EXT. If it isn't, see the OpenGL specification for the framebuffer object extension for a description of the other constants in the status enumeration.

  10. Draw the 2D pixel image to the renderbuffer.

  11. To view the contents of the renderbuffer, make the window the target of all rendering commands by calling the function glBindFramebufferEXT and passing the constant GL_FRAMEBUFFER_EXT and 0. The window is always specified as 0.

  12. To access the contents of the renderbuffer object, use OpenGL functions such as glReadPixels or glCopyTexImage2D.

  13. Delete the framebuffer object with its renderbuffer attachment.

Listing 4-3 shows code that sets up and draws to a single renderbuffer object. Your application can set up more than one renderbuffer object if it requires them.

Listing 4-3  Setting up a renderbuffer for drawing images

GLuint framebuffer, renderbuffer;
GLenum status;
// Set the width and height appropriately for you image
GLuint texWidth = 1024,
       texHeight = 1024;
//Set up a FBO with one renderbuffer attachment
glGenFramebuffersEXT(1, &framebuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
glGenRenderbuffersEXT(1, &renderbuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, texWidth, texHeight);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                 GL_RENDERBUFFER_EXT, renderbuffer);
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
                // Handle errors
//Your code to draw content to the renderbuffer
// ...
// Make the window the target
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
//Your code to use the contents
// ...
// Delete the renderbuffer attachment
glDeleteRenderbuffersEXT(1, &renderbuffer);


< Previous PageNext Page > Hide TOC


Last updated: 2008-06-09




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice