Installing gl-matrix

Installing and Importing gl-matrix

With a bundler such as Vite 25,978 (MERN Stack Development), install the package and import what you need; 3.4.4 ships ES modules, CommonJS and TypeScript declarations, and is marked side-effect free, so unused modules are tree-shaken away:

Installing gl-matrixShell
npm install gl-matrix@3.4.4

Without a build step, a page can import the ES modules straight from jsDelivr 15,886 , or load the UMD build with a classic <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.4.4/gl-matrix-min.js 306 "> tag (52,745 bytes), which defines one global, glMatrix 5,695 , holding mat4, vec3 and the rest; this chapter uses that tag. Either way you get the same functions:

Importing gl-matrix as an ES module and checking its defaultsJavaScript
import { glMatrix, mat4 } from 'https://cdn.jsdelivr.net/npm/gl-matrix@3.4.4/esm/index.js';
const m = mat4.create();
console.log(m.constructor.name, m.length, JSON.stringify([...m]));
console.log(glMatrix.toRadian(180), glMatrix.EPSILON, glMatrix.ANGLE_ORDER);
Output
Float32Array 16 [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
3.141592653589793 0.000001 zyx

create() returns a column-major identity Float32Array, ready for uniformMatrix4fv(). In the UMD build the settings object is glMatrix.glMatrix. Angles are in radians except in quat.fromEuler() and perspectiveFromFieldOfView(), which take degrees.

gl-matrix imported as an ES module from jsDelivr, spinning a book with mat4HTMLLive
<!doctype html>
<style>
  body { margin: 0; font: 11px system-ui, sans-serif; background: #f7f4ee; color: #333; }
  canvas { display: block; width: 100%; max-width: 600px; }
  pre { max-width: 600px; margin: 4px 0 0; padding: 6px 8px; background: #fff; border: 1px solid #ddd; }
</style>
<canvas id="view" width="600" height="240"></canvas>
<pre id="out"></pre>
<script type="module">
import { glMatrix, mat4 } from 'https://cdn.jsdelivr.net/npm/gl-matrix@3.4.4/esm/index.js';

const m = mat4.create();               // a column-major identity Float32Array
document.getElementById('out').textContent =
  `${m.constructor.name}(${m.length}) ${JSON.stringify([...m])}\n` +
  `toRadian(180) = ${glMatrix.toRadian(180)}   EPSILON = ${glMatrix.EPSILON}   ANGLE_ORDER = ${glMatrix.ANGLE_ORDER}`;

// A unit cube with per-vertex normals.
const faces = [[[0,0,1],[1,0,0],[0,1,0]], [[0,0,-1],[-1,0,0],[0,1,0]], [[1,0,0],[0,0,-1],[0,1,0]],
               [[-1,0,0],[0,0,1],[0,1,0]], [[0,1,0],[1,0,0],[0,0,-1]], [[0,-1,0],[1,0,0],[0,0,1]]];
const cube = [];
for (const [n, u, v] of faces)
  for (const [a, b] of [[-1,-1],[1,-1],[1,1],[-1,-1],[1,1],[-1,1]])
    cube.push(...[0, 1, 2].map(i => (n[i] + a * u[i] + b * v[i]) / 2), ...n);

const gl = document.getElementById('view').getContext('webgl2');
const program = gl.createProgram();
for (const [type, src] of [[gl.VERTEX_SHADER, `#version 300 es
layout(location = 0) in vec3 aPosition; layout(location = 1) in vec3 aNormal;
uniform mat4 uViewProjection, uModel; out float vLight;
void main() {
  vLight = 0.45 + 0.55 * max(dot(normalize(mat3(uModel) * aNormal), normalize(vec3(0.4, 0.7, 0.6))), 0.0);
  gl_Position = uViewProjection * uModel * vec4(aPosition, 1.0);
}`], [gl.FRAGMENT_SHADER, `#version 300 es
precision mediump float; in float vLight; out vec4 c;
void main() { c = vec4(vec3(0.36, 0.25, 0.6) * vLight, 1.0); }`]]) {
  const s = gl.createShader(type);
  gl.shaderSource(s, src); gl.compileShader(s);
  if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(s));
  gl.attachShader(program, s);
}
gl.linkProgram(program);
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cube), gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 24, 0); gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 24, 12); gl.enableVertexAttribArray(1);
gl.enable(gl.DEPTH_TEST);

const viewProjection = mat4.perspective(mat4.create(), glMatrix.toRadian(40), 600 / 240, 0.1, 20);  // radians
mat4.multiply(viewProjection, viewProjection, mat4.lookAt(mat4.create(), [0, 0.8, 4], [0, 0, 0], [0, 1, 0]));
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'uViewProjection'), false, viewProjection);
const uModel = gl.getUniformLocation(program, 'uModel');
const model = mat4.create();           // allocated once, rewritten every frame
function frame(ms) {
  mat4.fromYRotation(model, ms * 0.001);
  mat4.rotateX(model, model, 0.3);
  mat4.scale(model, model, [1.1, 1.6, 0.3]);
  gl.uniformMatrix4fv(uModel, false, model);
  gl.clearColor(0.97, 0.96, 0.93, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLES, 0, 36);
  requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
</script>