The Problem

Rendering large, high‑fidelity 3D Gaussian splat scenes in a web browser is computationally expensive. Existing libraries either lack WebGPU support, cannot stream detail on‑the‑fly, or expose a confusing API. The project addresses those gaps by providing a Three.js‑compatible renderer that runs on WebGPU / WebGL2, streams RAD and SOG levels of detail, and offers stochastic rendering with optional neural denoising.

What This Does

The core is a GaussianSplatRenderer (src/rendering/GaussianSplatRenderer.js) that plugs into a Three.js scene. It builds a splat mesh (src/capture/SplatMesh.js) from a URL or byte buffer, parses the data (src/loaders/SplatLoader.js → src/loaders/source.js → src/loaders/rad.js or src/loaders/sog.js), and feeds it to the GPU. The renderer uses WebGPU when available but falls back to WebGL2 (src/rendering/GaussianSplatRenderer.js checks renderer.isWebGPU). Streaming is handled by RadStreamScheduler or SogStreamScheduler (src/loaders/stream/rad-stream/*), which load additional LOD chunks as the camera moves.

The renderer also supports stochastic blending (src/rendering/uniforms.js defines the stochastic uniform) and optional neural denoising (src/addons/NeuralDenoiseNode.js). Off‑screen capture is implemented in src/capture/WebGPUCapture.js/WebGLCapture.js.

How It Is Wired

Execution starts at src/index.js. It imports the public API:

  • GaussianSplatRenderer → src/rendering/GaussianSplatRenderer.js
  • SplatMesh → src/capture/SplatMesh.js
  • RadStreamScheduler → src/loaders/stream/rad-stream/RadSelectionState.js

src/index.js exposes the classes via the package export. When a user creates a SplatMesh, the loader chain resolves: SplatMesh → SplatLoader → source → rad / sog → radFormat or sogZip → binary decoder (rust/gaussian-splat-lib/src/decoder.rs compiled to wasm). The decoded data is wrapped in an IndexedSplats object (src/data/IndexedSplats.js), which the renderer consumes.

The renderer builds a Three.js BufferGeometry from the indexed splats. It imports rendererUtils and unifroms—the most‑connected modules (32 and 22 Ca, respectively)—to set shader uniforms, bind GPU buffers, and dispatch draw calls. The shader program resides in src/addons/taaShared.js and src/addons/neuralDenoiseGL.js, which are compiled into WebGPU shader modules at runtime.

The fan‑out to the GPU is a single dispatch per frame; the heavy work is in the wasm decoder (called from wasmCall.js) and the GPU shader. No external network or filesystem calls occur after the initial asset fetch.

How To Use It

Setup

npm install gaussian-splat-lite three

The project ships with a bundled wasm module (rust/gaussian-splat-lib/src/lib.rs). If you need a fresh build, run:

cd rust
cargo build --target wasm32-unknown-unknown --release

Configuration

No environment variables are required. Asset URLs are passed directly to SplatMesh:

const splat = new SplatMesh({ url: '/assets/scene.spz' });

Running

A minimal example (copy the snippet from the README) starts in src/index.js and uses index.html as the hosting page. The demo page in the repo (index.html) shows the full workflow.

Real‑World Use

A GIS provider can stream a city‑scale RAD scene to mobile browsers. The RadStreamScheduler loads LOD chunks as the camera zooms in, while SplatMesh exposes the splat mesh as a standard Three.js object. The entire pipeline is driven by a single Three.js render loop, so the hosting application remains unchanged.

Code Health & Issues

  • High/clarity (Hub) – src/data/defines.js, src/rendering/uniforms.js, src/rendering/rendererUtils.js are imported by 32, 22, and 20 modules respectively. Any change here has a wide blast radius.
  • High/cognitive_load (Oversized) – bin/rad/storage.js, src/rendering/GaussianSplatRenderer.js, examples/viewer/cameraController.js each exceed 600 lines.
  • High/cognitive_load (Deep nesting) – src/rendering/tsl/ProjectionProgram.js, rust/gaussian-splat-lib/src/ply.rs, rust/gaussian-splat-lib/src/rad.rs have nesting depth 6.
  • High/clarity (Duplicated code) – 161 repeated 6‑line blocks across 55 files (e.g., bin/build-lod.js and bin/rad/rad.js).
  • Missing tests – Only two test files exist, covering minimal loader logic.
  • Outdated dependencies – typescript ^5.7.3, vite ^6.4.4, @biomejs/biome ^1.9.4 are behind the current major releases.

The Bottom Line

The library delivers a functional, WebGPU‑backed Gaussian splat renderer that integrates cleanly into Three.js and supports streaming LOD. Its API is straightforward for a developer familiar with Three.js. However, the codebase has significant cognitive complexity, duplicated logic, and outdated tooling, which will increase maintenance overhead. Teams that need immediate WebGPU rendering for large scenes should adopt it, but they should budget for refactoring critical hubs and adding test coverage.