luma.gl

Framebuffer

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 Textures and Renderbuffers.

For additional information, see OpenGL Wiki Framebuffer and Framebuffer Object

Functionality

luma.gl adds

Usage

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

Reading, copying or blitting data from a Framebuffer attachment.

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 (WebGL2), check blit

Using Multiple Render Targets

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 (WebGL2)

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

Methods

constructor(gl : WebGLRenderingContext, props : Object)

Creates a new framebuffer, optionally creating and attaching Texture and Renderbuffer attachments.

new Framebuffer(gl, {
  id,
  width,
  height,
  attachments,
  color,
  depth,
  stencil
})

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.

delete()

Destroys the underlying WebGL object. When destroying Framebuffers it can be important to consider that a Framebuffer can manage other objects that may also need to be destroyed.

initialize(props : Object) : Framebuffer

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

update(options: Object) : Framebuffer

Updates Framebuffers attachments using provided Texture and Renderbuffer objects. Optionally sets read and draw buffers when using WebGL2 context.

resize({width: Number, height: Number}) : Framebuffer

Framebuffer.resize({width, height})

Resizes all the Framebuffer’s current attachments to the new width and height by calling resize on those attachments.

Returns itself to enable chaining

WebGL References see initialize.

attach(attachments : Object, options: Object) : Framebuffer

Used to attach or unattach Textures and Renderbuffers from the Framebuffers various attachment points.

Framebuffer.attach(attachments)

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

This function makes calls to the following WebGL APIs:

gl.framebufferRenderbuffer, gl.bindFramebuffer, gl.framebufferTexture2D, gl.bindFramebuffer, gl.framebufferTextureLayer, gl.bindFramebuffer (This is for WebGL2 only)

checkStatus() : Framebuffer

Check that the framebuffer contains a valid combination of attachments

gl.checkFramebufferStatus, gl.bindFramebuffer

clear(options: Object) : Framebuffer

Clears the contents (pixels) of the framebuffer attachments.

Notes:

invalidate (WebGL2)

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

Limits

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.

Framebuffer Parameters

Framebuffer Attachment Points

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

Framebuffer Attachment Values

The following values can be provided for each attachment point

Remarks