One renderer, two APIs
Metal on macOS, Vulkan everywhere else. Shaders are written once in GLSL and turned into SPIR-V and Metal Shading Language at load time, then cached on disk.
Metal · Vulkan 1.2the Vulkan path is checked through MoltenVK on macOS
Ray-traced shadows
On Apple silicon, the sun's shadows are traced: one ray per pixel at half resolution, in a pass of its own, reused by the next frame. Elsewhere, cascaded shadow maps take over.
~2.7 msfor the ray-traced shadow pass
Temporal upscaling
Our own temporal upscaler, in the manner of FSR 2, runs on every backend; MetalFX where it exists; TAA at native resolution. Jitter, motion vectors and history clipping are all ours.
102–111 FPSat 67% render scale, against 84–92 native (forest, town, lake)
A streamed world
The world is cut into 64-metre chunks, each generated from the world seed alone. The client loads the nearest chunks first and drops the far ones; the server builds collision only where players are.
64 × 64 mchunks, the same on client and server
Surface relief
Parallax occlusion with self-shadowing on the ground and on walls: stones stand proud and mortar sinks. On walls the relief cuts the silhouette, so edges follow the stones instead of a flat line.
+2.8 msfor relief on the town plaza (15.9 → 18.7 ms)
Instancing and tree impostors
Props are culled and drawn instanced with two simpler levels of detail. Past 60 m a tree becomes an impostor: one quad showing the tree baked from eight directions, lit like everything else.
1.8×farther tree draw distance; Whisperwood props 1.99 → 1.42 ms
Particles from a fixed pool
Effects are data. Every particle lives in one pool reserved at start, so playing an effect never allocates, and each blend mode is one instanced draw.
12,000particles at most; ~11,800 live cost 0.14 ms to update
Lazy, compressed textures
Textures are block-compressed on every core and cached. Character parts load as placeholders and become real textures the first time they're drawn.
2.8 GB → 1.1 GBtexture memory in town; a full outfit's 24 textures in 10 ms
Servers that scale out
The world simulation is C++; accounts, characters, chat and the world directory are Go services on Postgres. Continents run as separate servers, and busy ones split into layers on Kubernetes.
~800players per world server process in our load tests