All Lessons
Lesson 2

Animating with WebGL

Code

const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

const vsSource = `
  attribute vec4 aVertexPosition;
  attribute vec4 aVertexColor;
  uniform float uRotation;
  varying lowp vec4 vColor;
  
  void main() {
    float c = cos(uRotation);
    float s = sin(uRotation);
    mat2 rotation = mat2(c, s, -s, c);
    vec2 rotated = rotation * aVertexPosition.xy;
    gl_Position = vec4(rotated, 0.0, 1.0);
    vColor = aVertexColor;
  }
`;

const fsSource = `
  varying lowp vec4 vColor;
  void main() {
    gl_FragColor = vColor;
  }
`;

function initShaderProgram(gl, vsSource, fsSource) {
  const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
  const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
  const shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  return shaderProgram;
}

function loadShader(gl, type, source) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  return shader;
}

const positions = [0.0, 0.5, -0.5, -0.5, 0.5, -0.5];
const colors = [1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0];

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
const vertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
const vertexColor = gl.getAttribLocation(shaderProgram, 'aVertexColor');
const rotationUniform = gl.getUniformLocation(shaderProgram, 'uRotation');

let rotation = 0;

function render() {
  rotation += 0.02;
  
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  gl.vertexAttribPointer(vertexPosition, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(vertexPosition);
  
  gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
  gl.vertexAttribPointer(vertexColor, 4, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(vertexColor);
  
  gl.useProgram(shaderProgram);
  gl.uniform1f(rotationUniform, rotation);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
  
  requestAnimationFrame(render);
}

render();

Preview