Terrain and 3D Features
This page documents the terrain rendering system and 3D features in Mapbox GL JS, with a focus on how terrain elevation, 3D buildings (fill extrusions), and lighting all work together. For information about the core rendering system, see Rendering System and Layer Rendering.
Overview
Mapbox GL JS supports rendering 3D terrain and extruded features like buildings, along with lighting and shadows to create realistic 3D maps. The terrain system uses Digital Elevation Models (DEMs) to create a 3D surface, while the fill extrusion system converts 2D polygons into 3D shapes with height.
Terrain System
The terrain system uses raster DEM (Digital Elevation Model) sources to render 3D terrain. When terrain is enabled, all map elements (including markers, layers, and 3D objects) are positioned relative to the terrain surface.
Terrain Configuration
Terrain is configured in the map style's terrain property:
{
"terrain": {
"source": "mapbox-dem",
"exaggeration": 1.5
}
}| Property | Type | Description | Default |
|---|---|---|---|
| source | string | ID of the raster-dem source | (required) |
| exaggeration | number | Scale factor for terrain elevation | 1 |
Terrain can also be enabled or updated programmatically:
map.setTerrain({ source: "mapbox-dem", exaggeration: 1.5 });To disable terrain:
map.setTerrain(null);Terrain Data Sources
Terrain requires a raster-dem source that provides elevation data. This source type is specifically designed for Digital Elevation Models:
{
"sources": {
"mapbox-dem": {
"type": "raster-dem",
"url": "mapbox://mapbox.mapbox-terrain-dem-v1",
"tileSize": 512,
"maxzoom": 14
}
}
}Terrain Processing Pipeline
The following diagram shows how terrain elevation data flows through the system:
Terrain Implementation Details
The terrain system includes several key functions in the shader code:
Elevation Sampling: The
elevation()function in the terrain vertex shader samples the DEM data to determine the height at any given point.Terrain-Layer Integration: All rendering layers query the terrain elevation using the shader functions and adjust their geometry accordingly.
Normal Calculation: Surface normals are computed for lighting calculations on the terrain.
When terrain is active, all map features including buildings, roads, and labels are positioned according to the underlying terrain elevation. This is why you'll see references to terrain elevation functions in various layer shaders, including fill extrusions.
The terrain shader includes functions to handle both flat and interpolated elevation, special handling for building footprints, and proper blending between terrain tiles.
Fill Extrusions
Fill extrusions convert 2D polygons into 3D shapes with height, used commonly for rendering buildings. They support advanced visual features like rounded edges, lighting, shadows, and patterns.
Fill Extrusion Configuration
Fill extrusions are configured as a layer type in the style:
{
"id": "buildings",
"type": "fill-extrusion",
"source": "composite",
"source-layer": "building",
"paint": {
"fill-extrusion-color": "#aaa",
"fill-extrusion-height": ["get", "height"],
"fill-extrusion-base": ["get", "min_height"],
"fill-extrusion-opacity": 0.8,
"fill-extrusion-edge-radius": 0.5
}
}Fill Extrusion Properties
| Property | Description | Default |
|---|---|---|
| fill-extrusion-height | Height of the extrusion | 0 |
| fill-extrusion-base | Base height of the extrusion | 0 |
| fill-extrusion-color | Color of the extrusion | "#000000" |
| fill-extrusion-opacity | Opacity of the extrusion | 1 |
| fill-extrusion-pattern | Image to use as a pattern | undefined |
| fill-extrusion-vertical-gradient | Whether to apply a vertical gradient | true |
| fill-extrusion-ambient-occlusion-intensity | Controls ambient occlusion effect | 0.3 |
| fill-extrusion-ambient-occlusion-radius | Radius for ambient occlusion | 3.0 |
| fill-extrusion-edge-radius | Radius for rounded edges | 0 |
| fill-extrusion-rounded-roof | Whether to round roof edges | true |
Fill Extrusion Processing Pipeline
This diagram shows how fill extrusions are processed and rendered:
Fill Extrusion and Terrain
When terrain is enabled, fill extrusions adjust to the underlying terrain elevation. This includes:
- Base Elevation: The base of the extrusion is positioned at the terrain elevation plus the base height
- Height: The extrusion extends from the base to the specified height above the terrain
- Normals: Surface normals are adjusted for proper lighting on sloped terrain
The shader code has special handling for ensuring buildings remain properly anchored to terrain, even on slopes. Fill extrusions query the terrain elevation through the elevation() function in the shader.
Lighting System
The lighting system provides realistic illumination for terrain and 3D features like fill extrusions. It supports ambient and directional lights with customizable properties.
Lighting Configuration
Lights are configured in the map style's lights array:
{
"lights": [
{
"id": "ambient",
"type": "ambient",
"properties": {
"color": "hsl(0, 0%, 100%)",
"intensity": 0.5
}
},
{
"id": "directional",
"type": "directional",
"properties": {
"color": "hsl(0, 0%, 100%)",
"intensity": 0.5,
"direction": [180, 30],
"cast-shadows": true,
"shadow-intensity": 0.8
}
}
]
}Lights can also be set programmatically:
map.setLights([
{
type: "ambient",
id: "ambient_light",
properties: {
color: "white",
intensity: 0.5
}
},
{
type: "directional",
id: "directional_light",
properties: {
color: "white",
intensity: 0.7,
direction: [180, 45],
"cast-shadows": true,
"shadow-intensity": 1.0
}
}
]);Light Types and Properties
| Type | Property | Description | Default |
|---|---|---|---|
| ambient | color | Light color | "white" |
| ambient | intensity | Light intensity (0-1) | 0.5 |
| directional | color | Light color | "white" |
| directional | intensity | Light intensity (0-1) | 0.5 |
| directional | direction | [azimuth, polar] in degrees | [180, 30] |
| directional | cast-shadows | Whether to cast shadows | false |
| directional | shadow-intensity | Shadow darkness (0-1) | 0.8 |
Lighting and Shadow System
Lighting and Shadow Implementation
The lighting system is implemented in shader code that applies lighting and shadow calculations to 3D features. Key components include:
- Ambient Lighting: Provides global illumination without directionality
- Directional Lighting: Simulates sunlight with direction and shadows
- Normal-based Lighting: Uses surface normals to calculate light intensity (NdotL)
- Shadow Mapping: Renders depth maps from the light's perspective to calculate shadows
- Shadow Biasing: Prevents shadow acne with intelligent bias calculation
- Cascaded Shadow Maps: Uses multiple shadow maps for different distance ranges
The lighting shader includes specialized functions:
apply_lighting(): Applies both ambient and directional lighting to a surfacecalculate_NdotL(): Calculates the dot product of normal and light directionshadow_occlusion(): Determines how much a fragment is in shadow
Advanced Fill Extrusion Features
Fill extrusions support several advanced visual features that enhance realism:
Ambient Occlusion
Ambient occlusion simulates the subtle darkening that occurs in corners and crevices where light is occluded. Fill extrusions support this through the fill-extrusion-ambient-occlusion-* properties:
"fill-extrusion-ambient-occlusion-intensity": 0.3,
"fill-extrusion-ambient-occlusion-radius": 3.0Flood Lighting
Flood lighting simulates light sources at the base of buildings, useful for night scenes:
"fill-extrusion-flood-light-color": "rgb(255, 255, 146)",
"fill-extrusion-flood-light-intensity": 0.2,
"fill-extrusion-flood-light-ground-attenuation": 0.7,
"fill-extrusion-flood-light-ground-radius": 5.0Rounded Edges
Fill extrusions support rounded edges and corners for more realistic buildings:
"fill-extrusion-edge-radius": 0.5,
"fill-extrusion-rounded-roof": truePatterns and Textures
Fill extrusions can be textured with image patterns:
"fill-extrusion-pattern": "building_pattern"Code Structure
Performance Considerations
When using terrain and 3D features, consider these performance tips:
- Terrain Complexity: Higher terrain exaggeration values require more geometry processing
- Fill Extrusion Density: Large numbers of 3D buildings can impact performance
- Shadows: Shadow maps require additional rendering passes and can be costly
- Edge Radius: Rounded edges on fill extrusions require more geometry processing
- Ambient Occlusion: Higher ambient occlusion values require more sampling
Debugging and Development Tools
Mapbox GL JS includes several debugging tools for terrain and 3D features:
- 3D Playground: A comprehensive debug page for testing 3D features (
debug/3d-playground.html) - Terrain Debug: A debug page specifically for terrain (
debug/terrain-debug.html) - Terrain Elevation Debug Widget: A widget that shows terrain elevation at cursor location
These tools allow you to adjust parameters like lighting, shadow quality, terrain exaggeration, and building appearance in real-time.
Complete Example
Here's a complete style example with terrain, 3D buildings, and lighting:
{
"version": 8,
"sources": {
"mapbox-dem": {
"type": "raster-dem",
"url": "mapbox://mapbox.mapbox-terrain-dem-v1",
"tileSize": 512,
"maxzoom": 14
},
"mapbox-streets": {
"type": "vector",
"url": "mapbox://mapbox.mapbox-streets-v8"
}
},
"terrain": {
"source": "mapbox-dem",
"exaggeration": 1.5
},
"lights": [
{
"id": "ambient",
"type": "ambient",
"properties": {
"color": "hsl(0, 0%, 100%)",
"intensity": 0.5
}
},
{
"id": "directional",
"type": "directional",
"properties": {
"color": "hsl(30, 80%, 95%)",
"intensity": 0.7,
"direction": [210, 40],
"cast-shadows": true,
"shadow-intensity": 0.8
}
}
],
"layers": [
// Base layers omitted for brevity
{
"id": "buildings",
"type": "fill-extrusion",
"source": "mapbox-streets",
"source-layer": "building",
"paint": {
"fill-extrusion-color": "hsl(35, 8%, 85%)",
"fill-extrusion-height": ["get", "height"],
"fill-extrusion-base": ["get", "min_height"],
"fill-extrusion-opacity": 0.9,
"fill-extrusion-edge-radius": 0.5,
"fill-extrusion-rounded-roof": true,
"fill-extrusion-ambient-occlusion-intensity": 0.3,
"fill-extrusion-ambient-occlusion-radius": 3.0
}
}
]
}