« All posts

Three.js gets native Gaussian Splatting support

Three.js gains native Gaussian Splatting via PR #33950, with WebGPU/TSL rendering, approximate GPU sorting, and a minimal loader API.

Gaussian Splatting has become a standard rendering primitive across the 3D ecosystem, with native support already in glTF's KHR_gaussian_splatting extension, USD, Babylon.js, Apple's RealityKit, NVIDIA Omniverse, and offline renderers like V-Ray and Arnold. Three.js was a notable exception until now — a new pull request (PR #33950) adds a native implementation, driven partly by the author's own need for splat support in a separate project.

The design splits cleanly into three layers: a plain BufferGeometry holding position, a 6-float covariance attribute, and rgba8 color, so it composes with existing Three.js tooling; format-agnostic loaders (for example, for .spz files) that populate that same geometry; and GaussianSplatMesh, a WebGPU/TSL NodeMaterial that handles the actual rendering. The API is deliberately minimal — load a file with SPZLoader, wrap it in GaussianSplatMesh, and add it to the scene.

Correct back-to-front blending requires sorting potentially millions of splats per frame, handled with an approximate O(N) counting sort instead of an exact GPU sort. The sort operates on a small index array rather than the splat data itself, and re-runs only when the camera moves past a threshold. It's implemented as four TSL compute passes (reset, histogram, prefix sum, scatter) with a CPU fallback for WebGL, packaged as a reusable CountingSort class independent of the mesh.

The renderer projects each splat's 3D covariance into a 2D screen-space ellipse using the Jacobian of the perspective projection, then rasterizes it as an alpha-blended quad, all written in TSL so it runs unmodified on both WebGPU and WebGL backends. The current version only supports flat per-splat color (SH0); higher-order spherical harmonics for view-dependent shading are not yet implemented.