Back to Journal

Perlin Noise and the Shape of Terrain

Perlin noise turns a lattice of random gradients into smooth, natural variation, and stacked in octaves it becomes the hills, ridges and coastlines of nearly every generated world; understanding its few parameters is understanding terrain itself.

Early computer graphics had a look that anyone who saw it remembers: surfaces too clean, edges too sharp, colours laid on like enamel. Everything resembled a showroom model of itself. Ken Perlin, who worked on the imagery of the film Tron (1982), was troubled by exactly this sterility, and in the early 1980s he developed a function meant to give synthetic images some of the irregularity of the physical world, the mottling of marble, the drift of smoke, the uneven grain of stone.

He described the technique in a 1985 paper, and in 1997 he received an Academy Award for Technical Achievement for it, an unusual honour for a few dozen lines of mathematics. The function, now simply called Perlin noise, has since escaped the film studio entirely. It shades clouds, animates fire, perturbs camera shake and, above all, raises terrain, because the smooth randomness it produces looks remarkably like the slow work of erosion and uplift.

This essay walks through that function from the inside: what makes it different from ordinary randomness, how stacking it at several scales produces convincing mountains, how its output becomes a heightmap in Unity, and what its successor, Simplex noise, changed. The aim is to make the parameters feel less like dials one turns until something looks right and more like a vocabulary one can speak with intent.

Why random numbers are not enough

Fill a grid with independent random values and read them as heights, and the result looks less like terrain than like television static frozen in place. Each value has no relationship with its neighbours, so the surface leaps from peak to pit at every step. Real ground is correlated: a point halfway up a slope sits between the higher point above it and the lower one below. What terrain requires is a function that is random in the large but smooth in the small.

The first obvious remedy is value noise: place random values only at integer lattice points and interpolate between them. It works, after a fashion, but the result betrays its grid. Peaks and valleys cluster on lattice points, and the eye soon picks out a faint checkerboard rhythm underneath, like the ribs of a ship showing through its hull. Perlin's insight was to randomise not the values at the lattice points but the slopes, and that small change made all the difference.

The resulting family is called gradient noise. Because the value at each lattice point is fixed at zero and only the direction of change is random, the highs and lows fall between grid points rather than on them, scattered more evenly and with less visible regularity. The function is still continuous, still deterministic for given coordinates, still cheap to evaluate. It simply hides its scaffolding better, which in graphics is most of what matters.

The mechanism of gradient noise

Consider the two dimensional case. Space is divided into unit squares by an integer lattice, and each lattice corner is assigned a pseudorandom gradient vector, usually chosen by hashing the corner's coordinates through a permutation table so the same corner always yields the same vector. To evaluate the noise at some point inside a square, one computes, for each of the four corners, the vector from that corner to the point, and takes its dot product with the corner's gradient.

Those four dot products are four opinions about the value at the point, each one saying how far the point lies along its corner's chosen direction. They are blended by interpolation, first along x and then along y. The blend is not linear. Perlin's original noise used the smoothstep curve 3t squared minus 2t cubed, and his improved noise of 2002 replaced it with 6t to the fifth minus 15t to the fourth plus 10t cubed, whose first and second derivatives both vanish at the cell boundaries.

That fade curve is the quiet hero of the method. With linear interpolation, the surface would be continuous but creased along every cell edge, and lighting would reveal the creases mercilessly as faint lines across the hills. With the quintic curve, slope and curvature both match across the boundary, so normals computed from the heightmap vary smoothly and the grid disappears beneath the shading. It is a small piece of calculus that saves an enormous amount of visual embarrassment.

One consequence of the construction deserves mention because it surprises people in practice. At every integer coordinate, the offset vector from the nearest corner is zero, so the dot product is zero and the raw noise is zero there. Sampling a noise function only at whole numbers therefore returns a constant, flat and lifeless. Unity's Mathf.PerlinNoise shows the same behaviour: feed it integer x and y and it returns the same value every time, so coordinates must be scaled into fractional positions.

Octaves and fractal detail

A single layer of Perlin noise produces gentle, rounded hills of roughly one size, pleasant but monotonous, like a quilt thrown over furniture. Real terrain has features at every scale at once: continental swells, mountain ranges, individual peaks, boulders, pebbles. The standard remedy is to sum several layers, called octaves, each sampled at a higher frequency and weighted by a smaller amplitude. The sum is known as fractal Brownian motion, usually abbreviated fBm, and it is the workhorse of terrain generation.

