Changed around line 1
+ const canvas = document.getElementById('webgl-canvas');
+ const gl = canvas.getContext('webgl');
+
+ if (!gl) {
+ console.error('WebGL not supported, falling back on experimental-webgl');
+ gl = canvas.getContext('experimental-webgl');
+ }
+
+ if (!gl) {
+ alert('Your browser does not support WebGL');
+ }
+
+ const vertexShaderSource = `
+ attribute vec4 a_position;
+ uniform mat4 u_matrix;
+ void main() {
+ gl_Position = u_matrix * a_position;
+ }
+ `;
+
+ const fragmentShaderSource = `
+ precision mediump float;
+ uniform vec4 u_color;
+ void main() {
+ gl_FragColor = u_color;
+ }
+ `;
+
+ const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
+ const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
+ const program = createProgram(gl, vertexShader, fragmentShader);
+
+ const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
+ const matrixUniformLocation = gl.getUniformLocation(program, 'u_matrix');
+ const colorUniformLocation = gl.getUniformLocation(program, 'u_color');
+
+ const positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ setGeometry(gl);
+
+ gl.useProgram(program);
+ gl.enableVertexAttribArray(positionAttributeLocation);
+ gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
+
+ let mouseX = 0;
+ let mouseY = 0;
+
+ canvas.addEventListener('mousemove', (event) => {
+ mouseX = event.clientX / canvas.width * 2 - 1;
+ mouseY = -(event.clientY / canvas.height * 2 - 1);
+ });
+
+ function render() {
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ const rotationX = mouseY * Math.PI;
+ const rotationY = mouseX * Math.PI;
+
+ const matrix = m4.xRotation(rotationX);
+ m4.yRotate(matrix, rotationY, matrix);
+
+ gl.uniformMatrix4fv(matrixUniformLocation, false, matrix);
+
+ gl.uniform4fv(colorUniformLocation, [1, 0, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ gl.uniform4fv(colorUniformLocation, [0, 1, 0, 1]);
+ gl.drawArrays(gl.TRIANGLES, 6, 6);
+
+ gl.uniform4fv(colorUniformLocation, [0, 0, 1, 1]);
+ gl.drawArrays(gl.TRIANGLES, 12, 6);
+
+ requestAnimationFrame(render);
+ }
+
+ render();
+
+ function createShader(gl, type, source) {
+ const shader = gl.createShader(type);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+ console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
+ gl.deleteShader(shader);
+ return null;
+ }
+ return shader;
+ }
+
+ function createProgram(gl, vertexShader, fragmentShader) {
+ const program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+ console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(program));
+ return null;
+ }
+ return program;
+ }
+
+ function setGeometry(gl) {
+ const positions = new Float32Array([
+ // Front face
+ -0.5, -0.5, 0.5,
+ 0.5, -0.5, 0.5,
+ 0.5, 0.5, 0.5,
+ -0.5, -0.5, 0.5,
+ 0.5, 0.5, 0.5,
+ -0.5, 0.5, 0.5,
+
+ // Back face
+ -0.5, -0.5, -0.5,
+ 0.5, -0.5, -0.5,
+ 0.5, 0.5, -0.5,
+ -0.5, -0.5, -0.5,
+ 0.5, 0.5, -0.5,
+ -0.5, 0.5, -0.5,
+
+ // Left face
+ -0.5, -0.5, -0.5,
+ -0.5, -0.5, 0.5,
+ -0.5, 0.5, 0.5,
+ -0.5, -0.5, -0.5,
+ -0.5, 0.5, 0.5,
+ -0.5, 0.5, -0.5,
+
+ // Right face
+ 0.5, -0.5, -0.5,
+ 0.5, -0.5, 0.5,
+ 0.5, 0.5, 0.5,
+ 0.5, -0.5, -0.5,
+ 0.5, 0.5, 0.5,
+ 0.5, 0.5, -0.5,
+
+ // Top face
+ -0.5, 0.5, -0.5,
+ 0.5, 0.5, -0.5,
+ 0.5, 0.5, 0.5,
+ -0.5, 0.5, -0.5,
+ 0.5, 0.5, 0.5,
+ -0.5, 0.5, 0.5,
+
+ // Bottom face
+ -0.5, -0.5, -0.5,
+ 0.5, -0.5, -0.5,
+ 0.5, -0.5, 0.5,
+ -0.5, -0.5, -0.5,
+ 0.5, -0.5, 0.5,
+ -0.5, -0.5, 0.5,
+ ]);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ }
+
+ const m4 = {
+ xRotation: function(angleInRadians) {
+ const c = Math.cos(angleInRadians);
+ const s = Math.sin(angleInRadians);
+ return [
+ 1, 0, 0, 0,
+ 0, c, s, 0,
+ 0, -s, c, 0,
+ 0, 0, 0, 1
+ ];
+ },
+ yRotate: function(m, angleInRadians, dst) {
+ const c = Math.cos(angleInRadians);
+ const s = Math.sin(angleInRadians);
+ const m00 = m[0 * 4 + 0];
+ const m01 = m[0 * 4 + 1];
+ const m02 = m[0 * 4 + 2];
+ const m03 = m[0 * 4 + 3];
+ const m20 = m[2 * 4 + 0];
+ const m21 = m[2 * 4 + 1];
+ const m22 = m[2 * 4 + 2];
+ const m23 = m[2 * 4 + 3];
+ dst = dst || new Float32Array(16);
+ dst[0] = c * m00 + s * m20;
+ dst[1] = c * m01 + s * m21;
+ dst[2] = c * m02 + s * m22;
+ dst[3] = c * m03 + s * m23;
+ dst[8] = c * m20 - s * m00;
+ dst[9] = c * m21 - s * m01;
+ dst[10] = c * m22 - s * m02;
+ dst[11] = c * m23 - s * m03;
+ if (m !== dst) {
+ dst[4] = m[4];
+ dst[5] = m[5];
+ dst[6] = m[6];
+ dst[7] = m[7];
+ dst[12] = m[12];
+ dst[13] = m[13];
+ dst[14] = m[14];
+ dst[15] = m[15];
+ }
+ return dst;
+ }
+ };