''Image'': For the purposes of this article, an image is a single 2D array of pixels. It has a [[Image Format|specific format]] for these pixels.

''Image'': For the purposes of this article, an image is a single 2D array of pixels. It has a [[Image Format|specific format]] for these pixels.

−

''Layered Image'': For the purposes of this article, a layered image is a sequence of ''images'' of a particular size.

+

''Layered Image'': For the purposes of this article, a layered image is a sequence of ''images'' of a particular size and format. Layered images are packaged together within a single OpenGL object.

−

''Texture'': For the purposes of this article, a texture is an object that contains some number of ''images'', as defined above. All of the images have the same format, but they do not have to have the same size (different mip-maps, for example). Textures can be bound to shaders and rendered with.

+

''[[Texture]]'': For the purposes of this article, a texture is an object that contains some number of ''images'', as defined above. All of the images have the same format, but they do not have to have the same size (different [[mip-map]]s, for example). Textures can be bound to [[shader]]s and rendered with.

''[[Renderbuffer Objects|Renderbuffer]]'': A renderbuffer is an object that contains a single image. Renderbuffers cannot be bound to shaders or otherwise rendered with; they can only be attached to FBOs.

''[[Renderbuffer Objects|Renderbuffer]]'': A renderbuffer is an object that contains a single image. Renderbuffers cannot be bound to shaders or otherwise rendered with; they can only be attached to FBOs.

Line 29:

Line 29:

== Framebuffer Object Structure ==

== Framebuffer Object Structure ==

−

As standard [[OpenGL Objects]], FBOs have the usual <code>glGen*/glDelete*</code> creation style. As expected, it also has the usual <code>glBindFramebuffer</code> function, to bind an FBO to the context.

+

As standard [[OpenGL Objects]], FBOs have the usual {{apifunc|glGenFramebuffers}} and {{apifunc|glDeleteFramebuffers}} functions. As expected, it also has the usual {{apifunc|glBindFramebuffer}} function, to bind an FBO to the context.

−

The <code>target</code> parameter for this object can take one of 3 values: GL_FRAMEBUFFER, GL_READ_FRAMEBUFFER, or GL_DRAW_FRAMEBUFFER. The last two allow you to bind an FBO so that reading commands (<code>glReadPixels</code>, <code>glCopyPixels</code>, etc) and writing commands (any command of the form <code>glDraw*</code>) can happen to two different buffers. The GL_FRAMEBUFFER target simply sets both the read and the write to the same FBO.

+

The {{param|target}} parameter for this object can take one of 3 values: {{enum|GL_FRAMEBUFFER}}, {{enum|GL_READ_FRAMEBUFFER}}, or {{enum|GL_DRAW_FRAMEBUFFER}}. The last two allow you to bind an FBO so that reading commands ({{apifunc|glReadPixels}}, etc) and writing commands (any command of the form {{code|glDraw*}}) can happen to two different buffers. The {{enum|GL_FRAMEBUFFER}} target simply sets both the read and the write to the same FBO.

−

When an FBO is bound to a target, the available surfaces change. The default framebuffer has buffers like GL_FRONT, GL_BACK, GL_AUXi, GL_ACCUM, and so forth. FBOs do not have these.

+

When an FBO is bound to a target, the available surfaces change. The default framebuffer has buffers like {{enum|GL_FRONT}}, {{enum|GL_BACK}}, {{enum|GL_AUXi}}, {{enum|GL_ACCUM}}, and so forth. FBOs do not have these.

Instead, FBOs have a different set of images. Each FBO image represents an attachment point, a location in the FBO where an image can be attached. FBOs have the following attachment points:

Instead, FBOs have a different set of images. Each FBO image represents an attachment point, a location in the FBO where an image can be attached. FBOs have the following attachment points:

−

