Interactive notes · radiance fields & robotics

A scene is a cloud of Gaussians.

Gaussian Splatting represents a scene as thousands of soft, colored ellipses — and learns them by gradient descent. On a moving sensor, that representation can support tracking and mapping. Every figure on this page is live: drag, train, drive.

Scroll

What is exact here? Figures 1 and 3 implement depth-ordered Gaussian alpha compositing. Figure 2 is an additive 2-D optimization analogy, not the 3DGS rasterizer. Figure 4 is a planar 360° range-scan mapper with Gaussian primitives, not image-based radiance-field SLAM. The notes call out these boundaries so the demos teach the shared ideas without conflating different sensors and algorithms.

§ 1 · The primitive

One splat is just a 2-D Gaussian with opinions.

A splat is a Gaussian blob carrying four things: a mean μ (where it sits), a covariance Σ (how it stretches and tilts), a color c, and an opacity α. The covariance is stored factored, Σ = R S SR — a rotation and two scales — so however hard the optimizer pushes the parameters, Σ remains a valid ellipse.

Rendering is nothing more than drawing every Gaussian, sorted by depth, and alpha-blending them front to back. That is the “splatting”. In 3-D, each ellipsoid is first projected to the image plane; here we stay in 2-D, where a splat already is its own projection.

Fig. 1 — Anatomy of a splatInteractive · drag & tune
Selected splat #1
σx
σy
θ
α
Color c
Σ = R S ST RT (px²)
Drag a splat to move it; drag the ring handle to rotate. Sliders edit the selected splat’s scales, angle, opacity and color. Notice how a handful of soft, overlapping primitives already compose a smooth image — and that depth order matters: “to front” changes the blend.

§ 2 · The trick

Rendering is differentiable — so run it backwards.

The real contribution of 3-D Gaussian Splatting isn’t the blob — it’s the loop. Render the Gaussians, compare the result with a photo, and backpropagate the pixel error into every parameter: positions drift, ellipses stretch and rotate, colors and opacities settle.

Adaptive density control adds, clones, or splits Gaussians where the representation needs more detail and prunes low-opacity primitives; practical 3DGS training also periodically resets opacity. The rendering core can be summarized in three lines:

G(x) = exp(−½ (xμ)Σ−1(xμ))One splat — a soft ellipse
Σ = R S SRFactored — valid under any gradient step
ai(p) = αiGi(p),   C(p) = Σi ciai(p) Πj<i(1−aj(p))Front-to-back blending — footprint included
Fig. 2 — Fitting by gradient descentInteractive · press train

A · Render — live

B · Target

C · |error| heatmap

log photometric loss ↓

step 0 splats 0 PSNR
adaptive density control: waiting…
Pick a target and press train. ~40 random splats optimize μ, Σ, c, α with Adam on photometric loss; every 140 steps high-gradient splats are split and faint ones pruned. Smooth gradients (sunset) are cheap; hard edges (letters) force crowds of small anisotropic splats.

Demo boundary: this fitter uses additive blending and a simplified split/prune rule so its gradients remain compact JavaScript. Full 3DGS differentiates through visibility-aware, depth-sorted alpha compositing and uses a richer clone/split/prune/opacity-reset schedule.

§ 3 · The viewpoint

One map, many views — move the ego.

So far the camera never moved. But the entire point of a scene representation is that one set of world-space Gaussians must explain every viewpoint. As the ego travels, each splat’s parameters (μ, Σ, c, α) stay fixed — what changes is the projection: the image position shifts with parallax, the footprint scales with 1/depth and skews with viewing angle through the projection Jacobian, splats slide out of the frustum and are culled, and the depth ordering that drives alpha blending reshuffles.

This pose-dependence is exactly the lever SLAM will pull in §4: because the render R(𝒢 ; T) changes smoothly with the pose T, you can differentiate it — and solve for where you are.

xc = RT(μt),   u = fyc / xcProject the mean — parallax & 1/depth scaling
σu2 = JΣJ,   J =u/∂μProject the covariance — the EWA / 3DGS Jacobian step
Fig. 3 — One map, many viewsInteractive · drive & inspect
in view 0 / 0

