Intermediate

Procedural Terrain Generation

Generate realistic, infinite terrain using noise functions, erosion simulation, and biome systems that create believable natural landscapes.

Heightmap-Based Terrain

The most common approach to terrain generation uses a heightmap — a 2D grid where each cell stores an elevation value. Multiple layers of noise at different frequencies (octaves) are combined to create natural-looking terrain.

Noise Layering

LayerFrequencyAmplitudeCreates
ContinentalVery lowVery highMajor landmasses and ocean basins
MountainLowHighMountain ranges and valleys
HillMediumMediumRolling hills and ridges
DetailHighLowSmall bumps and surface variation

Erosion Simulation

Raw noise terrain looks alien and unrealistic. Erosion simulation transforms it into natural-looking landscapes by simulating water and thermal processes.

  • Hydraulic erosion: Simulate water droplets flowing downhill, picking up sediment and depositing it. Creates river valleys, deltas, and realistic drainage patterns.
  • Thermal erosion: Material falls from steep slopes to shallow ones, creating talus slopes and softening sharp features.
  • Wind erosion: Simulate wind carrying particles, creating dunes and wearing down exposed surfaces.
Python - Hydraulic Erosion (Simplified)
def erode(heightmap, iterations=50000):
    for _ in range(iterations):
        # Random droplet starting position
        x = random.uniform(0, heightmap.shape[1] - 1)
        y = random.uniform(0, heightmap.shape[0] - 1)
        sediment = 0.0
        speed = 1.0
        water = 1.0

        for step in range(64):
            # Calculate gradient at current position
            gx, gy = compute_gradient(heightmap, x, y)

            # Move droplet downhill
            x -= gx
            y -= gy

            if out_of_bounds(heightmap, x, y):
                break

            # Calculate height difference
            h_new = sample(heightmap, x, y)
            h_diff = h_new - h_old

            # Deposit or erode
            if h_diff > 0:  # Going uphill
                deposit(heightmap, x, y, sediment)
            else:  # Going downhill
                erode_point(heightmap, x, y, -h_diff)

            water *= 0.99  # Evaporation
    return heightmap

Biome Distribution

Biomes are assigned based on elevation and moisture. Use a Whittaker diagram to map temperature/moisture combinations to biome types:

  • Low elevation + high moisture = Tropical rainforest
  • Low elevation + low moisture = Desert
  • High elevation + high moisture = Taiga/Snow
  • Medium elevation + medium moisture = Temperate forest

Infinite Terrain (Chunked Generation)

For open-world games, terrain is generated in chunks around the player. Since noise functions are deterministic and position-based, each chunk generates identically regardless of when it is created.

  • Load ring: Generate chunks within a radius around the player.
  • LOD levels: Nearby chunks get full resolution; distant chunks use lower resolution meshes.
  • Seamless borders: Because noise is continuous, chunk borders are automatically seamless.
  • Async generation: Generate chunks on background threads to avoid frame stutters.
Key takeaway: Realistic terrain comes from layered noise plus erosion simulation. Use multiple noise octaves for the base shape, apply hydraulic and thermal erosion for realism, and assign biomes based on elevation and moisture. Chunk-based systems enable infinite worlds.