MapMathMapMath

CHAPTER 19

How maps render: tiles, vectors, and the GPU pipeline

From lat/lon to pixels on screen: the full rendering pipeline for raster tiles, vector tiles, and WebGL-based maps like MapLibre and Mapbox.

4 min read

Understanding how a map renders helps you make better performance decisions: when to use raster tiles, when to switch to vector, why overzooming looks blurry, and what actually happens when you call map.setCenter().

The raster tile pipeline

A traditional web map works like this:

  1. Pre-render: The server renders every zoom level (0–22) of the world into 256×256 PNG tiles, storing them as /tiles/{z}/{x}/{y}.png
  2. Request: The browser calculates which tiles cover the viewport and requests them
  3. Stitch: The browser lays the tiles on a grid with CSS absolute positioning
  4. Pan: Moving the map repositions the grid; new tiles load at the edges
Zoom 0: 1 tile   (1×1 grid), whole world
Zoom 1: 4 tiles  (2×2 grid)
Zoom 2: 16 tiles (4×4 grid)
...
Zoom n: 4ⁿ tiles

Total tiles at zoom 14: 4¹⁴ ≈ 268 million. Pre-rendering the full world to zoom 14 takes terabytes. Most tile providers only pre-render land/sea separation at high zoom and compute city tiles on demand.

Raster tile pyramid

z2: 4×4 = 16 tiles

z01z14z216z364

Zoom

2

Tiles per axis

4

Total tiles

16

Tile coordinates

You saw the math in Chapter 5. The important rendering implication: at any zoom level, a tile is exactly 256×256 pixels (or 512×512 for HiDPI). The tile size never changes; the number of tiles grows.

Vector tiles (MVT)

optional, skip if familiarrefresher

MVT stands for Mapbox Vector Tile, now an open standard. Vector tiles are binary-encoded Protocol Buffer files, not images. Each tile contains geometry (points, lines, polygons) clipped to the tile boundary, plus attribute data for each feature.

Instead of pre-rendered images, vector tiles contain raw geometries and attributes. The browser renders them in real time using WebGL.

Raster tile: PNG image (opaque, ~50–200 KB)
Vector tile: Encoded features (lat/lon, properties, ~5–50 KB compressed)

Vector tiles enable:

  • Client-side styling, change colours, fonts, filters without new tiles
  • 3D extrusion, buildings, terrain
  • Interactivity, hover/click on individual features
  • Sharp text, labels re-render at native resolution

The Mapbox Vector Tile (MVT) format uses Protocol Buffers. Coordinates are quantised integers in a local tile coordinate space (usually 0–4096), not geographic degrees.

tile_x = Math.round((lon_merc - tile_origin_x) / tile_size * 4096)
tile_y = Math.round((lat_merc - tile_origin_y) / tile_size * 4096)

The quantisation to 4096 units per tile gives ~1/16th of a pixel resolution at zoom 14 (9.5 m/px), far more than visual precision requires. The integer encoding also compresses dramatically with delta-coding: consecutive vertices in a ring typically differ by small values.

The WebGL pipeline

Modern map renderers (Mapbox GL, MapLibre, deck.gl) use WebGL:

  1. Geometry upload, vertices uploaded to GPU memory as Float32Array
  2. Vertex shader, converts tile coordinates to clip space
  3. Rasterisation, GPU fills triangles and lines
  4. Fragment shader, computes final pixel colour (applies styles, lighting)
  5. Composite, multiple layers blended together

The vertex shader for a simple map tile looks roughly like:

uniform mat4 u_matrix;          // projection + view + model
attribute vec2 a_pos;           // tile coordinate (0–4096)

void main() {
  gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
}
Chapter 19 · Paid content

Continue reading "How maps render: tiles, vectors, and the GPU pipeline"

You've reached the end of the free preview. Unlock all 22 paid chapters, including distance math, bearings, polygons, spatial indexing, and 3D map rendering, plus a downloadable PDF and the companion code repo.

  • All 22 paid chapters with worked examples
  • Downloadable PDF for offline reading
  • Companion GitHub repo (JavaScript + Python)
  • Free updates for life

Multiple payment options: card, Wise, and bank transfer.