Framebuffer Beginner's Guide

WebGL Framebuffer with Texture Color Attachment

Framebuffer Example Background Colors Change Introduction Overview Advantages Steps Create a Framebuffer Render Summary Source Code More Framebuffer Examples

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 WebGL Post Processing Techniques. Post processing provides the ability to add visual effects such as blur and contrast.

Steps to Render a Framebuffer

  1. Initialize Interactive Square
  2. Upload the Vertex Buffer Object
  3. Create a Framebuffer
  4. Create a Framebuffer Texture
  5. Move Square Backward (Small Appearance)
  6. Render to the Framebuffer
  7. Move Square Forward (Fill the Viewport)
  8. 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. The WebGL E-Book Series explains the controller named GLControl in detail. The books aren't necessary for developers who use their own initialization code such as Three.js, Babylon.js, or Unity. The WebGL E-Book Series helps developers who want to learn WebGL from start to finish. Knowing pure WebGL improves the ability to debug and port code to other platforms such as Android 3D games and WebVR.

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 proprietary code which rotates the square based on interaction. The book WebGL Scenes includes similar code. For WebGL developers who use Three.js, Babylon.js, or Unity similar interactive code probably exists. Otherwise the e-book WebGL Scenes provides a good description of interactive WebGL movement.

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.

See more Framebuffer Examples below. Have fun and love learning!

WebGL Textures and Vertices eBook Screen Shots
Copyright © 2015 Seven Thunder Software. All Rights Reserved.