luma.gl/docs/api-reference/webgl/framebuffer.md
2019-03-29 09:04:57 -07:00

16 KiB

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_ATTACHMENT_0]: new Texture(gl, {...}),
  [GL.COLOR_ATTACHMENT_1]: [new TextureCube(gl, {...}), GL.TEXTURE_CUBE_MAP_POSITIVE_X],
  [GL.COLOR_ATTACHMENT_2]: [new TextureArray2D(gl, {...}), 0],
  [GL.COLOR_ATTACHMENT_3]: [new TextureArray2D(gl, {...}), 1],
  [GL.COLOR_ATTACHMENT_4]: [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.configure({
  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
})
  • 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.NEAREST
GL.TEXTURE_MAG_FILTER GL.NEAREST
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})

  • 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).
  • texture - shortcut to the attachment in GL.COLOR_ATTACHMENT0
  • 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

update(options: Object) : Framebuffer

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

  • attachments - a map of attachments.
  • readBuffer - Buffer to be set as read buffer (WebGL2)
  • drawBuffers - Buffers to be set as draw buffers (WebGL2)
  • 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.

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.

  • width (GLint) - width of Framebuffer in pixels
  • height (GLint) - height of Framebuffer in pixels

Returns itself to enable chaining

  • Each attachment's 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.
  • If a resize happens, resize erases the current content of the attachment in question.

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)

  • attachments - a map of attachments.
  • options
    • 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 binding
  • Renderbuffer - attaches the Renderbuffer
  • Texture - attaches the Texture
  • [Texture, layer=0 (Number), mipmapLevel=0 (Number)] - attaches the specific layer from the Texture (WebGL2)

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.

  • options.color (Boolean or Array) - clears all active color buffers (any selected drawBuffers) 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:

  • The scissor box bounds the cleared region.
  • The pixel ownership test, the scissor test, dithering, and the buffer writemasks affect the operation of clear.
  • Alpha function, blend function, logical operation, stenciling, texture mapping, and depth-buffering are ignored by clear.

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

  • attachments - list of attachments to invalidate

This function makes calls to the following WebGL APIs:

gl.invalidateFramebuffer, gl.invalidateSubFramebuffer, gl.bindFramebuffer

clearBuffers (WebGL2)

Use to clear specific buffers

  • GL.COLOR - Color buffer
  • GL.DEPTH - Depth buffer
  • GL.STENCIL - Stencil buffer
  • GL.DEPTH_STENCIL - clears depth and stencil buffers (used with clearBufferfi)

gl.clearBufferfv, gl.clearBufferiv, gl.clearBufferuiv, gl.clearBufferf, gl.bindFramebuffer

| GL.COLOR_ATTACHMENT{0-15} | Attaches the texture to one of the framebuffer's color buffers |

configure (WebGL2)

  • readBuffer= (GLenum) - If supplied, sets the target color buffer for reading.

  • drawBuffers= (GLEnum[]) - If supplied, sets the first draw buffer indices to the color attachments in the supplied array.

  • Read buffers are gl.COLOR_ATTACHMENT{0-15} - Reads from one of 16 color attachment buffers.

  • readBuffer selects a color buffer as the source for pixels for subsequent calls to Framebuffer.readPixels, Framebuffer.copyToTexture, Framebuffer.blit.

Parameters: src

  • gl.BACK - Reads from the back color buffer.
  • gl.NONE - Reads from no color buffer.

drawBuffers (WebGL2 or WebGL_draw_buffers)

glDrawBuffers defines an array of buffers into which outputs from the fragment shader data will be written. If a fragment shader writes a value to one or more user defined output variables, then the value of each variable will be written into the buffer specified at a location within bufs corresponding to the location assigned to that user defined output. The draw buffer used for user defined outputs assigned to locations greater than or equal to n is implicitly set to GL_NONE and any data written to such an output is discarded.

Parameters

  • buffers (Array) - Array of GLenum specifying the buffers into which fragment colors will be written.
Value Fragment shader output is:
GL.NONE not written into any color buffer.
GL.BACK written into the back color buffer.
GL.COLOR_ATTACHMENT{0-15} : written in the nth color attachment of the current framebuffer.
  • Except for GL_NONE, a constants may not appear more than once.
  • The maximum number of draw buffers.

This function makes calls to the following WebGL APIs:

gl.drawBuffers, gl.bindFramebuffer

Limits

  • GL.MAX_COLOR_ATTACHMENTS - The maximum number of color attachments supported. Can be 0 in WebGL1.
  • GL.MAX_DRAW_BUFFERS - The maximum number of draw buffers supported. Can be 0 in WebGL1, 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.

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
  • The attachment point GL.BACK refersn to the default framebuffer's back buffer.

  • The set of available attachments is larger in WebGL2, and also the extensions WEBGL_draw_buffers and WEBGL_depth_texture provide additional attachments that match or exceed the WebGL2 set.

Framebuffer Attachment Values

The following values can be provided for each attachment point

  • null - unattaches any current binding
  • Renderbuffer - attaches the Renderbuffer
  • Texture2D - attaches at mipmapLevel 0 of the supplied Texture2D.
  • [Texture2D, 0, mipmapLevel] - attaches the specified mipmapLevel from the supplied Texture2D (WebGL2), or cubemap face. The second element in the array must be 0. In WebGL1, mipmapLevel must be 0.
  • [TextureCube, face (Number), mipmapLevel=0 (Number)] - attaches the specifed cubemap face from the Texture, at the specified mipmap level. In WebGL1, 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.

Remarks

  • In the raw WebGL API, creating a set of properly configured and matching textures and renderbuffers can require a lot of careful coding and boilerplate.
  • This is further complicated by many capabilities (such as support for multiple color buffers and various image formats) depending on WebGL extensions or WebGL versions.