Radix

Radix draws 3D Gaussian splats in three.js, on WebGPU or on WebGL2 from the same shaders. Each frame it projects the splats of all objects in a scene, sorts them together, and draws them in one draw call.

Several objects in one sort · four projection methods · splats generated in shaders · stereo XR · one table format from files to the GPU

Overview

From a file to the screen

A file is decoded once on a worker and uploaded once. Then each render projects the splats for the camera, sorts them back to front, and draws them. On WebGPU these steps all run on the GPU in the same frame. On WebGL2 the sort runs on a worker, and its result arrives a few frames later.

// WebGPU, or WebGL2 where WebGPU is missing
const renderer = await createRenderer();

// Decode on a worker, then upload to textures
const data = await loadSplats("scene.spz");
const splats = GpuArrays.fromData(renderer, data);

const collection = new SplatCollection([SplatCollection.arrays(splats)]);
const splatRenderer = new SplatRenderer({ renderer, collection });
scene.add(splatRenderer);

renderer.setAnimationLoop(() => renderer.render(scene, camera));

See also: Quickstart What a render does The pipeline

Pages

Where to start

5 minutesComparison with SparkJSWhat Radix does differently, frame times measured against SparkJS, and the features Spark has that Radix lacks. 8 minutesDesign ideasEight design ideas, each with an interactive example: twin tables, 32-byte splats, generators, words, sort keys, one sort, views, and the two backends. 20 minutesHow the classes fit togetherThe classes and the data passed between them during a frame, with an interactive class map. ReferenceQuickstart and referenceA page that draws a file, explained line by line, and the reference for each class, option, and default.
In depthThe dataTables, formats, texture layout, splat layouts, octahedral codes, writers, workers, and files, with interactive codecs. In depthThe pipelineThe four projection methods, stereo, sort keys, radix sort, compaction, the WebGL2 path, and how quads are built. In depthDrawing many objectsHow one sort draws many objects, and why that takes collections, views, versioned orders, and releases. MeasuredBenchmarksRadix, SparkJS, and PlayCanvas on the same five scans: frame times, vsync frame rates, and the full report.
Key facts

What a renderer does

1 draw callfor the splats of all objects, sorted together so that overlapping objects blend correctly
0 readbackson WebGPU: compaction, the radix sort, and the indirect draw run on the GPU in the same frame
32 bytesper splat with HDR color and PBR fields, or 16 bytes packed, with the same bits on the CPU, in files, and on the GPU
4 methodsewa, 3dgut, htgs, and raygs: classic splatting or ray evaluation, set per renderer
9.2 msper frame for a 10M-splat interior scan on WebGPU (Apple M3 Max, 1920x1080); SparkJS takes 16.5 ms
2 backendsWebGPU and WebGL2, with the same TSL source and the same app code

See also: The comparison Benchmarks Performance

Layers

Five layers; each imports only the layers below it

All code is in src/, which imports nothing else from the project. Click a layer to see its classes and the pages about it. Beside them, controls/ (CameraControls) imports only three.js, and nothing imports it.

✕ ✕ ✕ ✕ render/collections, the splat renderer and its views, the projection, and the draw wgpu/WebGPU only: Wgpu* compute, sorting gpu/three.js on WebGPU and WebGL2 worker/a pool of Web Workers core/no three.js, no DOM: runs in browsers, workers, and Node

core/ is the data and the math, gpu/ puts that data in textures and reads and writes it in shaders, wgpu/ adds compute and the GPU sort, worker/ runs core/ off the main thread, and render/ projects and draws splats with all of them. Anything named Wgpu* needs WebGPU; everything else runs on WebGL2 too.

Status

Done and planned

✓ TablesArrayData, bundles, formats, transfers, and swaps, the same on the CPU and the GPU
✓ Splat codecsext, cov, and packed layouts on the CPU and in TSL, with the same bits
✓ Files and workersPLY (also compressed), SPZ, RAD, and RDX (chunked, range reads); a worker pool made on demand
✓ Projectionewa, 3dgut, htgs, and raygs; mono and stereo; packed words
✓ SortingGPU radix sort and compaction in the frame; a CPU sort on a worker for WebGL2
✓ Scenescollections of placed objects and generators, per-camera views, modifiers, and releases
✓ OutputHDR canvases, headroom tone mapping, and GPU profiling
✓ Spherical harmonicsdegree 1 to 3 in SH bundles (ext, packed) or palettes (RAD's clustered SH, SOG's), read and written by every format, drawn from each view
Level of detailBuilding trees and choosing LoD subsets. Trees load and save today; the Doom, Quake, SOG and LCC examples choose subsets in example code.
GeneratorsA library of splat generators and effects.
Depth outputsSoft and hard depth from the draw, for compositing with meshes.

See also: The reference Checks