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:

no-alignment

Five different levels of detail visualized by color (green = highest LOD, blue = lowest LOD)

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:

no-alignment

Four shadow map cascades, decreasing in detail from left to right

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.

no-alignment

Atmospheric scattering at sunset with visible Rayleigh and Mie scattering

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.

no-alignment

Physically based materials (top row: dielectric; bottom row: metallic; roughness increasing from left to right). Far right: test model and textures

Additional Features

  • Cross-platform support (Windows, Linux)
  • High dynamic range pipeline
    • Reinhard and filmic tone mapping
    • Adaptive camera exposure based on scene luminance
  • Custom mesh and scene formats with Blender importer/exporter
  • Dynamic text rendering using FreeType
  • Sortable render queue to minimize state changes