Library / SDK
toji/gl-matrix avatar
toji/gl-matrix

gl-matrix: JavaScript vector and matrix math for WebGL, without the allocation churn

Javascript Matrix and Vector library for High Performance WebGL apps

5,696 stars728 forksJavaScriptMIT

At a glance

What is it?
gl-matrix is a pure JavaScript math library for WebGL and physics work, shipped as ES modules and a UMD bundle under MIT. It is fast because every function writes into an output you pass in, which is also the reason it feels awkward the first hour.
Who is it for?
Adopt gl-matrix if you are writing WebGL, WebGPU-adjacent, or physics code in JavaScript and you are willing to manage output arrays yourself; the whole API is built around that contract. Do not adopt it if you want operator overloading, immutable value semantics, or a scene graph, because it deliberately has none of those.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 79 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap gl-matrix fills: realtime 3D math that JavaScript does not ship

JavaScript has no built-in vector or matrix type. The README states the motivation plainly: WebGL and physics simulations demand high performance vector and matrix math, which JavaScript does not provide by default. Without a library you end up writing your own 4x4 multiply, your own quaternion slerp, and your own perspective projection, and getting the row-major versus column-major convention wrong somewhere around the third file.

gl-matrix is aimed at people building WebGL renderers, physics simulations, and anything else where a mat4 gets multiplied thousands of times per frame. It is not a scene graph, not a math expression parser, and not a replacement for a full 3D engine. It is the arithmetic layer you would otherwise hand-roll.

The design bet is that the cost that matters is allocation, not arithmetic. Garbage collection pauses during a frame are visible; a few extra floating point multiplies are not. Every function in the library is shaped by that bet.

Why every function takes an out parameter, and what that costs you

The API convention is that operations write their result into an array you supply rather than returning a new one. That is the mechanism behind the performance claim, and it is also the sharpest edge for newcomers.

A typical call follows the same shape as the README's usage pattern: you allocate a mat4 once, then repeatedly pass it as the destination. Because the destination is explicit, you can also use the same array as both an input and an output in many operations, which avoids a temporary. The library encourages this through its conventions rather than through documentation of each case.

The cost is aliasing bugs. If you pass the same array as input and output where the operation does not support it, you get wrong numbers rather than an exception. There is no defensive copy and no runtime check. Teams coming from a value-semantics library such as a typical immutable math package will find this the hardest adjustment; the reward is that a render loop can run with essentially zero per-frame garbage from math.

There is a second, less obvious cost. Because results are written in place, code that reads naturally as a formula becomes a sequence of statements with pre-declared temporaries. That is a readability tax paid on every function, in exchange for predictable frame times.

Installing gl-matrix and wiring up a mat4

The package is published to npm as gl-matrix. The version in package.json is 3.4.4, and the package is declared as type module with sideEffects false, so bundlers can tree-shake unused modules. The README's Building section points at BUILDING.md for the build scripts, and the package.json scripts list build-umd, build-esm and build-dts separately.

bash
npm install gl-matrix

After install, the entry points are declared in the exports map. Importing the bare package name resolves to ./dist/esm/index.js, which pulls in the whole set. Importing a subpath such as gl-matrix/mat4 or gl-matrix/vec3 resolves to that single module, which is what you want in a renderer that only needs one or two types.

The README does not include a usage example, so the shape of a call is best read from the exports map and the module list rather than from a snippet. What matters is the contract: you create the destination array once and pass it in on every call. Nothing in the library allocates for you after that.

The exports map exposes ./common, ./mat2, ./mat2d, ./mat3, ./mat4, ./quat, ./quat2, ./vec2, ./vec3 and ./vec4 as separate entry points. The package ships TypeScript declarations at ./dist/index.d.ts, so the types come along with the install rather than from DefinitelyTyped.

Float32Array versus Array: the README's own performance caveat

The default array type is Float32Array, which is the right storage for data headed to a WebGL buffer. It is also, per the README, not always the fastest choice for the math itself.

The README states that regarding current performance in modern web browsers, calling glMatrix.setMatrixArrayType(Array) to use normal arrays instead of Float32Arrays can greatly increase the performance. That is a notable admission from a library whose pitch is speed. It means the default is a compromise between GPU upload convenience and CPU arithmetic speed, and the library authors are telling you to measure rather than assume.

Switching has a consequence the README does not spell out: plain Array values are doubles, so anything you hand to gl.bufferData as Float32Array-backed data needs a conversion step you did not need before. The switch is a global setting, not per-object, so you cannot mix the two styles in one process without care.

If you take one thing from the documentation, take this: the default configuration is not automatically the fast configuration on your target browser. Profile before you decide.

Where gl-matrix is the wrong tool

