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:
npm install gl-matrix@3.4.4Without 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:
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);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.
<!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>