logo
Kurashizu Blogwhere ideas flow
  • Home
  • News
  • Blog
  • About
  • Home
  • News
  • Blog
  • About

© 2026 Kurashizu. All rights reserved.

Admin·New Post·Service Status
Powered by Cloudflare·01.11.26
← Back to news

Perlin's Noise Algorithm

Original article
blog.jaysmito.dev|37 points|6 comments|by ibobev|Jul 22, 2026

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 NNN 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:

DimensionDescriptionCommon Use Case
1DSingle parameter inputSimple waveforms, 1D terrain profiles
2DTwo parameter inputsHeightmaps, textures, clouds
3DThree parameter inputsVolumetric fog, 3D caves, marble
NDNNN parameter inputsHigher-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 [0,1)[0, 1)[0,1). 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 PPP falls within a grid square defined by the nearest integers.

1. Identify the Corners Given a point P=(x,y)P = (x, y)P=(x,y), the four surrounding corners are:

  • P0=(⌊x⌋,⌊y⌋)P_0 = (\lfloor x \rfloor, \lfloor y \rfloor)P0​=(⌊x⌋,⌊y⌋)
  • P1=(⌊x⌋,⌊y⌋+1)P_1 = (\lfloor x \rfloor, \lfloor y \rfloor + 1)P1​=(⌊x⌋,⌊y⌋+1)
  • P2=(⌊x⌋+1,⌊y⌋)P_2 = (\lfloor x \rfloor + 1, \lfloor y \rfloor)P2​=(⌊x⌋+1,⌊y⌋)
  • P3=(⌊x⌋+1,⌊y⌋+1)P_3 = (\lfloor x \rfloor + 1, \lfloor y \rfloor + 1)P3​=(⌊x⌋+1,⌊y⌋+1)

2. The Process Flow The algorithm follows this logical sequence:

Perlin Noise Concept

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:

  1. A set of 256 random unit vectors.
  2. 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)