9.6 KiB
Framebuffer
:::caution The luma.gl v9 API is currently in public review and may be subject to change. :::
A Framebuffer holds textures that will be used as render targets for RenderPipelines
together with additional information on how the RenderPipeline should use the various attached textures:
- one or more color textures
- optionally a depth / stencil buffer
clearColor,clearDepthandclearStenciletc fields on the various attachments.
The list of attachments cannot be changed after creation, however a Framebuffer can be "resized" causing the attachments to be resized.
Special Framebuffers can be obtained from CanvasContexts that enabled rendering directly into HTML canvases (i.e. onto the screen).
The use of framebuffers is described in detail in the Rendering Guide/
Usage
Creating a framebuffer and have it auto-create color and depth attachments
const framebuffer = device.createFramebuffer({
width: window.innerWidth,
height: window.innerHeight,
colorAttachments: [{format: 'rgb8unorm'}],
depthStencilAttachment: {format: 'depth24unorm-stencil8'}
});
Creating a framebuffer with supplied color and depth attachments
const size = {
width: window.innerWidth,
height: window.innerHeight
};
const framebuffer = device.createFramebuffer({
...size,
colorAttachments: [device.createTexture({format: 'rgb8unorm', ...size})],
depthStencilAttachment: device.createTexture({format: 'depth24unorm-stencil8', ...size})
});
Resizing a framebuffer to the size of the browser's window by resizing all attachments.
framebuffer.resize(window.innerWidth, window.innerHeight);
To render into a canvas make sure you have a CanvasContext for that HTML or offscreen canvas.
You can the obtain a Framebuffer object from the CanvasContext using canvasContext.getDefaultFramebuffer().
For the
const canvasFramebuffer = canvasContext.getDefaultFramebuffer();
const canvasRenderPass = device.beginRenderPass({framebuffer: canvasFramebuffer});
model2.draw({renderPass: screenRenderPass, ...});
Alternatively can create texture based framebuffers for off-screen rendering. Specifying a separate offscreen framebuffer for rendering:
const offScreenFramebuffer = device.createFramebuffer(...);
const offScreenRenderPass = device.beginRenderPass({framebuffer: offScreenFramebuffer});
model1.draw({renderPass: offScreenRenderPass, ...});
offScreenRenderPass.endPass();
// Textures attached offscreenFramebuffer now contain the results of the first renderpass,
// and those textures can be used as input for a second to-screen render pass
const screenRenderPass = device.getDefaultRenderPass();
model2.draw({renderPass: screenRenderPass, ...});
Types
FramebufferProps
| Property | Type | Description |
|---|---|---|
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. |
colorAttachments |
ColorAttachment|Texture[] |
Array of render target textures. |
depthStencilAttachment? |
DepthStencilAttachment|Texture[] |
Depth/stencil texture. |
ColorAttachment
Framebuffer attachments lets the user specify the textures that will be used for a RenderPass, together with some additional options for how to clear color textures.
| Property | Type | Description |
|---|---|---|
texture |
Texture |
Describes the texture subresource that will be output to for this color attachment. |
clearValue? |
number[] |
Value to clear to prior to executing the render pass. Default: [0, 0, 0, 0]. Ignored if loadOp is not "clear". |
loadOp? |
'load', 'clear' |
Load operation to perform on texture prior to executing the render pass. Default: 'clear'. |
storeOp? |
'store', 'discard' |
The store operation to perform on texture after executing the render pass. Default: 'store'. |
- Clearing can be disabled by setting
loadOp='load'however this may have a small performance cost as GPUs are optimized for clearing. - WebGL does not support setting
storeOp: 'discard'for just some attachments, it is all or nothing.
DepthStencilAttachment
Framebuffer attachments lets the user specify the depth stencil texture that will be used for a RenderPass, together with some additional options for how to clear depth and stencil buffers.
| Property | Type | Description |
|---|---|---|
texture |
Texture |
Describes the texture subresource that will be output to and read from for this depth/stencil attachment. |
depthClearValue? |
number |
Value to clear depth component to prior to executing the render pass, if depthLoadOp is "clear". 0.0-1.0. |
depthLoadOp? |
'load', 'clear' |
Load operation to perform on depth component prior to executing the render pass. Default 'clear'. |
depthStoreOp? |
'store', 'discard' |
Store operation` to perform on depth component after executing the render pass. Default 'store'. |
depthReadOnly? |
boolean |
Depth component is read only. |
stencilClearValue? |
number |
Value to clear stencil component to prior to executing the render pass, if stencilLoadOp is "clear". |
stencilLoadOp? |
'clear', 'load' |
Load operation to perform on stencil component prior to executing the render pass. Prefer clearing. |
stencilStoreOp? |
'store', 'discard' |
Store operation to perform on stencil component after executing the render pass. |
stencilReadOnly? |
boolean |
Stencil component is read only. |
- Clearing can be disabled by setting
loadOp='load'however this may have a small performance cost as GPUs are optimized for clearing. - WebGL does not support setting
storeOp: 'discard'for just some attachments, it is all or nothing.
Members
device:Device- holds a reference to theDevicethat created thisFramebuffer.handle:unknown- WebGL: holds the underlyingWebGLFramebuffer. No underlying object on WebGPU.props:FramebufferProps- holds a copy of theFramebufferPropsused to create thisBuffer.
Methods
constructor
Create with device.createFramebuffer(...). (Framebuffer is an abstract class and cannot be instantiated directly with new Framebuffer().)
An application can render into an (HTML or offscreen) canvas by obtaining a
Framebuffer object from a CanvasContext using canvasContext.getDefaultFramebuffer(). Alternatively can create texture based framebuffers for off-screen rendering.
destroy(): void
Free up any GPU resources associated with this buffer immediately (instead of waiting for garbage collection).
TBD - When destroying Framebuffer will also destroy any Texture that was created automatically during Framebuffer creation. Supplied textures will not be destroyed (but will eventually be garbage collected and destroyed).
resize(width: number, height: number): void
Framebuffer.resize(width, height)
Resizes all the Framebuffer's current attachments to the new width and height by calling resize on those attachments.
width- the new width ofFramebufferin pixelsheight- the new height ofFramebufferin pixels
Returns itself to enable chaining
Note the framebuffer.resize() method has been designed so that it can be called every frame without performance concerns. While the actual resizing of attachments can be expensive, the resize() methods checks if width or height have changed before actually resizing any attachments.
Remarks
- WebGPU:
resize()will destroy and recreate textures (meaning the the underlyingGPUTexture/GPUTextureViewhandles are no longer the same after aresize() - WebGL:
resize()will erase the current content of any attachments, but not actually create them (The underlyingWebGLTexture/WebGLRenderbufferhandles are not changed). - WebGPU: The
Framebufferclass is a pure luma.gl class as this concept does not exist natively in WebGPU (attachment information has to be provided through theGPURenderPassDescriptorcolorAttachmentsand thedepthStencilAttachmentfields every frame when a render pass is created).`. - WebGL: The
Framebufferclass wraps theWebGLFramebufferobject exists, see e.g. Framebuffer and Framebuffer Object in the OpenGL Wiki.