Framebuffer Beginner's Guide
WebGL Framebuffer with Texture Color Attachment
Introduction
This tutorial provides a short beginner's guide to WebGL framebuffers. The tutorial explains steps required to render to the framebuffer, then display the framebuffer. Steps display code where needed. See the Framebuffer Beginner's Guide Source Code for more details.
The
WebGL Simple Framebuffer
example renders random colors to a texture along with an interactive square.
The example uses a framebuffer with one texture
color attachment.
The random colors and interactive square are rendered to a framebuffer.
After rendering, the scene is displayed over a larger square quad
.
This example uses one technique to keep it simple.
The code re-uses the same square quad Vertex Buffer Object(VBO).
This framebuffer tutorial covers the following eight steps. First initialize the interactive square. Second upload the Vertex Buffer Object (VBO). Third create a framebuffer. Fourth create a framebuffer texture. Fifth move the square backward to appear small. Sixth Render to the framebuffer. Seventh move the square forward to fill the viewport. Last Render the framebuffer.
Overview
Essentially a framebuffer is simply an invisible rendering surface. The software developer renders to the framebuffer surface, then displays the surface to the visible canvas.
The WebGL Simple Framebuffer example renders a texture which includes a random colored background, plus a texture mapped square. The square moves interactively. Rendering to the framebuffer applies both the square and the random colored background to the framebuffer.
The entire rendered texture is mapped to a large square or quad
,
then
displayed to the canvas.
See random background colors
and the texture mapped to a small interactive
square in the center.
Advantages
Framebuffers offer many advantages including the ability to add visual effects with post processing. Post processing provides the ability to add VFX effects such as blur and contrast.
Steps to Render a Framebuffer
- Initialize Interactive Square
- Upload the Vertex Buffer Object
- Create a Framebuffer
- Create a Framebuffer Texture
- Move Square Backward (Small Appearance)
- Render to the Framebuffer
- Move Square Forward (Fill the Viewport)
- Render the Framebuffer
First initialize the interactive square for the scene.
The following listing creates a square with the colored
texture map.
Class
Square
is simply a square flat
plane with texels which map the square from edge
to edge.
You may download the Square.js model.
Square
includes the number of elements and
an array of elements to draw.
The array includes interleaved vertices and texels.
The line new GLEntity(s,0)
creates an entity which downloads and initiliazes a texture.
The string s
is a path to the
image for the texture.
The value 0
indicates this texture
uses texture unit 0
.
var shapes = new Square(); var aIm = new Array(); var e = new GLEntity( s, 0 ); e.nOffset = Number( shapes.aOffset[0] ); e.nCount = Number( shapes.aCount[0] ); aIm.push( e );
Second create a controller which uploads the vertex buffer object (VBO) with interleaved vertices and texels for the square.
Create a Framebuffer
Third create and save a framebuffer.
The following listing creates a framebuffer,
assigns the framebuffer to a
property of glUtils
,
and sets the state of the buffer
as a FRAMEBUFFER
.
Keep a reference to
the framebuffer somewhere.
Save a reference to
the framebuffer for rendering later.
glUtils.fb = gl.createFramebuffer(); gl.bindFramebuffer( gl.FRAMEBUFFER, glUtils.fb );
You might want to verify the framebuffer
initialized without errors.
To do so call the WebGLContext
method checkFrameBufferStatus()
,
which returns a set of constant error codes.
Fourth create a texture
for use with the framebuffer. The texture processes
RGBA
color values.
The texture unit equals 3
.
The texture size equals 512 x 512
.
glUtils.fbTex = gl.createTexture(); gl.activeTexture ( gl.TEXTURE3 ); gl.bindTexture( gl.TEXTURE_2D, glUtils.fbTex ); gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 512, 512, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glUtils.fbTex, null );
Render
Now everything's ready to render! This simple example renders a square, then uses the same VBO to render a square quad framebuffer to the screen. Both examples use the same square. Move the square away from the viewport and render the interactive textured square to the framebuffer. Next move the square toward the viewport and render the framebuffer to fill the viewport.
Fifth before rendering the framebuffer, move the square backward into
the viewport.
Sixth render the square and background to the framebuffer.
The square displays at a distance from
the viewport. The textured square appears small.
The random colored background appears larger.
Render everything to the framebuffer. The rendering method assigns viewport dimensions the same as framebuffer texture dimensions. Bind the framebuffer for use.
The following listing demonstrates resizing the viewport to match the framebuffer's dimensions. The listing binds the framebuffer in preparation to render to the framebuffer.
gl.viewport( 0, 0, 512, 512 ); gl.bindFramebuffer( gl.FRAMEBUFFER, glUtils.fb );
Generate a random clear color, then clear the canvas with that random value.
gl.clearColor( Math.random(), Math.random(), Math.random(), 1 ); gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
Activate the texture applied to
the small square.
e0.uSampler
is the location
of the fragment shader's Sampler2D
.
Render the small square's
texture specified with texture unit zero.
gl.uniform1i ( e0.uSampler, 0 ); gl.activeTexture ( gl.TEXTURE0 );
Move the small square away from the viewport.
e0.matrix
represents the square's matrix.
e0.matrix[14] = -8
assigns -8
to the matrix's Z location.
The square moves into the distance after the
matrix uploads to the GPU and processes.
Call glUtils.renderInteractiveXY()
.
Class
glUtils
includes
code which rotates the square, based on user interaction.
e0.matrix[14] = -8; glUtils.renderInteractiveXY( controller, e0 );
Now the little square has rotated interactively and drawn to the framebuffer with some random colored background. All that's left is to display the framebuffer.
Assign the canvas's current dimensions
to the viewport.
Variable nDimCanvas
is the square
canvas's current dimensions.
Unbind the framebuffer with a call
to bindFramebuffer(...,null)
.
Instruct the shader's Sampler2D
to use texture unit 3
.
Remember texture unit 0
represents the small square's texture.
Texture unit 3
represents
the framebuffer's texture.
Clear the canvas with any color, since the framebuffer will fill the canvas. Perhaps there's no need to clear the canvas at all.
Seventh move the square's matrix toward the viewport
with e0.matrix[14] = -2
.
Fill the viewport with the texture mapped to the square.
Eighth
method renderQuad(...)
just draws a square flat plane which faces
the viewport.
In this case that square flat plane is
mapped with the contents of the framebuffer.
gl.viewport( 0, 0, nDimCanvas, nDimCanvas ); / Draw the rendered // texture to a square. gl.bindFramebuffer( gl.FRAMEBUFFER, null ); gl.uniform1i ( e0.uSampler, 3 ); gl.clearColor( 1, 0, 1, 1 ); gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT ); e0.matrix[14] = -2; glUtils.renderQuad( controller, e0 );
Summary
This tutorial provided a short beginner's guide to WebGL framebuffers. The tutorial explains steps required to render to the framebuffer, then display the framebuffer. Steps displayed code where needed.
The
WebGL Simple Framebuffer
example renders random colors to a texture along with an interactive square.
The example uses a framebuffer with one texture
color attachment.
The random colors and interactive square are rendered to a framebuffer.
After rendering, the scene is displayed over a larger square quad
.
This example uses one technique to keep it simple.
The code re-uses the same square quad Vertex Buffer Object(VBO).
This framebuffer tutorial covered the following eight steps. First initialize the interactive square. Second upload the Vertex Buffer Object (VBO). Third create a framebuffer. Fourth create a framebuffer texture. Fifth move the square backward to appear small. Sixth Render to the framebuffer. Seventh move the square forward to fill the viewport. Last Render the framebuffer.