JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 27
  • Score
    100M100P100Q51641F
  • License MIT

Package Exports

  • glmaths

Readme

glmaths

Linear algebra functions for working with WebGL in TypeScript, aimed to be looking similar to GLSL code. Inspired by gl-matrix.

How to install

You can take dist/glmaths.min.js, or install with npm:

npm install glmaths

There are also dist/cjs/ and dist/esm/ builds for different import formats.

Usage Example

// from glmaths[.min].js:
const { vec3, vec4, mat4, quat } = glmaths
// from npm:
import { vec3, vec4, mat4, quat } from 'glmaths'

const vertex = vec3(2, 1, 0)
vertex.rotateX(Math.PI / 3, vec3(0.5))

const proj = mat4.perspective(Math.PI / 2, 16 / 9, 0.001, 1000)
const view = mat4.lookAt(vec3(0, 0, -10), vec3(0), vec3(0, 0, 1))
const ndc = vertex.transformMat4(proj.mult(view))

// All types extend Float32Array, so you can pass them to webgl
gl.uniformMatrix4fv(u_proj, false, proj)

Swizzles!

.xyzw, .rgba, .stpq, .uv swizzles are supported on vec2, vec3, vec4.

0 and 1 on not first symbol are also supported, f.ex: a.x0z, b.rgb1, c.uv01.

Vector packing

You can pass vector in a vector, just like in GLSL: vec4(vec2(0, 1), 2, 3)

Operator Overloading!

If you code in TypeScript, you can opt for a fork of TypeScript to enable operator overloading in code! glmaths implements functions needed to overload these operators: + - * / % == ===

const ndc = proj * view * vertex
let model = mat4()
model *= mat4.fromRotation(Math.PI / 2, vec3(0, 1, 0))
vec4(vec2(1.0, 2.0) / 2.0 + 4.0, 0.0, 1.0) + vec4(1) * vec4(4, 2, 0, 0)

With this done, it totally looks like GLSL! :D

out argument

Like gl-matrix, all functions have out argument, but it is located at the end as an optional argument:

const a = vec3(0, 1, 2)
const b = vec3(2, 3, 4)
const c = vec3()
a.plus(b, /* out = */ c)

The idea behind glmaths is to make tinkering fun — so by default every operation returns a new copy, and you can just write a.plus(b) without thinking about memory. But when you need performance, you can pre-allocate structures and pass them as out, just like you would in gl-matrix.

You can also set glmaths.ALWAYS_COPY = false to make instance methods modify the structure in place by default, skipping the copy entirely. But this can bring confusion, hence why this is not the default:

glmaths.ALWAYS_COPY = false
const a = vec3(0, 1, 2)
const b = a.plus(5)
// a.x === 5, a was modified in place

Docs

  • EPSILON = 0.000001 — used in a.equals(b) functions
  • RANDOM = Math.random — used in .random() functions
  • ANGLE_ORDER = 'zyx' — used in Quat.fromEuler
  • ALWAYS_COPY = false
  • LEFT_HANDED = false — set to true for left handed geometry, used in mat4

mat2

mat2x3

mat3

mat4

quat

quat2

vec2

vec3

vec4

mat2x3

mat3

quat

mat4

vec4

vec3

mat2

vec2

quat2

Benchmark results

You can run benchmark with npm run bench.

Suprisingly, in most operations glmaths comes faster than its simpler gl-matrix library? I honestly quite skeptical about it.

This benchmark, though, doesn't tell the difference in loading up a library. When I started running benchmarks, I noticed how on first test glmaths was consistently slower, than gl-matrix; and I believe this is a setup cost for extending Float32Array with all methods and getters for swizzles. There is a hack in bencmark.js to overcome this.

Benchmark is run with glmaths.ALWAYS_COPY = false.

