Skip to content

dkaraush/glmaths

Repository files navigation

glmaths

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

83KB minified, 18KB gzipped

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

Other number formats

glmaths supports also float64, int32, uint32 variants:

  • Float64Array: vec2d/dvec2, vec3d/dvec3, vec4d/dvec4, quatd/dquat, quat2d/dquat2, mat2d/mat2x2d/dmat2/dmat2x2, mat3d/mat3x3d/dmat3/dmat3x3, mat4d/mat4x4d/dmat4/dmat4x4
  • Int32Array: vec2i/ivec2, vec3i/ivec3, vec4i/ivec4
  • Uint32Array: vec2u/uvec2, vec3u/uvec3, vec4u/uvec4

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 = true
  • LEFT_HANDED = false — set to true for left handed geometry, used in mat4

Mat2: mat2, mat2d

Mat2x3: mat2x3, mat2x3d

Mat3: mat3, mat3d

Mat4: mat4, mat4d

Quat: quat, quatd

Quat2: quat2, quat2d

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 42.8M ops/s ±1.1% 41.5M ops/s ±0.7% -3%
Vec3 add 139.5M ops/s ±1.9% 202.6M ops/s ±3.2% +45%
Vec3 dot 149.9M ops/s ±3.2% 234.8M ops/s ±4.6% +57%
Vec3 cross 131.8M ops/s ±2.8% 194.0M ops/s ±3.7% +47%
Vec3 normalize 140.0M ops/s ±2.2% 210.2M ops/s ±3.2% +50%
Vec3 scale 146.8M ops/s ±3.3% 217.3M ops/s ±3.5% +48%
Vec3 length 162.3M ops/s ±2.6% 261.0M ops/s ±6.6% +61%
Vec3 distance 153.7M ops/s ±2.5% 250.1M ops/s ±3.9% +63%
Vec3 lerp 133.5M ops/s ±2.5% 193.2M ops/s ±3.8% +45%
Vec2 creation 41.5M ops/s ±1.1% 41.0M ops/s ±0.8% -1%
Vec2 add 145.7M ops/s ±2.6% 218.7M ops/s ±4.1% +50%
Vec4 add 128.2M ops/s ±1.6% 103.8M ops/s ±1.8% -19%
Vec4 normalize 130.8M ops/s ±3.3% 106.7M ops/s ±1.9% -18%
Mat4 creation 41.5M ops/s ±0.7% 44.5M ops/s ±1.1% +7%
Mat4 multiply 59.5M ops/s ±0.9% 61.9M ops/s ±1.1% +4%
Mat4 invert 61.9M ops/s ±0.8% 69.4M ops/s ±0.9% +12%
Mat4 transpose 106.5M ops/s ±1.6% 142.2M ops/s ±2.1% +34%
Mat4 translate 75.7M ops/s ±2.9% 96.8M ops/s ±1.7% +28%
Mat4 scale 96.0M ops/s ±1.5% 123.2M ops/s ±1.7% +28%
Mat4 rotateX 92.5M ops/s ±2.3% 122.1M ops/s ±1.9% +32%
Mat4 determinant 136.0M ops/s ±2.2% 197.2M ops/s ±4.5% +45%
Mat4 perspective 125.9M ops/s ±2.6% 176.6M ops/s ±3.1% +40%
Mat4 lookAt 45.7M ops/s ±1.1% 56.0M ops/s ±3.3% +22%
Mat3 multiply 93.6M ops/s ±1.6% 78.9M ops/s ±1.0% -16%
Mat3 invert 107.6M ops/s ±1.9% 137.3M ops/s ±2.2% +28%
Quat multiply 117.5M ops/s ±2.2% 167.5M ops/s ±2.9% +43%
Quat slerp 61.1M ops/s ±1.7% 126.1M ops/s ±0.8% +106%
Quat normalize 134.2M ops/s ±2.0% 151.4M ops/s ±2.7% +13%
Quat invert 134.9M ops/s ±3.1% 198.4M ops/s ±4.3% +47%
Quat fromAxisAngle 145.9M ops/s ±3.4% 208.2M ops/s ±3.6% +43%
Vec3 transformMat4 102.1M ops/s ±2.0% 140.5M ops/s ±1.8% +38%
Vec3 transformQuat 123.6M ops/s ±2.3% 169.3M ops/s ±3.1% +37%
Vec3 scaleAndAdd 134.3M ops/s ±3.4% 186.8M ops/s ±4.6% +39%
Vec3 mix (lerp) 134.3M ops/s ±1.9% 187.0M ops/s ±3.2% +39%
Vec4 transformMat4 98.1M ops/s ±1.9% 83.3M ops/s ±1.3% -15%
Mat4 project 30.1M ops/s ±0.4%
Mat4 unProject 11.4M ops/s ±0.2%
Quat eulerAngles / pitch / yaw / roll 241.5M ops/s ±6.0%
Quat toMat4 vs Mat4.fromQuat 150.1M ops/s ±2.4%
Quat2 multiply 88.5M ops/s ±2.2%
Quat2 getTranslation 42.6M ops/s ±0.7%

Tests

You can run tests with npm run test

About

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

Topics

Resources

Stars

Watchers

Forks

Contributors