wgpu-matrix 481 (greggman/wgpu-matrix (https://github.com/greggman/wgpu-matrix 481 ), MIT, 3.4.2) is gl-matrix 5,695 's counterpart for WebGPU (WebGL used gl-matrix 3.4.4): mat4, vec3, quat and friends, returning Float32Arrays ready for writeBuffer(). Two differences matter. Functions return a new array unless you pass a destination last (gl-matrix takes the output first), and its projections map depth to WebGPU's 0 to 1:
<script type="module">
import { mat4, vec3 } from 'https://cdn.jsdelivr.net/npm/wgpu-matrix@3.4.2/+esm';
import * as glm from 'https://cdn.jsdelivr.net/npm/gl-matrix@3.4.4/+esm'; // Chapter 3's
const near = [0, 0, -0.5], far = [0, 0, -20]; // points on the near and far planes
const projection = mat4.perspective(Math.PI / 4, 16 / 9, 0.5, 20); // returns a Float32Array
const glProjection = glm.mat4.perspective(glm.mat4.create(), Math.PI / 4, 16 / 9, 0.5, 20);
const z = (p, m) => vec3.transformMat4(p, m)[2].toFixed(3); // divides by w too
console.log('wgpu-matrix depth, near to far:', z(near, projection), 'to', z(far, projection));
console.log('gl-matrix depth, near to far:', z(near, glProjection), 'to', z(far, glProjection));
const viewProjection = mat4.multiply(projection, mat4.lookAt([0, 1, 4], [0, 0, 0], [0, 1, 0]));
console.log('origin in clip space:', [...vec3.transformMat4([0, 0, 0], viewProjection)]
.map((v) => v.toFixed(3)).join(', '));
window.__done = true;
</script>wgpu-matrix depth, near to far: 0.000 to 1.000 gl-matrix depth, near to far: -1.000 to 1.000 origin in clip space: 0.000, 0.000, 0.901
gl-matrix's perspective() produces OpenGL's -1 to 1, so in WebGPU the near part of the frustum, mapped below 0, would be clipped away; gl-matrix does offer perspectiveZO() for 0 to 1, which is the fix when you keep it for a port. For new WebGPU code, wgpu-matrix removes that trap, and it is small and dependency-free.