1. Baseline (current)
Multi-mesh per pin (5+ meshes), per-frame ring + crystal animation.
Desktopwhy → Mirrors today's BeaconCluster cost profile. Heaviest. On mobile, the cumulative geometry + draw-call count is what was driving the 'Renderer Recovering' cycling (~143 geometries, 336 draw calls per frame measured on a Galaxy device).
2. Simple
One sphere mesh per pin. No animation. No HTML overlay.
Mobilewhy → Floor-level cost — fewest moving parts. Works as a fallback if InstancedMesh has issues. Visually plain (no pulse, no rings) but the data still reads. Pure 'safety net' option.
3. InstancedMesh
All pins drawn in 1 draw call via THREE.InstancedMesh. Per-pin colour via instance attribute.
Bothwhy → Industry-standard pattern for many copies of a shape. Best perf for any scenario with N>20 markers. Same visual as the simple sphere but ~99% fewer draw calls. The architecturally-best winner for both tiers.
4. InstancedMesh + pulse
Same instancing, plus per-frame matrix update for a subtle scale pulse.
Bothwhy → Adds the 'alive' feel of the baseline pulse without the per-pin mesh count. Demonstrates that animation on InstancedMesh is just one matrix update per pin per frame, not per-mesh state. Recommended for desktop; potentially mobile if perf allows.
5. Sprite billboards
2D camera-facing canvas-texture sprites, one shared material per category.
Mobilewhy → Cheapest possible — no 3D geometry, just textured quads. Always face the camera. Useful when 3D crystal/reticle isn't worth the cost. Visual is flat-iconic, less 'tactical hologram' feel.
6. Points cloud
Single THREE.Points object, custom GLSL for size + colour per point.
Mobilewhy → Maximum efficiency — entire pin set is one draw call with one shader. Looks like data viz / a starfield. Loses the 'pin' affordance; reads as 'glowing dot.' Good for satellite-imagery basemap where pins shouldn't compete.
7. Instanced 3D pin model
Cone-shaped 3D pin oriented outward, instanced. Per-pin colour + scale.
Desktopwhy → Most recognisable as a 'pin' (vs a flat dot). Single draw call. Heavier vertex count than a sphere but the silhouette pays back. Recommended for desktop where the extra vertex shading is essentially free.
8. Instanced + straight-line connections
Pulsing instanced pins + cyan straight-chord lines between pins of the same story-group.
Desktopwhy → Earlier connection-line attempt — straight chords cut through the sphere. Operator feedback: 'I don't see the connection between?' Variant 12 below replaces this with proper great-circle arcs along the sphere surface, which is the actual idiom for 'connections between places' (think Apple Maps / Flightradar24). Kept here for direct comparison.
9. Pin model + shader pulse
Same pin geometry as variant 7, plus a custom shader that pulses the colour intensity over time. Single uTime uniform updated once per frame.
Bothwhy → Demonstrates the key trick: animation in the GPU (one uniform update for ALL pins) instead of in JS (per-pin per-frame). Same 'alive' feel as the baseline pulse without ANY per-pin work. Great default for both tiers — visually richer than static pins, basically free.
10. Pin model + halo ring
Two instanced meshes total: pin (cone, oriented outward) + halo (ring, flat on sphere surface beneath each pin).
Bothwhy → Halo gives the 'ground footprint' affordance — eye reads 'pin anchored at this spot' instead of 'pin floating somewhere.' 2 draw calls regardless of pin count. The richer-look-cheap-cost sweet spot.
11. Holographic pin (Fresnel rim glow)
Same cone geometry, but the fragment shader computes Fresnel (rim brightness based on view angle). Edges glow as if emitting light. Adds subtle scan-line over time.
Desktopwhy → The 'tactical hologram' look that matches the mission-control aesthetic, achieved with a 4-line shader trick. Same geometry cost as variant 7 — Fresnel is pure shader math. Best on desktop where the alpha-blended translucency reads cleanest.
12. Pin model + great-circle arcs
Pin model (variant 7) + curved arcs along the sphere surface connecting story-group members. Each arc has 24 segments, lifted slightly above the surface, with an animated dashed shader showing 'data flowing.'
Desktopwhy → Replaces variant 8's straight chords (which cut THROUGH the sphere — operator: 'I don't see the connection'). Great-circle arcs follow the surface like flight paths — THE idiomatic 'connections between places' look. Animated dash shows direction. Premium desktop polish.
Reading the counters
The most important number is calls/frame. Mobile GPUs choke on draw-call count more than triangle count. The baseline runs ~5-7 draw calls per pin × 50 pins = ~250-350 calls. InstancedMesh / Points / Sprites collapse that to 1-2 calls regardless of pin count. That single change is what stopped the context-loss cycling on real-device QA.
The geom counter shows allocated GPU geometry buffers. Each per-pin mesh allocates one; InstancedMesh allocates one for the whole set. After context loss, the browser has to re-upload every geometry — keeping this number small is what lets the GPU restore cleanly without immediately triggering another loss.