facett render engine — for idiots (use the new components)
The 5-minute version of render-engine.md. If you just want to use the map/graph components, read this. If you're changing the render path, read the full spec.
The mental model (one sentence)
One render kernel (facett-core), two skins (map, graph), two hardware categories (CPU, CPU+GPU) the box picks for you. You feed data + a Theme; you get a navigable component. SIMD, GPU-vs-CPU, wasm bundles — all auto.
Draw a map (3 lines)
use facett_map::MapView;
use facett_core::Theme;
// OSM data + borders are already GeoParquet (osm-katana convert did that).
let ways = facett_osm::read_ways("sweden.ways.parquet", 0, &Theme::skade())?;
let map = MapView::new("map", points).with_ways(ways); // category auto-selected
// drop `map` into any egui Ui: map.ui(ui);
- No GPU? It renders on
vello_cpu(SIMD auto, scalar if none). You do nothing. - GPU present? It uses the instanced wgpu path + vello overlay. You do nothing.
- Want it prettier?
Theme::skade()is the cyan/OKLCH preset. Effects auto-off on CPU.
Draw a graph (3 lines)
use facett_graphview::GraphView;
use facett_core::Theme;
let g = GraphView::new("g", nodes, edges).with_theme(Theme::skade());
g.layout_force(); // or .layout_sugiyama() / .layout_radial()
// g.ui(ui);
Same deal: CPU → vello_cpu; GPU → L0 instanced nodes/edges + vello L1 curves/labels. Graph data comes from knut (FalkorDB/Cypher) — facett never speaks Cypher.
Which crate do I use?
| I want… | use | notes |
| a 2D map | facett-map |
folds in the old facett-geomap (slippy/scroll mode) |
| a 3D map / city | facett-map3d |
extruded buildings, orbit camera |
| a node-edge graph | facett-graphview |
the engine; facett-graph/graph3d are thin skins |
| a system diagram | facett-syschart |
a graph skin |
| a pipeline / DAG | facett-pipeline |
graph skin + status/gantt overlay |
| to read OSM data | facett-osm |
GeoParquet/WKB → ways/points |
| theming / camera / SDF | facett-core |
the shared kernel; you rarely touch it directly |
The rules you must not break (if you edit the render path)
- L0 first, vello L1 optional. The base (SDF instanced wgpu + CPU fallback) must look great with zero vello. vello is the cherry on top, desktop-only.
- Inject-assert + emit every part-step. Don't bench/test only "draw map" — test project / clip / cull / shade / scissor / composite each (see the clip-pipeline SVG). Emitters are
testmatrix-feature-gated → stripped in release. - The final frame is emitted as a PNG blob. So a robot/agent can see the render without a human. Use it: render → emit →
Readthe PNG → judge. - Part-step benchers. Every step gets
facett.<skin>.<step>in the Bencher. - Modern-first. WebGPU / wgpu-compute / AVX2-NEON / Linebender stack. Legacy gets a free fallback or nothing. Small stack > big compat matrix.
How to debug "it draws but it's wrong" (the clipping bug, recipe)
- Run the matrix/robot test at the failing pose (e.g. street-level dolly-in).
- Walk the emit chain in order:
project → near_clip → cull → shade → scissor → composite. - The first red oracle is your stage. For the clip bug it's
scissor.ink_outside_rect > 0. Readthe emitted final-picture PNG to confirm with your own eyes (no human needed).- Fix, add a fail-on-bug / pass-on-fix matrix row, re-run. Don't regress the golden PNG.
How it ships
facett releases through nornir release from workspace_nordisk (it's [repo.facett] in the catalog, crates.io-publishable). nornir release publish does bump → gate → strip [patch] → publish → record → regenerate the book. Don't hand-cargo publish.