XR Briefing: 10M Splats at 9.2 ms in a Browser Tab
The number that matters is the frame time
A browser tab drew a 10 million splat interior scan in 9.2 milliseconds per frame at 1920 by 1080, on an Apple M3 Max in Chrome 154. The renderer is Radix, shipping as @sparkjsdev/radix 0.0.1 from a commit dated October 29, and the figure is on the project’s own comparison page, against SparkJS 2.3.1 on the same PLY files and camera path. Spark takes 16.5 ms on that cathedral interior. Over five scans from 0.5M to 10M splats, Radix is 1.37 times as fast, and 1.8 times at the top end.
Ten million splats is not a demo scene. It is the upper range of what photogrammetry produces for a room, and the state of Gaussian Splatting three years in is exactly this: capture works, decoding works, getting the result into a headset does not. Radix is not a new algorithm. It moves the bottleneck into the frame that draws it.
Sorting was the whole problem
A splat renderer does not depth test. It alpha blends back to front, so every splat needs an order for the camera you are looking through right now. Move the camera and the order changes. WebGL2 has no compute shaders, so SparkJS and everything else projects on the GPU, hands keys to a worker, sorts there, and uploads an index buffer. The drawn order is stale, and the docs admit it: “a few frames old while the camera moves.”
Flat, that is a shimmer. In a headset, at hundreds of degrees of head rotation per second, the blend order at the centre of the display can be several frames stale when the photon leaves the panel, and overlapping splats resolve in the wrong order.
Radix does it in-frame. Projection writes a sort key per splat, compaction and a radix sort run as compute passes, and the draw reads the visible count from a GPU buffer. The project’s summary: “0 readbacks: compaction, the radix sort, and the indirect draw run on the GPU in the same frame.” Keys are 24-bit by default, with 16 and 32 available; Spark uses 32. Every object in the scene is projected and sorted together, so overlapping objects blend in one draw call and animation continues while the order is rebuilt.
One sort for two eyes
The XR decision matters more. Radix projects once from the head with a small per-eye correction and sorts once for both eyes, through the WebXR and WebGPU binding or WebGL2 XR. The sort is per splat per frame, so running it twice nearly doubles the cost of the most expensive pass. Shaders are TSL, which compiles to WGSL or GLSL, and the tradeoffs between those APIs are why this needs its own renderer.
A splat is 32 bytes with HDR colour and PBR fields, or 16 packed, and files can be PLY, SPZ, RAD or RDX, the last a chunked container with range reads, so a large scan streams instead of downloading. The bandwidth budget in a headset is what makes 16 bytes more than a nicety.
Where it loses
Against PlayCanvas 2.23.1 on WebGPU, with culling matched, Radix runs at 1.03 times PlayCanvas: parity. Read that as WebGPU renderers being about a third faster than WebGL2 ones, not as Radix beating everyone. On its WebGL2 backend it is slower than SparkJS, 1.09 times by the project’s own measurement, because the worker sort costs more when the camera moves.
The feature list has holes where production work lives. It loads and saves level of detail trees but does not choose subsets; skinning, paged RAD streaming, SOG and raycasting are missing. 31 of 42 SparkJS examples port unchanged, the rest blocked by those. A 0.0.1 package from last week is not for shipping.
Browser splatting also depends on the WebXR and WebGPU binding reaching browsers people actually have, narrower than WebGL2’s reach. Nobody has published a Quest frame time. What changed this week is narrower than the headline: 10M splats inside 16 ms is a browser problem now, not a native-engine one.
→ Radix documentation and comparison · Benchmarks · source · HN discussion
Also worth knowing
- VRChat refused an “AI-generated” content label despite roughly 95 percent of 21,000 survey respondents wanting one, and its Steam rating fell to 33 percent positive over 30 days. → Road to VR
- Titanfall 2’s VR mod opened its multiplayer beta to everyone, the first time a flat-to-VR conversion of a competitive shooter has had public servers. → Road to VR
- Ultrawings Remastered and Ultrawings 2 Gold Edition were rebuilt for Quest 3 with a higher native resolution and TruTouch haptics, at $14.99 and $19.99, with no confirmed upgrade path. → UploadVR
How this was reported: this briefing summarises reporting published by the sources linked throughout. Figures, quotes and claims belong to those outlets and are attributed at the point of use; the analysis and framing are ExplorXR's. Editorial standards.
Background reading
The explainers behind today's stories, if you want the fundamentals first.
Gaussian Splatting, Three Years In: What Shipped, What Still Breaks
Khronos put splats inside glTF, SPZ 4 cut encode times again, and Quest 3 measurements show where the frame budget goes. A state of play for splats in XR.
August 2026: The Roadmap Slipped, the Tools Got Cheaper
Apple cut Vision Pro staff, Pico pushed its flagship to Q4, Schell laid off for the first time in 24 years. The month XR's constraint became cost, not capability.
XR's Next Platform War Is Over the 3D Compositor
OpenXR standardized spatial windows, Meta caps apps at two slots, and Pico moved rendering into the OS core. The compositor is XR's next platform.
Related reading
XR Daily: Meta's Glasses Heard What They Shouldn't
Ray-Ban Meta recorded speech without the wake word, photos became splats inside a browser, Steam's Linux client went 64-bit, and a Godot sky got rebuilt.
XR Daily: Mario 64 on Your Table
Super Mario 64 as a tabletop diorama on Vision Pro, Owlchemy's Hyper Visor leads XREAL Aura's launch, browser Gaussian splatting, and Getty's Chapter 11.
XR Daily: College Football Kicks Off in 8K
Meta streams college football to Quest in 8K, VR Glasses reshape the Quest line, WebGPU shader components go mainstream, and hand tracking hits VR games.