* GL_COLOR_ATTACHMENT''i'': These are an implementation-dependent number of attachment points. You can query GL_MAX_COLOR_ATTACHMENTS to determine the number of color attachments that an implementation will allow. The minimum value for this is 1, so you are guaranteed to be able to have at least color attachment 0. These attachment points can only have images bound to them with color-renderable formats. All [[Image Formats#Compressed formats|compressed image formats]] are not color-renderable, and thus cannot be attached to an FBO.

+

* {{enum|GL_COLOR_ATTACHMENT''i''}}: These are an implementation-dependent number of attachment points. You can query {{enum|GL_MAX_COLOR_ATTACHMENTS}} to determine the number of color attachments that an implementation will allow. The minimum value for this is 1, so you are guaranteed to be able to have at least color attachment 0. These attachment points can only have images bound to them with color-renderable formats. All [[Image Formats#Compressed formats|compressed image formats]] are not color-renderable, and thus cannot be attached to an FBO.

−

* GL_DEPTH_ATTACHMENT: This attachment point can only have images with depth formats bound to it.

+

* {{enum|GL_DEPTH_ATTACHMENT}}: This attachment point can only have images with depth formats bound to it. The image attached becomes the [[Depth Buffer]] for the FBO.

−

* GL_STENCIL_ATTACHMENT: This attachment point can only have images with stencil formats bound to it.

+

* {{enum|GL_STENCIL_ATTACHMENT}}: This attachment point can only have images with stencil formats bound to it. The image attached becomes the [[Stencil Test|stencil buffer]] for the FBO.

−

* GL_DEPTH_STENCIL_ATTACHMENT: This is shorthand for "both depth and stencil".

+

* {{enum|GL_DEPTH_STENCIL_ATTACHMENT}}: This is shorthand for "both depth and stencil". The image attached becomes both the depth and stencil buffers.

−

: '''Note:''' If you use GL_DEPTH_STENCIL_ATTACHMENT, you should use a packed depth-stencil [[Image Formats|internal format]] for the texture or renderbuffer you are attaching.

+

: '''Note:''' If you use {{enum|GL_DEPTH_STENCIL_ATTACHMENT}}, you should use a packed depth-stencil [[Image Format|internal format]] for the texture or renderbuffer you are attaching.

== Attaching Images ==

== Attaching Images ==

Line 52:

Line 52:

Remember that textures are a set of images. Textures can have mipmaps; thus, each individual mipmap level can contain one or more images.

Remember that textures are a set of images. Textures can have mipmaps; thus, each individual mipmap level can contain one or more images.

−

A 1D texture contains 2D images that have the vertical size of 1. Each individual image can be uniquely identified by a mipmap <code>level</code>.

+

A 1D texture contains 2D images that have the vertical height of 1. Each individual image can be uniquely identified by a mipmap {{param|level}}.

−

A 2D texture contains 2D images. Each individual image can be uniquely identified by a mipmap <code>level</code>.

+

A 2D texture contains 2D images. Each individual image can be uniquely identified by a mipmap {{param|level}}.

−

Each mipmap level of a 3D texture is considered a set of 2D textures, with the number of these being the extent of the Z coordinate. Each integer value for the depth of a 3D texture mipmap level is a layer. So each image in a 3D texture is uniquely identified by a <code>layer</code> and a mipmap <code>level</code>.

+

A [[Rectangle Texture]] has a single 2D image, and thus is identified by mipmap {{param|level}} 0.

−

[[Cubemap Textures|Cubemaps]] contain 6 targets, each of which is equivalent to a 2D texture. Thus, each image in a cubemap texture can be uniquely identified by a <code>target</code> and a mipmap <code>level</code>.

+

Each mipmap level of a 3D texture is considered a set of 2D images, with the number of these being the extent of the Z coordinate. Each integer value for the depth of a 3D texture mipmap level is a layer. So each image in a 3D texture is uniquely identified by a {{param|layer}} and a mipmap {{param|level}}.

−

[[Array Textures|Array textures]] are much like 3D textures. Each image in an array texture can be uniquely identified by a <code>layer</code> (the array index) and a mipmap <code>level</code>.

+

[[Cubemap Textures|Cubemaps]] contain 6 targets, each of which is a 2D image. Thus, each image in a cubemap texture can be uniquely identified by a {{param|target}} and a mipmap {{param|level}}.

+

+

Each mipmap level of a 1D [[Array Texture]]s contains a number of images, equal to the count images in the array. While these images are technically one-dimensional, they are promoted to 2D status for FBO purposes in the same way as a non-array 1D texture: by using a height of 1. Thus, each individual image is uniquely identified by a {{param|layer}} (the array index) and a mipmap {{param|level}}.

+

+

2D [[Array Textures|Array textures]] are much like 3D textures, except instead of the number of Z slices, it is the array count. Each 2D image in an array texture can be uniquely identified by a {{param|layer}} (the array index) and a mipmap {{param|level}}. Unlike 3D textures, the array count doesn't change when going down the mipmap hierarchy.

+

+

Cubemap array textures work like 2D array textures, only with 6 times the number of images. Thus a 2D image in the array is identified by the array {{param|layer}} (technically layer-face) and a mipmap {{param|level}}.

+

+

[[Buffer Texture]]s work like 1D texture, only they have a single image, identified by mipmap {{param|level}} 0.

The highlighted words above are significant, as they match the parameters of the following functions used for attaching textures:

The highlighted words above are significant, as they match the parameters of the following functions used for attaching textures:

The <code>target</code> parameter here is the same as the one for bind. However, GL_FRAMEBUFFER doesn't mean both read and draw (as that would make no sense); instead, it is the same as GL_DRAW_FRAMEBUFFER. The <code>attachment</code> parameter is one of the above attachment points.

+

The {{param|target}} parameter here is the same as the one for bind. However, GL_FRAMEBUFFER doesn't mean both read and draw (as that would make no sense); instead, it is the same as GL_DRAW_FRAMEBUFFER. The {{param|attachment}} parameter is one of the above attachment points.

−

The <code>texture</code> argument is the texture object name you want to attach from. If you pass zero as <code>texture</code>, this has the effect of clearing the attachment for this <code>attachment</code>, regardless of what kind of image was attached there.

+

The {{param|texture}} argument is the texture object name you want to attach from. If you pass zero as {{param|texture}}, this has the effect of clearing the attachment for this {{param|attachment}}, regardless of what kind of image was attached there.

−

Because texture objects can hold multiple images, you must specify exactly which image to attach to this attachment point. The parameters match their above definitions, with the exception of <code>textarget</code>.

+

Because texture objects can hold multiple images, you must specify exactly which image to attach to this attachment point. The parameters match their above definitions, with the exception of {{param|textarget}}.

−

When attaching a non-cubemap, <code>textarget</code> should be the proper texture type: GL_TEXTURE_1D, GL_TEXTURE_2D_MULTISAMPLE, etc. When attaching a cubemap, you must use the Texture2D function, and the <code>textarget</code> must be one of the 6 targets for [[Cubemap Textures|cubemap binding]].

+

When attaching a non-cubemap, {{param|textarget}} should be the proper texture type: GL_TEXTURE_1D, GL_TEXTURE_2D_MULTISAMPLE, etc. When attaching a cubemap, you must use the Texture2D function, and the {{param|textarget}} must be one of the 6 targets for [[Cubemap Textures|cubemap binding]].

−

: '''Legacy Note:''' There is a function, <code>glFramebufferTexture3D</code>, specifically for 3D textures. However, you shouldn't bother with it, as the TextureLayer function can do everything it can and more.

+

: '''Legacy Note:''' There is a function, {{apifunc|glFramebufferTexture|3D}}, specifically for 3D textures. However, you shouldn't bother with it, as the TextureLayer function can do everything it can and more.

[[Renderbuffer Objects|Renderbuffers]] can also be attached to FBOs. Indeed, this is the only way to use them besides just creating the storage for them.

[[Renderbuffer Objects|Renderbuffers]] can also be attached to FBOs. Indeed, this is the only way to use them besides just creating the storage for them.

Line 82:

Line 90:

Once you have created a renderbuffer object and made storage for it (given a size and format), you can attach it to an FBO with this function:

Once you have created a renderbuffer object and made storage for it (given a size and format), you can attach it to an FBO with this function:

The parameters work mostly the same as with texture attachment. The <code>renderbuffertarget</code> param must be GL_RENDERBUFFER. The <code>renderbuffer</code> parameter is the renderbuffer object's name.

+

The parameters work mostly the same as with texture attachment. The {{param|renderbuffertarget}} param must be {{enum|GL_RENDERBUFFER}}. The {{param|renderbuffer}} parameter is the renderbuffer object's name.

=== Layered Images ===

=== Layered Images ===

Line 90:

Line 98:

A layered image, as previously defined, is an ordered sequence of images of a particular size. A number of different kinds of textures can be considered layered.

A layered image, as previously defined, is an ordered sequence of images of a particular size. A number of different kinds of textures can be considered layered.

−

A single mipmap level of an array texture (1D or 2D array) is a layered image. A single mipmap level of a 3D texture is likewise a layered image. Also, a mipmap level of a cubemap is a layered image. For cubemaps, you get 6 layers, one for each face. And the order of the faces is the same as the order of the enumerators:

+

A single mipmap level of a 1D or 2D array texture is a layered image, where the number of layers is the array size. A single mipmap level of a 3D texture is likewise a layered image, where the number of layers is the depth of that particular mipmap level. Also, a mipmap level of a cubemap is a layered image. For cubemaps, you get exactly 6 layers, one for each face. And the order of the faces is the same as the order of the enumerators:

−

{| class="wikitable" border="1"

+

{{cubemap layer face ordering}}

−

|-

+

−

! Layer number

+

−

! Cubemap face

+

−

|-

+

−

| 0

+

−

| GL_TEXTURE_CUBEMAP_POSITIVE_X

+

−

|-

+

−

| 1

+

−

| GL_TEXTURE_CUBEMAP_NEGATIVE_X

+

−

|-

+

−

| 2

+

−

| GL_TEXTURE_CUBEMAP_POSITIVE_Y

+

−

|-

+

−

| 3

+

−

| GL_TEXTURE_CUBEMAP_NEGATIVE_Y

+

−

|-

+

−

| 4

+

−

| GL_TEXTURE_CUBEMAP_POSITIVE_Z

+

−

|-

+

−

| 5

+

−

| GL_TEXTURE_CUBEMAP_NEGATIVE_Z

+

−

|}

+

−

Each texture, when taken as a layered image, has a specific number of layers. For array and 3D textures, this is the depth of the texture. For cubemaps, this is always exactly 6 layers: one per face.

+

For [[Cubemap Texture#Cubemap array textures|cubemap arrays]], the value that {{code|gl_Layer}} represents is the layer-face index. Thus it is the face within a layer, ordered as above. So if you want to render to the 3rd layer, +z face, you would set {{code|gl_Layer}} to (2 * 6) + 4, or 16.

+

+

Each texture, when taken as a layered image, has a specific number of layers. For array and 3D textures, this is the depth of the texture. For cubemaps, this is always exactly 6 layers: one per face. Cubemap arrays have 6 * the number of layers, which is the number of layer-faces.

The parameters have the same meaning as above. Indeed, this function can replace many of the usese for glFramebufferTexture1D, 2D, or Layer, as long as you do not intend to attach specific layers of array textures, cubemaps, or 3D textures as regular, non-layered images. If the ''texture'' is one of these kinds of textures, then the given mipmap ''level'' will be attached as a layered image with the number of layers that the given texture has.

+

The parameters have the same meaning as above. Indeed, this function can replace many of the uses for {{apifunc|glFramebufferTexture|1D, 2D, or Layer}}, as long as you do not intend to attach specific layers of array textures, cubemaps, or 3D textures as regular, non-layered images. If the {{param|texture}} is one of these kinds of textures, then the given mipmap {{param|level}} will be attached as a layered image with the number of layers that the given texture has.

It is possible to render to a framebuffer object that has no attachments. Obviously none of the fragment shader outputs will be written to anywhere in this case, but rendering can otherwise proceed as normal. This is useful for using [[Image Load Store|arbitrary reading and writing of image data]], instead of writing to a bound framebuffer.

+

+

However, the rasterization of primitives is always based on the area and characteristics of the bound framebuffer. Normally, these characteristics (size, number of samples for [[Multisample|multisample rendering]], etc) are defined by the attached images. If no images are attached, these characteristics must be defined in some other fashion.

+

+

The width and height of an FBO with no attachments can be set with this function:

{{param|target}} is the location where the framebuffer object is bound. To set the width, set {{param|pname}} to {{enum|GL_FRAMEBUFFER_DEFAULT_WIDTH}}; to set the height, use {{enum|GL_FRAMEBUFFER_DEFAULT_HEIGHT}}.

+

+

Layered framebuffers can be simulated by using {{enum|GL_FRAMEBUFFER_DEFAULT_LAYERS}}. Multisample framebuffers can be simulated using {{enum|GL_FRAMEBUFFER_DEFAULT_SAMPLES}} to set the number of samples. Fixed multisample location can similarly be simulated with {{enum|GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS}}.

+

+

Note that rendering is ''only'' limited to these parameters if no images are attached to the FBO. If images are attached, then these parameters are ignored. You should only set these values if you intend to use the FBO without images.

== Framebuffer Completeness ==

== Framebuffer Completeness ==

Line 132:

Line 141:

An FBO that is valid for use is said to be "framebuffer complete". To test framebuffer completeness, call this function:

An FBO that is valid for use is said to be "framebuffer complete". To test framebuffer completeness, call this function:

−

GLenum glCheckFramebufferStatus(GLenum ''target'');

+

GLenum {{apifunc|glCheckFramebufferStatus}}(GLenum {{param|target}});

−

You are not required to call this. Using an incomplete FBO is an error, so it's always a good idea to check.

+

You are not required to call this manually. However, using an incomplete FBO is an error, so it's always a good idea to check.

−

The return value is GL_FRAMEBUFFER_COMPLETE if the FBO can be used. If it is something else, then there is a problem. Below are the rules for completeness, and the associated return values you will receive if they are not followed.

+

The return value is {{enum|GL_FRAMEBUFFER_COMPLETE}} if the FBO can be used. If it is something else, then there is a problem. Below are the rules for completeness and the associated return values you will receive if they are not followed.

=== Attachment Completeness ===

=== Attachment Completeness ===

Line 143:

Line 152:

* The source object for the image still exists and has the same type it was attached with.

* The source object for the image still exists and has the same type it was attached with.

−

* The image has a non-zero width and height.

+

* The image has a non-zero width and height (the height of a 1D image is assumed to be 1). The width/height must also be less than {{enum|GL_MAX_FRAMEBUFFER_WIDTH}} and {{enum|GL_MAX_FRAMEBUFFER_HEIGHT}} respectively (if GL 4.3/ARB_framebuffer_no_attachments).

−

* The layer for 3D or depth textures attachments is less than the depth of the texture.

+

* The layer for 3D or array textures attachments is less than the depth of the texture. It must also be less than {{enum|GL_MAX_FRAMEBUFFER_LAYERS}} (if GL 4.3/ARB_framebuffer_no_attachments).

+

* The number of samples must be less than {{enum|GL_MAX_FRAMEBUFFER_SAMPLES}} (if GL 4.3/ARB_framebuffer_no_attachments).

These are the rules for framebuffer completeness. The order of these rules matters.

These are the rules for framebuffer completeness. The order of these rules matters.

−

# If the <code>target</code> of <code>glCheckFramebufferStatus</code> is the default framebuffer (FBO object number 0 is bound), and the default framebuffer does not exist, then you will get GL_FRAMEBUFFER_UNDEFINED. If the default framebuffer exists, then you always get GL_FRAMEBUFFER_COMPLETE. The rest of the rules apply when an FBO is bound.

+

# If the {{param|target}} of {{apifunc|glCheckFramebufferStatus}} references the default framebuffer (ie: FBO object number 0 is bound), and the default framebuffer does not exist, then you will get {{enum|GL_FRAMEBUFFER_UNDEFINED}}. If the default framebuffer exists, then you always get {{enum|GL_FRAMEBUFFER_COMPLETE}}. The rest of the rules apply when an FBO is bound.

−

# All attachments that are set as a draw buffer or read buffer (see below) must be attachment complete, as defined above. (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT when false).

+

# All attachments that are set as a draw buffer or read buffer (see below) must be attachment complete, as defined above. ({{enum|GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT}} when false).

−

# There must be at least one image attached to the FBO. (GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT when false).

+

# There must be at least one image attached to the FBO, or if GL 4.3/{{extref|framebuffer_no_attachment}} is available, the {{enum|GL_FRAMEBUFFER_DEFAULT_WIDTH}} and {{enum|GL_FRAMEBUFFER_DEFAULT_HEIGHT}} parameters of the framebuffer must both be non-zero. ({{enum|GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT}} when false).

# All draw buffers (see below) must specify color attachment points that have images attached. ({{enum|GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER}} when false). Note that this test is not performed if GL 4.2/{{extref|ES2_compatibility}} is available.

−

# If the read buffer is set, then it must specify an attachment point that has an image attached. (GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER when false).

+

# If the read buffer is set, then it must specify an attachment point that has an image attached. ({{enum|GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER}} when false). Note that this test is not performed if GL 4.2/{{extref|ES2_compatibility}} is available.

−

# All images must have the same number of [[Multisampling|multisample samples]]. (GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE when false).

+

# All images must have the same number of [[Multisampling|multisample samples]]. ({{enum|GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE}} when false).

−

# If a layered image is attached to one attachment, then all attachments must be layered attachments. The attached layers do not have to have the same number of layers, nor do the layers have to come from the same kind of texture (a cubemap color texture can be paired with an array depth texture) (GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS when false).

+

# If a layered image is attached to one attachment, then all attachments must be layered attachments. The attached layers do not have to have the same number of layers, nor do the layers have to come from the same kind of texture (a cubemap color texture can be paired with an array depth texture) ({{enum|GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS}} when false).

Notice that there is no restriction based on size. The effective size of the FBO is the intersection of all of the sizes of the bound images (ie: the smallest in each dimension).

Notice that there is no restriction based on size. The effective size of the FBO is the intersection of all of the sizes of the bound images (ie: the smallest in each dimension).

−

These rules are all code-based. If you ever get any of these values from <code>glCheckFramebufferStatus</code>, it is because your program has done something wrong in setting up the FBO. Each one has a specific remedy for it.

+

These rules are all code-based. If you ever get any of these values from {{apifunc|glCheckFramebufferStatus}}, it is because your program has done something wrong in setting up the FBO. Each one has a specific remedy for it.

OpenGL allows implementations to state that they do not support some combination of image formats for the attached images; they do this by returning GL_FRAMEBUFFER_UNSUPPORTED when you attempt to use an unsupported format combinaton.

+

OpenGL allows implementations to state that they do not support some combination of image formats for the attached images; they do this by returning {{enum|GL_FRAMEBUFFER_UNSUPPORTED}} when you attempt to use an unsupported format combination.

−

However, the OpenGL specification also requires that implementations support certain formats; that is, if you use these formats, implementations are forbidden to return GL_FRAMEBUFFER_UNSUPPORTED. This list of required formats is also the list of required [[Image Formats|image formats]] that all OpenGL implementations must support. These are most of the useful formats. Basically, don't concern yourself with GL_FRAMEBUFFER_UNSUPPORTED too much. Check for it, but you'll be fine as long as you stick to the required formats.

+

However, the OpenGL specification also requires that implementations support certain formats; that is, if you use these formats, implementations are forbidden to return {{enum|GL_FRAMEBUFFER_UNSUPPORTED}}. This list of required formats is also the list of required [[Image Formats|image formats]] that all OpenGL implementations must support. These are most of the useful formats. Basically, don't concern yourself with {{enum|GL_FRAMEBUFFER_UNSUPPORTED}} too much. Check for it, but you'll be fine as long as you stick to the required formats.

−

{{legacy note|GL_FRAMEBUFFER_UNSUPPORTED was initially, in the days of EXT_framebuffer_object, much less forgiving. The specification didn't have a list of required image formats. Indeed, the only guarantee that the EXT_FBO spec made was that there was at least ''one'' combination of formats that implementations supported; it provided no hints as to what that combination might be. The core extension ARB_framebuffer_object does differ from the core specification in one crucial way: it uses the EXT wording for GL_FRAMEBUFFER_UNSUPPORTED. So if you're using 3.0, you don't have to worry much about unsupported. If you're using ARB_framebuffer_object, then you should be concerned and do appropriate testing.}}

+

{{legacy note|{{enum|GL_FRAMEBUFFER_UNSUPPORTED}} was initially, in the days of EXT_framebuffer_object, much less forgiving. The specification didn't have a list of required image formats. Indeed, the only guarantee that the EXT_FBO spec made was that there was at least ''one'' combination of formats that implementations supported; it provided no hints as to what that combination might be. The core extension ARB_framebuffer_object does differ from the core specification in one crucial way: it uses the EXT wording for {{enum|GL_FRAMEBUFFER_UNSUPPORTED}}. So if you're using 3.0, you don't have to worry much about unsupported. If you're using ARB_framebuffer_object, then you should be concerned and do appropriate testing.}}

== Multiple Render Targets ==

== Multiple Render Targets ==

Line 177:

Line 187:

Modern [[GLSL|shaders]] allow the user to render to multiple render targets simultaneously. To facilitate this, FBOs (and the default framebuffer) have a mapping that allows the user to define which fragment shader outputs go to which buffers. The way this works is somewhat complicated.

Modern [[GLSL|shaders]] allow the user to render to multiple render targets simultaneously. To facilitate this, FBOs (and the default framebuffer) have a mapping that allows the user to define which fragment shader outputs go to which buffers. The way this works is somewhat complicated.

−

When linking a fragment shader, the user will assign each fragment shader output variable to a number. This number is between 0 and GL_MAX_DRAW_BUFFERS-1 under normal circumstances, or between 0 and GL_MAX_DUAL_SOURCE_DRAW_BUFFERS - 1 when a fragment shader is outputting values to the second color of a buffer, for [[Blending#Dual Source Blending|dual source blending]]. The draw buffers list in the FBO (or the default framebuffer) is used to map between the values set into the fragment shader and the attachment names in the FBO (or buffers in the default framebuffer).

+

When linking a fragment shader, the user will assign each fragment shader output variable to a number. This number is between 0 and {{enum|GL_MAX_DRAW_BUFFERS}}-1 under normal circumstances, or between 0 and {{enum|GL_MAX_DUAL_SOURCE_DRAW_BUFFERS}} - 1 when a fragment shader is outputting values to the second color of a buffer, for [[Blending#Dual Source Blending|dual source blending]]. The draw buffers list in the FBO (or the default framebuffer) is used to map between the values set into the fragment shader and the attachment names in the FBO (or buffers in the default framebuffer).

When you link your shader, you use <code>glBindFragDataLocation</code> or <code>glBindFragDataLocationIndex</code> to assign 0 to <code>mainColor</code> and 1 to <code>subsideraryInfo</code>. You can also use <code>layout</code> syntax to define this directly in the shader, as you would for attribute indices:

+

When you link your shader, you use {{apifunc|glBindFragDataLocation}} or {{apifunc|glBindFragDataLocationIndexed}} to assign 0 to {{code|mainColor}} and 1 to {{code|subsideraryInfo}}. You can also use {{code|layout}} syntax to define this directly in the shader, as you would for attribute indices:

layout(location = 0) out vec4 mainColor;

layout(location = 0) out vec4 mainColor;

−

layout(location = 0) out vec2 subsideraryInfo;

+

layout(location = 1) out vec2 subsideraryInfo;

It is up to the draw buffers state in the FBO to state where these get rendered to. To set this mapping, you use this function:

It is up to the draw buffers state in the FBO to state where these get rendered to. To set this mapping, you use this function:

This function sets up the entire mapping table in one shot. The indices in the list correspond to the values set with <code>glBindFragDataLocation</code> or <code>glBindFragDataLocationIndex</code>. This means that the list can only be as large as GL_MAX_DRAW_BUFFERS or GL_MAX_DUAL_SOURCE_DRAW_BUFFERS when using dual source blending. The entries in the <code>bufs</code> array are enumerators referring to buffer names in the framebuffer.

+

This function sets up the entire mapping table in one shot. The indices in the list correspond to the values set with {{apifunc|glBindFragDataLocation}} or {{apifunc|glBindFragDataLocationIndexed}}. This means that the list can only be as large as {{enum|GL_MAX_DRAW_BUFFERS}} or {{enum|GL_MAX_DUAL_SOURCE_DRAW_BUFFERS}} when using [[Blending#Dual_Source_Blending|dual source blending]]. The entries in the {{param|bufs}} array are enumerators referring to buffer names in the framebuffer.

−

When the default framebuffer is active, these enumerators are from the list of the default framebuffer buffer names. GL_AUX''i'', GL_BACK_LEFT, and so on. When an FBO is active (in the GL_DRAW_FRAMEBUFFER slot), these enumerators are GL_COLOR_ATTACHMENT''i'' values (less than GL_MAX_COLOR_ATTACHMENTS, of course). In either case, an entry in the list can be GL_NONE, which means that the output (if the shader outputs a value for it at all) is discarded.

+

The default framebuffer and FBOs have different names for their attached images. The default framebuffer uses {{enum|GL_AUX''i''}}, {{enum|GL_BACK_LEFT}}, and so on. FBOs use {{enum|GL_COLOR_ATTACHMENT''i''}} values, where ''i'' is less than {{enum|GL_MAX_COLOR_ATTACHMENTS}}. These attachments are passed to {{apifunc|glDrawBuffers}}. An entry in the list can be {{enum|GL_NONE}}, which means that the output (if the shader outputs a value for it at all) is discarded.

−

If you are only setting up one draw buffer, you may use <code>glDrawBuffer</code>. It takes one enumeration value and sets the fragment data location 0 to draw to that buffer. All other fragment data location values are set to GL_NONE.

+

If you are only setting up one draw buffer, you may use {{apifunc|glDrawBuffer}}. It takes one enumeration value and sets the fragment data location 0 to draw to that buffer. All other fragment data location values are set to {{enum|GL_NONE}}.

−

The state set by glDrawBuffers is part of the FBO (or default framebuffer). So you can generally set this up once and leave it set.

+

The state set by {{apifunc|glDrawBuffers}} is part of the state of the FBO (or default framebuffer). So you can generally set this up once and leave it set.

−

== Framebuffer Bliting ==

+

== Framebuffer Blitting ==

−

The reason for the separation of GL_DRAW_FRAMEBUFFER and GL_READ_FRAMEBUFFER bindings is to allow data in one buffer to be blitted to another buffer.

+

The reason for the separation of {{enum|GL_DRAW_FRAMEBUFFER}} and {{enum|GL_READ_FRAMEBUFFER}} bindings is to allow data in one buffer to be blitted to another buffer.

−

A blit operation is a special form of copy operation; it copies a rectangular area of pixels from one framebuffer to another. It is not the same as a simple <code>glCopyPixels</code>, as it has some very specific properties with regard to [[Multisampling|multisampling]].

+

A blit operation is a special form of copy operation; it copies a rectangular area of pixels from one framebuffer to another. This function also has some very specific properties with regard to [[Multisampling|multisampling]].

−

Performing a blit between framebuffers is quite simple. You bind the source framebuffer to GL_READ_FRAMEBUFFER, then bind the destination framebuffer to GL_DRAW_FRAMEBUFFER. After that, you call this function:

+

You bind the source framebuffer to {{enum|GL_READ_FRAMEBUFFER}}, then bind the destination framebuffer to {{enum|GL_DRAW_FRAMEBUFFER}}.

The pixels in the rectangular area specified by the <code>src</code> values are copied to the rectangular area specified by the <code>dst</code> values. The <code>mask</code> parameter is a bitfield that specifies which kinds of buffers you want copied: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT, or some combination. The <code>filter</code> parameter specifies how you want filtering performed if the two rectangles are not the same size.

+

The pixels in the rectangular area specified by the {{param|src}} values are copied to the rectangular area specified by the {{param|dst}} values. The {{param|mask}} parameter is a bitfield that specifies which kinds of buffers you want copied: {{enum|GL_COLOR_BUFFER_BIT}}, {{enum|GL_DEPTH_BUFFER_BIT}}, {{enum|GL_STENCIL_BUFFER_BIT}}, or some combination. The {{param|filter}} parameter specifies how you want filtering performed if the two rectangles are not the same size.

−

Now one thing to keep in mind is this: blit operations only read from the color buffer specified by <code>glReadBuffer</code> and will only write to the color buffers specified by <code>glDrawBuffers</code>. If multiple draw buffers are specified, then multiple color buffers are updated. This assumes that <code>mask</code> included the color buffer. The depth and stencil buffers of the source framebuffers are blitted to the destination if the <code>mask</code> specifies them.

+

One thing to keep in mind is this: blit operations only read from the color buffer specified by {{apifunc|glReadBuffer}} in the read FBO and will only write to the color buffers specified by {{apifunc|glDrawBuffers}} in the write FBO. If multiple draw buffers are specified, then multiple color buffers are updated. This assumes that {{param|mask}} included the color buffer. The depth and stencil buffers of the source framebuffers are blitted to the destination if the {{param|mask}} specifies them.

−

The <code>glReadBuffer</code> state is stored with the FBO/default framebuffer, just like the <code>glDrawBuffers</code> state.

+

The {{apifunc|glReadBuffer}} state is stored with the FBO/default framebuffer, just like the {{apifunc|glDrawBuffers}} state.

Note that it is perfectly valid to read from the default framebuffer and write to an FBO, or vice-versa.

Note that it is perfectly valid to read from the default framebuffer and write to an FBO, or vice-versa.

As explained in the article on [[Multisampling]], a multisampled buffer must be resolved into a single sample before it can be displayed. Normally, this resolving operation is automatic, occurring during framebuffer swapping (though reading from the framebuffer can cause it to happen anyway).

+

As explained in the article on [[Multisampling]], a multisampled buffer must be resolved into a single sample before it can be displayed. When the default framebuffer uses multisampling, this resolving operation is automatic, occurring during framebuffer swapping (though reading from the framebuffer can cause it to happen anyway).

Each FBO or framebuffer has a specific number of multisample samples (remember: an FBO cannot be framebuffer-complete if all of the attached images do not have the same number of samples). When you blit between two FBOs with the same number of samples, the copy is done directly; the destination buffer gets the same information the source had.

Each FBO or framebuffer has a specific number of multisample samples (remember: an FBO cannot be framebuffer-complete if all of the attached images do not have the same number of samples). When you blit between two FBOs with the same number of samples, the copy is done directly; the destination buffer gets the same information the source had.

Line 241:

Line 253:

In this special case, two things can happen. If the read framebuffer is the one with zero samples, then the draw buffer has all of its samples per-pixel replaced with the values from the read framebuffer. However, if the draw framebuffer is the one with zero samples, then it causes the multisampled framebuffer to have its multisamples resolved into a single sample per pixel. This explicit resolution is very useful when dealing with multisampled buffers.

In this special case, two things can happen. If the read framebuffer is the one with zero samples, then the draw buffer has all of its samples per-pixel replaced with the values from the read framebuffer. However, if the draw framebuffer is the one with zero samples, then it causes the multisampled framebuffer to have its multisamples resolved into a single sample per pixel. This explicit resolution is very useful when dealing with multisampled buffers.

−

As with all multisample behavior, none of this works at all unless <code>glEnable(GL_MULTISAMPLE)</code> is in effect.

+

As with all multisample behavior, none of this works at all unless {{apifunc|glEnable|(GL_MULTISAMPLE)}} is in effect (which is the default).

== Feedback Loops ==

== Feedback Loops ==

+

{{main|Memory Model#Framebuffer objects}}

−

It is possible to bind a texture to an FBO, bind that same texture to a shader, and then try to render with it.

+

It is possible to bind a texture to an FBO, bind that same texture to a shader, and then try to render with it at the same time.

−

This is bad. Mostly.

+

It is perfectly valid to bind one ''image'' from a texture to an FBO and then render with that texture, as long as you prevent yourself from ''sampling'' from that image. If you do try to read and write to the same image, you get undefined results. Meaning it may do what you want, the sampler may get old data, the sampler may get ''half'' old and half new data, or it may get garbage data. Any of these are possible outcomes.

−

It is perfectly valid to bind one ''image'' from a texture to an FBO and then render with that texture, as long as you prevent yourself from ''sampling'' from that image. If you do try to read and write to the same image, you get undefined results. Meaning it may do what you want, the sampler may get old data, the sampler may get ''half'' old and half new data, or it may get garbage data. Any of these are possible.

+

Do not do this. What you will get is undefined behavior.

−

Do not try this.

+

== Invalidation ==

−

+

{{missing|section}}

−

It is possible to get the same effect by doing a <code>glCopyPixels</code> or a <code>glBlitFramebuffer</code> operation. Similarly, if you try to read and write to the same image, you get undefined results.

+

== EXT_Framebuffer_object ==

== EXT_Framebuffer_object ==

−

+

{{deprecated|section=}}

−

{{deprecated}}

+

The original form of FBOs was this extension. It lacked quite a bit of the above functionality, which later extensions granted. The biggest difference is that it has more hard-coded restrictions on framebuffer completeness. All of the images have to be the same size in the EXT spec, for example. Some of these limitations were hardware-based. So there may be hardware that supports EXT_FBO and not ARB_FBO, even thought they support things like EXT_FBO_blit and other parts of ARB_FBO.

The original form of FBOs was this extension. It lacked quite a bit of the above functionality, which later extensions granted. The biggest difference is that it has more hard-coded restrictions on framebuffer completeness. All of the images have to be the same size in the EXT spec, for example. Some of these limitations were hardware-based. So there may be hardware that supports EXT_FBO and not ARB_FBO, even thought they support things like EXT_FBO_blit and other parts of ARB_FBO.

Framebuffer Objects are a mechanism for rendering to images other than the default OpenGL Default Framebuffer. They are OpenGL Objects that allow you to render directly to textures, as well as blitting from one framebuffer to another.

Semantics

Framebuffer objects are very complicated. As such, we need to explicitly define certain terminology.

Image: For the purposes of this article, an image is a single 2D array of pixels. It has a specific format for these pixels.

Layered Image: For the purposes of this article, a layered image is a sequence of images of a particular size and format. Layered images are packaged together within a single OpenGL object.

Texture: For the purposes of this article, a texture is an object that contains some number of images, as defined above. All of the images have the same format, but they do not have to have the same size (different mip-maps, for example). Textures can be bound to shaders and rendered with.

Renderbuffer: A renderbuffer is an object that contains a single image. Renderbuffers cannot be bound to shaders or otherwise rendered with; they can only be attached to FBOs.

Framebuffer-attachable image: Any image, as previously described, that can be attached to a framebuffer object.

Framebuffer-attachable layered image: Any layered image, as previously described, that can be attached to a framebuffer object.

Attachment point: A named location within a framebuffer object that a framebuffer-attachable image or layered image can be attached to. Attachment points can have limitations on the format of the images attached there.

Attach: To connect one object to another. This is not limited to FBOs, but attaching is a big part of them. Attachment is different from binding. Objects are bound to the context; they are attached to each other.

Framebuffer Object Structure

The target​ parameter for this object can take one of 3 values: GL_FRAMEBUFFER, GL_READ_FRAMEBUFFER, or GL_DRAW_FRAMEBUFFER. The last two allow you to bind an FBO so that reading commands (glReadPixels​, etc) and writing commands (any command of the form glDraw*​) can happen to two different buffers. The GL_FRAMEBUFFER target simply sets both the read and the write to the same FBO.

When an FBO is bound to a target, the available surfaces change. The default framebuffer has buffers like GL_FRONT, GL_BACK, GL_AUXi, GL_ACCUM, and so forth. FBOs do not have these.

Instead, FBOs have a different set of images. Each FBO image represents an attachment point, a location in the FBO where an image can be attached. FBOs have the following attachment points:

GL_COLOR_ATTACHMENTi: These are an implementation-dependent number of attachment points. You can query GL_MAX_COLOR_ATTACHMENTS to determine the number of color attachments that an implementation will allow. The minimum value for this is 1, so you are guaranteed to be able to have at least color attachment 0. These attachment points can only have images bound to them with color-renderable formats. All compressed image formats are not color-renderable, and thus cannot be attached to an FBO.

GL_DEPTH_ATTACHMENT: This attachment point can only have images with depth formats bound to it. The image attached becomes the Depth Buffer for the FBO.

GL_STENCIL_ATTACHMENT: This attachment point can only have images with stencil formats bound to it. The image attached becomes the stencil buffer for the FBO.

GL_DEPTH_STENCIL_ATTACHMENT: This is shorthand for "both depth and stencil". The image attached becomes both the depth and stencil buffers.

Note: If you use GL_DEPTH_STENCIL_ATTACHMENT, you should use a packed depth-stencil internal format for the texture or renderbuffer you are attaching.

Attaching Images

Now that we know where images can be attached to FBOs, we can start talking about how to actually attach images to these. Of course, in order to attach images to an FBO, we must first bind the FBO to the context.

You can attach images from any kind of texture to the framebuffer object.

Remember that textures are a set of images. Textures can have mipmaps; thus, each individual mipmap level can contain one or more images.

A 1D texture contains 2D images that have the vertical height of 1. Each individual image can be uniquely identified by a mipmap level​.

A 2D texture contains 2D images. Each individual image can be uniquely identified by a mipmap level​.

A Rectangle Texture has a single 2D image, and thus is identified by mipmap level​ 0.

Each mipmap level of a 3D texture is considered a set of 2D images, with the number of these being the extent of the Z coordinate. Each integer value for the depth of a 3D texture mipmap level is a layer. So each image in a 3D texture is uniquely identified by a layer​ and a mipmap level​.

Cubemaps contain 6 targets, each of which is a 2D image. Thus, each image in a cubemap texture can be uniquely identified by a target​ and a mipmap level​.

Each mipmap level of a 1D Array Textures contains a number of images, equal to the count images in the array. While these images are technically one-dimensional, they are promoted to 2D status for FBO purposes in the same way as a non-array 1D texture: by using a height of 1. Thus, each individual image is uniquely identified by a layer​ (the array index) and a mipmap level​.

2D Array textures are much like 3D textures, except instead of the number of Z slices, it is the array count. Each 2D image in an array texture can be uniquely identified by a layer​ (the array index) and a mipmap level​. Unlike 3D textures, the array count doesn't change when going down the mipmap hierarchy.

Cubemap array textures work like 2D array textures, only with 6 times the number of images. Thus a 2D image in the array is identified by the array layer​ (technically layer-face) and a mipmap level​.

Buffer Textures work like 1D texture, only they have a single image, identified by mipmap level​ 0.

The highlighted words above are significant, as they match the parameters of the following functions used for attaching textures:

The target​ parameter here is the same as the one for bind. However, GL_FRAMEBUFFER doesn't mean both read and draw (as that would make no sense); instead, it is the same as GL_DRAW_FRAMEBUFFER. The attachment​ parameter is one of the above attachment points.

The texture​ argument is the texture object name you want to attach from. If you pass zero as texture​, this has the effect of clearing the attachment for this attachment​, regardless of what kind of image was attached there.

Because texture objects can hold multiple images, you must specify exactly which image to attach to this attachment point. The parameters match their above definitions, with the exception of textarget​.

When attaching a non-cubemap, textarget​ should be the proper texture type: GL_TEXTURE_1D, GL_TEXTURE_2D_MULTISAMPLE, etc. When attaching a cubemap, you must use the Texture2D function, and the textarget​ must be one of the 6 targets for cubemap binding.

Legacy Note: There is a function, glFramebufferTexture3D​, specifically for 3D textures. However, you shouldn't bother with it, as the TextureLayer function can do everything it can and more.

Renderbuffers can also be attached to FBOs. Indeed, this is the only way to use them besides just creating the storage for them.

Once you have created a renderbuffer object and made storage for it (given a size and format), you can attach it to an FBO with this function:

The parameters work mostly the same as with texture attachment. The renderbuffertarget​ param must be GL_RENDERBUFFER. The renderbuffer​ parameter is the renderbuffer object's name.

Layered Images

A layered image, as previously defined, is an ordered sequence of images of a particular size. A number of different kinds of textures can be considered layered.

A single mipmap level of a 1D or 2D array texture is a layered image, where the number of layers is the array size. A single mipmap level of a 3D texture is likewise a layered image, where the number of layers is the depth of that particular mipmap level. Also, a mipmap level of a cubemap is a layered image. For cubemaps, you get exactly 6 layers, one for each face. And the order of the faces is the same as the order of the enumerators:

Layer number

Cubemap face

0

GL_TEXTURE_CUBE_MAP_POSITIVE_X

1

GL_TEXTURE_CUBE_MAP_NEGATIVE_X

2

GL_TEXTURE_CUBE_MAP_POSITIVE_Y

3

GL_TEXTURE_CUBE_MAP_NEGATIVE_Y

4

GL_TEXTURE_CUBE_MAP_POSITIVE_Z

5

GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

For cubemap arrays, the value that gl_Layer​ represents is the layer-face index. Thus it is the face within a layer, ordered as above. So if you want to render to the 3rd layer, +z face, you would set gl_Layer​ to (2 * 6) + 4, or 16.

Each texture, when taken as a layered image, has a specific number of layers. For array and 3D textures, this is the depth of the texture. For cubemaps, this is always exactly 6 layers: one per face. Cubemap arrays have 6 * the number of layers, which is the number of layer-faces.

The parameters have the same meaning as above. Indeed, this function can replace many of the uses for glFramebufferTexture1D, 2D, or Layer​, as long as you do not intend to attach specific layers of array textures, cubemaps, or 3D textures as regular, non-layered images. If the texture​ is one of these kinds of textures, then the given mipmap level​ will be attached as a layered image with the number of layers that the given texture has.

Empty framebuffers

It is possible to render to a framebuffer object that has no attachments. Obviously none of the fragment shader outputs will be written to anywhere in this case, but rendering can otherwise proceed as normal. This is useful for using arbitrary reading and writing of image data, instead of writing to a bound framebuffer.

However, the rasterization of primitives is always based on the area and characteristics of the bound framebuffer. Normally, these characteristics (size, number of samples for multisample rendering, etc) are defined by the attached images. If no images are attached, these characteristics must be defined in some other fashion.

The width and height of an FBO with no attachments can be set with this function:

target​ is the location where the framebuffer object is bound. To set the width, set pname​ to GL_FRAMEBUFFER_DEFAULT_WIDTH; to set the height, use GL_FRAMEBUFFER_DEFAULT_HEIGHT.

Layered framebuffers can be simulated by using GL_FRAMEBUFFER_DEFAULT_LAYERS. Multisample framebuffers can be simulated using GL_FRAMEBUFFER_DEFAULT_SAMPLES to set the number of samples. Fixed multisample location can similarly be simulated with GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS.

Note that rendering is only limited to these parameters if no images are attached to the FBO. If images are attached, then these parameters are ignored. You should only set these values if you intend to use the FBO without images.

Framebuffer Completeness

Each attachment point in a FBO has specific restrictions on the format of images that can be attached to it. However, it is not an immediate GL error to attach an image to an attachment point that doesn't support that format. It is an error to try to use an FBO that has been improperly set up. There are also a number of other issues with regard to sizes of images and so forth that must be detected in order to be able to safely use the FBO.

An FBO that is valid for use is said to be "framebuffer complete". To test framebuffer completeness, call this function:

You are not required to call this manually. However, using an incomplete FBO is an error, so it's always a good idea to check.

The return value is GL_FRAMEBUFFER_COMPLETE if the FBO can be used. If it is something else, then there is a problem. Below are the rules for completeness and the associated return values you will receive if they are not followed.

Attachment Completeness

Each attachment point itself must be complete according to these rules. Empty attachments (attachments with no image attached) are complete by default. If an image is attached, it must adhere to the following rules:

The source object for the image still exists and has the same type it was attached with.

The image has a non-zero width and height (the height of a 1D image is assumed to be 1). The width/height must also be less than GL_MAX_FRAMEBUFFER_WIDTH and GL_MAX_FRAMEBUFFER_HEIGHT respectively (if GL 4.3/ARB_framebuffer_no_attachments).

The layer for 3D or array textures attachments is less than the depth of the texture. It must also be less than GL_MAX_FRAMEBUFFER_LAYERS (if GL 4.3/ARB_framebuffer_no_attachments).

The number of samples must be less than GL_MAX_FRAMEBUFFER_SAMPLES (if GL 4.3/ARB_framebuffer_no_attachments).

Completeness Rules

These are the rules for framebuffer completeness. The order of these rules matters.

If the target​ of glCheckFramebufferStatus​ references the default framebuffer (ie: FBO object number 0 is bound), and the default framebuffer does not exist, then you will get GL_FRAMEBUFFER_UNDEFINED. If the default framebuffer exists, then you always get GL_FRAMEBUFFER_COMPLETE. The rest of the rules apply when an FBO is bound.

All attachments that are set as a draw buffer or read buffer (see below) must be attachment complete, as defined above. (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT when false).

There must be at least one image attached to the FBO, or if GL 4.3/ARB_framebuffer_no_attachment is available, the GL_FRAMEBUFFER_DEFAULT_WIDTH and GL_FRAMEBUFFER_DEFAULT_HEIGHT parameters of the framebuffer must both be non-zero. (GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT when false).

All draw buffers (see below) must specify color attachment points that have images attached. (GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER when false). Note that this test is not performed if GL 4.2/ARB_ES2_compatibility is available.

If the read buffer is set, then it must specify an attachment point that has an image attached. (GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER when false). Note that this test is not performed if GL 4.2/ARB_ES2_compatibility is available.

All images must have the same number of multisample samples. (GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE when false).

If a layered image is attached to one attachment, then all attachments must be layered attachments. The attached layers do not have to have the same number of layers, nor do the layers have to come from the same kind of texture (a cubemap color texture can be paired with an array depth texture) (GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS when false).

Notice that there is no restriction based on size. The effective size of the FBO is the intersection of all of the sizes of the bound images (ie: the smallest in each dimension).

These rules are all code-based. If you ever get any of these values from glCheckFramebufferStatus​, it is because your program has done something wrong in setting up the FBO. Each one has a specific remedy for it.

OpenGL allows implementations to state that they do not support some combination of image formats for the attached images; they do this by returning GL_FRAMEBUFFER_UNSUPPORTED when you attempt to use an unsupported format combination.

However, the OpenGL specification also requires that implementations support certain formats; that is, if you use these formats, implementations are forbidden to return GL_FRAMEBUFFER_UNSUPPORTED. This list of required formats is also the list of required image formats that all OpenGL implementations must support. These are most of the useful formats. Basically, don't concern yourself with GL_FRAMEBUFFER_UNSUPPORTED too much. Check for it, but you'll be fine as long as you stick to the required formats.

Legacy Note:GL_FRAMEBUFFER_UNSUPPORTED was initially, in the days of EXT_framebuffer_object, much less forgiving. The specification didn't have a list of required image formats. Indeed, the only guarantee that the EXT_FBO spec made was that there was at least one combination of formats that implementations supported; it provided no hints as to what that combination might be. The core extension ARB_framebuffer_object does differ from the core specification in one crucial way: it uses the EXT wording for GL_FRAMEBUFFER_UNSUPPORTED. So if you're using 3.0, you don't have to worry much about unsupported. If you're using ARB_framebuffer_object, then you should be concerned and do appropriate testing.

Multiple Render Targets

Modern shaders allow the user to render to multiple render targets simultaneously. To facilitate this, FBOs (and the default framebuffer) have a mapping that allows the user to define which fragment shader outputs go to which buffers. The way this works is somewhat complicated.

When linking a fragment shader, the user will assign each fragment shader output variable to a number. This number is between 0 and GL_MAX_DRAW_BUFFERS-1 under normal circumstances, or between 0 and GL_MAX_DUAL_SOURCE_DRAW_BUFFERS - 1 when a fragment shader is outputting values to the second color of a buffer, for dual source blending. The draw buffers list in the FBO (or the default framebuffer) is used to map between the values set into the fragment shader and the attachment names in the FBO (or buffers in the default framebuffer).

This function sets up the entire mapping table in one shot. The indices in the list correspond to the values set with glBindFragDataLocation​ or glBindFragDataLocationIndexed​. This means that the list can only be as large as GL_MAX_DRAW_BUFFERS or GL_MAX_DUAL_SOURCE_DRAW_BUFFERS when using dual source blending. The entries in the bufs​ array are enumerators referring to buffer names in the framebuffer.

The default framebuffer and FBOs have different names for their attached images. The default framebuffer uses GL_AUXi, GL_BACK_LEFT, and so on. FBOs use GL_COLOR_ATTACHMENTi values, where i is less than GL_MAX_COLOR_ATTACHMENTS. These attachments are passed to glDrawBuffers​. An entry in the list can be GL_NONE, which means that the output (if the shader outputs a value for it at all) is discarded.

If you are only setting up one draw buffer, you may use glDrawBuffer​. It takes one enumeration value and sets the fragment data location 0 to draw to that buffer. All other fragment data location values are set to GL_NONE.

The state set by glDrawBuffers​ is part of the state of the FBO (or default framebuffer). So you can generally set this up once and leave it set.

Framebuffer Blitting

The reason for the separation of GL_DRAW_FRAMEBUFFER and GL_READ_FRAMEBUFFER bindings is to allow data in one buffer to be blitted to another buffer.

A blit operation is a special form of copy operation; it copies a rectangular area of pixels from one framebuffer to another. This function also has some very specific properties with regard to multisampling.

You bind the source framebuffer to GL_READ_FRAMEBUFFER, then bind the destination framebuffer to GL_DRAW_FRAMEBUFFER.
It is possible to use the same source and target buffer.
After that, you call this function:

The pixels in the rectangular area specified by the src​ values are copied to the rectangular area specified by the dst​ values. The mask​ parameter is a bitfield that specifies which kinds of buffers you want copied: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT, or some combination. The filter​ parameter specifies how you want filtering performed if the two rectangles are not the same size.

One thing to keep in mind is this: blit operations only read from the color buffer specified by glReadBuffer​ in the read FBO and will only write to the color buffers specified by glDrawBuffers​ in the write FBO. If multiple draw buffers are specified, then multiple color buffers are updated. This assumes that mask​ included the color buffer. The depth and stencil buffers of the source framebuffers are blitted to the destination if the mask​ specifies them.

Note that it is perfectly valid to read from the default framebuffer and write to an FBO, or vice-versa.

Format Considerations

Blitting is not the same as performing a pixel transfer operation. The conversion between source and destination format is more limited. Blitting depth and stencil buffers works as expected: values are converted from one bitdepth to the other as needed. Conversion between color formats is different.

A blit operation can only convert between formats within 3 groups. Signed integral and unsigned integral formats make up two groups, with all normalized and floating-point formats making up the third. Thus, it is legal to blit from an GL_RGB8 buffer to a GL_RGB32F and vice versa. But it is not legal to blit a GL_RGB8 from or to a GL_RGBI8 format image.

The data during blitting is converted according to simple rules. Blitting from a floating-point format to a normalized integer format will cause clamping, either to [0, 1] for unsigned normalized or [-1, 1] for signed normalized.

Multisampling Considerations

As explained in the article on Multisampling, a multisampled buffer must be resolved into a single sample before it can be displayed. When the default framebuffer uses multisampling, this resolving operation is automatic, occurring during framebuffer swapping (though reading from the framebuffer can cause it to happen anyway).

Each FBO or framebuffer has a specific number of multisample samples (remember: an FBO cannot be framebuffer-complete if all of the attached images do not have the same number of samples). When you blit between two FBOs with the same number of samples, the copy is done directly; the destination buffer gets the same information the source had.

It is an error to blit between buffers with different numbers of samples, unless one of them has zero samples. You get this by not attaching multisampled images to that FBO, or not using multisampled default framebuffers.

In this special case, two things can happen. If the read framebuffer is the one with zero samples, then the draw buffer has all of its samples per-pixel replaced with the values from the read framebuffer. However, if the draw framebuffer is the one with zero samples, then it causes the multisampled framebuffer to have its multisamples resolved into a single sample per pixel. This explicit resolution is very useful when dealing with multisampled buffers.

As with all multisample behavior, none of this works at all unless glEnable(GL_MULTISAMPLE)​ is in effect (which is the default).

Feedback Loops

It is possible to bind a texture to an FBO, bind that same texture to a shader, and then try to render with it at the same time.

It is perfectly valid to bind one image from a texture to an FBO and then render with that texture, as long as you prevent yourself from sampling from that image. If you do try to read and write to the same image, you get undefined results. Meaning it may do what you want, the sampler may get old data, the sampler may get half old and half new data, or it may get garbage data. Any of these are possible outcomes.

Do not do this. What you will get is undefined behavior.

Invalidation

This section is missing information. Further details can be found on the talk page.

The original form of FBOs was this extension. It lacked quite a bit of the above functionality, which later extensions granted. The biggest difference is that it has more hard-coded restrictions on framebuffer completeness. All of the images have to be the same size in the EXT spec, for example. Some of these limitations were hardware-based. So there may be hardware that supports EXT_FBO and not ARB_FBO, even thought they support things like EXT_FBO_blit and other parts of ARB_FBO.