The rendering section describes what happens every time a new frame of animation is rendered. This will occur every time the user clicks and drags within the canvas

First, we compose matrices for the persective, view, and model transformations. The textbook's matrix library helps. This example chooses a field-of-view of 45°, an aspect ratio of 1, and a depth range from 1 to 10.

〈Rendering〉 ≡
  function draw()
    projectionMatrix ← perspective(45, 1, 1, 10);
    viewMatrix ← translation(0, 0, -5);
    modelMatrix ← rotation(modelRotationX, 1, 0, 0)
      · rotation(modelRotationY, 0, 1, 0)

These are delivered to the vertex shader via the uniforms we configured.

    gl.uniformMatrix4fv(projectionMatrixLocation, false, projectionMatrix)
    gl.uniformMatrix4fv(viewMatrixLocation, false, viewMatrix)
    gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix)

Finally, having finished with the uniforms, move on to configure the attributes. Each of the array buffers contains a list of 3-component floating point vectors.

    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
    gl.vertexAttribPointer(vertexPositionLocation, 3, gl.FLOAT, false, 0, 0)

    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
    gl.vertexAttribPointer(vertexColorLocation, 3, gl.FLOAT, false, 0, 0)

With all configuration in place, we can finally render. Begin by clearing the screen, make sure the depth test is enabled, and finish by drawing the contents of the triangle element buffer.

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

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleBuffer)
    gl.drawElements(gl.TRIANGLES, triangleArray.length, gl.UNSIGNED_SHORT, 0)