Procedural Terrain Generation
The terrain system uses a chunk-based approach with geologically-inspired geography types that smoothly transition between regions. Each region is assigned a geography type deterministically based on its position, ensuring consistent generation. This approach combines techniques from procedural generation research with geological principles.
Overview
The terrain generation combines several techniques:
-
Fractal Brownian Motion (FBM): Multi-octave noise for realistic height variation. FBM combines multiple octaves of noise at different frequencies and amplitudes to create natural-looking terrain.
-
Region-based Geography Types: Deterministic assignment of geography types based on position using hash functions, ensuring the same region always generates the same type.
-
Smooth Boundary Blending: Distance-weighted interpolation between regions using smoothstep functions, creating seamless transitions.
-
Edge Caching: Ensures perfect continuity between terrain chunks by caching edge heights and reusing them for adjacent chunks.
-
Elevation Smoothing: Additional smoothing applied when large elevation differences occur between regions, preventing discontinuities and holes.
The interactive visualization above demonstrates the terrain generation system. Adjust grid size, region size, and rotation to see how these parameters affect the terrain appearance. Click and drag to rotate the camera, or scroll to zoom.
Geography Types
The system supports twelve distinct geography types, each with unique geological characteristics:
Primary Terrain Types
-
Mountain: High elevation (3.0 base), significant variation (2.5), detailed noise (6 octaves) - Represents alpine and mountainous regions
-
Valley: Low elevation (0.5 base), moderate variation (1.0), smooth noise (4 octaves) - River valleys and lowlands
-
Plateau: Medium-high elevation (2.0 base), low variation (0.8), simple noise (3 octaves) - Elevated flatlands
-
Coastal: Low-medium elevation (0.8 base), moderate variation (1.2), organic noise (3 octaves) - Coastal plains and beaches
-
Desert: Medium elevation (1.5 base), low variation (0.6), subtle noise (4 octaves) - Arid desert landscapes
-
Forest: Medium elevation (1.2 base), high variation (1.5), detailed noise (5 octaves) - Forested hills and valleys
Advanced Geological Features
-
Canyon: Deep elevation (0.3 base), high variation (2.0), erosion patterns (5 octaves) - River-carved canyons with steep walls
-
River Delta: Very low elevation (0.2 base), gentle variation (0.4), branching patterns (4 octaves) - Low-lying deltas with distributary channels
-
Badlands: Medium elevation (1.0 base), high variation (1.8), fine detail (6 octaves) - Eroded, rugged terrain with sharp features
-
Tundra: Low elevation (0.6 base), minimal variation (0.5), smooth noise (3 octaves) - Flat, cold regions with gentle hills
-
Volcanic: High elevation (2.5 base), high variation (2.2), steep cones (7 octaves) - Volcanic mountains and cones
-
Karst: Medium elevation (1.3 base), moderate variation (1.6), sinkhole patterns (5 octaves) - Limestone terrain with sinkholes
Smooth Boundary Blending
The key innovation is the smooth boundary blending system. Instead of hard transitions between geography types, the system:
-
Identifies the current region and all neighboring regions
-
Calculates distance-based weights for each neighbor
-
Blends elevations from all contributing regions
-
Applies additional smoothing when large elevation differences occur
-
Ensures continuous terrain without visible seams
Elevation Smoothing Algorithm
To prevent discontinuities and holes when very different terrain types meet (e.g., mountain to valley), the system applies additional smoothing:
// Calculate elevation range
const minElevation = Math.min(...elevations);
const maxElevation = Math.max(...elevations);
const elevationRange = maxElevation - minElevation;
// If there's a large elevation difference, apply extra smoothing
if (elevationRange > 2.0) {
const smoothFactor = 0.7; // Blend towards average
const avgElevation = elevations.reduce((sum, e, i) => sum + e * weights[i], 0);
elevation = elevation * (1 - smoothFactor) + avgElevation * smoothFactor;
}
// Ensure minimum elevation to prevent holes
elevation = Math.max(0, elevation);
This prevents the artifacts visible in the visualization where sharp transitions create holes or depressions.
Chunk-Based System with LOD
Each chunk is a dynamically-sized grid of vertices (adapts based on distance from camera for Level of Detail):
-
Close to camera: 120×30 grid, high detail
-
Medium distance: 160×30 grid, medium detail
-
Far away: 160×5 grid, low detail
Chunks are generated ahead of the camera and disposed when out of view, creating an infinite landscape.
Edge Continuity
To ensure seamless terrain between chunks, the system implements edge caching:
-
Each chunk caches the heights of its back edge
-
The next chunk uses these cached heights for its front edge
-
This guarantees perfect continuity without gaps or discontinuities
-
Detail noise is only applied to interior points, preserving edge alignment
Example: Edge Caching Implementation
// Store edge heights cache globally for continuity
if (!(window as any).terrainEdgeCache) {
(window as any).terrainEdgeCache = new Map<number, number[]>();
}
const edgeCache = (window as any).terrainEdgeCache;
// Get front edge Z position
const chunkFrontZ = zOffset - (gridSizeZ / 2) * spacing;
const chunkBackZ = zOffset + (gridSizeZ / 2) * spacing;
// Get cached front edge heights if available
const frontEdgeKey = Math.round(chunkFrontZ * 10) / 10;
const cachedFrontEdge = edgeCache.get(frontEdgeKey);
// When generating terrain
for (let i = 0; i <= gridSizeX; i++) {
for (let j = 0; j <= gridSizeZ; j++) {
const isFrontEdge = j === 0;
if (isFrontEdge && cachedFrontEdge && cachedFrontEdge[i] !== undefined) {
// Use exact cached height for perfect continuity
y = cachedFrontEdge[i];
} else {
// Generate new height with detail noise
y = baseElevation + detailNoise;
}
heightMap[i][j] = y;
}
}
// Cache back edge heights for next chunk
const backEdgeHeights: number[] = [];
for (let i = 0; i <= gridSizeX; i++) {
backEdgeHeights.push(heightMap[i][gridSizeZ]);
}
const backEdgeKey = Math.round(chunkBackZ * 10) / 10;
edgeCache.set(backEdgeKey, backEdgeHeights);
Geological Principles
The terrain generation is informed by geological principles:
Erosion Patterns
-
Canyons: Formed by river erosion, characterized by deep valleys with steep walls
-
River Deltas: Formed by sediment deposition, creating low-lying, branching patterns
-
Badlands: Result from rapid erosion, creating rugged, highly varied terrain
Tectonic Features
-
Mountains: Formed by tectonic uplift, with high elevation and significant variation
-
Volcanic: Created by volcanic activity, with steep cones and high variation
-
Plateaus: Formed by uplift without significant folding, creating elevated flatlands
Weathering and Erosion
-
Karst: Limestone terrain shaped by chemical weathering, creating sinkholes and irregular patterns
-
Desert: Shaped by wind erosion, creating smooth, low-variation terrain
-
Tundra: Minimal erosion due to permafrost, creating flat, gentle terrain
References
Academic Papers
-
Perlin, K. (1985). "An Image Synthesizer." ACM SIGGRAPH Computer Graphics, 19(3), 287-296. DOI - Original Perlin noise paper
-
Musgrave, F. K., et al. (1989). "The Synthesis and Rendering of Eroded Fractal Terrains." ACM SIGGRAPH Computer Graphics, 23(3), 41-50. DOI - Fractal terrain generation with erosion
-
Kelley, A. D., et al. (1988). "Terrain Simulation Using a Model of Stream Erosion." ACM SIGGRAPH Computer Graphics, 22(4), 263-268. DOI - Hydraulic erosion simulation
-
Prusinkiewicz, P., & Hammel, M. (1993). "A Fractal Model of Mountains with Rivers." In Graphics Gems III (pp. 2-7). Academic Press.
Online Resources
-
Perlin Noise - The foundation of procedural terrain, developed by Ken Perlin
-
Fractal Landscapes - Mathematical basis for terrain generation using fractals
-
Procedural Generation - General techniques for algorithmic content creation
-
Diamond-Square Algorithm - Alternative terrain generation technique
-
Worley Noise - Cellular noise for natural patterns
-
Hydraulic Erosion - Natural erosion processes
Books
-
Ebert, D. S., et al. (2002). Texturing & Modeling: A Procedural Approach. Morgan Kaufmann. (Chapter on terrain modeling)
-
Parberry, I. (1995). "A Simple Method for Procedural Terrain Generation." In Game Programming Gems (pp. 473-475). Charles River Media.
Related Articles
-
An adventure with 3js 3d Backgrounds - Overview of the animated background system
-
L-System 3D Tree Generation - Tree generation techniques that populate the terrain
-
3d Background - Cell Shading - Rendering techniques used for the terrain
-
Noise Functions - Detailed explanation of Perlin noise, FBM, and other noise functions
-
Erosion Simulation - Hydraulic and thermal erosion algorithms that can enhance terrain realism by simulating natural processes that shape landscapes over time
Future Enhancements
Potential improvements based on current research:
-
Hydraulic Erosion: Simulate water flow to carve realistic river valleys and canyons. See Erosion Simulation for detailed algorithms and implementation approaches.
-
Thermal Erosion: Model material movement down slopes for more natural mountain shapes
-
Tectonic Simulation: Generate terrain based on plate tectonics for more realistic continental features
-
Weathering Models: Add chemical and physical weathering effects
-
Sediment Deposition: Model sediment transport and deposition in deltas and floodplains