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
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.
// 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).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.
You can pass vector in a vector, just like in GLSL: vec4(vec2(0, 1), 2, 3)
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
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 placeglmaths 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/dmat4x4Int32Array:vec2i/ivec2,vec3i/ivec3,vec4i/ivec4Uint32Array:vec2u/uvec2,vec3u/uvec3,vec4u/uvec4
- EPSILON =
0.000001— used ina.equals(b)functions - RANDOM =
Math.random— used in.random()functions - ANGLE_ORDER =
'zyx'— used inQuat.fromEuler - ALWAYS_COPY =
true - LEFT_HANDED =
false— set to true for left handed geometry, used inmat4
- clone(): mat2
- transpose(out?: Mat2): Mat2
- invert(out?: Mat2): Mat2
- adjoint(out?: Mat2): Mat2
- determinant(): number
- rotate(rad: number, out?: Mat2): Mat2
- scale(v: Vec2, out?: Mat2): Mat2
- static fromRotation(rad: number, out?: Mat2): Mat2
- static fromScaling(v: Vec2, out?: Mat2): Mat2
- toString(): string
- str → toString
- frob(): number
- LDU(L?: Mat2, D?: Mat2, U?: Mat2):
- plus(b: Mat2, out?: Mat2): Mat2
- add → plus
- minus(b: Mat2, out?: Mat2): Mat2
- sub → minus
- subtract → minus
- multiply(b: Mat2 | Vec2, out?: any): any
- mul → multiply
- mult → multiply
- times → multiply
- exactEquals(b: Mat2): boolean
- equals(b: Mat2): boolean
- scaleScalar(b: number, out?: Mat2): Mat2
- multiplyScalar → scaleScalar
- invert(out?: Mat2x3): Mat2x3
- determinant(): number
- rotate(rad: number, out?: Mat2x3): Mat2x3
- scale(v: Vec2, out?: Mat2x3): Mat2x3
- translate(v: Vec2, out?: Mat2x3): Mat2x3
- static fromRotation(rad: number, out?: Mat2x3): Mat2x3
- static fromScaling(v: Vec2, out?: Mat2x3): Mat2x3
- static fromTranslation(v: Vec2, out?: Mat2x3): Mat2x3
- toString(): string
- str → toString
- frob(): number
- plus(b: Mat2x3, out?: Mat2x3): Mat2x3
- add → plus
- minus(b: Mat2x3, out?: Mat2x3): Mat2x3
- sub → minus
- subtract → minus
- multiply(b: Vec2 | Mat2x3, out?: Mat2x3): vec2 | Mat2x3
- mul → multiply
- mult → multiply
- times → multiply
- equals(b: Mat2x3): boolean
- exactEquals(b: Mat2x3): boolean
- scaleScalar(b: number, out?: Mat2x3): Mat2x3
- multiplyScalar → scaleScalar
- clone(): mat2x3
- clone(): mat3
- transpose(out?: Mat3): Mat3
- invert(out?: Mat3): Mat3
- adjoint(out?: Mat3): Mat3
- determinant(): number
- multiply(b: Vec2 | Mat3 | Vec3, out?: Mat3): vec2 | vec3 | Mat3
- mul → multiply
- mult → multiply
- times → multiply
- translate(v: Vec2, out?: Mat3): Mat3
- rotate(rad: number, out?: Mat3): Mat3
- scale(v: Vec2, out?: Mat3): Mat3
- static fromTranslation(v: Vec2, out?: Mat3): Mat3
- static fromRotation(rad: number, out?: Mat3): Mat3
- static fromScaling(v: Vec2, out?: Mat3): Mat3
- static fromMat2x3(a: Mat2x3, out?: Mat3): Mat3
- static fromQuat(q: Quat, out?: Mat3): Mat3
- static normalFromMat4(a: Mat4, out?: Mat3): Mat3
- static fromMat4(a: Mat4, out?: Mat3): Mat3
- static fromMat4x4 → fromMat4
- static projection(width: number, height: number, out?: Mat3): Mat3
- frob(): number
- plus(b: Mat3, out?: Mat3): Mat3
- add → plus
- minus(b: Mat3, out?: Mat3): Mat3
- sub → minus
- subtract → minus
- scaleScalar(b: number, out?: Mat3): Mat3
- multiplyScalar → scaleScalar
- multiplyScalarAndAdd(b: Mat3, scale: number, out?: Mat3): Mat3
- toString(): string
- str → toString
- exactEquals(b: Mat3): boolean
- equals(b: Mat3): boolean
- clone(): mat4
- transpose(out?: Mat4): Mat4
- invert(out?: Mat4): Mat4
- adjoint(out?: Mat4): Mat4
- determinant(): number
- multiply(b: Vec2 | Vec3 | Mat4 | Vec4, out?: Vec2 | Vec3 | Mat4 | Vec4): Vec2 | Vec3 | Mat4 | Vec4
- mul → multiply
- mult → multiply
- times → multiply
- translate(v: Vec3, out?: Mat4): Mat4
- scale(v: Vec3, out?: Mat4): Mat4
- rotate(rad: number, axis: Vec3, out?: Mat4): Mat4
- rotateX(rad: number, out?: Mat4): Mat4
- rotateY(rad: number, out?: Mat4): Mat4
- rotateZ(rad: number, out?: Mat4): Mat4
- getTranslation(out?: Vec3): Vec3
- getScaling(out?: Vec3): Vec3
- getRotation(out?: Quat): Quat
- decompose(out_r?: Quat, out_t?: Vec3, out_s?: Vec3): Quat
- static fromTranslation(v: Vec3, out?: Mat4): Mat4
- static fromScaling(v: Vec3, out?: Mat4): Mat4
- static fromRotation(rad: number, axis: Vec3, out?: Mat4): Mat4
- static fromXRotation(rad: number, out?: Mat4): Mat4
- static fromYRotation(rad: number, out?: Mat4): Mat4
- static fromZRotation(rad: number, out?: Mat4): Mat4
- static fromRotationTranslation(q: Quat, v: Vec3, out?: Mat4): Mat4
- static fromRotationTranslationScale(q: Quat, v: Vec3, s: Vec3, out?: Mat4): Mat4
- static fromRotationTranslationScaleOrigin(q: Quat, v: Vec3, s: Vec3, o: Vec3, out?: Mat4): Mat4
- static fromQuat(q: Quat, out?: Mat4): Mat4
- static frustum(left: number, right: number, bottom: number, top: number, near: number, far: number, out?: Mat4): Mat4
- static perspectiveNO(fovy: number, aspect: number, near: number, far: number, out?: Mat4): Mat4
- static perspectiveZO(fovy: number, aspect: number, near: number, far: number, out?: Mat4): Mat4
- static perspectiveFromFieldOfView(fov: { updegrees: number; downdegrees: number; leftdegrees: number; rightdegrees: number; }, near: number, far: number, out?: Mat4): Mat4
- static orthoNO(left: number, right: number, bottom: number, top: number, near: number, far: number, out?: Mat4): Mat4
- static orthoZO(left: number, right: number, bottom: number, top: number, near: number, far: number, out?: Mat4): Mat4
- static lookAt(eye: Vec3, center: Vec3, up: Vec3, out?: Mat4): Mat4
- static targetTo(eye: Vec3, target: Vec3, up: Vec3, out?: Mat4): Mat4
- static infinitePerspective(fovy: number, aspect: number, near: number, out?: Mat4): Mat4
- static project(obj: Vec3, model: Mat4, proj: Mat4, viewport: Vec4, out?: Vec3): Vec3
- static unProject(win: Vec3, model: Mat4, proj: Mat4, viewport: Vec4, out?: Vec3): Vec3
- frob(): number
- plus(b: Mat4, out?: Mat4): Mat4
- add → plus
- minus(b: Mat4, out?: Mat4): Mat4
- sub → minus
- subtract → minus
- scaleScalar(b: number, out?: Mat4): Mat4
- multiplyScalar → scaleScalar
- multiplyScalarAndAdd(b: Mat4, scale: number, out?: Mat4): Mat4
- toString(): string
- str → toString
- exactEquals(b: Mat4): boolean
- equals(b: Mat4): boolean
- multiply(b: number | Quat, out?: Quat): Quat
- mult → multiply
- mul → multiply
- scale → multiply
- times → multiply
- static fromAxisAngle(axis: Vec3, rad: number, out?: Quat): Quat
- setAxisAngle(axis: Vec3, rad: number, out?: Quat): Quat
- getAxisAngle(out_axis: Vec3): number
- static angle(a: Quat, b: Quat): number
- static getAngle → angle
- rotateX(rad: number, out?: Quat): Quat
- rotateY(rad: number, out?: Quat): Quat
- rotateZ(rad: number, out?: Quat): Quat
- calculateW(): number
- static exp(q: Quat, out?: Quat): Quat
- exp(out?: Quat): Quat
- static ln(q: Quat, out?: Quat): Quat
- ln(out?: Quat): Quat
- pow(b: number): this
- static slerp(a: Quat, b: Quat, t: number, out?: Quat): Quat
- slerp(b: Quat, t: number, out?: Quat): Quat
- static random(out?: Quat): Quat
- static invert(q: Quat, out?: Quat): Quat
- invert(out?: Quat): Quat
- static conjugate(q: Quat, out?: Quat): Quat
- conjugate(out?: Quat): Quat
- static fromMat3(m: Mat3, out?: Quat): Quat
- static fromEuler(x: number, y: number, z: number, order?: string, out?: Quat): Quat
- toString(): string
- str → toString
- static dot(a: Quat, b: Quat): number
- dot(b: Quat): number
- equals(b: Quat): boolean
- static rotationTo(a: Vec3, b: Vec3, out?: Quat): Quat
- static sqlerp(a: Quat, b: Quat, c: Quat, d: Quat, t: number, out?: Quat): Quat
- static setAxes(view: Vec3, right: Vec3, up: Vec3, out?: Quat): Quat
- static normalize(q: Quat, out?: Quat): Quat
- normalized → normalize
- normalize(out?: Quat): Quat
- normalized → normalize
- static quatLookAt(direction: Vec3, up: Vec3, out?: Quat): Quat
- pitch(): number
- yaw(): number
- roll(): number
- eulerAngles(out?: Vec3): Vec3
- toMat3(out?: Mat3): Mat3
- toMat4(out?: Mat4): Mat4
- clone(): quat
- getReal(out?: Quat): Quat
- getDual(out?: Quat): Quat
- setReal(q: Quat): this
- setDual(q: Quat): this
- getTranslation(out?: Vec3): Vec3
- static fromRotationTranslation(q: Quat, t: Vec3, out?: Quat2): Quat2
- static fromTranslation(t: Vec3, out?: Quat2): Quat2
- static fromRotation(q: Quat, out?: Quat2): Quat2
- static fromMat4(m: Mat4, out?: Quat2): Quat2
- clone(): quat2
- multiply(b: Quat2, out?: Quat2): Quat2
- translate(v: Vec3, out?: Quat2): Quat2
- conjugate(out?: Quat2): Quat2
- invert(out?: Quat2): Quat2
- squaredLength(): number
- sqrLen → squaredLength
- len(): number
- static normalize(q: Quat2, out?: Quat2): Quat2
- normalized → normalize
- normalize(out?: Quat2): Quat2
- normalized → normalize
- static dot(a: Quat2, b: Quat2): number
- static lerp(a: Quat2, b: Quat2, t: number, out?: Quat2): Quat2
- plus(b: Quat2, out?: Quat2): Quat2
- add → plus
- scale(s: number, out?: Quat2): Quat2
- equals(b: Quat2): boolean
- exactEquals(b: Quat2): boolean
- toString(): string
- str → toString
- plus(b: number | Vec2, out?: Vec2): Vec2
- add → plus
- minus(b: number | Vec2, out?: Vec2): Vec2
- sub → minus
- subtract → minus
- mult(b: number | Vec2, out?: Vec2): Vec2
- mul → mult
- multiply → mult
- scale → mult
- times → mult
- div(b: number | Vec2, out?: Vec2): Vec2
- divide → div
- invDiv(a: number | Vec2, out?: Vec2): Vec2
- rem(b: number | Vec2, out?: Vec2): Vec2
- negate(out?: Vec2): Vec2
- neg → negate
- unaryMinus → negate
- unaryPlus(out?: Vec2): Vec2
- static normalize(v: Vec2, out?: Vec2): Vec2
- normalized → normalize
- normalize(out?: Vec2): Vec2
- normalized → normalize
- equals(b: Vec2): boolean
- exactEquals(b: Vec2): boolean
- squaredLength(): number
- sqrLen → squaredLength
- len(): number
- floor(out?: Vec2): Vec2
- round(out?: Vec2): Vec2
- ceil(out?: Vec2): Vec2
- inverse(out?: Vec2): Vec2
- clone(): vec2
- rotate(rad?: number, origin?: Vec2, out?: Vec2): Vec2
- toString(): string
- str → toString
- static random(scale?: number, out?: Vec2): Vec2
- static angle(a: Vec2, b: Vec2): number
- static signedAngle(a: Vec2, b: Vec2): number
- static dot(a: Vec2, b: Vec2): number
- dot(b: Vec2): number
- static cross(a: Vec2, b: Vec2, out?: Vec3): Vec3
- static distance(a: Vec2, b: Vec2): number
- static dist → distance
- static squaredDistance(a: Vec2, b: Vec2): number
- static sqrDist → squaredDistance
- static lerp(a: Vec2, b: Vec2, t: number, out?: Vec2): Vec2
- static max(a: Vec2, b: Vec2, out?: Vec2): Vec2
- static min(a: Vec2, b: Vec2, out?: Vec2): Vec2
- static clamp(v: Vec2, min: number | Vec2, max: number | Vec2, out?: Vec2): Vec2
- static mix(a: Vec2, b: Vec2, t: number | Vec2, out?: Vec2): Vec2
- lerpV → mix
- static smoothstep(edge0: number | Vec2, edge1: number | Vec2, v: Vec2, out?: Vec2): Vec2
- scaleAndAdd(b: Vec2, scale: number, out?: Vec2): Vec2
- abs(out?: Vec2): Vec2
- sign(out?: Vec2): Vec2
- fract(out?: Vec2): Vec2
- clamp(min: number | Vec2, max: number | Vec2, out?: Vec2): Vec2
- saturate(out?: Vec2): Vec2
- mix(b: Vec2, t: number | Vec2, out?: Vec2): Vec2
- lerpV → mix
- step(edge: number | Vec2, out?: Vec2): Vec2
- smoothstep(edge0: number | Vec2, edge1: number | Vec2, out?: Vec2): Vec2
- transformMat2(m: mat2, out?: Vec2): Vec2
- transformMat2x2 → transformMat2
- transformMat2x3(m: mat2x3, out?: Vec2): Vec2
- transformMat3(m: mat3, out?: Vec2): Vec2
- transformMat3x3 → transformMat3
- transformMat4(m: mat4, out?: Vec2): Vec2
- transformMat4x4 → transformMat4
- static scaleAndAdd(a: Vec2, b: Vec2, scale: number, out?: Vec2): Vec2
- static reflect(I: Vec2, N: Vec2, out?: Vec2): Vec2
- plus(b: number | Vec3, out?: Vec3): Vec3
- add → plus
- minus(b: number | Vec3, out?: Vec3): Vec3
- sub → minus
- subtract → minus
- mult(b: number | Vec3, out?: Vec3): Vec3
- mul → mult
- scale → mult
- multiply → mult
- times → mult
- div(b: number | Vec3, out?: Vec3): Vec3
- divide → div
- invDiv(b: number | Vec3, out?: Vec3): Vec3
- negate(out?: Vec3): Vec3
- neg → negate
- unaryMinus → negate
- unaryPlus(out?: Vec3): Vec3
- static normalize(v: Vec3, out?: Vec3): Vec3
- normalized → normalize
- normalize(out?: Vec3): Vec3
- normalized → normalize
- equals(b: Vec3): boolean
- exactEquals(b: Vec3): boolean
- squaredLength(): number
- sqrLen → squaredLength
- len(): number
- static floor(v: Vec3, out?: Vec3): Vec3
- static round(v: Vec3, out?: Vec3): Vec3
- static ceil(v: Vec3, out?: Vec3): Vec3
- floor(out?: Vec3): Vec3
- round(out?: Vec3): Vec3
- ceil(out?: Vec3): Vec3
- static inverse(v: Vec3, out?: Vec3): Vec3
- inverse(out?: Vec3): Vec3
- clone(): vec3
- toString(): string
- str → toString
- static random(scale?: number, out?: Vec3): Vec3
- static angle(a: Vec3, b: Vec3): number
- static dot(a: Vec3, b: Vec3): number
- dot(b: Vec3): number
- static cross(a: Vec3, b: Vec3, out?: Vec3): Vec3
- static distance(a: Vec3, b: Vec3): number
- static dist → distance
- static squaredDistance(a: Vec3, b: Vec3): number
- static sqrDist → squaredDistance
- static lerp(a: Vec3, b: Vec3, t: number, out?: Vec3): Vec3
- static slerp(a: Vec3, b: Vec3, t: number, out?: Vec3): Vec3
- static max(a: Vec3, b: Vec3, out?: Vec3): Vec3
- static min(a: Vec3, b: Vec3, out?: Vec3): Vec3
- static clamp(v: Vec3, min: number | Vec3, max: number | Vec3, out?: Vec3): Vec3
- static mix(a: Vec3, b: Vec3, t: number | Vec3, out?: Vec3): Vec3
- lerpV → mix
- static smoothstep(edge0: number | Vec3, edge1: number | Vec3, v: Vec3, out?: Vec3): Vec3
- static rotateX(v: Vec3, rad: number, origin?: Vec3, out?: Vec3): Vec3
- rotateX(rad: number, origin?: Vec3, out?: Vec3): Vec3
- static rotateY(v: Vec3, rad: number, origin?: Vec3, out?: Vec3): Vec3
- rotateY(rad: number, origin?: Vec3, out?: Vec3): Vec3
- static rotateZ(v: Vec3, rad: number, origin?: Vec3, out?: Vec3): Vec3
- rotateZ(rad: number, origin?: Vec3, out?: Vec3): Vec3
- static hermite(a: Vec3, b: Vec3, c: Vec3, d: Vec3, t: number, out?: Vec3): Vec3
- static bezier(a: Vec3, b: Vec3, c: Vec3, d: Vec3, t: number, out?: Vec3): Vec3
- static scaleAndAdd(a: Vec3, b: Vec3, scale: number, out?: Vec3): Vec3
- static reflect(I: Vec3, N: Vec3, out?: Vec3): Vec3
- static refract(I: Vec3, N: Vec3, eta: number, out?: Vec3): Vec3
- static faceforward(N: Vec3, I: Vec3, Nref: Vec3, out?: Vec3): Vec3
- static triangleNormal(p1: Vec3, p2: Vec3, p3: Vec3, out?: Vec3): Vec3
- static project(a: Vec3, b: Vec3, out?: Vec3): Vec3
- static orientedAngle(a: Vec3, b: Vec3, ref: Vec3): number
- scaleAndAdd(b: Vec3, scale: number, out?: Vec3): Vec3
- abs(out?: Vec3): Vec3
- clamp(min: number | Vec3, max: number | Vec3, out?: Vec3): Vec3
- mix(b: Vec3, t: number | Vec3, out?: Vec3): Vec3
- lerpV → mix
- step(edge: number | Vec3, out?: Vec3): Vec3
- smoothstep(edge0: number | Vec3, edge1: number | Vec3, out?: Vec3): Vec3
- fract(out?: Vec3): Vec3
- sign(out?: Vec3): Vec3
- saturate(out?: Vec3): Vec3
- transformMat3(m: Mat3, out?: Vec3): Vec3
- transformMat3x3 → transformMat3
- transformMat4(m: Mat4, out?: Vec3): Vec3
- transformMat4x4 → transformMat4
- transformQuat(q: Quat, out?: Vec3): Vec3
- plus(b: number | Vec4, out?: Vec4): Vec4
- add → plus
- minus(b: number | Vec4, out?: Vec4): Vec4
- sub → minus
- subtract → minus
- mult(b: number | Vec4, out?: Vec4): Vec4
- mul → mult
- scale → mult
- times → mult
- multiply → mult
- div(b: number | Vec4, out?: Vec4): Vec4
- divide → div
- invDiv(b: number | Vec4, out?: Vec4): Vec4
- negate(out?: Vec4): Vec4
- neg → negate
- unaryMinus → negate
- unaryPlus(out?: Vec4): Vec4
- static normalize(v: Vec4, out?: Vec4): Vec4
- normalized → normalize
- normalize(out?: Vec4): Vec4
- normalized → normalize
- equals(b: Vec4): boolean
- exactEquals(b: Vec4): boolean
- squaredLength(): number
- sqrLen → squaredLength
- len(): number
- floor(out?: Vec4): Vec4
- round(out?: Vec4): Vec4
- ceil(out?: Vec4): Vec4
- inverse(out?: Vec4): Vec4
- clone(): vec4
- toString(): string
- str → toString
- static random(scale?: number, out?: Vec4): Vec4
- static dot(a: Vec4, b: Vec4): number
- dot(b: Vec4): number
- static cross(u: Vec4, v: Vec4, w: Vec4, out?: Vec4): Vec4
- static distance(a: Vec4, b: Vec4): number
- static dist → distance
- static squaredDistance(a: Vec4, b: Vec4): number
- static sqrDist → squaredDistance
- static lerp(a: Vec4, b: Vec4, t: number, out?: Vec4): Vec4
- static max(a: Vec4, b: Vec4, out?: Vec4): Vec4
- static min(a: Vec4, b: Vec4, out?: Vec4): Vec4
- static clamp(v: Vec4, min: number | Vec4, max: number | Vec4, out?: Vec4): Vec4
- static mix(a: Vec4, b: Vec4, t: number | Vec4, out?: Vec4): Vec4
- lerpV → mix
- static smoothstep(edge0: number | Vec4, edge1: number | Vec4, v: Vec4, out?: Vec4): Vec4
- scaleAndAdd(b: Vec4, scale: number, out?: Vec4): Vec4
- abs(out?: Vec4): Vec4
- clamp(min: number | Vec4, max: number | Vec4, out?: Vec4): Vec4
- mix(b: Vec4, t: number | Vec4, out?: Vec4): Vec4
- lerpV → mix
- step(edge: number | Vec4, out?: Vec4): Vec4
- smoothstep(edge0: number | Vec4, edge1: number | Vec4, out?: Vec4): Vec4
- fract(out?: Vec4): Vec4
- sign(out?: Vec4): Vec4
- saturate(out?: Vec4): Vec4
- transformMat4(m: mat4, out?: Vec4): Vec4
- transformMat4x4 → transformMat4
- transformQuat(q: quat, out?: Vec4): Vec4
- static scaleAndAdd(a: Vec4, b: Vec4, scale: number, out?: Vec4): Vec4
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% | — |
You can run tests with npm run test