simplex noise
Sampling canvas-sketch-util's simplex noise at UV coordinates scaled by a frequency, with an amplitude multiplier, extended to a third argument (time) to animate it.
Run it
What it looks like when it goes wrong (4)
- The signal is still continuous — simplex noise is smooth by construction at every frequency. What breaks is the SAMPLING: once one cell spans more than about half a period, neighbouring samples land on unrelated parts of the wave and the field reads as static. Nothing is wrong with the noise; the grid is too coarse for it. Raise the resolution and the smoothness comes back.
- The field looks washed out but the structure is identical — same blobs, same positions, less contrast. Frequency changes what the field IS; amplitude only changes how far the output swings. They are not two dials for busyness, and reaching for amplitude when you wanted frequency is the most common way to spend an afternoon on the wrong knob.
- Aliasing. Eight cells cannot represent twenty periods, so the field folds onto itself and shows large smooth blobs that are not in the signal at all. This is the failure that looks most like success — the output is plausible, and it is an artefact of the sampling grid.
- Scaled to twice what the output can hold, so everything above and below the midtones clips to pure white and pure black. The blobs get harder edges and read as higher contrast, which is why this gets mistaken for a good setting — but the structure inside the light and dark regions is gone, not enhanced. Clipping is destructive and there is no way back from it later in the pipeline.
Clean-room implementation — written from the described algorithm, not from source. Reuse policy
What it is
Simplex noise, in this bundle, isn’t something you build up from primitives —
it’s a library call: canvas-sketch-util’s noise2D / noise3D, the aliases
this entity is filed under. Give it coordinates — two for noise2D, three for
noise3D, and the underlying algorithm generalizes to however many dimensions
you need — and it returns a continuous signal that “smoothly varies between
-1…1.” That continuity is the whole reason to reach for it instead of
Math.random(): feed it two nearby inputs and you get two nearby outputs,
which is what makes a field of samples read as terrain or wind instead of
static.
How it works
What’s here documents the calling convention, not the internal construction — no grid, no gradient vectors, no simplex-cell subdivision reaches this bundle. For that, go to the primary source linked under Go deeper. As a recipe:
- Decide how many coordinates you need. Two (
noise2D) for a flat field sampled once; three (noise3D) once one of those coordinates is going to move. - Scale each coordinate by a
frequencybefore it goes in:amplitude * random.noise2D(u * frequency, v * frequency). - Multiply the return value by an
amplitudeto move it out of the fixed -1..1 range. - To animate the field rather than resample it, leave
u/valone and advance a third argument throughamplitude * random.noise3D(u * frequency, v * frequency, time)— the same spatial field then evolves continuously frame to frame instead of jumping between unrelated states. - There’s no
noise1D. The workaround given is to callnoise2Dwith the second argument pinned at zero and increment the first argument yourself each step — the worked example is a ball moved with organic, oscillating motion by incrementing its x and reading the return value as y.
Parameters & tuning
Two knobs are tied to a specific effect on the output here. frequency
“changes how chaotic the noise signal will be” — push it up and the field
wobbles over shorter stretches of u/v; pull it down and you get long, slow
swells instead. amplitude only rescales what comes back — it “can be used to
scale the value to something smaller or larger than -1..1 range” — it doesn’t
touch the shape of the field at all, only how far it swings.
Past that, nothing in the bundle specifies a breaking point: no numeric extreme where the field degrades toward static, no clipping threshold for either knob. That’s worth stating as a gap rather than guessing at — check it by eye once steps 1–4 above are running.
Where it’s been used
What’s on record here is two teaching contexts, not a named artwork crediting its use: Matt Deslauriers’ workshop cheat sheet, which gives the canvas-sketch-util calling convention directly, and Varun Vachhar’s practical-js post at varun.ca, source of the “no noise1D” workaround and the dimension-generalization note. Treat “used simplex noise” as unremarkable on its own — most canvas-sketch work does — until a source says something more specific than that.
Variants & neighbours
Worley noise is a genuinely different construction, not a retuning of this one: instead of interpolating a smooth field, it shades every point by its distance to the nearest of a set of scattered feature points, which is what gives it a cellular, tessellated look rather than a continuous wave.
mapRange solves a different problem entirely — it takes a
number you already have and rescales it into a new range via
inverseLerp+lerp. Simplex noise generates the number in the first place;
the amplitude step above is doing, informally, what mapRange would do more
explicitly. That’s presumably why the two end up contrasted with each other in
this graph rather than left unrelated.
Perlin noise is the one this page most needs to get
right, and the bundle only gets it partway there. What’s supported: the same
source treats Perlin noise as the earlier of the two flavours (built, per that
entry’s own record, for Tron’s CG effects) and simplex as what came after —
“he then improved on it with Simplex noise and made it a bit faster.” This
project’s own graph already keeps the two as contrast-with, not
variant-of — they are not the same construction with one setting changed.
What the excerpts don’t give is why: no grid shape, no argument about cost
scaling with dimension count reaches this bundle. That’s a real gap, not a
place to reach for what’s generally believed about simplicial versus
hypercubic lattices — the mechanism itself has to come from the linked entry
or the primary source, not from here.
Go deeper
- varun.ca/noise — Varun Vachhar’s practical-js post; source of the dimension-generalization note, the “no noise1D” workaround, and the Perlin-to-Simplex succession.
- mattdesl/workshop-generative-art cheat sheet —
the canvas-sketch-util calling convention (
noise2D,noise3D,frequency,amplitude) used throughout this page. - Linear interpolation is listed as a related primitive in this graph; nothing supplied here ties it to simplex noise directly, so take that as the graph’s adjacency, not a claim this page is making.
Connected to
Variant of: Perlin noise
Used to build: Seamless noise loop