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
- Pass 1: Scan the layer, collect keys, values, and feature byte-ranges
- 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
- Camera position determines viewport bounds via
get_viewport_bounds() - Bounds are expanded by
TILE_BUFFER = 1ring of tiles - 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
- Place labels in priority order (style layer order, then by feature rank)
- Test each candidate against a spatial grid of already-placed labels
- Rejected labels with
text-variable-anchorretry with alternative anchor positions - 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.wgslshader 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 = 24pxShapedText::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.