WilliamLiu-1997/Gaussian-Splat-Lite

Public

High performance 3D Gaussian Splatting (3DGS) renderer for Three.js. WebGPU and WebGL2. Supports PLY, SPZ, Streaming LOD including SOG and RAD.

  • Stars270+17 tuần này
  • Forks30
  • Watchers11
  • Issues2
  • Ngày tạo03/08/2026
  • Cập nhật gần nhất28/10/2026
  • Ngôn ngữJavaScript
  • Giấy phépApache-2.0
README.md25.9 KBRaw

Gaussian-Splat-Lite

npm version CI License

Three.js Gaussian Splatting · WebGPU · Streaming

High performance 3D Gaussian Splatting (3DGS) renderer for Three.js with WebGPU/WebGL2. Supports PLY, SPZ, Streaming LOD including SOG and RAD.

Gaussian Splat Lite — default example with a seamless 90-degree camera orbit

Features

Focus What you get
WebGPU / WebGL2 Use the same Three.js scene API with either renderer
Large-scene streaming Load RAD and SOG detail as the camera moves, with smooth transitions
Stochastic rendering Optional transparency mode, with built-in temporal anti-aliasing or an experimental neural denoiser to smooth it
Offscreen capture Render Splats to images, cube maps, and environment maps for reflections
SDF edits Recolor or hide parts of a model without moving Splats
Data and precision Load URLs, files, or bytes; place local models in large GIS/ECEF scenes

Installation

npm install gaussian-splat-lite three

Requires Three.js >=0.186.0.

Quick start

SplatMesh is a scene object. Add one GaussianSplatRenderer to display all visible Splat models in the scene.

WebGPU

import * as THREE from "three";
import { WebGPURenderer } from "three/webgpu";
import { GaussianSplatRenderer, SplatMesh } from "gaussian-splat-lite";

const renderer = new WebGPURenderer({ antialias: false });
await renderer.init(); // Initialize before constructing GaussianSplatRenderer.
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  60, window.innerWidth / window.innerHeight, 0.1, 1000,
);
camera.position.set(0, 0, 3);

const splatRenderer = new GaussianSplatRenderer({
  renderer,
});
scene.add(splatRenderer);

const splat = new SplatMesh({ url: "/assets/scene.spz" });
scene.add(splat);
await splat.initialized;

renderer.setAnimationLoop(() => renderer.render(scene, camera));
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

WebGL2

WebGPURenderer automatically falls back to its WebGL2 backend when WebGPU is unavailable. To choose WebGL2 explicitly:

const renderer = new WebGPURenderer({ antialias: false, forceWebGL: true });
await renderer.init();

For the classic WebGL renderer, replace the WebGPU renderer creation and initialization with:

const renderer = new THREE.WebGLRenderer({ antialias: false });

Keep the rest of the example unchanged.

Stochastic rendering

Sorted alpha blending is the default. To enable stochastic rendering:

splatRenderer.stochastic = true;

This mode produces visible noise. Smooth it with temporal anti-aliasing, or use the experimental neural denoiser to help reduce trails behind moving objects. Both support WebGPU and WebGL2. See Stochastic rendering for setup and requirements.

Streaming large scenes

Use RadStreamScheduler for RAD scenes with levels of detail (LOD), or SogStreamScheduler for SOG lod-meta.json scenes. Both load detail as the camera moves and work on WebGPU and WebGL2.

For RAD, replace the SplatMesh loading and animation loop in the quick start with:

import { RadStreamScheduler } from "gaussian-splat-lite";

const streaming = new RadStreamScheduler({
  url: "/assets/scene.rad",
  splatBudget: 3_000_000,
  fadeDurationMs: 200, // Smooth LOD transitions (default).
});
scene.add(streaming.group);
streaming.setCamera(camera);
streaming.setResolutionFromRenderer(camera, renderer); // CSS pixels; again after resizing.
await streaming.initialized;

renderer.setAnimationLoop(() => {
  streaming.update();
  renderer.render(scene, camera);
});

// The update loop must be running before awaiting the first visible data.
await streaming.firstRenderable;

// When removing the model:
// streaming.dispose();
// streaming.group.removeFromParent();

For streamed SOG, use this constructor. Register the camera with setCamera(camera) and call streaming.update() before rendering each frame; SOG detail follows distance, so it needs no resolution. The group and readiness lifecycle are the same:

import { SogStreamScheduler } from "gaussian-splat-lite";

const streaming = new SogStreamScheduler({
  url: "/assets/scene/lod-meta.json",
  splatBudget: 3_000_000,
  fadeDurationMs: 200, // Smooth LOD transitions (default).
});

Documentation

Rendering

Models

Large scenes

Development

Requires Node.js 20.19+ or 22.12+, Rust via rustup, and the wasm32-unknown-unknown target. build:wasm installs wasm-pack through Cargo if needed.

npm ci
npm run build:wasm
npm run dev

Open the URL printed by Vite (normally http://localhost:8080/) and drop a .ply, .spz, .sog, or .rad file into the viewer, choose a local file, or load one from an HTTP(S) URL. For split SOG, select or drop meta.json together with its .webp images; for split RAD, include the header and its .radc pages. Files are decoded locally. Choose WebGPU / WebGL2 / WebGPU · WebGL2 in the viewer to compare backends.

See Contributing for validation commands. npm run build emits ESM, CommonJS, declarations, and source maps in dist/.

Acknowledgements

The overall architecture of Gaussian Splat Lite draws on Spark and SuperSplat.

Example model adapted from shehabmekky (CC BY 4.0).

License

Licensed under Apache 2.0. See NOTICE and third-party licenses for attribution.

Nội dung README thuộc về WilliamLiu-1997 và cộng đồng đóng góp, giấy phép Apache-2.0. Nguồn: github.com/WilliamLiu-1997/Gaussian-Splat-Lite