Skip to content

Rendering System ​

OpenLayers implements a multi-renderer architecture that supports Canvas, WebGL, and DOM-based rendering backends. This flexible system allows applications to choose the optimal rendering approach based on performance requirements, feature complexity, and browser capabilities. The rendering system abstracts the complexity of different graphics APIs while providing specialized renderers for different layer types and use cases.

Multi-Renderer Architecture ​

The rendering system is built around a core abstraction that supports three primary rendering backends: Canvas (2D), WebGL, and DOM. Each backend provides specialized renderers optimized for different layer types and performance characteristics.

Core Renderer Hierarchy ​

SVG
100%

Renderer Selection Strategy ​

Layer TypeCanvas RendererWebGL RendererDOM Renderer
Vector featuresCanvasVectorLayerRendererWebGLPointsLayerRendererN/A
Tile layersCanvasTileLayerRendererWebGLTileLayerRendererN/A
Image layersCanvasImageLayerRendererN/AN/A
Vector tilesCanvasVectorTileLayerRendererN/AN/A
HTML overlaysN/AN/ADOM positioning

Rendering Pipeline ​

The rendering pipeline is implemented through a standardized interface across all renderer types, with each layer renderer implementing the core methods prepareFrame(), renderFrame(), and renderDeferred().

Core Rendering Flow ​

SVG
100%

Frame State Structure ​

Each rendering cycle operates on a FrameState object containing:

PropertyPurposeUsed By
viewStateCamera position, zoom, rotationAll renderers
extentVisible area boundsCulling, tile selection
pixelRatioDevice pixel ratioCanvas sizing, WebGL buffers
layerStatesArrayLayer visibility, opacityLayer iteration
declutterDecluttering treesText/symbol positioning

Canvas Rendering System ​

The Canvas rendering system uses the HTML5 Canvas API to draw map elements. It forms the default rendering backend for OpenLayers and supports all layer types.

Canvas Rendering Hierarchy ​

The Canvas rendering system is built around a core set of renderer classes:

Renderer ClassPurposeMain Methods
CanvasLayerRendererBase class for all Canvas renderersprepareFrame(), renderFrame()
CanvasTileLayerRendererRenders tile-based layers (OSM, etc.)drawTile(), enqueueTiles()
CanvasVectorLayerRendererRenders vector featuresrenderFeature(), renderWorlds()
CanvasImageLayerRendererRenders image-based layersloadImage(), getImage()
CanvasVectorTileLayerRendererRenders vector tilesdrawTile(), updateExecutorGroup_()

Canvas Rendering Process ​

SVG
100%

Canvas Instruction-Based Rendering ​

Canvas renderers implement an instruction-based rendering system that separates command generation from execution, enabling efficient caching and decluttering.

Builder/Executor Pattern Implementation ​

SVG
100%

Vector Tile Rendering Specifics ​

The CanvasVectorTileLayerRenderer extends this pattern with tile-specific optimizations:

// From src/ol/renderer/canvas/VectorTileLayer.js:203-320
updateExecutorGroup_(tile, pixelRatio, projection) {
  // Create CanvasBuilderGroup for tile extent
  const builderGroup = new CanvasBuilderGroup(0, sharedExtent, resolution, pixelRatio);
  
  // Render features to instructions
  const render = function (feature, index) {
    const dirty = this.renderFeature(feature, squaredTolerance, styles, builderGroup, declutter, index);
  };
  
  // Create executor group from instructions
  const executorGroupInstructions = builderGroup.finish();
  const renderingReplayGroup = new CanvasExecutorGroup(replayExtent, resolution, pixelRatio, ...);
}

WebGL GPU-Accelerated Rendering ​

The WebGL rendering system leverages GPU acceleration through shader-based rendering, providing high performance for large datasets and complex visual effects.

WebGL Architecture Components ​

SVG
100%

WebGL Buffer Management ​

The WebGLHelper class centralizes WebGL resource management:

ClassPurposeKey Methods
WebGLHelperWebGL context and resource managementbindBuffer(), flushBufferData(), useProgram()
WebGLArrayBufferTyped array management for GPUfromArray(), getArray(), getSize()
WebGLPostProcessingPassShader-based post-processingrender(), setUniforms()
WebGLRenderTargetOff-screen rendering targetsclearCachedData(), readPixel()

WebGL Points Rendering Pipeline ​

The WebGLPointsLayerRenderer implements a specialized pipeline for high-performance point feature rendering using GPU acceleration and web workers.

Points-to-GPU Data Flow ​

SVG
100%

Shader Attribute System ​

Points are rendered as quads with the following vertex structure:

// From src/ol/renderer/webgl/PointsLayer.js:205-236
this.attributes = [
  {
    name: 'a_localPosition',  // Quad corner: (0,0), (1,0), (1,1), (0,1)
    size: 2,
    type: AttributeType.FLOAT,
  },
];

this.instanceAttributes = [
  {
    name: 'a_position',      // World position of point center
    size: 2,
    type: AttributeType.FLOAT,
  },
  {
    name: 'a_hitColor',      // Hit detection color encoding
    size: 2,
    type: AttributeType.FLOAT,
  },
  {
    name: 'a_featureUid',    // Feature unique identifier
    size: 1,
    type: AttributeType.FLOAT,
  },
  // ... custom attributes from user configuration
];

Hit Detection Implementation ​

WebGL hit detection uses GPU-based color encoding:

