Five steps, two revisions
Both versions run the same five-step pipeline. The 2002 revision touched exactly two of the steps — the gradients and the ease curve — and simplified the machinery around a third.
Snap to the unit-cube grid
Floor the input to find its cell, keep the fractional part xf = x − ⌊x⌋, and wrap cell indices with & 255. Cheap, but it means the noise repeats every 256 units — invisible in practice because you sample at fractional coordinates.
Hash every cell corner
Nested permutation lookups G[(i + P[(j + P[k]) & 255]) & 255] — the hash is only an index into a second table, G, that stores actual gradient vectors.
Same doubled p[512] table hashes each of the 8 corners — but the hash is the gradient now: its low 4 bits pick a vector directly. The whole G table disappears.
Pick a gradient per corner
256 precomputed pseudorandom unit vectors — every direction equally likely, which is elegant but lets gradients clump near the coordinate axes by chance.
Just 12 vectors, from the cube's center to its edge midpoints: (±1,±1,0), (±1,0,±1), (0,±1,±1). No axis-aligned bias, and every dot product collapses into adds and subtracts — zero multiplies.
Dot products at 8 corners
dot(gradient, point − corner) — positive downhill of the gradient, negative against it, zero perpendicular. A side effect both versions share: the noise is exactly 0 at every lattice point, because the distance vector there is zero.
Ease, then interpolate
Warp t with 3t² − 2t³ before the trilinear lerp. Continuous slope (C¹) — but its second derivative jumps at every cell wall, which surfaces as creases the moment you compute normals for bump mapping.
Swap in 6t⁵ − 15t⁴ + 10t³. First and second derivatives are both zero at the endpoints (C²), so derivative-based effects come out clean.
Octaves (the standard post-process)
Not part of either core algorithm — but almost every real use sums several noises at frequency = 2ⁱ, amplitude = persistenceⁱ to layer mountains over hills over pebbles. Lab 03 below.
No ease → cubic → quintic
Gradients are held fixed (v2's 12 vectors) — only the interpolant changes. The raw noise looks similar in all three. Switch the view to slope or curvature to see where each simpler choice breaks: artifacts show up as straight, grid-aligned seams.
Values → random gradients → 12 vectors
The fade is held fixed (v2's quintic) — only the thing stored at each lattice corner changes. The simplest idea, storing plain random values, isn't Perlin noise at all — it's value noise, and its energy visibly clings to the grid.
One octave vs. a fractal sum
A single octave of Perlin noise is smooth but featureless — nature has detail at every scale. Layering octaves at doubling frequency and shrinking amplitude (set by persistence) is what turns wobble into terrain.