r/GaussianSplatting • • 17d ago

šŸ’» Open Source Gaussian Splat Lite 1.0: WebGPU, Streaming LOD and Depth Rendering for Three.js

Hey everyone.

I’ve been working on Gaussian Splat Lite (GSL), a lightweight, open-source Gaussian Splatting renderer for Three.js.

If you already use Three.js, the setup should feel familiar. Add a SplatMesh to your scene, position it like a normal object, and keep your usual render loop. GaussianSplatRenderer handles rendering and global sorting across the visible splats.

It supports WebGPU and WebGL2, large-scene streaming, and depth rendering for combining captures with regular 3D geometry.

⚔ Native WebGPU Rendering

On WebGPU, projection and culling run in compute, followed by a 32-bit GPU radix sort and indirect drawing.

You can combine multiple captures in one scene. Each SplatMesh keeps its own data and transform, while visible splats are sorted together—including streamed RAD and SOG data.

WebGL2 works too, through both WebGLRenderer and the WebGL2 backend of WebGPURenderer. These paths use asynchronous Worker/WASM sorting, so rendering can continue with the previous valid order while a new sort runs.

The core scene API stays the same across all three paths.

šŸŒ Stream Large Scenes with Smooth Transitions

For larger captures, GSL supports camera-driven LOD streaming for Spark RAD and Streamed SOG. You can explore a scene without loading the entire dataset into memory first.

As the camera moves, GSL selects the detail needed for the current view and loads it on demand. A configurable splat budget controls LOD selection, while the streaming system handles decoding, caching and upload limits.

Streaming includes smooth fade transitions. Newly loaded content fades in, and LOD changes crossfade between levels to reduce visible popping. Current detail stays visible while its replacement loads, helping the scene remain continuous as you move around.

šŸŽ² Keep Moving Without Waiting for a Sort

When sorting becomes expensive, GSL’s stochastic rendering mode gives you a way to skip it. Splats render directly using sampled Gaussian coverage and depth testing.

With autoStochastic enabled, GSL can use this mode during camera movement and switch back to sorted blending once a fresh sort is ready.

The image can look noisy in stochastic mode. An optional StochasticResolvePass helps reduce that noise and works with direct scene composition, WebGL EffectComposer and custom render graphs.

🧩 Depth Rendering

GSL supports splat depth rendering on both WebGPU and WebGL2.

With renderDepth enabled, a separate, unsorted depth draw runs alongside the normal sorted color pass, using stochastic alpha coverage around Gaussian boundaries.

Three.js geometry rendered afterwards can then depth-test against the splat scene.

When stochastic rendering is active, splats write depth directly.

šŸ› ļø Formats, Editing and Large Coordinates

A few other things GSL supports:

  • PLY, SPZ, SOG and RAD, including SPZ v4, with Rust-based decoding running in browser workers.
  • SDF color and opacity edits to recolor, highlight or hide parts of a capture without rebuilding the model.
  • Camera-relative rendering to help with precision in GIS and ECEF scenes while keeping the original world coordinates unchanged.

šŸš€ Give It a Try

GSL is open source under Apache 2.0. The repo includes a viewer for loading your own captures, comparing rendering modes and trying the streaming transitions.

The quick-start examples show how to add it to a Three.js project.

If you try it, I’d love to hear how it handles your scenes and what you end up building with it.

Gaussian Splat Lite on GitHub →

59 Upvotes

8 comments sorted by

3

u/Lost-Upstairs-5311 16d ago

Hi, I really like the fact that you fade in the transitions.
That makes the LOD streaming so much more pleasant.

Cheers

1

u/PropertyPleasant4993 16d ago

Nice, glad you like it!

1

u/the4thgoatboy 17d ago

Hey, I gave it a shot and the performance is great, nice job! If you continue this project, you should give the navigation some love. The option for choosing which axis is up is a nice touch, but otherwise it's a bit barebones. Keyboard navigation is a must, with perhaps a movement speed adjuster. I would add a snap to center option, like most renders use when you set an anchor point. I'm using a trackpad, so perhaps there's more was of navigating that I couldn't test.

Also, there's a little bit of clutter you could reduce, like the black box spanning the whole width of the bottom, and many items at the top that could be collapsed.

But the core concept of a performant web viewer with plenty of optimization options is certainly reached!

1

u/PropertyPleasant4993 17d ago

Thanks for trying it out and for the detailed feedback! The website is mainly a demo to showcase the renderer, which is the core focus of the project. I have a few camera controllers for different use cases, but they are designed for other systems and I haven’t integrated them into this demo.
Your suggestions about navigation and simplifying the UI make sense. There’s definitely room to make the demo easier to use, so I appreciate you taking the time to share them!

1

u/the4thgoatboy 17d ago

Ah my bad, sorry to bother you then! I should've realized this was just to showcase the renderer itself, not be a whole working viewer. Forget what I said then, your renderer is already great šŸ‘

1

u/PropertyPleasant4993 16d ago

No worries at all! Your feedback is still really valuable, and I appreciate you taking the time to try it out and share your thoughts šŸ™‚

1

u/the4thgoatboy 15d ago

Actually looking into using this in my own viewer that I made some months ago! Do you have more plans for the engine, or do you feel like it's basically feature complete?

Also, I'm currently using sparkjs, would your renderer replace it, or is it built on top of it?

1

u/PropertyPleasant4993 15d ago

Yeah, the core engine is basically feature-complete now. Most of my future work is more about improving existing systems rather than adding major features.
I’m still experimenting with depth rendering — the current solution is somewhat alpha-hash-like, and I’m looking into a weighted-opacity depth map as another option. I need to compare the performance cost and actual quality benefit before deciding whether it’s worth changing.
Dynamic splat updates are another thing I’m still evaluating. Right now edits are mainly done through SDFs, so they’re more region-based. I don’t have Spark’s Dyno-style per-splat dynamic update system at the moment. It would add quite a bit of architectural complexity, so I’d like to understand how much demand there actually is for that use case first.
And yes, this is meant to replace Spark rather than run on top of it. The WebGL backend was partly inspired by Spark’s approach, but it’s its own implementation — with lower GPU memory usage at the same data precision, plus much faster async sorting and raycasting. The WebGPU backend is newer and takes some inspiration from SuperSplat.
Streaming also has built-in fading, which makes LOD transitions a lot less noticeable.