Perlin's Noise Algorithm
Perlin's Noise Algorithm
Published: 05 March 2023
Understanding "Noise"
If you have ever dipped your toes into the world of procedural generation, you have undoubtedly encountered the concept of noise. While it sounds simple, the reality is a bit more nuanced.
At its most fundamental level, noise is simply a function that accepts parameters and returns a value based on a specific set of algorithmic rules.
Dimensionality of Noise
Depending on how many input parameters the function requires, we categorize noise by its dimensionality:
| Dimension | Description | Common Use Case |
|---|---|---|
| 1D | Single parameter input | Simple waveforms, 1D terrain profiles |
| 2D | Two parameter inputs | Heightmaps, textures, clouds |
| 3D | Three parameter inputs | Volumetric fog, 3D caves, marble |
| ND | parameter inputs | Higher-dimensional data mapping |
For those learning to implement these algorithms, I recommend starting with 2D noise. It is significantly easier to visualize, and once you have a working 2D system, you can generally generalize the logic to 1D or 3D.
Generating Textures from Noise
To turn a noise function into a visual texture, we iterate through every pixel of an image. Here is the logic represented in pseudocode:
for (int i = 0; i < image.height; i++) {
for (int j = 0; j < image.width; j++) {
// Normalize coordinates to [0, 1) range
float n = noise((float)j / image.width, (float)i / image.height);
// Scale noise to a [0, 1] range
n = n / NOISE_MAX;
// Assign grayscale value to R, G, and B channels
image.SetPixel(j, i, n, n, n);
}
}
Why Normalize?
You might wonder why we divide the coordinates j and i by the width and height. This process normalizes the values, mapping them to a range of . While this might seem arbitrary now, this step is crucial for applying transformations to the noise later to achieve specific visual effects.
The Failure of Pure Randomness
If we try to create noise using a basic rand() function, like this:
float noise(float x, float y) { return rand(x + y); }(Note: Here, x and y act as the seed)
The result is visually chaotic. There are no discernible patterns or features—just "static." To get something useful, we need Coherent Noise.
Coherent Noise Properties
Coherent noise is essentially a "smoothed" version of random noise. For a noise function to be considered coherent, it must satisfy these criteria:
- Determinism: Providing the same input always yields the same output.
- Local Continuity: A slight shift in input results in a slight shift in output.
- Global Randomness: A significant shift in input results in a seemingly random change in output.
The Perlin Noise Algorithm
While many coherent noise algorithms exist, Perlin Noise is the gold standard.
A Bit of History
Ken Perlin created this algorithm in 1983 because he was tired of the stiff "machine-like" appearance of early CGI. His work was formally presented in the 1985 SIGGRAPH paper An Image Synthesizer. Perlin developed this while working at the Mathematical Applications Group (MAGI) on Disney's sci-fi film Tron (1982). For his contribution to the field, he received an Academy Award for Technical Achievement in 1997.
How the Algorithm Works
In a 2D plane, any input point falls within a grid square defined by the nearest integers.
1. Identify the Corners Given a point , the four surrounding corners are:
2. The Process Flow The algorithm follows this logical sequence:
The Implementation Challenge
We can precalculate every possible integer point. Since there are infinite integers, we cannot store infinite vectors. To solve this, the original algorithm uses:
- A set of 256 random unit vectors.
- A permutation table of 256 random values.
By using these, the algorithm assigns a pseudo-random vector to any integer coordinate. The trade-off is that the noise pattern will repeat every 256 units.
Starting the Code
To begin implementing this, we define our global storage for the gradients and the permutation mapping:
static Vector2 gradients[B + B + 2];
static int permutation[B + B];
(Where B represents the base size of the permutation table)