Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path →
Gaussian splatting,
explained.
NeRF proved you could turn a handful of photos into a photorealistic 3D scene you could fly through — beautiful, and painfully slow, because rendering each frame meant marching a neural network along thousands of rays. Gaussian Splatting kept the photorealism and threw out the slowness by changing what a scene is: not a neural network to query, but a cloud of millions of fuzzy 3D blobs you paint onto the screen back-to-front. The result renders in real time, over 100 frames a second. Here's the representation, and the blending math that makes it fast.
What changes against NeRF: the scene becomes explicit, and rasterised
This rung supersedes rung 9 on the axis rung 9 lost on, and it does it by reversing the representation. Rung 9's cost is structural: every sample along every ray is a network evaluation, so rendering cost is the product of pixels, samples per ray and the size of the network. No amount of optimisation removes a term from that product.
The change is to represent the scene as millions of 3D Gaussians — each with a position, an anisotropic extent and orientation, an opacity and a view-dependent colour — and to render by projecting them onto the image plane and compositing them front to back. That is rasterisation: exactly the operation graphics hardware was built to do, at enormous rates. There is no network to query while rendering, because the scene is data rather than a function.
Crucially it keeps rung 9's method while discarding its representation. The rasteriser is differentiable, so the Gaussians are still fitted by rendering and comparing against the photographs, with the optimiser splitting and cloning Gaussians where detail is missing and pruning transparent ones — so the scene's complexity is discovered rather than fixed. Stated in rung 9's units: training in minutes rather than days, rendering at over a hundred frames per second rather than seconds per frame, at comparable or better quality. That is not an incremental win; it is the difference between a research artefact and something usable interactively.
NeRF's speed problem
Neural radiance fields (NeRF) represent a scene implicitly: a small neural network that, given a 3D point and a viewing direction, returns a color and density. To render one pixel you cast a ray into the scene and march along it, querying that network at many sample points and integrating the results. Gorgeous quality — but that's dozens or hundreds of network evaluations per pixel, per frame. Rendering is seconds per image, nowhere near interactive.
Gaussian Splatting asks: what if the scene were explicit — a concrete geometric thing you could draw directly, the way GPUs love to draw triangles — instead of a function you have to probe? Then rendering becomes rasterization, which hardware does astonishingly fast. The trick is choosing a primitive that's explicit and drawable, yet soft enough to represent fuzzy real-world appearance and be optimized smoothly. That primitive is the 3D Gaussian.
Represent the scene as millions of 3D Gaussian blobs and render by projecting and alpha-blending them front-to-back — fast rasterization instead of slow ray-marching through a network.
A scene of Gaussians
The scene is a collection of 3D Gaussians, each a soft ellipsoidal blob defined by four things: a position (its center), a covariance (its shape and orientation — how stretched, in which directions), a color (view-dependent, via spherical harmonics), and an opacity. A single Gaussian is a smooth lump of colored, semi-transparent fog; a million of them, arranged in space, can reconstruct a whole scene in fine detail.
The softness matters. Because each Gaussian falls off smoothly from its center — its footprint is densest in the middle and fades outward — the representation has no hard edges to alias, and every parameter is differentiable. That means the whole scene can be optimized by gradient descent (section 04), which a mesh of hard triangles can't be nearly as gracefully. Explicit enough to rasterize, soft enough to optimize: that combination is the whole design.
Splat and composite
To render a view: project every 3D Gaussian onto the image plane (a "splat" — a 2D Gaussian footprint), sort them by depth, and blend them front-to-back with alpha compositing. A pixel's color accumulates each Gaussian's contribution, weighted by how much light is still unblocked by everything in front of it — the transmittance:
Transmittance Ti is the running product of "what got past" all the nearer, more opaque splats, so a fully opaque Gaussian in front (α = 1) drives T to zero and occludes everything behind it — exactly as physical over-painting should. It's the same volume-rendering equation NeRF integrates, but applied to a sorted, discrete set of Gaussians you can rasterize in one fast pass, not sampled along rays through a network. The runnable version below computes this compositing and shows why depth order matters.
Fitting to photos
How do you get the millions of Gaussians in the first place? You optimize them to reproduce your input photos. The pipeline is fully differentiable, so gradient descent can tune every Gaussian's position, shape, color, and opacity to minimize the difference between rendered views and the real photos:
That last step — adaptive density control — is what lets the scene allocate detail where it's needed: splitting Gaussians in under-reconstructed regions, removing ones that contribute nothing. After roughly six minutes (the 7K-iteration model) to about forty (the full one) of optimization you have a scene that renders novel viewpoints in real time. Training is fast, rendering is faster.
How 3D Gaussian Splatting builds and renders a scene, step by step
Kerbl, Kopanas, Leimkühler and Drettakis start from the same inputs as NeRF, posed photographs, and replace the network with an explicit set of anisotropic 3D Gaussians optimized through a differentiable rasterizer.
- Initialize from structure-from-motion. COLMAP, run to calibrate the cameras, also produces a sparse point cloud for free. Each point becomes a Gaussian with an isotropic covariance whose radius is the mean distance to its three nearest neighbors. For the synthetic NeRF scenes, random initialization inside the scene bounds also works.
- Parameterize each Gaussian. A Gaussian has a center μ, an opacity α stored through a sigmoid, spherical-harmonic color coefficients up to degree 3 (16 per color channel, 48 in all), a scale vector s stored through an exponential, and a rotation quaternion q. The covariance is built as Σ = R S S^T R^T rather than optimized directly, because gradient steps on a raw covariance matrix can leave the set of valid, positive semi-definite matrices.
- Project to the screen. For a camera with viewing transform W, each Gaussian's 2D covariance is Σ′ = J W Σ W^T J^T, where J is the Jacobian of the local affine approximation to perspective projection, the EWA splatting formula of Zwicker and colleagues.
- Cull and bin into tiles. The screen is split into 16×16-pixel tiles. Gaussians whose 99% confidence ellipse misses the view frustum are culled, a guard band rejects ones near the camera plane whose projection would be unstable, and each survivor is duplicated once for every tile its footprint overlaps.
- Sort once. Each duplicate gets a key with the tile index in its high bits and view-space depth in its low 32 bits, and a single GPU radix sort over all keys yields a depth-ordered list per tile. Ordering is per splat, not per pixel, so blending is approximate where splats interpenetrate.
- Blend front to back. One thread block per tile loads its splats into shared memory, and each pixel accumulates color and opacity front to back, stopping once its opacity saturates.
- Backpropagate. The backward pass walks each tile's list back to front. Rather than storing every intermediate opacity, it keeps each pixel's final accumulated value and recovers intermediate ones by dividing out each splat's α, so any number of splats per pixel can receive gradients. Gradients for all parameters are derived explicitly rather than by automatic differentiation.
- Optimize. The loss is (1 − λ) L1 + λ LD-SSIM with λ = 0.2, minimized with Adam, with an exponentially decaying learning rate for positions. Training starts at a quarter of the image resolution, upsampled twice early on, and adds one spherical-harmonics band every 1,000 iterations, starting from the constant term.
- Control density. Every 100 iterations, Gaussians whose average view-space position gradient exceeds 0.0002 are densified: small ones are cloned and moved along the gradient (under-reconstruction), large ones split into two with scales divided by 1.6 and positions sampled from the original (over-reconstruction). Nearly transparent and overly large Gaussians are removed. Every 3,000 iterations all opacities are reset close to zero, and Gaussians that do not recover are pruned.
- Train and render. The full model trains for 30,000 iterations, and a 7,000-iteration model is reported too. A novel view is rendered by steps 3 to 6 alone, with no network to evaluate.
Covariance, projection and the blended pixel
R S S^T R^T— equal to (RS)(RS)^T, so positive semi-definite for any s and q: the optimizer cannot produce an invalid covariance.W,J— the camera's viewing transform and the Jacobian of the affine approximation to perspective projection at the Gaussian's center.α′i(p)— the Gaussian's opacity at pixel p: its learned α scaled by its 2D footprint.ci(d)— color from the spherical harmonics, evaluated at the viewing direction.𝓛D-SSIM— structural dissimilarity, which rewards matching local structure and contrast rather than only pixel values.
Extremes: a scale component near zero flattens a Gaussian into a disc, which is how thin surfaces are represented, and α near 1 makes a splat occlude everything behind it. The affine approximation in J holds for footprints that are small relative to their distance and fails for Gaussians very close to the camera, which is what the guard band excludes.
What 3D Gaussian Splatting measured against Mip-NeRF 360 and Instant-NGP
Evaluation covered 13 real scenes, the nine of the Mip-NeRF 360 dataset plus two from Tanks and Temples and two from Deep Blending, and the synthetic Blender scenes. Mip-NeRF 360 was the quality baseline and Plenoxels and Instant-NGP the speed baselines; the headline claim is real-time rendering, at least 30 frames per second, at 1080p. On the Mip-NeRF 360 scenes:
| Method | PSNR | SSIM | LPIPS | Train | FPS | Memory |
|---|---|---|---|---|---|---|
| Plenoxels | 23.08 | 0.626 | 0.463 | 26 min | 6.79 | 2.1 GB |
| Instant-NGP (big) | 25.59 | 0.699 | 0.331 | 7.5 min | 9.43 | 48 MB |
| Mip-NeRF 360 | 27.69 | 0.792 | 0.237 | 48 h | 0.06 | 8.6 MB |
| 3DGS, 7K iterations | 25.60 | 0.770 | 0.279 | 6.4 min | 160 | 523 MB |
| 3DGS, 30K iterations | 27.21 | 0.815 | 0.214 | 42 min | 134 | 734 MB |
Three things in that table cut against the headline. On its own dataset Mip-NeRF 360 keeps the best PSNR, 27.69 against 27.21; Gaussian Splatting wins on SSIM and LPIPS, so "matches or exceeds" depends on the metric. The fast 7,000-iteration model is roughly Instant-NGP quality, not Mip-NeRF 360 quality. And memory goes up about 85-fold, 734 MB against 8.6 MB, the trade that makes speed possible. On Tanks and Temples and Deep Blending the full model matched or beat Mip-NeRF 360 on all three quality metrics.
Ablations, run on selected scenes, removed one component at a time: SfM initialization (random initialization degraded mainly the background), splitting, cloning, anisotropy (isotropic Gaussians lost fine and thin structure), spherical harmonics, and unlimited gradient flow (capping how many splats per pixel receive gradients hurt quality severely). Each removal cost quality. The authors also note visible artifacts in poorly observed regions and peak training memory that can exceed 20 GB in their unoptimized prototype.
What the authors admit, and what happened next
The cost is memory and file size. Millions of primitives, each with position, covariance, opacity and colour coefficients, is orders of magnitude larger than a small network's weights — so rung 9's representation was compact and slow and this one is bulky and fast, which is a clean trade rather than a free win, and it matters for anything that has to be transmitted.
There are characteristic artefacts: elongated Gaussians fitted to one set of views can look like visible streaks from angles the optimisation never checked, and the representation has no surface — it is a cloud of translucent blobs, so extracting a mesh, computing a collision, or relighting the scene needs additional machinery it does not provide. View-dependent colour is represented by a low-order expansion, which handles gentle shine and not sharp mirror reflections.
How it held up: it became the default for real-time novel-view synthesis almost immediately, and the pendulum it swung is the ladder's closing lesson. An explicit representation with a hardware-friendly differentiable renderer beat an elegant implicit one — which is the same finding as flash attention on the serving ladder, arrived at independently: the win came from matching the computation to what the hardware does well, and the neural formulation was carrying cost that the problem did not require.
Alpha compositing, splat by splat
The rendering equation is a few lines. This composites depth-sorted splats front-to-back — pixel color = Σ cᵢ·αᵢ·Tᵢ with transmittance Tᵢ the running product of (1−α) in front — so two semi-transparent splats blend to 0.75, and a fully opaque front splat (α=1) occludes everything behind it. It also shows a Gaussian's footprint peaking at its center and fading with distance, and why depth order matters: the same two splats give a different color depending on which is in front, because it's occlusion, not a plain sum. Change the colors, opacities, or order and watch it composite.
Write the body of alpha_composite. Everything else in the file is
already written; this is the function the paper is about. Press ▶ Run to check it against
the 5 assertions below — they start red.
- Alpha compositing matches C = sum c*a*T front-to-back
- Transmittance is non-increasing with depth
- An opaque front splat occludes everything behind
- The Gaussian footprint peaks at the center
- Depth order matters (occlusion, not a plain sum)
Why it took off
Gaussian Splatting spread through graphics and vision almost overnight, spawning a huge wave of follow-ups: dynamic and animatable scenes, avatars, SLAM, compression, generative 3D. The reason is the same one that made it fast — an explicit, differentiable, GPU-friendly primitive sits at a sweet spot the field had been circling, and once someone showed it worked at real-time speed with NeRF-level quality, everyone could build on it.
Its deeper lesson is about representation choice. NeRF's implicit network was a beautiful idea whose cost was baked into the representation itself — you couldn't make querying-a-network-per-sample cheap. Switching to an explicit set of soft primitives didn't just optimize the old approach; it changed the computational character of the problem from "evaluate a function millions of times" to "rasterize millions of things," which is exactly what graphics hardware was built for. Sometimes the biggest speedup comes from picking a representation the hardware already loves.
The front-to-back sorting is the one part that isn't free — correctly ordering millions of splats per frame is a real engineering challenge, handled with fast GPU radix sorts and approximations, and it's where much follow-up work focuses.
Questions people ask about 3D Gaussian Splatting
How is the covariance of a 3D Gaussian parameterized in Gaussian splatting?
Each Gaussian stores a three-component scale vector and a rotation quaternion instead of a raw covariance matrix. The covariance is rebuilt as R S Sᵀ Rᵀ, where S is the diagonal matrix of scales and R the rotation matrix of the normalized quaternion. Because that product equals M Mᵀ with M = RS, it is always positive semi-definite, so gradient descent can move the parameters freely without ever producing an invalid covariance, which direct optimization of the matrix entries cannot guarantee. Scales are stored through an exponential so they stay positive, and the authors derive the gradients for scale and rotation explicitly rather than relying on automatic differentiation. For rendering, the covariance is projected as J W Σ Wᵀ Jᵀ to an ellipse on screen.
How does densification work in 3D Gaussian Splatting?
Every 100 iterations the optimizer checks each Gaussian's average view-space position gradient; a large gradient means its region is not yet well reconstructed, and the paper's threshold is 0.0002. Small Gaussians above the threshold are cloned, with the copy moved in the direction of the gradient, to fill under-reconstructed areas. Large Gaussians above it are split into two smaller ones, with scales divided by 1.6 and new positions sampled from the original Gaussian, to break up regions that one blob covers too coarsely. Nearly transparent Gaussians and ones that grow very large are removed. Every 3,000 iterations all opacities are reset close to zero, which lets the optimizer prune the Gaussians whose opacity never recovers.
Why does Gaussian splatting reset opacity during training?
Densification keeps adding Gaussians, and some of them become floaters: semi-transparent blobs near the input cameras that help fit a few training views but are wrong in 3D, and that also inflate the Gaussian count. The paper's remedy is to set every Gaussian's opacity close to zero every 3,000 iterations. Optimization then raises opacity again only where the photographs require it, and Gaussians whose opacity stays below the pruning threshold are removed. This moderates the growth in the number of Gaussians and clears out floaters without any explicit regularizer. It is a blunt heuristic rather than a principled prior, and later work proposed alternatives, but it remained part of the standard recipe.
How does the tile-based rasterizer in Gaussian splatting work?
The screen is divided into 16 by 16 pixel tiles. After culling Gaussians outside the view frustum, each remaining Gaussian is projected and duplicated once for every tile its 99 percent confidence ellipse overlaps. Each duplicate gets a key with the tile index in the high bits and the view-space depth in the low bits, and one fast GPU radix sort over all keys yields, for every tile, a list of splats in depth order. A thread block per tile then loads those splats into shared memory and blends them front to back for each pixel, stopping once the pixel's accumulated opacity saturates. The backward pass walks the same lists back to front and recovers intermediate opacities from the final accumulated value instead of storing them all.
What loss function does 3D Gaussian Splatting use?
The loss is a weighted sum of an L1 pixel loss and a D-SSIM term, the structural dissimilarity derived from the SSIM index: (1 − λ) times L1 plus λ times D-SSIM, with λ = 0.2 throughout. L1 matches colors pixel by pixel; D-SSIM compares local means, variances and covariances over small windows, rewarding correct structure and contrast. There is no depth or geometry loss and no regularizer on the Gaussians, so all geometry comes from fitting the photographs, and adaptive density control does the work a regularizer otherwise might. The loss is minimized with Adam, with an exponentially decaying learning rate for positions, while the number of spherical-harmonic bands grows during training.
How does Gaussian Splatting compare with Mip-NeRF 360 in quality, speed and memory?
On the Mip-NeRF 360 dataset the full 30,000-iteration model scored 27.21 PSNR, 0.815 SSIM and 0.214 LPIPS, against Mip-NeRF 360's 27.69, 0.792 and 0.237: slightly lower PSNR with better structural and perceptual scores. Training took about 42 minutes instead of about 48 hours, and rendering ran at 134 frames per second instead of 0.06. The price is memory, 734 MB per scene against 8.6 MB for Mip-NeRF 360's network. A 7,000-iteration model trained in about 6 minutes and rendered at 160 frames per second, at lower quality, 25.60 PSNR. On Tanks and Temples and Deep Blending the full model matched or beat Mip-NeRF 360 on all three quality metrics.
4 questions to test what you just read
Work each one out before you open it — a number, a prediction or a reason, not a definition. Producing the answer is what makes it stick. Your progress is kept on this device.
How many floats does one Gaussian store with degree-3 spherical harmonics, and roughly how much memory do 3 million Gaussians need at 32 bits each?
Show answer
Position 3 + rotation 4 + scale 3 + opacity 1 + SH 16 × 3 = 48, so 59 floats, 236 bytes. Three million Gaussians: about 708 MB, the same order as the 734 MB reported on the Mip-NeRF 360 scenes and about 80× Mip-NeRF 360's 8.6 MB of weights.
With S = diag(2, 1, 1) and R a 90° rotation about the z-axis, what is Σ, and why is R S Sᵀ Rᵀ always a valid covariance?
Show answer
S S^T = diag(4, 1, 1); a 90° rotation about z swaps the x and y axes, so Σ = diag(1, 4, 1) and the long axis now points along y. Validity: Σ = (RS)(RS)^T, so v^TΣv = ‖(RS)^Tv‖² ≥ 0 for every v, whatever values the optimizer gives s and q.
One splat’s 99% ellipse touches 3 tiles and another’s touches 6. How many sort keys do they add, and why can a large splat cost more than many small ones?
Show answer
Each Gaussian is duplicated once per overlapped tile, so 3 + 6 = 9 keys. Sorting and per-tile blending scale with these duplicates, not with the number of Gaussians, so a few large splats near the camera can cost more than many small distant ones.
Why does resetting all opacities to near zero every 3,000 iterations remove floaters instead of destroying the scene?
Show answer
Gaussians the photographs need regain opacity quickly, because the loss gradient pushes them back up. Floaters that only helped a few views get weak or conflicting gradients, stay below the pruning threshold and are removed. The reset turns every Gaussian's survival into a test it must pass again.
Generating pixels
Ten papers from the first latent-variable generator to video and real-time 3D. The diffusion half is strictly cumulative — each rung removes a cost the last one paid.
- 1VAE2014
- 2GANs2014
- 3VQ-VAE2017
- 4DDPM2020
- 5DDIM2021
- 6Classifier-Free Guidance2021
- 7Latent Diffusion2022
- 8Sora2024
- 9NeRF2020
- 103D Gaussian Splatting2023
Explore the topic
See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.
More Paper Breakdowns
- Attention Is All You NeedThe paper that introduced the Transformer — the architecture underneath GPT, BERT, Claude, and Gemini. Self-attention, Query/Key/Value, multi-head attention, positional encoding, and the real BLEU results, explained in depth with analogies and animated visuals, not just equations.Read →
- Word2VecHow words became math. Dense word vectors learned from the company a word keeps, so king − man + woman lands near queen. Skip-gram, CBOW, the distributional hypothesis, and the origin of every embedding model powering search and RAG.Read →
- ResNetThe skip connection that made deep learning deep. Why stacking layers made networks worse, and how residual learning let them reach 150+ layers and win ImageNet — the identity shortcut every Transformer still uses inside every block.Read →
- Vision Transformer (ViT)When an image became 16×16 words. Cut a picture into patches, treat each patch as a token, and feed them to a plain Transformer — no convolutions. Patch embeddings, the class token, and why data scale lets attention beat the CNNs that ruled computer vision for a decade.Read →
- Latent DiffusionThe paper behind Stable Diffusion. Compress an image into a small latent space with a VAE, run the diffusion denoising there instead of on pixels for a tens-of-times efficiency win, and steer it with text via cross-attention. The architecture that put text-to-image generation on consumer GPUs.Read →
- DDPMThe original denoising diffusion math — the paper that made diffusion work. A fixed forward process adds Gaussian noise over many steps; a U-Net learns the reverse. The masterstroke: train the network to simply predict the added noise with a plain MSE loss. The foundation under every modern image generator.Read →