Two parameters govern the stacking. Lacunarity is the multiplier applied to frequency from one octave to the next; persistence is the multiplier applied to amplitude. With lacunarity of two and persistence of one half, four octaves have frequencies of 1, 2, 4 and 8 and amplitudes of 1, 0.5, 0.25 and 0.125. Each layer has twice the detail and half the influence of the one before, which mirrors, roughly, how natural surfaces distribute their roughness across scales.

The amplitudes in that example add up to 1.875, so the summed noise can range almost twice as wide as a single octave. Most implementations divide by the total amplitude to bring the result back into a predictable range before using it. Raising persistence toward one makes fine detail dominate, producing jagged, noisy ground; lowering it toward zero leaves the large forms alone and the surface grows smooth and soft. Lacunarity much above two leaves visible gaps between scales of detail.

The number of octaves is a question of resolution and cost. Each octave doubles, under the usual lacunarity, the frequency of the finest detail, and there is no point adding layers whose features are smaller than the spacing between heightmap samples, since they will only alias into speckle. Six to eight octaves is common for a terrain of moderate size. Each one costs a full noise evaluation per sample, so in a large world this choice is felt directly in generation time.

From noise to heightmap

A heightmap is the simplest bridge between a noise function and a visible landform: a two dimensional array in which each entry is an elevation. In Unity the built in Terrain component reads one through TerrainData.SetHeights, which takes a float array indexed by row and column with values from zero to one, scaled by the terrain's configured height. The heightmap resolution must be a power of two plus one, such as 513 or 1025, so that the grid of vertices divides evenly.

Filling it is straightforward. For each sample, one computes world coordinates, multiplies them by a base frequency so that a hill spans many samples rather than one, adds an offset derived from the world seed so different seeds produce different terrain, and evaluates the fBm sum. Mathf.PerlinNoise returns values roughly between zero and one, though it can stray slightly outside that range, so clamping before writing is a sensible precaution against small spikes at the edges of tolerance.

Raw fBm, written straight into the heightmap, tends to look uniformly lumpy. The interesting terrain comes from shaping it. Raising normalised height to a power greater than one flattens the lowlands and sharpens the peaks, giving broad valleys beneath steep mountains. Taking one minus the absolute value of signed noise produces ridged noise, with sharp crests like mountain spines. Domain warping, in which the input coordinates are themselves displaced by another noise field, bends features into the swirled, folded forms of eroded ground.

Simplex noise and other descendants

In 2001 Perlin introduced Simplex noise to address the limitations of his original design. Classic noise evaluates the corners of a square, a cube or, in n dimensions, a hypercube with two to the n corners, which grows expensive quickly in higher dimensions. Simplex noise instead divides space into simplices, triangles in two dimensions and tetrahedra in three, which have only n plus one corners. Each corner's contribution falls off radially, so no separate interpolation step is needed at all.

The practical gains are fewer directional artifacts, since the classic grid's axis aligned bias is reduced, and lower cost in three and four dimensions, where animated or volumetric noise is often computed. For a static two dimensional heightmap the difference is less dramatic, and plenty of shipped games use classic noise without regret. Simplex noise was patented for some years, which prompted alternatives such as OpenSimplex; the patent has since expired, and the choice is now mostly a matter of taste.

Other descendants address other needs. Worley noise, sometimes called cellular noise, measures distance to scattered feature points and produces cell patterns suited to cracked mud, stone tiles or scales. Erosion simulations, hydraulic and thermal, can be run over a noise heightmap to carve channels and deposit sediment, adding the marks of history that pure noise lacks. In practice terrain generators combine several of these, with Perlin or Simplex noise still forming the foundation beneath.

Tuning by eye and by reason

The temptation with noise is to tweak numbers until something looks right and then stop asking why. It is worth resisting. Every parameter has a physical meaning: base frequency sets the size of the largest features, octaves set how fine the smallest go, persistence sets how rough the ground feels underfoot, lacunarity sets how cleanly the scales separate. A designer who knows this can ask for broader valleys or sharper ridges and know which number to change.

Good tooling helps the reasoning along. An editor window that renders the heightmap as a greyscale image, updated as sliders move, turns tuning from guesswork into observation, and exposing the parameters on a ScriptableObject lets several terrain profiles, marsh or highland or coast, live side by side as data rather than code. Seeds should be visible and editable too, so that an interesting or broken world can be reproduced and shared with a colleague in a sentence.

It is a curious thing that so much of what looks like geology in games is really one function, evaluated again and again at different scales and summed. There is no erosion in it, no tectonics, no time. And yet a few lines of interpolation produce hillsides on which settlements are built and lost, valleys in which night gathers early, ridgelines that seem to have stood for ages. Perlin set out to make images less sterile; he gave developers a way of faking deep time.