Math
The arithmetic you write your own paint with. Every word takes expressions or plain numbers
and returns an expression the GPU works out once per pixel: mul(color, coverage) fades a
color, smoothstep(a, b, dist) turns a distance into a soft mask, mix(a, b, t) blends two
colors. Props reach you as params.uniforms.<name> (or uniformOf(p('name'), params)), a
frame gives you the coordinate, and the words compose by nesting until you return a vec4
color from paint:. Wrap anything you read twice in local so it is computed once.
import {math} from 'shaders/std'
Reach for it when
| When you need | Use |
|---|---|
| combining numbers, colors or coordinates | add, sub, mul, div |
| blending two colors or values by an amount | mix with splat3 for colors |
| a soft edge from a distance | smoothstep; step for a hard one |
| keeping a value in range | clamp, min, max |
| a value you read more than once | local |
| the distance from a center or between points | length, distance |
| a pattern that repeats across the canvas | fract and floor on a scaled coordinate |
| a wave or a rotation over time | sin, cos, rotate2 |
| an angle around a center | atan2 |
| a smooth falloff or a bell shape | exp, gaussBell |
| a hinge that bends instead of creasing | softPlus |
| picking one of two values per pixel | select with lt, gt, le, ge |
| several motions that must not move in step | hashPhase |
| the final color | vec4 from a vec3 and an alpha |
Example
import {defineShader, p, uniformOf, animatedTime, math, frames, transformColor, transformPosition} from 'shaders/std'
const {add, sub, mul, sin, smoothstep, mix, splat3, local, vec4} = math
// Rings: concentric waves spreading from a draggable center, blended between two colors.
export const Rings = defineShader({
name: 'Rings',
animatedTime: {speed: 'speed'},
props: {
center: {default: {x: 0.5, y: 0.5}, transform: transformPosition},
colorA: {default: '#0b1026', transform: transformColor},
colorB: {default: '#7dd3fc', transform: transformColor},
frequency: {default: 24},
softness: {default: 0.25},
speed: {default: 1},
},
paint: (params) => {
const u = (name: string) => uniformOf(p(name), params)
const {dist} = frames.centredFrame({center: p('center')})(params, frames.surfaceOf(params))
// A −1..1 wave along the distance, moved into 0..1 and computed once.
const wave = local(add(mul(sin(sub(mul(dist, u('frequency')), animatedTime(params))), 0.5), 0.5), 'wave')
// softness 0 is a hard ring, 0.5 a smooth gradient between rings.
const band = smoothstep(sub(0.5, u('softness')), add(0.5, u('softness')), wave)
const rgb = mix(u('colorA').member('rgb'), u('colorB').member('rgb'), splat3(band))
return vec4(rgb, 1)
},
})
Words
- addThe sum of two values.
- subThe first value minus the second.
- mulThe product of two values.
- divThe first value divided by the second.
- mixA blend from
atobbyt, where 0 givesaand 1 givesb. - smoothstepA soft edge: 0 below
e0, 1 abovee1, an S-curve between. - clampThe value limited to the range
lo..hi. - localA value computed once per pixel and shared by everything that reads it.
- vec4A 4D vector, usually the final color with alpha.
- vec3A 3D vector from three values, often a color without alpha.
- vec2A 2D vector from two values.
- splat3One number copied into all three channels of a vec3.
- lengthThe length of a vector.
- distanceThe distance between two points.
- absThe value without its sign.
- fractThe fractional part of a value, 0..1.
- floorThe value rounded down to a whole number.
- minThe smaller of two values.
- maxThe larger of two values.
- sinThe sine of an angle in radians, −1..1.
- cosThe cosine of an angle in radians, −1..1.
- stepA hard edge: 0 when
xis belowedge, 1 fromedgeon. - powThe first value raised to the power of the second.
- expe raised to the value.
- sqrtThe square root of a value.
- negThe value with its sign flipped.
- select
ifTruewhen the condition holds, otherwiseifFalse. - ltTrue when
ais less thanb. - gtTrue when
ais greater thanb. - leTrue when
ais less than or equal tob. - geTrue when
ais greater than or equal tob. - atan2The angle of the point (x, y) in radians, −π..π.
- dotThe dot product of two vectors.
- normalizeThe vector scaled to length 1.
- rotate2A 2D point rotated around the origin.
- gaussBellA bell curve: 1 at zero, falling toward 0 on both sides.
- softPlusA soft hinge: about 0 for values well below zero, about
xabove, rounded near zero. - hashPhaseA random but stable angle in radians, 0..2π, from a seed.
- sign−1, 0 or 1 by the sign of the value.
- ceilThe value rounded up to a whole number.
- logThe natural logarithm of a value.
- exp22 raised to the value.
- tanThe tangent of an angle in radians.
- crossThe cross product of two 3D vectors.
- reflectThe direction
ibounced off a surface with unit normaln. - refractThe direction
ibent through a surface with unit normaln. - floatA plain number as an expression.