Overview#

Radix draws 3D Gaussian splats with three.js's WebGPURenderer, on WebGPU or on its WebGL2 fallback, from one set of TSL shaders. It keeps data in tables of typed arrays (ArrayData) that have the same layout on the CPU, in workers, in files, and on the GPU (GpuArrays), so a splat takes the same 32 bytes in each of them.

Import it as @sparkjsdev/radix (everything) or as @sparkjsdev/radix/core (only the CPU code, which doesn't use three.js and so runs in workers and in Node). The code is in src/; it imports no other src/ folder.

A first page#

import * as THREE from "three";
import {
  CameraControls,
  GpuArrays,
  SplatCollection,
  SplatRenderer,
  createRenderer,
  loadSplats,
} from "@sparkjsdev/radix";

// WebGPU, or WebGL2 where WebGPU is missing
const renderer = await createRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.append(renderer.domElement);

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.01, 1000);
camera.position.set(0, 0, 3);
const controls = new CameraControls({
  canvas: renderer.domElement,
  object: camera,
  settings: { mode: "orbit" },
});

// Fetch and decode the file on a worker, then upload it to textures
const data = await loadSplats("scene.spz");
const splats = GpuArrays.fromData(renderer, data);

// A collection of one object, drawn by a SplatRenderer in the scene
const collection = new SplatCollection([SplatCollection.arrays(splats)]);
const splatRenderer = new SplatRenderer({ renderer, collection });
scene.add(splatRenderer);

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

Each render projects every splat for the camera, sorts all of them back to front, and draws them in one draw call. With WebGPU the sort runs on the GPU in the same frame. With WebGL2 it runs on a worker and arrives a few frames later. Quickstart explains each line.

The layers#

Each layer imports only the layers above it in this table:

LayerImportRuns onContents
core/@sparkjsdev/radix/coreno three.js: the browser, workers, and Nodetables, bundles, formats; splat layouts and codecs; spherical harmonics codecs and palettes; sort keys; PLY (standard and compressed), SPZ (gzip and SPZ 4), RAD, and RDX files; coordinate systems
gpu/@sparkjsdev/radixthree.js WebGPURenderer on WebGPU or WebGL2, TSL shaders onlycreateRenderer; tables in textures; readers and writers; splat and SH codecs in TSL; generators
wgpu/@sparkjsdev/radixWebGPU only (Wgpu*), on top of gpu/compute kernels and buffers; compute writers; radix sort, compaction, WgpuSplatSorter
worker/@sparkjsdev/radixa pool of workers over core/, made on first useloadSplats, writeSplats, sortSplatKeys, WorkerPool
render/@sparkjsdev/radixall of the above together; nothing imports itSplatCollection, SplatRenderer, SplatView; the projection and the draw
controls/@sparkjsdev/radixthree.js only; nothing imports itCameraControls: orbit and fly

Anything named Wgpu* needs WebGPU. Everything else also runs on WebGL2.

Where to start#

To...Read
draw a splat fileQuickstart, Rendering, Params
look up a termConcepts
draw several objects, move them, or generate splats in a shaderRendering, Generators and modifiers, Recipes
draw from several cameras, or support WebGL2Views and CPU orders, Sorting, Lifetimes
render in VRWebXR and stereo
write an effect for every splatGenerators and modifiers, Shaders
load, save, or convert filesSplat files, RDX files, Workers
draw view-dependent color (spherical harmonics)Spherical harmonics
keep data of your own on the GPU, or run computeArrayData, GPU arrays, WebGPU compute
understand why it works this wayMulti-splat design, Projection
make it fasterPerformance
compare it with SparkJS or PlayCanvaswhy.html, bench.html
find any exportAPI index

Naming#

Pages#

Start here#

Drawing splats#

Data and files#

GPU#

Internals and design#

Reference#

In a browser#

npm run build (or npm run docs alone) writes these pages as HTML to ref/, and the docs site links to them. Start at index.html. Run npm run serve and open http://localhost:8000/docs/: the pages also open from disk in Chrome, but some editor previews do not follow links between file:// pages. The site has these pages of its own:

Source: docs/overview.md