Skip to content

Rendering System

The Rendering System in Mapbox GL JS is responsible for transforming geographic data and styling information into visual representations on the screen. It leverages WebGL to provide hardware-accelerated rendering of map elements including fills, lines, symbols, and 3D features like terrain and buildings. This page explains the core rendering architecture, shader system, and rendering process, providing a foundation for understanding more specific aspects of the system. For details on the Painter class that coordinates rendering operations, see Painter, and for information about specific layer types, see Layer Rendering.

Rendering Architecture

The Mapbox GL JS rendering system follows a pipeline architecture that transforms geographic data and styles into pixels on the screen.

SVG
100%

Key Components

  1. Painter: Coordinates the rendering process, manages WebGL context, and handles drawing of different layer types. The Painter controls the rendering order, depth and stencil settings, and dispatches draw calls to the GPU.

  2. Shader Programs: WebGL shader programs specialized for each layer type with:

    • Vertex shaders for position transformation and attribute processing
    • Fragment shaders for determining pixel colors, textures, and effects
  3. Data Buckets: Layer-specific data structures optimized for efficient rendering, containing:

    • Vertex arrays for geometric data
    • Index arrays for defining primitives
    • Program configurations for style properties
  4. Transform State: Manages the viewport, camera position, and projection matrices used to convert geographic coordinates to screen space.

Shader System

Mapbox GL JS uses GLSL (OpenGL Shading Language) shaders for rendering different layer types with specialized visual effects. The shader system consists of multiple interconnected components:

SVG
100%

Shader Preludes

Shader preludes are included at the beginning of vertex and fragment shaders to provide common functionality:

  1. Terrain Prelude (_prelude_terrain.vertex.glsl):

    • Handles elevation sampling from DEM textures
    • Calculates terrain elevations and exaggeration
    • Provides vertex displacement for terrain-following layers
  2. Lighting Prelude (_prelude_lighting.glsl):

    • Implements ambient and directional lighting calculations
    • Handles shadow mapping and lighting effects
    • Controls material properties for 3D objects
  3. Fog Prelude (_prelude_fog.fragment.glsl):

    • Implements atmospheric effects and distance fog
    • Handles color blending based on distance
  4. Shadow Prelude (_prelude_shadow.fragment.glsl):

    • Implements shadow mapping techniques
    • Handles shadow sampling and filtering
    • Controls shadow intensity and bias

GLSL Pragma Instructions

The shader system uses a special pragma-based template system to inject style properties into shaders:

#pragma mapbox: define highp vec4 color
#pragma mapbox: define lowp float opacity

// Later in the shader:
#pragma mapbox: initialize highp vec4 color
#pragma mapbox: initialize lowp float opacity

This allows the shaders to access style properties defined in the style specification, bridging the gap between JavaScript style definitions and GLSL shader code.

Rendering Process

The rendering pipeline processes data from source to screen through several stages:

SVG
100%

Layer Rendering

Let's examine how line layers are rendered as an example:

  1. Preparation Phase:

    • Check if the layer has opacity and width
    • Load necessary textures (for patterns or gradients)
    • Determine elevated sections for terrain interaction
  2. Shader Selection:

    • Choose between regular line or pattern programs
    • Add appropriate #define values for features like dashes, gradients, or borders
  3. Draw Call Execution:

    • Set appropriate depth and stencil states
    • Upload uniforms like matrices, widths, and colors
    • Bind vertex and index buffers
    • Execute WebGL draw calls

Uniform Values

Uniforms transfer style properties and state to shaders. For line layers, these include:

// From line_program.ts
'u_matrix': calculateMatrix(painter, tile, layer, matrix),
'u_pixels_to_tile_units': pixelsToTileUnits,
'u_device_pixel_ratio': pixelRatio,
'u_width_scale': widthScale,
'u_floor_width_scale': floorWidthScale,
'u_units_to_pixels': [
    1 / transform.pixelsToGLUnits[0],
    1 / transform.pixelsToGLUnits[1]
],
// ... additional uniforms

Data Structures

To efficiently organize geometric data for rendering, Mapbox GL JS uses specialized data structures:

Bucket System

Each layer type has a corresponding bucket type that organizes data for rendering:

SVG
100%

Array Types

Mapbox GL JS uses typed arrays with specific layouts to efficiently transfer data to WebGL:

SVG
100%

These array types are defined with specific memory layouts to match WebGL vertex attributes exactly, minimizing data conversion overhead.

Advanced Rendering Features

Mapbox GL JS includes several advanced rendering features:

Terrain Rendering

The terrain system samples elevation data to create 3D terrain surfaces and affects how other layers are rendered:

SVG
100%

Lighting System

The 3D lighting system provides realistic shading for 3D elements:

SVG
100%

The lighting system supports both flat lighting for simple maps and 3D lighting for more complex scenes with terrain and 3D buildings.

Rendering Modes and Effects

Mapbox GL JS supports various rendering modes and effects that can be combined to create diverse visual styles:

EffectDescriptionKey Files
FillRendering filled polygonsfill.vertex.glsl, fill.fragment.glsl
LineRendering lines with various stylesline.vertex.glsl, line.fragment.glsl
PatternTextured fills and linesfill_pattern.vertex.glsl, line_pattern.vertex.glsl
Extrusion3D buildings and extruded polygonsfill_extrusion.vertex.glsl, fill_extrusion.fragment.glsl
TerrainElevation-based terrain rendering_prelude_terrain.vertex.glsl
FogAtmospheric distance fog_prelude_fog.fragment.glsl
ShadowsDynamic shadows for 3D elements_prelude_shadow.fragment.glsl, _prelude_shadow.vertex.glsl

WebGL Integration

Mapbox GL JS interacts with WebGL through a carefully designed abstraction layer:

SVG
100%

This abstraction layer provides:

  • WebGL state caching to minimize redundant state changes
  • Cross-browser compatibility handling
  • Resource management for programs, buffers, and textures
  • Error handling and debugging support

Performance Optimizations

The rendering system employs several optimizations to maintain high performance:

  1. Bucket system: Organizes data for efficient GPU transfer and rendering
  2. Shader preprocessing: Generates specialized shaders for different styling needs
  3. Buffer reuse: Minimizes GPU memory allocation and transfer
  4. Draw call batching: Reduces WebGL state changes
  5. WebGL state caching: Avoids redundant state changes
  6. Web Workers: Processes tile data in parallel threads

These optimizations allow Mapbox GL JS to render complex maps with high performance, even on mobile devices.