WebGL Essentials

Clearing 3D Canvas

After a Web application has successfully created a valid WebGL context, it can start rendering. The first stage is the clearing of the buffers: the application clears the canvas to a certain color and specifies a depth value for each pixel on the drawing surface. If stenciling is enabled, the stencil buffer is cleared, too.

The initial values for the color buffer are declared by the clearColor() method:

gl.clearColor(0.0, 0.0, 0.0, 1.0);

The code line above clears the canvas to the opaque black. Each of the color components is clamped to [0, 1]: 0 denotes the minimum intensity of the color, and 1 sets the maximum.

The way of using CSS colors in a WebGL application is rather straightforward: 8 bits are used for each component, so it can be represented as an integer between 0 and 255 (28 = 256); integers from the [0, 255] range correspond to GLclampf values of [0/255, 255/255]. As a result, such CSS color as cornflowerblue (R = 100, G = 149, B = 237) can be passed to the clearing routine as

gl.clearColor(100/255, 149/255, 237/255, 1.0);

The number of distinct colors available to a WebGL application depends on the number of bits used for encoding red, green and blue components. As WebGL uses 8 bits per component, the canvas is able to display up to 16,777,216 colors.

Clearing the depth buffer is a preliminary step for the depth test: WebGL will render only those fragments that are not obscured by other three-dimensional objects. For initialization, the buffer should be filled with a value that as far from the viewer as possible:

gl.clearDepth(1.0);

Depth values of any incoming fragments will be compared with the value stored in the buffer. A comparison function is declared by another WebGL command:

gl.depthFunc(gl.LEQUAL);

The depthFunc() method of the WebGL context can accept one of eight parameters. These are

  • GL_ALWAYS: the depth test always passes;
  • GL_EQUAL: the test passes if the incoming depth value is equal to the stored depth value;
  • GL_GEQUAL: the test passes if the incoming value is greater than or equal to the stored value;
  • GL_GREATER: the test passes if the incoming value is greater than the stored value;
  • GL_LEQUAL: the test passes if the incoming value is less than or equal to the stored value;
  • GL_LESS: the test passes if the incoming value is less than the stored value; this is the default comparison function;
  • GL_NEVER: the depth test never passes;
  • GL_NOTEQUAL: the test passes if the incoming value is not equal to the stored value.

Depth testing is disabled by default:

// the method returns false
gl.isEnabled(gl.DEPTH_TEST);

The enable() method of the WebGLRenderingContext switches on comparison of depth values:

gl.enable(gl.DEPTH_TEST);

Let's summarize. Both context creation and clearing can be listed as

var canvas = document.querySelector('canvas');
var gl = canvas.getContext('webgl');

// clearing the canvas to CSS crimson
gl.clearColor(220/255, 20/255, 60/255, 1.0);

gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);

gl.clear(gl.COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);

The last command performs real clearing to the values declared earlier. Buffers to be cleared are shown as a result of the bitwise OR operation.

WebGL Errors

Before proceeding further in exploring 3D graphics on the Web, we should say a few words about WebGL errors handling. OpenGL detects just a subset of error conditions: a thorough error checking can drastically reduce performance in error-free applications. Values returned by the getError() method of the WebGLRenderingContext are

  • INVALID_ENUM: an unacceptable value for an enumerated argument;
  • INVALID_FRAMEBUFFER_OPERATION: framebuffer is incomplete;
  • INVALID_OPERATION: the specified operation is not allowed in the current state;
  • INVALID_VALUE: a numeric argument is out of range;
  • NO_ERROR: no error has been recorded;
  • OUT_OF_MEMORY: not enough memory left to execute the command.

The example below performs a boolean comparison to obtain error information:

console.log(gl.getError() == gl.NO_ERROR);

Commands that have generated INVALID_ENUM, INVALID_OPERATION and INVALID_VALUE errors are ignored by WebGL.