A · World — fixed Gaussians, moving ego

B · What the ego sees — projections & 1-D image

click a splat to inspect its projection
drag the ego off the path — press play to rejoin
The world-space Gaussians never change — their projections do. Play the loop and watch panel B: each curve is one splat’s projected footprint α·G(u), and the strip below is the depth-sorted, front-to-back blended 1-D image — the splatting equation from §2, now with a pose in it. Nearby splats balloon (1/depth), oblique ones squash (the Jacobian), splats leaving the frustum vanish (culling), and the near→far blend order reshuffles as you pass. Click a splat to pin its projection across both panels; drag the ego anywhere to break off the trajectory.

§ 4 · The leap

Make the pose a variable too — and you can build SLAM.

In §3 the ego moved, but its pose was always given. SLAM drops that assumption: a sensor moves through an unknown scene, and both the map and the trajectory must be estimated — simultaneously. Gaussian-Splatting SLAM alternates two optimizations against the same differentiable representation:

t = argminT L( R(𝒢 ; T), Zt )Tracking — pose given map (map frozen)
𝒢̂ = argmin𝒢 Σk L( R(𝒢 ; k), Zk )Mapping — map given poses (poses frozen)

Tracking: freeze the Gaussians, adjust the current pose T until what the map predicts matches what the sensor just measured. Mapping: freeze recent poses, then insert and refine Gaussians wherever the observation is poorly explained. Frame-to-model alignment can reduce local odometry drift, but it does not guarantee global consistency: model error, weak geometry, dynamics, bad initialization, and uncorrected loops can still move the map away from reality.

Fig. 4 — GS-SLAM in a toy worldInteractive · toggle & drive
ground truth odometry only GS-SLAM estimate

A · Reality — ground-truth world

B · Belief — the robot’s Gaussian map

pose error 0.00 m odometry drift 0.00 m map 0 gaussians
manual mode: ← ↑ ↓ → or the pad below
This is a 2-D range-scan analogy, not visual GS-SLAM. Left is reality; right is a Gaussian map grown from noisy 360° scan points, with each covariance estimated from nearby hits. Every frame the robot registers the fresh scan to the map and then spawns or refines splats. Turning registration off isolates dead-reckoning drift; turning it on shows local frame-to-model correction in this favorable static toy world. No loop detector or global optimization is implemented. The top-right room is never visited by the autopilot: take manual control and map it yourself.

§ 5 · The real thing

From this page to 3-D systems.

The 3-D representation preserves the core primitive but adds substantial machinery: ellipsoids with Σ = R S SR, view-dependent color (commonly spherical harmonics), visibility-aware projection, depth sorting, tiled rasterization, and GPU optimization. That fast differentiable renderer is what makes Gaussian maps attractive inside estimation loops.

Systems such as Gaussian-SLAM and SplaTAM use RGB-D images and frame-to-model photometric/geometric objectives, keyframes, and online Gaussian insertion/refinement. Architectures vary: early systems do not all include loop closure or global bundle adjustment, while later work explicitly adds global-consistency mechanisms. Local tracking by itself cannot remove all accumulated drift.

LiDAR methods require sensor-specific rendering and geometry rather than merely swapping one scalar loss. For example, Splat-LOAM refines Gaussian primitives through spherical projection of LiDAR measurements. A differentiable forward model helps, but successful estimation also depends on observability, calibrated noise and sensor models, correspondence or visibility handling, robust optimization, and initialization.

Our companion radio-SLAM benchmark uses synthetic radio returns—not a separate camera or LiDAR stream. The raw export stores path-separated complex antenna coefficients alongside delay, Doppler, Sionna zenith/azimuth angles, interaction geometry, and materials; it does not save a CIR or channel-tap tensor. The current v5 estimator input is one unlabeled radio measurement per resolved path: total delay-derived path length, AoA toward the last bounce, and amplitude. Every method also receives the known first position and BS position; later trajectory truth and all provenance stay evaluation-only. The Splat-LOAM result is specifically a radio-adapted NDT front end plus its Gaussian mapping back end. See the upstream data inventory →