Operation gl-matrix glmaths Diff
Vec3 creation 41.8M ops/s ±3.0% 40.9M ops/s ±1.5% -2%
Vec3 add 137.9M ops/s ±3.1% 193.8M ops/s ±4.6% +40%
Vec3 dot 151.6M ops/s ±3.5% 234.1M ops/s ±5.3% +54%
Vec3 cross 135.0M ops/s ±2.8% 196.2M ops/s ±3.6% +45%
Vec3 normalize 136.5M ops/s ±2.5% 207.2M ops/s ±4.0% +52%
Vec3 scale 143.2M ops/s ±4.0% 216.0M ops/s ±4.1% +51%
Vec3 length 162.0M ops/s ±3.1% 258.5M ops/s ±5.1% +60%
Vec3 distance 155.4M ops/s ±2.8% 235.8M ops/s ±5.3% +52%
Vec3 lerp 132.8M ops/s ±3.6% 192.0M ops/s ±4.3% +45%
Vec2 creation 41.8M ops/s ±1.4% 42.4M ops/s ±1.2% +2%
Vec2 add 142.5M ops/s ±3.3% 220.5M ops/s ±4.2% +55%
Vec4 add 131.1M ops/s ±2.4% 107.3M ops/s ±2.5% -18%
Vec4 normalize 127.3M ops/s ±2.2% 111.6M ops/s ±3.0% -12%
Mat4 creation 41.1M ops/s ±1.6% 44.0M ops/s ±1.4% +7%
Mat4 multiply 58.1M ops/s ±2.1% 52.6M ops/s ±1.4% -9%
Mat4 invert 60.6M ops/s ±2.7% 69.5M ops/s ±1.0% +15%
Mat4 transpose 107.7M ops/s ±2.4% 120.1M ops/s ±2.6% +11%
Mat4 translate 78.0M ops/s ±2.0% 73.7M ops/s ±2.2% -5%
Mat4 scale 96.6M ops/s ±2.2% 123.3M ops/s ±2.1% +28%
Mat4 rotateX 95.3M ops/s ±2.6% 102.5M ops/s ±2.8% +8%
Mat4 determinant 133.1M ops/s ±2.6% 194.2M ops/s ±5.2% +46%
Mat4 perspective 125.5M ops/s ±2.1% 175.5M ops/s ±3.2% +40%
Mat4 lookAt 45.7M ops/s ±1.9% 55.6M ops/s ±2.1% +22%
Mat3 multiply 94.3M ops/s ±1.7% 78.5M ops/s ±2.1% -17%
Mat3 invert 106.1M ops/s ±2.3% 139.9M ops/s ±2.6% +32%
Quat multiply 121.1M ops/s ±2.6% 167.3M ops/s ±4.3% +38%
Quat slerp 56.6M ops/s ±2.0% 125.3M ops/s ±1.6% +121%
Quat normalize 130.7M ops/s ±2.2% 173.0M ops/s ±3.5% +32%
Quat invert 133.4M ops/s ±2.7% 195.1M ops/s ±4.2% +46%
Quat fromAxisAngle 143.0M ops/s ±3.2% 201.9M ops/s ±4.5% +41%
Vec3 transformMat4 102.4M ops/s ±2.7% 140.3M ops/s ±2.0% +37%
Vec3 transformQuat 121.1M ops/s ±3.0% 165.9M ops/s ±4.5% +37%
Vec3 scaleAndAdd 137.1M ops/s ±2.5% 191.9M ops/s ±4.3% +40%
Vec3 mix (lerp) 134.1M ops/s ±2.8% 189.6M ops/s ±3.6% +41%
Vec4 transformMat4 100.5M ops/s ±2.5% 84.8M ops/s ±1.8% -16%
Mat4 project 31.5M ops/s ±1.0%
Mat4 unProject 11.9M ops/s ±1.1%
Quat eulerAngles / pitch / yaw / roll 248.4M ops/s ±5.1%
Quat toMat4 vs Mat4.fromQuat 148.5M ops/s ±2.9%
Quat2 multiply 89.9M ops/s ±2.2%
Quat2 getTranslation 42.5M ops/s ±1.1%

Tests

You can run tests with npm run test