// From src/ol/renderer/webgl/PointsLayer.js:655-666
const data = this.hitRenderTarget_.readPixel(pixel[0] / 2, pixel[1] / 2);
const color = [data[0] / 255, data[1] / 255, data[2] / 255, data[3] / 255];
const index = colorDecodeId(color);
const opacity = this.renderInstructions_[index];
const uid = Math.floor(opacity).toString();
const feature = source.getFeatureByUid(uid);

WebGL Tile Rendering System ​

The WebGLTileLayerRenderer extends WebGLBaseTileLayerRenderer to provide texture-based tile rendering with custom shader support.

Tile-to-Texture Pipeline ​

SVG
100%

Tile Rendering Uniforms ​

The tile renderer provides these uniforms to shaders:

// From src/ol/renderer/webgl/TileLayer.js:23-31
export const Uniforms = {
  TILE_TEXTURE_ARRAY: 'u_tileTextures',      // Texture array sampler
  TEXTURE_PIXEL_WIDTH: 'u_texturePixelWidth', // Texture dimensions
  TEXTURE_PIXEL_HEIGHT: 'u_texturePixelHeight',
  TEXTURE_RESOLUTION: 'u_textureResolution',   // Map units per pixel
  TEXTURE_ORIGIN_X: 'u_textureOriginX',       // World coordinate origin
  TEXTURE_ORIGIN_Y: 'u_textureOriginY',
};

Tile Quad Rendering ​

Each tile is rendered as a quad with texture coordinates:

// From src/ol/renderer/webgl/TileLayer.js:115-116
// Triangle A: P0, P1, P3
// Triangle B: P1, P2, P3
this.indices_.fromArray([0, 1, 3, 1, 2, 3]);

Coordinate Transformations ​

A crucial aspect of the rendering system is transforming between different coordinate spaces:

SVG
100%

Every renderer maintains transformation matrices to convert between these spaces:

pixelTransform: Transforms from world coordinates to pixel coordinates
inversePixelTransform: Transforms from pixel coordinates to world coordinates
renderTransform: Transforms from pixel coordinates to render target coordinates

Cross-Renderer Hit Detection ​

Hit detection implementations vary significantly between rendering backends, each optimized for their respective graphics API constraints.

Canvas Hit Detection Strategies ​

StrategyImplementationUse Case
GeometricDirect coordinate-in-geometry testsSimple shapes, precise detection
Color-codedOff-screen rendering with unique colorsComplex styling, overlapping features
Executor replayRe-execute drawing commands for hit testingVector tile features

Canvas Vector Hit Detection ​

// From src/ol/renderer/canvas/VectorLayer.js:370-460
getFeatures(pixel) {
  if (!this.hitDetectionImageData_ && !this.animatingOrInteracting_) {
    // Create hit detection image with color-coded features
    this.hitDetectionImageData_ = createHitDetectionImageData(
      size, transforms, this.renderedFeatures_, 
      layer.getStyleFunction(), extent, resolution, rotation
    );
  }
  return hitDetect(pixel, this.renderedFeatures_, this.hitDetectionImageData_);
}

Canvas Vector Tile Hit Detection ​

// From src/ol/renderer/canvas/VectorTileLayer.js:332-425
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, matches) {
  for (let i = 0; i < renderedTiles.length; i++) {
    const executorGroups = tile.executorGroups[layerUid];
    for (let t = 0; t < executorGroups.length; t++) {
      found = executorGroups[t].forEachFeatureAtCoordinate(
        coordinate, resolution, rotation, hitTolerance, featureCallback
      );
    }
  }
}

WebGL Hit Detection Implementation ​

WebGL hit detection uses GPU-accelerated color encoding for high-performance feature identification:

// From src/ol/renderer/webgl/PointsLayer.js:635-667
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, matches) {
  const pixel = applyTransform(frameState.coordinateToPixelTransform, coordinate.slice());
  const data = this.hitRenderTarget_.readPixel(pixel[0] / 2, pixel[1] / 2);
  
  // Decode feature ID from pixel color
  const color = [data[0] / 255, data[1] / 255, data[2] / 255, data[3] / 255];
  const index = colorDecodeId(color);
  const uid = Math.floor(this.renderInstructions_[index]).toString();
  
  const feature = source.getFeatureByUid(uid);
  if (feature) {
    return callback(feature, this.getLayer(), null);
  }
}

Decluttering System ​

Decluttering prevents overlapping labels and symbols for better readability:

  1. Features are assigned Z-index values based on their importance
  2. Features are rendered in Z-index order
  3. Features that would overlap already-rendered features are skipped or repositioned
SVG
100%

Performance Considerations ​

Caching Strategies ​

The rendering system employs various caching strategies to improve performance:

  1. Tile Caching: Rendered tiles are cached to avoid re-fetching and re-rendering
  2. Canvas Caching: Canvas elements are reused when possible
  3. Executor Caching: Vector rendering instructions are cached and reused

Render Optimization Techniques ​

  1. Viewport Culling: Only rendering features within the visible viewport
  2. Level-of-Detail: Using appropriate tile levels based on zoom
  3. Preloading: Loading tiles at nearby zoom levels for smooth transitions
  4. Web Workers: Using web workers for offloading processing (WebGL)

Canvas vs. WebGL Guidelines ​

ScenarioRecommended RendererReason
Large number of points (>10,000)WebGLHardware acceleration for better performance
Complex vector stylingCanvasBetter support for complex styles
Standard map visualizationCanvasSimpler implementation, good browser compatibility
Custom data visualizationWebGLCustom shaders for visual effects
Mobile devicesContext-dependentWebGL may be faster but Canvas is more reliable