Computer Graphics
Terrain and LOD: Landscape From Planet to Blade of Grass
Microsoft Flight Simulator 2020 renders the entire Earth surface - 510 million km² - on a laptop, with no multi-minute loading screens. This is possible because at any given moment only the tiles and polygons that are actually needed are rendered. Everything else is hidden behind quadtree LOD and tile streaming.
- Microsoft Flight Simulator 2020: Bing Maps Elevation tiles + streaming + LOD over Earth's surface in real time
- Ghost of Tsushima: 11 km² island at 1 m/pixel in 60 fps through LRU tile cache and aggressive LOD
- The Witcher 3: quadtree LOD with 6 levels, 1.5 km view distance without frame rate drops
- Unreal Engine 5 Nanite: virtual geometry without manual LOD - automatic cluster-based LOD for any mesh
Heightmap: A Planet From One Texture
Microsoft Flight Simulator 2020 renders the entire Earth surface - 510 million km². The only way to store that landscape: heightmaps. One 16-bit value per pixel encodes elevation in meters. A 1024x1024 texture at 1 m/pixel covers 1 km². The whole planet via Bing Maps Elevation: 32 TB of tiles.
**From heightmap to mesh.** The naive approach - generate an N×N vertex grid, each vertex displaced by the texture value. Problem: a 4096×4096 grid is 16 million vertices. With a tessellation shader, only a coarse 64×64 grid is sent from the CPU; the GPU adds vertices near the camera at runtime.
**R16 vs R32F heightmap.** 16-bit integer (65536 levels) gives about 1.5 mm precision per 100 m of elevation range - sufficient for games. 32-bit float is needed for geodetically accurate systems. USGS Elevation Data (public DEM) is distributed as GeoTIFF: R32F with CRS coordinates.
Why are terrain normals computed from the heightmap rather than stored in a separate texture?
Quadtree LOD: Fewer Polygons in the Distance
The Witcher 3 has a 1.5 km view distance. Rendering the entire terrain at max resolution: 2.25 km² times 1 vertex/m² = 2.25 million vertices. The eye cannot distinguish polygons at 500 m. Quadtree LOD divides the terrain into patches and picks mesh density based on camera distance.
**T-junction problem.** At the boundary between patches of different LOD levels, T-junction artifacts appear - gaps in the mesh that reveal the background. Two solutions: 1) skirts - drop the patch edge downward to cover the gap; 2) vertex morphing - smoothly move high-detail vertices toward low-detail positions near LOD boundaries.
What problem do 'skirts' solve in terrain quadtree LOD?
GPU Tessellation: Polygons From Thin Air
DirectX 11 introduced the tessellation pipeline in 2009. The idea: instead of sending millions of vertices from the CPU, send a coarse patch. The Hull Shader sets the subdivision factor, the fixed-function Tessellator subdivides geometrically, the Domain Shader reads the heightmap and displaces each new vertex. Detail on demand with zero CPU overhead.
**Displacement mapping vs normal mapping.** A normal map changes only shading normals - the silhouette stays flat. Displacement mapping (via tessellation) actually moves geometry - the object gains real volume at its edges. For terrain this is critical: cliffs on the horizon need a correct silhouette. The standard combination: tessellation + displacement for large forms, normal maps for fine surface detail.
How does tessellation + displacement differ from normal mapping?
Terrain Streaming: World Bigger Than VRAM
Ghost of Tsushima has an island of 11 km² at 1 m/pixel resolution. A 16-bit heightmap alone: 11 * 10^6 * 2 bytes = 22 MB. With normal maps, albedo, roughness, splat maps - 500+ MB. VRAM budget: 8 GB. Solution: tile-based streaming - load only the tiles around the camera.
**Virtual Texturing (Sparse Textures).** DirectX 11.2 / OpenGL 4.4 support sparse textures - one huge virtual texture (128K x 128K pixels) without allocating all of VRAM. The GPU maps visible tiles to physical memory on demand. Unreal Engine 5 uses Virtual Shadow Maps on the same principle. Assassin's Creed: Origins terrain virtual texturing: a single 16K x 16K albedo map for all of Egypt.
More polygons always means better visuals
The LOD rule: optimal detail is the level where additional polygons are imperceptible at the target viewing distance. Terrain quadtree + tessellation delivers detail where the eye sees it and saves budget everywhere else.
Ghost of Tsushima renders a full island at 60 fps on PS4 Pro not through raw hardware power but through aggressive LOD: 1 polygon/m at 1 km instead of 1 polygon/cm. The polygon budget goes exactly where it matters.
Why does terrain tile streaming use LRU eviction rather than simply clearing tiles when they leave the view frustum?
Key ideas
- Heightmap: R16 texture with elevation, normals from central differences - cheaper than a separate normal map
- Quadtree LOD: recursive patch subdivision until Camera Distance < 2 * patch.size - fewer polygons in the distance
- T-junctions: skirts (drop edges down) or vertex morphing - mandatory at LOD boundaries
- Tessellation: Hull Shader sets the factor, Domain Shader samples heightmap for each new vertex
- Streaming: LRU tile cache in VRAM, async HTTP load, virtual texturing for megatextures
Related topics
Terrain LOD completes the geometry rendering cycle.
- GPU Graphics Pipeline — Tessellation shaders - Hull, Tessellator, Domain - are GPU pipeline stages
- Post-Processing — Terrain renders into the HDR G-buffer and passes through bloom and tone mapping
- Animation: Skeletal and Morph — Vegetation animation on terrain needs the LOD level of each patch
Вопросы для размышления
- Unreal Engine 5 Nanite eliminates manual LOD. At what cost? What can traditional quadtree terrain do that Nanite cannot?
- How would deformable terrain (explosion craters) be implemented while accounting for quadtree LOD and the need to update normals?
- Virtual texturing solves the megatexture problem. What new problems does it introduce (feedback buffer, mip selection, latency)?
Связанные уроки
- cg-15 — Terrain passes through the same HDR post pipeline: bloom, tone mapping
- cg-08 — Tessellation shaders are part of the GPU graphics pipeline between VS and PS
- alg-10 — Quadtree LOD is a spatial tree: the same BFS/DFS traversal used for culling
- cg-17 — Vegetation animation on terrain needs the LOD level of each patch
- arch-08-memory-hierarchy