Skip to content

Internals

Deep dives into the major subsystems.

MVT Decoder

src/mvt.rs contains a hand-rolled protobuf decoder (no prost dependency) that parses Mapbox Vector Tiles.

Two-Pass Parsing

  1. Pass 1: Scan the layer, collect keys, values, and feature byte-ranges
  2. Pass 2: Parse features using the collected keys/values

This avoids allocating intermediate structures for the entire tile. Feature properties are stored as HashMap<String, serde_json::Value>.

Geometry Types

ID Type Decoded as
1 Point Single [x, y] coordinate
2 LineString Vec of coordinate pairs
3 Polygon Vec of rings (outer + holes)

Tile coordinates (0–4096 extent) are converted to world coordinates during decoding. The tile is gzip-compressed (flate2 for native, browser DecompressionStream for WASM).

Varint Handling

read_varint uses u64 internally (not usize) to prevent shift-left overflow on wasm32 where usize is 32 bits.

Tile Loading

src/tile_loader/ implements an async tile fetcher with an LRU cache.

State Machine

Each tile request progresses through: Requested → Loading → Loaded | Failed

Visible Tile Calculation

  1. Camera position determines viewport bounds via get_viewport_bounds()
  2. Bounds are expanded by TILE_BUFFER = 1 ring of tiles
  3. Tiles are sorted center-first before requesting (closest to camera = highest priority)

Over/Dezoom Fallback

When a tile hasn't loaded yet:

  • Overzoom: find_loaded_ancestor() walks up 3 zoom levels for a coarser tile
  • Dezoom: find_loaded_descendants() BFS walks down 3 zoom levels for finer tiles

Ancestor tiles are clipped to the target tile's bounds via clip_bounds in the per-tile storage buffer.

LRU Cache

Tiles are stored as Rc<VectorTile> in an LRU cache. get_tile() returns Option<Rc<VectorTile>> for O(1) clone.

Tile Fade-In

New tiles fade in over 300ms. Opacity is tracked via a tile_first_seen HashMap and interpolated per-frame.

Symbol Collision

src/collision.rs (51 KB) handles label placement to prevent overlapping text and icons.

Algorithm

  1. Place labels in priority order (style layer order, then by feature rank)
  2. Test each candidate against a spatial grid of already-placed labels
  3. Rejected labels with text-variable-anchor retry with alternative anchor positions
  4. Accepted labels fade in, rejected labels fade out

Smart Collision Skipping

The renderer tracks camera center and zoom at last collision resolve. If the camera has moved less than 2px since the last resolve, full collision is skipped — only fade animations advance. This avoids expensive O(n log n) collision work during smooth panning.

Per-Label Opacity

Label opacity is stored in a GPU storage buffer (binding 2, group 1), separate from vertex data. The shader reads label_opacity[label_index] * tile_opacity. This means only a small ~2–4 KB array is uploaded when collision state or fades change, rather than rebuilding the entire vertex buffer.

Text & Glyph Rendering

Glyph Atlas (src/glyph_atlas.rs)

  • Parses PBF protobuf glyph data (SDF bitmaps)
  • Packs glyphs into a dynamic shelf-packed texture atlas (1024x1024, grows by doubling)
  • SDF byte stored in the alpha channel — reuses the icon.wgsl shader with zero shader changes
  • Basic Latin (0–255) loaded on style load; additional Unicode ranges loaded lazily

Text Shaper (src/text_shaper.rs)

  • SimplePbfShaper: 1:1 codepoint-to-glyph mapping at PBF_BASE_SIZE = 24px
  • ShapedText::wrap(max_width_px, line_height): word wraps at spaces, forced break if no space

SDF Thresholds

The is_sdf vertex attribute encodes both mode and halo information:

Value Mode
0.0 RGBA (no SDF)
1.0 Sprite SDF
2.0 + halo_buff PBF glyph SDF

Fill: buff = 192/256 = 0.75. Halo: buff = (6.0 - halo_width/fontScale) / 8.0. Both use smoothstep(buff - gamma, buff + gamma, dist) with gamma = 0.105.

Tessellation Cache

src/tessellation_cache.rs caches polygon triangulation results (earcutr output) keyed by tile coordinate + feature identity. This avoids re-tessellating the same geometry when tiles are re-extracted due to camera changes. The cache uses get_or_insert_with() — no clones needed.

Raster Tiles

src/raster.rs implements a raster tile rendering pipeline for satellite imagery. Raster tiles are fetched, decoded (PNG/JPEG/WebP via the image crate), and rendered as textured quads below vector geometry using raster.wgsl.