Noise built from distance, not gradients
Worley noise — invented by Steven Worley in 1996 and also called cellular noise — takes a completely different approach from Perlin's gradient noise. Scatter a set of random feature points across the plane, then for every pixel find the distance to the nearest feature point and use that distance as the noise value. The result isn't smooth and cloud-like; it's cellular — each feature point owns a region around it, and the boundaries between regions form sharp or soft edges depending entirely on which distance metric and which ranked neighbour you use.
F1, F2 and the algebra between them
The convention is to compute, for every pixel, the sorted list of distances to feature points: F1 is the distance to the nearest point, F2 the distance to the second-nearest, and so on. Using F1 alone produces a Voronoi-like cellular pattern where each cell is roughly a uniform colour that darkens toward its centre and brightens at the boundary — this is what stone, cracked mud and organic cell textures start from. Combining F1 and F2 opens up a whole different family: F2 − F1 produces bright, thin lines exactly along the Voronoi cell boundaries (the value goes to zero only where a pixel is equidistant from two feature points), which is the standard technique for procedural cracked-earth, reptile-scale and stained-glass textures.
for each pixel p: distances = sort([ dist(p, feature_i) for feature_i in nearby_points ]) F1 = distances[0] F2 = distances[1] value = F1 // classic cellular blobs value = F2 - F1 // bright cell-boundary lines (~0 at edges) value = F1 * F2 // sharper, more contrasted cell interiors
Distance metrics change the cell shape entirely
Everything above assumes Euclidean distance, which produces the familiar rounded, organic cell shapes. Swapping in Manhattan distance (|Δx| + |Δy|) produces diamond-shaped cells with straight, angular boundaries; Chebyshev distance (max(|Δx|, |Δy|)) produces square cells. This one parameter is enough to move the same underlying algorithm from "looks like biological cells" to "looks like a circuit board" or "looks like cracked ceramic tile", without touching the feature-point placement at all.
Making it fast: bucketing feature points
A naive implementation checks every pixel against every feature point in the whole image — O(pixels × points), hopeless at any real resolution. The standard fix is the same spatial-hashing trick used across computer graphics: divide the plane into a grid of cells, guarantee at most one (or a small fixed number of) random feature point per grid cell using a hash of the cell's coordinates as a seed, and for any query pixel only check feature points in its own grid cell and the eight immediate neighbours. Because feature-point density is bounded per cell by construction, this reduces the per-pixel cost from O(points) to O(1) — and critically, because the feature points are derived from a hash of grid coordinates rather than stored in an array, the noise is infinite, seamlessly tileable and needs no precomputed lookup table.
// bucketed Worley — check only the pixel's own cell + 8 neighbours
function nearestFeatureDist(p) {
const cell = floor(p / cellSize);
let best = Infinity;
for (let dy = -1; dy <= 1; dy++)
for (let dx = -1; dx <= 1; dx++) {
const c = cell + [dx, dy];
const feature = hashToPoint(c); // deterministic per-cell pseudo-random point
best = Math.min(best, dist(p, feature));
}
return best;
}
Where it shows up
Worley noise is the standard technique behind procedural stone and rock textures, water caustics and foam patterns, organic cell-membrane and biological-tissue shaders, and — layered at multiple scales the way fractal Brownian motion layers Perlin noise — cracked mud, dry lakebeds and giraffe-pattern skin. It composes well with domain warping (feeding coordinates through one noise function before sampling another) to break up the otherwise very regular, evenly-spaced look that comes from placing exactly one feature point per grid cell.
Frequently asked questions
What is the difference between Worley noise and Perlin noise?
Perlin noise interpolates smooth gradients between grid points, producing soft, cloud-like variation. Worley noise instead measures the distance from each pixel to the nearest of a set of scattered feature points, producing cellular, Voronoi-like patterns with distinct regions and boundaries — it looks fundamentally different even though both are common building blocks for procedural textures.
What does F2 minus F1 give you, and why is it useful?
F1 is the distance to the nearest feature point and F2 the distance to the second-nearest. F2 - F1 approaches zero only at points equidistant from two feature points, which is exactly the boundary between Voronoi cells — so this combination draws bright, thin lines along cell edges, the standard technique for cracked-earth and reptile-scale textures.
How is Worley noise made fast enough for real-time rendering?
By bucketing feature points into a spatial grid and deriving each cell's feature point from a hash of the cell's coordinates rather than storing points in an array. A pixel then only needs to check its own grid cell and its eight neighbours, giving O(1) cost per pixel instead of comparing against every feature point in the image.
Try it live
Everything above runs in your browser — open Worley Noise and change the parameters while it is running. Nothing is installed, nothing is uploaded, the whole model lives in one tab.
▶ Open Worley Noise simulation