SplatsThe evolution of media, in brief
RSS

The framework under deck.gl just shipped a Gaussian splat renderer

A soft, hazy Gaussian splat render of San Francisco seen from Telegraph Hill, with Coit Tower rising in the centre of the frame and the downtown skyline behind it

Screenshot: luma.gl Gaussian Splat Viewer, rendering Spark's Coit Tower RAD capture · Tools

Theo Lindqvist

Theo Lindqvist

Aug 26, 2026, 12:40 PM ET-Tools

vis.gl has published a Gaussian splat module for luma.gl, the WebGPU and WebGL framework that deck.gl is built on. The package went up as a beta on Friday and a third build followed on Monday; it is MIT-licensed, it is about four hundred kilobytes of TypeScript, and the part that matters is that it reads a file format someone else designed.

Why it matters: Spark, World Labs' three.js splat renderer, introduced the .RAD format with its 2.0 release: a precomputed level-of-detail tree stored so that a viewer can pull arbitrary chunks over HTTP range requests instead of downloading a scene whole. It is a good design, and until now it had one implementation — the one that shipped with it.

A format with one implementation is a file layout. A format with two is closer to a standard. luma.gl reading RAD means a capture authored for Spark can now be rendered by the stack that deck.gl sits on, which is a different audience entirely: geospatial dashboards, not three.js scenes.

What shipped: The module exports eighteen source files' worth of machinery, and the division of labour is legible from the names alone. `SplatRADHierarchyManager` walks the authored per-row child links and decides what to refine based on where the camera is. `SplatResidencyManager` decides what to evict. `GPUPagedSplatRenderer` projects sparse rows, evaluates spherical harmonics to degree three, does one radix ordering across pages, and writes its own indirect draw commands on the GPU.

There is also `splat-gltf.ts`, which reads splat primitives out of glTF — the Khronos extension route rather than the Spark one — plus GPU picking, semantic filtering and a covariance projection helper. The viewer offers four backends: WebGPU in three capability tiers, and a WebGL2 fallback.

The out-of-core work landed in a single pull request earlier in the month that added 6,140 lines across eighteen files. Its verification section reports 2,007 Node tests and 1,953 Chromium browser tests passing, with hardware WebGPU regressions covering interleaved cross-page transparency, exact global depth ordering and forced 12-KiB binding limits.

By the numbers:

  • The Coit Tower scene in the shipped demo reports 50,937,127 rows. Loading it on a laptop this morning, the viewer's own readout said: 15,454 active rows against a 1,000,000-row budget, 983,040 resident rows across 15 pages, 2 pages pending, 205 fallback rows, 24.7 ms for the last refinement slice.
  • 15 of 778 source batches had been fetched at that point. The picture on screen was a recognisable San Francisco.
  • The asset file is named coit-40m. The hierarchy reports 50.9 million rows because Spark's tree stores merged, downsampled parent nodes above the original splats — the extra ten million are interior nodes, not captured Gaussians.
  • A 128-MiB binding limit supports roughly 2.8 million rows in the contiguous renderer, and up to 33,554,432 simultaneously active four-byte global-sort references in the segmented one.
  • The other scenes in the picker are conventional PLY captures from the public Hugging Face catalog — Train, Truck, Dr Johnson, Playroom — at 741,883 splats and 184 MB for the largest.

Yes, but: This is a beta, and the pull request that added it is unusually candid about what it does not claim. It says outright that traversing the Coit source through a bounded residency window "does not claim all authored rows fit in memory or that Spark visual/performance parity has been benchmarked." It notes that the published loaders.gl decodes RAD pages on the main thread and that applications wanting worker decoding must supply their own bridge. It notes that the segmented renderer has no GPU picker yet.

The bounded window is visible in the output. At a thousandth of the capture resident and a fraction of that drawn, the render is soft — the tower reads as a tower, the streets read as streets, and the detail that fifty million Gaussians presumably encode is somewhere else at that moment.

The independence of the implementation also has an asterisk. A refactor merged on Friday replaced what its author described as a "close Rust-derived foveation translation" with an independently structured version, and narrowed the Spark attribution in that file to a piece of MIT-licensed GLSL. Read plainly: the first cut was closer to a port than a reimplementation, and someone went back and did it properly.

The big picture: Splat formats have been proliferating faster than anyone can implement them — PLY, SPZ, SPLAT, KSPLAT, SOG, the Khronos glTF extension, and now RAD. Most will not survive. The ones that do will be the ones that get read by software their authors did not write.

That this particular reimplementation happened inside vis.gl is the part worth watching. luma.gl's users are not making three.js demos; they are drawing millions of data points on maps. A splat is just another primitive to that crowd, and out-of-core paging is a problem they solved for point clouds a decade ago.

Go deeper:

  • @luma.gl/splats on npm
  • Gaussian Splat Viewer example
  • Spark, World Labs' three.js splat renderer
⟵ Back to the brief

More stories

The Tanks and Temples Truck scene — a pale blue vintage flatbed pickup parked on a pavement — rendered sharply inside the Splat.js browser interface, with a readout showing 579,748 splats and a Train button in the toolbar

Arrival.Space gave away the browser version of what it sells

Just now

Two rows of underwater reef photographs, each showing a raw teal-cast frame, a SeaSplat restoration and NemoSplat's restoration, in which the water's colour cast lifts and pink and orange coral becomes visible

Where the light fails, optical flow still beats the foundation models

6 hours ago

A grid comparing a reconstructed electric fan at t = -0.5, 0, 0.5, 1.0 and 3.0. The upper row, from conventional dynamic splatting, is marked unavailable at negative time and shows a smeared, collapsing fan at t = 3.0. The lower row, from LagrangeGS, renders the fan cleanly at every timestep with orange arcs marking particle velocity, and adds a physics-editing column

These dynamic splats run backwards, and the round trip loses 1.3%

10 hours ago

Three grayscale novel views of the International Space Station's Kibō module — a stowage corridor, an airlock hatch and a crew workstation — above their corresponding rainbow-coloured depth maps

A free-flyer rebuilt the ISS interior from photos it took five years ago

Yesterday

splats

Short daily briefs on the evolution of media — gaussian splats, volumetric video, dome theaters, headsets, and the research underneath.

Newsroom

  • Latest
  • All stories
  • RSS feed
© 2026 Splats · Terms · Privacy