Overview
This is a real-time terrain renderer written using C++ and OpenGL 3.3. The terrain is rendered as a series of static meshes (chunks) that are displaced in a vertex shader based on a heightmap. The chunks are assembled into a quadtree that is traversed at runtime to provide dynamic level of detail. Instanced meshes such as trees and rocks are scattered across the terrain and assigned to chunks.
Level of Detail
The heightmap is divided into chunks of varying sizes during a preprocessing stage. These chunks are then assembled into a quadtree. At runtime, the quadtree is subdivided from its root based on a simple distance heuristic. The result is a dynamic level of detail optimization, visualized here:
Cascaded Shadow Maps
Before the forward lighting pass, the renderer generates a set of cascaded shadow maps for the visible scene. This provides high quality shadows at both near and far distances without requiring an extremely large shadow map. The number of cascades is configurable, with the commonly used four being shown here:
Atmospheric Scattering
The sky is rendered with a fullscreen quad that samples a set of precomputed textures. These textures are generated based on the work of Precomputed Atmospheric Scattering (Bruneton 2017). As a result, the renderer supports dynamic time of day for both the sky and for ambient light contribution.
Physically Based Rendering
The renderer supports a physically based material model. Each material is represented by four textures (or constants):
- Albedo (base color)
- Normal
- Metallic
- Roughness
The material is then shaded by combining the diffuse Lambertian and specular Cook-Torrance BRDFs based on the incoming direct and indirect light.
Additional Features
- Cross-platform support (Windows, Linux)
- High dynamic range pipeline
- Custom mesh and scene formats with Blender importer/exporter
- Dynamic text rendering using FreeType
- Sortable render queue to minimize state changes