Drawing a cube in WebGL

Above you see a spinning cube, with faces of different colors. This is drawn with WebGL. The vertex shader accepts one uniform parameter, a transformation matrix:

uniform mat4 transformation;
attribute vec4 coord;
void main(void) {
  gl_Position = transformation * coord;
}

To draw the six faces of the cube, I only define the vertices for the “front” face:

const vertBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
 -0.5, -0.5, 0.5, 1,
  0.5, -0.5, 0.5, 1,
  0.5,  0.5, 0.5, 1,
 -0.5,  0.5, 0.5, 1,
]), gl.STATIC_DRAW);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0,1,2,3]), gl.STATIC_DRAW);

To draw the other five faces of the cube, I rotate the “front” face into the desired position. I do this in JavaScript using a library called glMatrix, which provides functions mat4.rotateX(out, in, angle).

function rotateX(ang) { const mat = mat4.create(); return mat4.rotateX(mat, mat, ang); }
function rotateY(ang) { const mat = mat4.create(); return mat4.rotateY(mat, mat, ang); }
const faces = [
  { color: new Float32Array([0,0,0,1]), transformation: mat4.create() },
  { color: new Float32Array([0,0,1,1]), transformation: rotateX(Math.PI * 1/2) },
  { color: new Float32Array([0,1,0,1]), transformation: rotateX(Math.PI) },
  { color: new Float32Array([0,1,1,1]), transformation: rotateX(Math.PI * 3/2) },
  { color: new Float32Array([1,0,0,1]), transformation: rotateY(Math.PI * 1/2) },
  { color: new Float32Array([1,0,1,1]), transformation: rotateY(Math.PI * 3/2) },
];

const startTime = new Date().getTime();
function redraw() {
  const t = (new Date().getTime() - startTime) / 1000;
  const timeTrans = mat4.create();
  mat4.rotateX(timeTrans, timeTrans, t);
  mat4.rotateY(timeTrans, timeTrans, t/2);
  mat4.rotateZ(timeTrans, timeTrans, t*2);
  gl.clear(gl.COLOR_BUFFER_BIT);
  for (let face of faces) {
    const trans = mat4.create();
    mat4.multiply(trans, timeTrans, face.transformation);
    gl.uniformMatrix4fv(transformationLoc, false, trans);
    gl.uniform4fv(faceColorLoc, face.color);
    gl.drawElements(gl.TRIANGLE_FAN, 4, gl.UNSIGNED_BYTE, 0);
  }
  window.requestAnimationFrame(redraw);
}
Tagged #programming, #graphics, #webgl.
👋 I'm Jim, a full-stack product engineer. Want to build an amazing product and a profitable business? Read more about me or Get in touch!

More by Jim

This page copyright James Fisher 2017. Content is not associated with my employer. Found an error? Edit this page.