A Framebuffer
is a WebGL container object that the application can use for "off screen" rendering. A framebuffer does not itself contain any image data but can optionally contain attachments (one or more color buffers, a depth buffer and a stencil buffer) that store data. Attachments must be in the form of Texture
s and Renderbuffer
s.
For additional information, see OpenGL Wiki Framebuffer and Framebuffer Object
luma.gl adds
Creating a framebuffer with default color and depth attachments
const framebuffer = new Framebuffer(gl, {
width: window.innerWidth,
height: window.innerHeight,
color: true,
depth: true
});
Attaching textures and renderbuffers
framebuffer.attach({
[GL.DEPTH_ATTACHMENT]: new Renderbuffer(gl, {...}),
[GL.COLOR_ATTACHMENT0]: new Texture(gl, {...}),
[GL.COLOR_ATTACHMENT1]: [new TextureCube(gl, {...}), GL.TEXTURE_CUBE_MAP_POSITIVE_X],
[GL.COLOR_ATTACHMENT2]: [new TextureArray2D(gl, {...}), 0],
[GL.COLOR_ATTACHMENT3]: [new TextureArray2D(gl, {...}), 1],
[GL.COLOR_ATTACHMENT4]: [new Texture3D(gl, {..., depth: 8}), 2]
});
framebuffer.checkStatus(); // optional
Resizing a framebuffer to the size of a window. Resizes all attachements with a single framebuffer.resize()
call
// Note: this resizes (and possibly clears) all attachments
framebuffer.resize({width: window.innerWidth, height: window.innerHeight});
Clearing a framebuffer
framebuffer.clear();
framebuffer.clear({color: [0, 0, 0, 0], depth: 1, stencil: 0});
Specifying a framebuffer for rendering in each render calls
const offScreenBuffer = new Framebuffer();
program1.draw({
framebuffer: offScreenBuffer,
parameters: {}
});
model.draw({
framebuffer: null, // the default drawing buffer
parameters: {}
});
Binding a framebuffer for multiple render calls
const framebuffer1 = ...;
const framebuffer2 = ...;
withParameters(gl, {framebuffer: framebuffer1}, () => {
// Any draw call that doesn't specify a framebuffer will now draw into framebuffer1
program1.draw({...}); // -> framebuffer1
program2.draw({...}); // -> framebuffer1
// Explicit specification of framebuffer overrides (for that call only)
program2.draw({framebuffer: framebuffer1, ...); // -> framebuffer2
program2.draw({...}); // -> framebuffer1
});
// framebuffer1 is not longer bound
For reading data into CPU memory check readPixelsToArray
For reading into a Buffer object (GPU memory), doesn't result in CPU and GPU sync, check readPixelsToBuffer
For reading into a Texture object (GPU memory), doesn't result in CPU and GPU sync, check copyToTexture
For blitting between framebuffers (WebGL 2), check blit
Specify which framebuffer attachments the fragment shader will be writing to when assigning to gl_FragData[]
framebuffer.update({
drawBuffers: [
GL.COLOR_ATTACHMENT0, // gl_FragData[0]
GL.COLOR_ATTACHMENT1, // gl_FragData[1]
GL.COLOR_ATTACHMENT2, // gl_FragData[2]
GL.COLOR_ATTACHMENT3 // gl_FragData[3]
]
});
Writing to multiple framebuffer attachments in GLSL fragment shader
#extension GL_EXT_draw_buffers : require
precision highp float;
void main(void) {
gl_FragData[0] = vec4(0.25);
gl_FragData[1] = vec4(0.5);
gl_FragData[2] = vec4(0.75);
gl_FragData[3] = vec4(1.0);
}
Clearing a specific draw buffer in a framebuffer (WebGL 2)
framebuffer.clear({
[GL.COLOR]: [0, 0, 1, 1], // Blue
[GL.COLOR]: new Float32Array([0, 0, 0, 0]), // Black/transparent
[GL.DEPTH_BUFFER]: 1, // Infinity
[GL.STENCIL_BUFFER]: 0 // no stencil
});
framebuffer.clear({
[GL.DEPTH_STENCIL_BUFFER]: [1, 0] // Infinity, no stencil
});
Creates a new framebuffer, optionally creating and attaching Texture
and Renderbuffer
attachments.
new Framebuffer(gl, {
id,
width,
height,
attachments,
color,
depth,
stencil
})
id
= - (String) - An optional name (id) of the buffer.width
=1
- (number) The width of the framebuffer.height
=1
- (number) The height of the framebuffer.attachments
={} - (Object, optional) - a map of Textures and/or Renderbuffers, keyed be "attachment points" (see below).color
- shortcut to the attachment in GL.COLOR_ATTACHMENT0
depth
- shortcut to the attachment in GL.DEPTH_ATTACHMENT
stencil
- shortcut to the attachment in GL.STENCIL_ATTACHMENT
The luma.gl Framebuffer
constructor enables the creation of a framebuffer with all the proper attachments in a single step and also the resize
method makes it easy to efficiently resize a all the attachments of a Framebuffer
with a single method.
When no attachments are provided during Framebuffer
object creation, new resources are created and used as default attachments for enabled targets (color and depth).
For color, new Texture2D
object is created with no mipmaps and following filtering parameters are set.
Texture parameter | Value |
---|---|
GL.TEXTURE_MIN_FILTER | GL.LINEAR |
GL.TEXTURE_MAG_FILTER | GL.LINEAR |
GL.TEXTURE_WRAP_S | GL.CLAMP_TO_EDGE |
GL.TEXTURE_WRAP_T | GL.CLAMP_TO_EDGE |
For depth, new Renderbuffer
object is created with GL.DEPTH_COMPONENT16
format.
Destroys the underlying WebGL object. When destroying Framebuffer
s it can be important to consider that a Framebuffer
can manage other objects that may also need to be destroyed.
Initializes the Framebuffer
to match the supplied parameters. Unattaches any existing attachments, attaches any supplied attachments. All new attachments will be resized if they are not already at the right size.
Framebuffer.initialize({width, height})
width
=1
- (number) The width of the framebuffer.height
=1
- (number) The height of the framebuffer.attachments
={} - (Object, optional) - a map of Textures and/or Renderbuffers, keyed be "attachment points" (see below).color
- shortcut to the attachment in GL.COLOR_ATTACHMENT0
depth
- shortcut to the attachment in GL.DEPTH_ATTACHMENT
stencil
- shortcut to the attachment in GL.STENCIL_ATTACHMENT
Updates Framebuffers attachments using provided Texture and Renderbuffer objects. Optionally sets read and draw buffers when using WebGL 2 context.
attachments
- a map of attachments.readBuffer
- Buffer to be set as read buffer (WebGL 2)drawBuffers
- Buffers to be set as draw buffers (WebGL 2)clearAttachments
- When set to true, will first unattach all binding points, default value is false
.resizeAttachments
- When set to true, all attachments will be re-sized to Framebuffers size, default value is true
.Framebuffer.resize({width, height})
Resizes all the Framebuffer
's current attachments to the new width
and height
by calling resize
on those attachments.
width
(GLint) - width of Framebuffer
in pixelsheight
(GLint) - height of Framebuffer
in pixelsReturns itself to enable chaining
resize
method checks if width
or height
have actually changed before reinitializing their data store, so calling resize
multiple times with the same width
and height
does not trigger multiple resizes.resize
erases the current content of the attachment in question.WebGL References see initialize
.
Used to attach or unattach Texture
s and Renderbuffer
s from the Framebuffer
s various attachment points.
Framebuffer.attach(attachments)
attachments
- a map of attachments.clearAttachments
- When set to true, will first unattach all binding points, default value is false
.resizeAttachments
- When set to true, all attachments will be re-sized to Framebuffers size, default value is true
.Returns itself to enable chaining.
The key of an attachment must be a valid attachment point, see below.
The following values can be provided for each attachment
null
- unattaches any current bindingRenderbuffer
- attaches the Renderbuffer
Texture
- attaches the Texture
Texture
, layer=0 (Number), mipmapLevel=0 (Number)] - attaches the specific layer from the Texture
(WebGL 2)This function makes calls to the following WebGL APIs:
gl.framebufferRenderbuffer
,
gl.bindFramebuffer
,
gl.framebufferTexture2D
,
gl.bindFramebuffer
,
gl.framebufferTextureLayer
,
gl.bindFramebuffer
(This is for WebGL 2 only)
Check that the framebuffer contains a valid combination of attachments
gl.checkFramebufferStatus
, gl.bindFramebuffer
Clears the contents (pixels) of the framebuffer attachments.
options.color
(Boolean or Array) - clears all active color buffers (any selected drawBuffer
s) with either the provided color or the default color.options.depth
options.stencil
options.drawBuffers
=[]
- An array of color values, with indices matching the buffers selected by drawBuffers
argument.Notes:
clear
.clear
.Signals to the GL that it need not preserve the pixels of a specified region of the framebuffer (by default all pixels of the specified framebuffer attachments are invalidated).
Parameters
This function makes calls to the following WebGL APIs:
gl.invalidateFramebuffer
, gl.invalidateSubFramebuffer
, gl.bindFramebuffer
GL.MAX_COLOR_ATTACHMENTS
- The maximum number of color attachments supported. Can be 0
in WebGL 1.GL.MAX_DRAW_BUFFERS
- The maximum number of draw buffers supported. Can be 0
in WebGL 1, which means that gl_FragData[]
is not available in shaders.It is possible that you can have a certain number of attachments, but you can't draw to all of them at the same time.
Attachment Point | Description |
---|---|
GL.COLOR_ATTACHMENT0 | Attaches the texture to one of the framebuffer's color buffers |
GL.COLOR_ATTACHMENT {1-15} | Attaches the texture to one of the framebuffer's color buffers |
GL.DEPTH_ATTACHMENT | Attaches the texture to the framebuffer's depth buffer |
GL.STENCIL_ATTACHMENT | Attaches the texture to the framebuffer's stencil buffer |
GL.DEPTH_STENCIL_ATTACHMENT | Combined depth and stencil buffer |
The attachment point GL.BACK
refersn to the default framebuffer's back buffer.
The set of available attachments is larger in WebGL 2, and also the extensions WEBGL_draw_buffers
and WEBGL_depth_texture
provide additional attachments that match or exceed the WebGL 2 set.
The following values can be provided for each attachment point
null
- unattaches any current bindingRenderbuffer
- attaches the Renderbuffer
Texture2D
- attaches at mipmapLevel 0 of the supplied Texture2D
.Texture2D
, 0, mipmapLevel] - attaches the specified mipmapLevel from the supplied Texture2D
(WebGL 2), or cubemap face. The second element in the array must be 0
. In WebGL 1, mipmapLevel must be 0.TextureCube
, face (Number), mipmapLevel=0 (Number)] - attaches the specifed cubemap face from the Texture
, at the specified mipmap level. In WebGL 1, mipmapLevel must be 0.Texture2DArray
, layer (Number), mipmapLevel=0 (Number)] - attaches the specifed layer from the Texture2DArray
, at the specified mipmap level.Texture3D
, layer (Number), mipmapLevel=0 (Number)] - attaches the specifed layer from the Texture3D
, at the specified mipmap level.