gl-matrix has no error handling to speak of. Pass a vec3 where a vec4 is expected and you get silently wrong numbers, because the functions index into the arrays by position. There is no length check, no type check, and no shape metadata. In a codebase with many contributors and long-lived math state, that is a real failure mode, and it is the reason some teams wrap the library in their own typed layer.

It is also the wrong choice if you want the math to be part of a larger scene abstraction. gl-matrix gives you mat4 and vec3 and stops. If your project needs nodes, transforms propagated down a hierarchy, frustum culling, or an animation system, you will be building all of that on top, and a full 3D engine will get you there faster even if its math layer is slower per call.

Finally, if your math is not on a hot path, the out-parameter convention is pure overhead. A form-heavy page that computes one projection matrix on resize gains nothing from gl-matrix's allocation discipline and pays for it in code verbosity. The library is optimized for a problem you may not have.

How it compares to three.js's math classes

The most common alternative in practice is the math layer inside three.js, where Vector3 and Matrix4 are classes with methods that return this or a new instance depending on the method. That is a genuinely different approach to the same problem.

In three.js, matrix.multiplyMatrices(a, b) mutates the receiver, so the object identity is the state. In gl-matrix, the destination array is named explicitly as an argument, so the array is just storage. The three.js style reads better and composes with the rest of the engine; the gl-matrix style is easier to reason about when you want to keep a pool of arrays and never allocate.

Three.js also carries the Object3D graph, materials, and renderer. Adopting it for math alone means pulling in a much larger dependency. If you already use three.js, its math classes are the path of least resistance and gl-matrix adds little. If you are writing a custom WebGL renderer with no engine, gl-matrix is the smaller and more direct dependency, and its exports map lets you import only mat4 if that is all you need.

Maintenance, licence, and the build you actually ship

The repository is not archived, and the last push was on 2026-07-13. The most recent release listed is v3.4.4 from 2025-08-08, following v3.4.1 in 2021 and v3.3.0 in 2020. The release cadence is slow and the version numbers between v3.4.1 and v3.4.4 suggest patch-level work rather than new surface area. Treat this as a stable, quiet library rather than one that is changing under you, and plan upgrades accordingly: there is little to gain from tracking every patch, and little risk in staying on an older one for a while.

The licence is MIT, declared in package.json and shipped as LICENSE.md. That permits commercial use and modification with attribution, but it is a permissive grant with no patent language and no warranty. If your organisation has a policy about patent grants in dependencies, that is the clause to check with your own counsel, not something this article can settle.

One practical upgrade cost: the package is type module with an exports map and no CommonJS main beyond the ESM entry. The scripts list a build-umd target for the UMD bundle, so that build is the fallback for projects that cannot consume the ESM output. Check which file your toolchain resolves before assuming an upgrade is a one-line version bump.

Editorial conclusion

Adopt gl-matrix if you are writing WebGL, WebGPU-adjacent, or physics code in JavaScript and you are willing to manage output arrays yourself; the whole API is built around that contract. Do not adopt it if you want operator overloading, immutable value semantics, or a scene graph, because it deliberately has none of those. Before committing, verify which build your bundler resolves from the exports map in package.json, and check whether Float32Array is actually the faster path in your target browser, since the README states that calling glMatrix.setMatrixArrayType(Array) can greatly increase performance on modern engines.

Frequently asked questions

How do you use gl-matrix in a WebGL project?

Install it from npm and import the submodules you need, such as gl-matrix/mat4 or gl-matrix/vec3, which are declared as separate entry points in the exports map. Each operation writes into an output array you supply, so a render loop can run without allocating new arrays per frame.

What is the gl-matrix library?

It is a JavaScript matrix and vector library for high performance WebGL apps, according to the repository description. It provides mat2, mat2d, mat3, mat4, quat, quat2, vec2, vec3 and vec4 modules as separate entry points.

Does gl-matrix ship TypeScript types?

Yes. package.json declares types at ./dist/index.d.ts, and the build includes a build-dts script that emits declarations from the source. You do not need a separate @types package.

Is gl-matrix still maintained?

The repository is not archived and the last push was on 2026-07-13. Releases are infrequent: v3.4.4 was published on 2025-08-08, after v3.4.1 in 2021.

Can gl-matrix use plain arrays instead of Float32Array?

Yes. The README states that calling glMatrix.setMatrixArrayType(Array) to use normal arrays instead of Float32Arrays can greatly increase performance in modern web browsers. Note that plain arrays hold doubles, so data headed to a WebGL buffer may need conversion.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. toji/gl-matrix on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/toji-gl-matrix.svg)](https://hysenlabs.com/projects/toji-gl-matrix)