When Kerbl et al. released 3D Gaussian Splatting in August 2023, a scene on disk was typically
1.4 GB. Three years later, the same scene can be squeezed to 3 MB with almost no visible
degradation — three orders of magnitude. This survey walks through how, why it works, and the
key distinctions between methods, from the ground up.
Assumed background: basic NeRF, SDF, ML, calculus, linear algebra. If you've never touched 3DGS
before, the primer chapters bring you up to speed.
Forget radiance fields for a moment. A 3D Gaussian, in the splatting sense, is just an
anisotropic blob of color floating in space. Mathematically:
G(x)=exp(−21(x−μ)⊤Σ−1(x−μ))
where μ∈R3 is the center, Σ∈R3×3 is a
symmetric positive-definite covariance saying how the blob is stretched and rotated. Covariance is
always parameterized as Σ=RSS⊤R⊤ with R from a unit quaternion
(4 floats) and S a diagonal anisotropic scale (3 floats). You optimize q and s;
the resulting Σ is positive-definite by construction, never blowing up.
Drag to orbit · slide to deform
The wireframe is the 2σ iso-surface — where the Gaussian's value has fallen to e−2 of its peak. The colored blob is what gets splatted on screen.
§1.2"Splatting" — what is it?
To draw a 3D Gaussian on screen, you don't ray-march or root-find. Take a shortcut:
Project the 3D mean μ to a 2D screen point;
Project the 3D covariance Σ via the EWA-splatting linearization to a 2D Σ′;
You get a 2D ellipse with exponential falloff. Draw it into the framebuffer, alpha-blended.
That's it. Step (3) is what people mean by "splat" — the Gaussian gets splattered onto the screen like wet paint. Vastly cheaper than NeRF's 64–256 MLP queries per ray, which is why 3DGS hits 100+ FPS on consumer GPUs.
A pixel's final color comes from back-to-front depth-sorting the Gaussians touching it, then classical Porter-Duff "over" compositing:
Cpixel=i∑ciαij<i∏(1−αj)
The 1980s alpha-compositing formula. αi combines the Gaussian's stored opacity with its 2D footprint at this pixel.
§1.3Spherical harmonics in two minutes
3DGS scenes look photographic — specular highlights move as you orbit — because each Gaussian doesn't store one color but a tiny function of viewing direction: "from above, I'm bright white; from the side, dim gray." That function lives on the unit sphere S2.
How do you compress a function on a sphere? Same way as on a circle (Fourier series) or a line (Taylor series): pick a basis and expand. The natural basis on the sphere is spherical harmonicsYℓm — eigenfunctions of the spherical Laplacian. Up to degree L, there are (L+1)2 basis functions:
Degree
# bands
Per-channel coeffs
RGB coeffs
What it captures
0
1
1
3
constant color (average)
1
3
4
12
linear gradient
2
5
9
27
broad lobes — soft specular
3
7
16
48
sharp lobes — crisp highlights
Vanilla 3DGS uses degree 3, so 48 coefficients per Gaussian for color alone. That's the elephant in the storage budget.
Radiance lobe at different SH degrees
Slide degree 3 → 0, the sphere goes from view-dependent pattern to flat — the price of "SH-degree truncation." Many methods drop matte Gaussians to degree 0 and reserve degree 3 only for the shiny ones.
§1.4The training loop
Compression methods plug into different stages of training. Here's the loop in 30 lines of pseudo-code:
python
def train_3dgs(cameras, photos, iters=30000): G = init_from_sfm_points() # 从稀疏点云起步 / start from SfM points optimizer = Adam(G.parameters()) for step in range(iters): cam, photo = sample(cameras, photos) rendered = rasterize(G, cam) # splatting pipeline loss = L1(rendered, photo) + λ * D_SSIM(rendered, photo) loss.backward() optimizer.step() # --- adaptive density control(魔法所在 / where the magic is) --- if step % 100 == 0 and step < warmup_iters: clone_high_gradient_gaussians(G) split_oversized_gaussians(G) prune_low_opacity_gaussians(G) return G # ~3M Gaussians, ~700 MB on disk
Three things to internalize:
It's gradient descent the whole way. Every per-Gaussian attribute (position, scale, rotation, opacity, SH coefficients) is an Adam-optimized parameter.
Adaptive density control grows the population during training: high-gradient Gaussians get cloned/split, low-opacity ones get culled. The final 3M-Gaussian count is a learned outcome.
The image-space rasterizer is differentiable. Gradients flow from photo pixels back to 3D positions and shapes — the key engineering trick.
Compression methods hook in at three places:
Train-time: change density-control rules (Mini-Splatting, Taming-3DGS) or add a rate-aware loss (HAC, ContextGS).
Post-hoc: after training, prune / quantize / re-encode the .ply (LightGaussian's stage 3, MesonGS, FlexGaussian).
Feed-forward at inference: one pretrained network compresses any scene, no retraining (FCGS).
§1.5Anatomy of a 3DGS .ply
Inria's original 2023 code saved scenes as .ply — yes, that 1990s point-cloud format, repurposed. Open a real 3DGS .ply and the header looks like this:
Even the "wasted" stuff is real — three normal floats always zero (a .ply convention) eat ~36 MB of nothing. Format choices to note:
Opacity is a logit, not a [0,1] probability. Apply sigmoid for α. Smoother optimization, and logits can be clipped freely.
Scales are log-scale. Actual σ is exp(scale_i). Same reason: optimization friendliness + forced positivity.
SH splits into DC + rest. DC is degree 0 (average color over all directions); the rest are 45 higher-frequency coefficients.
Where the bytes actually live
Most bytes go into SH.
Why so much redundancy?
Not that the format is dumb. Hiding in those 750 MB are several flavors of redundancy, and each compression family is good at exposing a different one:
Redundancy type
What it means
Who exploits it
Bit-level
Each float is 32 bits, but really only needs 8-12.
Quantization (Compact3D, EAGLES, MesonGS, NSVQ)
Vector-level
Many Gaussians have very similar attribute tuples; snap to a codebook.
Vector quantization (Compact3D, C3DGS, MesonGS)
Spatial
Spatial neighbors share color / scale / orientation.
Almost every modern method exploits 2-3 of these at once. The art of a compression paper is choosing which combination, and in what order.
Compose your own compression recipe
live
800 / 800
baseline
— MB
current
— MB
ratio
1×
est. PSNR
30 dB
Note: the PSNR shown is a toy heuristic, not a real PSNR. Qualitative behavior is correct though — pruning kills geometry, quantization kills smoothness, SH truncation kills highlights, they roughly compose. Real methods use cleverness to dodge each failure mode.
PART IIThe Map
§2.1The six knobs — overall taxonomy
Both the 3DGS.zip survey and the IEEE 2025 survey draw a subtle but useful distinction:
Compaction
Compression
Reduce the number of Gaussians (or substitute a stronger primitive). Bit length per primitive stays roughly fixed; there are just fewer of them. Examples: pruning, GES, Mini-Splatting, Reduced-3DGS.
Same number of Gaussians (more or less), but fewer bits per Gaussian. The renderer may decode back to the original count. Examples: quantization, entropy coding, SOG, anchor-based regeneration.
You can do both at once — most SOTA pipelines do. The six knobs below split the orthogonal levers so you can reason about combinations.
The six knobs at a glance
① Pruning — "delete what doesn't matter." Most direct. Post-training you can usually drop 80-90% with no perceptible loss because adaptive density control overshoots. The interesting question is the scoring function: opacity, ray hits, Hessian log-determinant, maxα⋅τ… Pure pruning typically buys 5-10×.
② Quantization — "fewer bits per number." Float32 is overkill for nearly every attribute. Three flavors: scalar / vector (VQ) / learned latent. Adds another 5-10× on top of pruning.
③ SH attack — "the 75% sub-problem." SH dominates 3/4 of the file. Three sub-strategies: per-Gaussian adaptive degree, distillation to lower degree, full replacement with hash grid / SGs / factorized. Highest leverage attack in the family.
④ Anchors — "decode dense from sparse." Scaffold-GS's foundational move: sparse anchors + tiny MLP generate nearby Gaussians at render time. The most architectural reformulation in the literature; most SOTA papers build on the Scaffold-GS backbone.
⑤ Entropy coding — "spend bits proportional to surprise." Shannon's old idea, combined with learned priors (hash-grid hyperpriors, autoregressive context, closed-form Laplace for SH...). Combined with anchors, this is what gets you below 10 MB without quality loss.
⑥ Industry formats — "reuse what works." SOG/SOGS (image codecs), SPZ (quantize + gzip), glTF KHR_gaussian_splatting (Khronos 2026 standard). The bridge between research methods and real deployment.
Which combinations actually win
Recipe
Examples
Typical Mip-NeRF 360 size
Prune + scalar quant
LightGaussian, Trimming, FlexGaussian
30–70 MB
Prune + VQ + SH distillation
LightGaussian (full), Compact3D
18–45 MB
SH→hash grid + residual VQ
Compact-3DGS (Lee), EAGLES
20–50 MB
Sort into 2D grid + image codec
SOG, PlayCanvas SOGS
16–40 MB
Anchors + entropy (hash-grid context)
HAC, HAC++, CompGS (Liu)
6–16 MB
Anchors + AR entropy
ContextGS, PCGS
7–13 MB
Feature planes + HEVC
CodecGS
~10 MB
Aggressive compress + diffusion restore
ExGS / Zip-GS, NiFi
1–4 MB (+diffusion model)
§2.2The size–PSNR Pareto in one chart
Before diving into individual families, the lay of the land. Each method on Mip-NeRF 360 — x is size (log scale, lower-left is better), y is PSNR (higher is better). Hover for names:
Hover for details
A few observations: vanilla 3DGS sits at ~734 MB / 27.4 dB; HAC++, ContextGS, CodecGS hover at 3–10 MB while matching or exceeding the baseline — 70–100× already in production; SOG/SOGS is a notch larger but is what production runtimes actually ship; FCGS sits at the right edge of the entropy cluster, paying a size premium to skip per-scene training.
PART IIIPruning
§3.1Pruning — which Gaussians can we just delete?
Vanilla 3DGS grows the Gaussian population during training: anywhere the loss has a high gradient, the densifier clones or splits. Intentionally aggressive — better too many than too few, hoping the opacity prune kills the freeloaders. Except it doesn't, really. The final 3M-Gaussian count includes a long tail of dim, tiny, or occluded ones that contribute nothing.
The compression question reduces to designing a scoring function.
What different scoring functions throw away
Random destroys the silhouette before anything else; opacity-only gives up high-frequency detail first. The art is approximating the loss-Hessian without computing it.
The raw .ply is too big; we want to both prune and shrink the SH on what's left.
Key idea A three-stage pipeline:
(1) global-significance pruning by opacity × hit count × volume;
(2) SH distillation—a full-SH teacher supervises a degree 3→2 student on pseudo-views;
(3) VecTree quantization—Morton-order octree on positions, K=8192 codebook on lowest-significance SH, float16 on geometry.
The volume normalization (by the 90th-percentile Gaussian volume) is the load-bearing innovation: without it, the score is dominated by background blobs that cover many rays but encode no detail.
Training against noisy photos makes Gaussians waste capacity modeling the noise itself.
Key idea Train a Zip-NeRF first as both teacher and initializer; then fit Gaussians to the teacher's clean renders; finally prune by max-contribution.
Max — not sum — is essential: a Gaussian seen only from one side shouldn't be penalized; that side might be the whole reason it exists. Score h(pi)=maxrαirτir over all training rays.
Opacity heuristics don't actually tell you how much a Gaussian matters to the loss landscape.
Key idea Compute the log-determinant of the Hessian of the L2 loss w.r.t. each Gaussian's spatial parameters. High score = loss is sharp around this Gaussian — it really matters. Ui=logdet(∇x,sIG⋅∇x,sIG⊤). At a converged model this equals Fisher information restricted to spatial params. One-shot 90% prune + brief fine-tune.
The most theoretically grounded score in the family — straight from second-order optimization. Trade-off: per-Gaussian Hessian is more expensive than opacity heuristics.
Taming 3DGS— High-Quality Radiance Fields with Limited Resources
If density control always overshoots, can we prevent the overshoot instead of pruning after?
Key idea Budget-aware density control during training. Composite score combines positional gradient×50 + opacity×100 + blending weights×50 + distance-to-center×50 + view saliency×10 + scale×25 + coverage×0.1 + depth×5. Each round only the top-scoring Gaussians clone/split until the user budget is hit. Population never explodes.
0.63M Gaussians vs 3.31M baseline (∼5×)PSNR 27.31 vs 27.46train 11 min vs 43 min
Preventive medicine instead of post-hoc surgery. Pedagogically: compression can begin at training time, not just at the end.
GaussianSpa— Sparse 3D Gaussian Splatting via Optimization-based Pruning
Key idea Frame Gaussian-count reduction as a sparse optimization problem with an explicit ℓ0-like penalty on Gaussian "existence." ADMM-style alternating optimization. 10–15× compression, no quality loss.
Mip-NeRF 360 ~17 MB / 27.4 dB
Brings classical sparse-optimization machinery (LASSO, ADMM) to 3DGS. "Compression as ℓ0 regularization" is a unifying view.
PART IVQuantization
§4.1Quantization — fewer bits per number
Quantization maps a continuous (or high-bit) value to a smaller discrete alphabet. For 3DGS, four flavors dominate:
Type
How
Used for
Scalar (SQ)
Round each float independently to N bits
opacity, log-scale, quaternion components
Vector (VQ)
K-means clustering, replace with index
SH coefficients, full covariance
Residual VQ (RVQ)
Cascade of codebooks; each stage codes the residual
⚠ Naming mess: this is not the Lee Compact-3DGS, nor the Liu CompGS.
Key idea K-means VQ on SH coefficients and covariance, jointly with training (re-run K-means during the last 10K iters). Two codebooks: 4096 codes for color (SH), 16384 codes for covariance (scale+rotation). Position and opacity are not quantized — too sensitive. Indices Morton-sorted then RLE'd.
Adjacent Gaussians fall into the same cluster, so RLE gets long runs for free.
SH dominates 75% of the file — can we replace it entirely with a shared neural field?
Key idea Drop SH entirely. View-dependent color comes from a shared Instant-NGP-style hash grid queried at the Gaussian's position + view direction through a tiny MLP. Scale & rotation get Residual VQ; opacity gets 8-bit scalar; hash-grid params get 8-bit + Huffman.
RVQ trick: a 256-code book captures coarse geometry, a second 256-code book captures the residual… 4 stages = 32 bits but expressive equivalent to a 2564≈4-billion-entry single codebook.
>25× compression on Mip-NeRF 360~28–48 MB depending on settings
The most structurally aggressive quantization paper. The "shared hash grid for appearance" thread changed how everyone thinks about SH.
EAGLES— Efficient Accelerated 3D Gaussians with Lightweight Encodings
Key idea Don't quantize raw attributes — quantize a learned latent, decode with a small MLP. SH color → 16-D latent; rotation → 8-D; opacity → 1-D. Position, scale, SH-DC stay full precision (too sensitive). Round latents in the forward pass; use straight-through estimator for backprop.
Analogy: VQ is a dictionary lookup; EAGLES is an autoencoder — trade a small MLP for low-bit integer latents that still cover the full attribute manifold.
Key idea Standard K-means weights all dimensions equally. But a slot whose change visibly distorts rendering should be closer to its codebook entry. Compute per-parameter sensitivity =∂image/∂param, weight K-means by it. Then quantization-aware fine-tune.
Up to 31× compression (avg 26×)Bicycle: 1.5 GB → 47 MBTruck: 600 MB → 21 MB∼4× faster rendering
Sensitivity-weighting = natural generalization of importance sampling. RadSplat weights Gaussians, this weights attribute slots.
MesonGS— Post-training Compression of 3D Gaussians via Eulerian + RAHT
Key idea Borrow tools from MPEG point-cloud compression (G-PCC): RAHT wavelet transform, quaternion→Euler (3 numbers instead of 4), block scalar quantization + brief fine-tune.
RAHT (Region Adaptive Hierarchical Transform) is the layered wavelet from PCC standards — concentrates spatially-correlated attributes into DC + low-entropy AC residuals, like JPEG's DCT but on irregular point sets.
Key idea Don't use straight-through estimator. Instead, inject matched noise as a surrogate for the quantization step during training. Gradients flow naturally; at inference, the same codebook quantizes for real.
A small but important trick: classical VQ training has a chicken-and-egg problem (gradients can't flow through arg-min); STE is biased; matched-noise substitution is unbiased and dramatically better in practice.
Up to 45× model-size reduction
Reduced-3DGS— Reducing the Memory Footprint of 3D Gaussian Splatting
Key idea Each Gaussian gets its own SH degree from {0,1,2,3}. Matte Gaussians on a wall only need degree 0 (one RGB triple); shiny ones keep degree 3. Then codebook-quantize the remainder.
∼27× total compressionPSNR drop: 0.21 dB
Cleanest example of "not all pixels deserve the same bitrate." You'll see this idea again in the Anchor and SH chapters.
Key idea Given a freshly-trained 3DGS file, compress it in seconds, no fine-tuning. Attribute-discriminative pruning + INT8/INT4 channel-wise mixed-precision quantization + online adaptation. Mobile-deployable.
Up to 96.4% reduction<1 dB PSNR drop
The fastest practical compressor — usable file in seconds. Critical for capture-then-share workflows.
PART VSH compression
§5.1Spherical Harmonics — the 75% sub-problem
Recall: 48 SH coefficients per Gaussian×3M Gaussians=~570 MB — ~75% of the file. Anything you do to SH has 4-5× the leverage of equivalent work elsewhere.
Interestingly, most coefficients are near zero. Most surfaces are nearly diffuse — degree 0 is enough. Only specular highlights and view-dependent reflections actually need the high bands.
Higher-band coefficients are peaked near zero — perfect for entropy coding or aggressive pruning.
Five strategies, in increasing aggressiveness:
Per-Gaussian degree adaptation
SH distillation from high-degree teacher to low-degree student
Replace SH with a shared neural field
Change the basis — Spherical Gaussian lobes or factorized
Parametric entropy code — exploit the Laplace shape
Strategy 1: Reduced-3DGS
Covered in PART IV. Highlight: per-Gaussian adaptive degree 0/1/2/3 + codebook quantize the rest. ∼27× compression at only 0.21 dB drop.
Strategy 2: LightGaussian SH distillation
Covered in PART III. SH distillation: take the full-SH model as teacher, train a low-degree student on pseudo-view-jittered renderings. The student learns to fake the high-band specular look with limited coefficients.
Same trick as classical Hinton-style knowledge distillation, ported to view-dependent appearance.
Strategy 3: Compact-3DGS (Lee) — SH → hash grid
Covered in PART IV. Drop SH entirely; view-dependent color comes from a shared hash grid + tiny MLP. Per-Gaussian SH cost: 0 floats. Shared: ~30 MB hash grid + ~100 KB MLP, amortized over millions of Gaussians.
Effectively = NeRF appearance + 3DGS geometry. The cleanest fusion of the two worlds.
Key idea Swap the primitive: exp(−x2) → exp(−∣x∣β) with learnable β. Sharper edges need fewer primitives → indirectly saves SH.
Strictly speaking this isn't SH compression — it's "primitive redesign that shrinks the SH footprint as a side effect." Often filed with SH methods but really belongs to the compaction axis.
Key idea Treat the giant (Ngaussians×Nattr) matrix as low-rank. CP decomposition (rank ∼16) reconstructs each Gaussian's attributes from a few axis-wise factor vectors.
The TensoRF lineage: a 3D tensor factorizes as a sum of outer products of 1D vectors. For 3DGS, the tensor is "Gaussian × attribute"; rank is much smaller than either dimension.
Key idea Replace 48 SH coefficients with ~10 Spherical Gaussian lobes. An SG is exp(λ(d⋅μ−1)) — a directional Gaussian on the sphere centered at μ with sharpness λ.
SH is a global basis (each band has support over the whole sphere); SGs are local (each lobe only lights up near its center). For typical appearance (few highlights, mostly diffuse), SGs are a much more compact representation.
2000s graphics already used SGs for precomputed radiance transfer (Tsai & Shih 2006); this is the rediscovery in the 3DGS era.
Key idea Plot the SH AC coefficient histogram. It's almost exactly Laplace. So just fit a Laplace, arithmetic-code under it. No context model, no MLP — just a closed-form distribution.
Other attributes (rotation, scale, opacity) use Gaussian mixtures. Per-Gaussian distribution parameters drive the arithmetic coder.
∼30× rate reduction10× model sizefast decode (no neural net)
A pedagogical gem: 100-year-old statistics still works. Sometimes you don't need a neural network.
Strategy
Mechanism
Representative
Leverage
Degree adapt
per-Gaussian degree
Reduced-3DGS
∼3×
Distillation
teacher–student
LightGaussian
∼2×
Replace w/ field
shared hash grid
Compact-3DGS (Lee)
∼5×
Change basis
SG lobes / CP factor
SG-Splatting, F-3DGS
∼3–8×
Entropy
Laplace / GMM
EntropyGS
∼3–4×
PART VIAnchor-based
§6.1Anchor-based — Store sparse, decode dense
Walk through a 3DGS scene and one fact is obvious: neighboring Gaussians have nearly identical attributes. A coffee tabletop is covered by hundreds of Gaussians all saying the same thing: "I'm brown, flat, matte." Storing 59 floats per Gaussian for every one of them is staggeringly wasteful.
What if you stored attributes at sparse anchor points (voxel grid) and let a tiny MLP regenerate the local Gaussians on demand? That's the Scaffold-GS bet — and it changed the field.
Scaffold-GS— Structured 3D Gaussians for View-Adaptive Rendering
CVPR 2024 HighlightLu, Yu et al. · CUHK / Shanghai AI Lab · arXiv:2312.00109 · code
Each Gaussian floats independently — massive redundancy + brittleness to view/lighting changes.
Key idea Don't store each Gaussian. Scatter sparse anchors on a voxel grid; each anchor carries a feature vector (e.g. 32-D) and k learnable offset vectors (e.g. k=10). At render time, an MLP takes (anchor feature, view direction, view distance) → predicts opacity, color (no SH — direct RGB), scale, rotation of k neural Gaussians at anchor_pos + offset_i. Anchors grow/prune dynamically during training.
Stored on disk: anchor positions + features + scaling + k offsets + MLP weights (~few hundred KB). Regenerated at render time: every Gaussian's attributes.
View-dependent trick: the MLP takes view direction as input — no SH needed. That's why Scaffold-GS often improves PSNR: the MLP expresses smoother view-dependence than degree-3 SH.
The most important paper after vanilla 3DGS. Not really a compression paper — a reformulation of what a 3DGS scene is. Almost every SOTA paper (HAC, HAC++, ContextGS, CompGS, GaussianForest) builds on the Scaffold-GS backbone.
Key idea Put Scaffold-GS anchors in an octree; choose fractional LOD per pixel based on camera footprint. Distant pixels decode only coarse levels. Cumulative LOD across octree levels; a learnable per-anchor LOD bias supplements high-freq regions.
The bridge between anchor compression and "scalable rendering for huge scenes." Size comparable to Scaffold-GS; the win is rendering consistency across view distances.
Key idea Organize Gaussians into trees: leaves store rapidly-varying attributes (position, opacity) explicitly; internal nodes hold shared features that an MLP decodes into smoothly-varying attributes (rotation, scale, color) for many leaves.
The clean pedagogical statement: store what varies a lot, share what varies smoothly.
Key idea Replace per-Gaussian attributes with a multi-level tri-plane (three 2D feature grids); a tiny MLP decodes each Gaussian by position lookup. The tri-plane is a 2D smooth field, designed to be compressible by off-the-shelf image codecs. Positions are stored separately for lossless coding.
Shows how flexible the "anchors → tiny MLP → Gaussians" template is — the "anchor" can be a point, voxel, hash bucket, tri-plane sample, or tree node.
CompGS (Liu)— Compressed Gaussian Splatting via Hybrid Primitives
ACM MM 2024Liu et al. · ⚠ Different from Compact3D (Navaneet) and Compact-3DGS (Lee). · arXiv:2404.09458
Key idea Two kinds of primitives: a few anchor primitives with full geometry + many coupled primitives that store only tiny residuals predicted from the anchor. Rate-distortion loss λR+D + hyperprior Gaussian entropy models drive quantization.
Exact video codec analogy: anchors = I-frames, coupled = P-frames, only delta stored.
Key idea Compact representation around octree positional encoding + learned per-splat features. Recursive voxel hierarchy for coordinates; entropy-based feature compression. Mip-NeRF 360: 4.87 MB / 27.61 PSNR — among the smallest reported in late 2025.
PART VIIEntropy coding
§7.1Entropy coding — where the SOTA lives
If quantization is "round each number," entropy coding is "spend bits proportional to surprise." Combined with anchors, this is what pushes 3DGS past 100× without quality loss.
Three ways to get a prior
Type
How
Representative
Parametric
Fit Laplace/Gaussian/GMM to empirical histogram
EntropyGS
Hyperprior
Jointly learn coarse-grained feature grid predicting fine-grained distribution
HAC, HAC++, CompGS, FCGS
Autoregressive context
Predict each anchor from already-coded neighbors (like PixelCNN)
ContextGS, PCGS, FCGS+
Off-the-shelf codec prior
Let HEVC/WebP/JPEG-XL's built-in predictors handle it
CodecGS, SOG/SOGS
HAC— Hash-grid Assisted Context for 3DGS Compression
Scaffold-GS got down to 156 MB and stopped — can we go further?
Key idea Take Scaffold-GS anchors. Jointly train a multiresolution binary hash grid. Each anchor queries the hash grid at its position → feature; a tiny MLP_c outputs (μ,σ) of a Gaussian distribution for each attribute; arithmetic-code the anchor under that predicted distribution.
This is the learned image compression framework (Ballé 2017/2018) ported to 3DGS — hash grid = hyperprior, MLP translates hyperprior into per-anchor distribution. The entropy is explicitly minimized as a training loss (λR+D).
"Binary" = hash grid values quantized to {−1,+1} — the hyperprior itself is essentially free.
Key idea On top of HAC: (1) intra-anchor context — the k sibling Gaussians of one anchor predict each other; (2) per-attribute adaptive quantization; (3) a learnable mask drops useless Gaussians during training.
Intra-anchor fills HAC's gap: the k=10 Gaussians from one anchor are obviously correlated (shared parent feature), but HAC didn't exploit it. HAC++ adds autoregressive coupling among siblings on top of the hash-grid prior.
Key idea Where HAC predicts each anchor from a hash-grid feature, ContextGS predicts each anchor from its already-coded neighbors. Like PixelCNN for 3D anchors.
Split anchors into hierarchical levels (coarse → medium → fine). Coarsest first, coded under a small hyperprior. Once decoded, those anchors serve as context for the next level's distribution, arithmetic-coded. And so on. Directly exploits inter-anchor spatial redundancy — which HAC exploits only indirectly via the hash grid.
Key idea Lay 3DGS attributes on 2D feature planes; run HEVC — the same codec that streams Netflix. Get 25 years of video-codec engineering for free, with hardware decoders included.
HEVC has intra prediction, transform coding, CABAC, rate control — why reinvent? Train the feature planes to be HEVC-friendly (frequency-domain entropy model aligned with what HEVC will do).
Key idea Every method above re-trains a neural codec on each new scene (minutes per scene). FCGS doesn't: a single pretrained network compresses any 3DGS scene in one forward pass — ~1 second per 100K Gaussians.
Entropy module is a 3-component Gaussian Mixture conditioned on: (1) hyperprior h (coarse scene-wide latent), (2) inter-Gaussian context s (grid-interpolated from already-decoded Gaussians), (3) intra-Gaussian context c (within-Gaussian channel chunks). Multi-path entropy module routes each attribute to a different rate-constraint path.
The amortization turning point. ∼5× larger than HAC++ but ∼100× faster. Mirrors the trajectory of learned image codecs from per-image training to amortized.
Key idea One bitstream, multiple decode quality levels. Clients can stop early for a decent preview; reading more refines. Progressive JPEG for 3DGS.
Progressive anchor masking (add anchors as you decode more) + progressive quantization (step size shrinks as more bits arrive). Single training, multiple bitrates extractable at decode time.
The first true progressive 3DGS — natural successor to HAC++ for streaming and bandwidth-adaptive AR/VR.
Key idea Sort Gaussians along a Morton (Z-order) curve: nearby in the bitstream ⇔ nearby in 3D. Then exploit the resulting coherence with a neural field + adaptive SH bandwidth.
3DGS is unstructured — image codecs can't be applied directly.
Key idea Sort N Gaussians onto a N×N 2D grid so that grid-neighbors have similar attributes. Each attribute (position-x, scale-y, SH-coeff-k…) becomes a smooth 2D image. Save with PNG/JPEG-XL/WebP/AVIF — let the image codec do the entropy coding.
Sorting algorithm: PLAS (Parallel Linear Assignment Sorting) — a custom GPU algorithm that assigns N high-D vectors to a 2D grid in seconds, optimizing local smoothness.
The most pedagogically elegant idea in the whole field. Make the unstructured problem structured; existing tools solve it.
Key idea SOG productionized. Each attribute is a WebP texture bundled in an archive. Decoded natively by the browser; loaded straight to the GPU in Morton order.
SOG v2 (late 2025) adds: Morton ordering for GPU-friendly loading, WebGPU-only encoder (no CUDA needed to write .sog), single self-contained archive.
The "boring baseline that actually works." Used by Scaniverse on-device. Now the official compression payload of Khronos KHR_gaussian_splatting_compression_spz.
Key idea A "trimmed PLY" binary: 8-bit SH, struct layout matching the Three.js renderer's internal Gaussian. Load bytes, point a buffer view, render — zero transformation.
Multiple compression levels; the most aggressive 8-bit-quantizes SH. Emphasizes decode speed over absolute size.
"Small on disk" = "fast on GPU." KSPLAT is bigger than SOGS but loads faster.
glTF KHR_gaussian_splatting— Khronos Industry Standard
Standard · Release candidate Feb 2026 · press release
Key idea The first cross-vendor 3DGS-in-glTF standard. SPZ is the official compression payload; design is algorithm-agnostic so future codecs can drop in.
Two extensions:
KHR_gaussian_splatting defines the uncompressed structure: position, rotation, scale, opacity, SH split into diffuse (deg 0) + specular (deg 1-3).
KHR_gaussian_splatting_compression_spz wraps SPZ-compressed blobs as glTF buffers.
Backed by Niantic, Cesium/Bentley, Esri, OGC, and Khronos. The analog of the moment JPEG got written into a web spec.
MPEG-GSC— Gaussian Splatting Coding (ISO Future Standard)
Future ISO Standard · MPEG 153rd meeting Jan 2026
Key idea The same standards body that gave us MPEG-2 and HEVC now treats 3DGS as a first-class media type. Goal: interoperable ISO codec, with HEVC/VVC as starting points. Reference standard expected 2027-2028.
glTF + SPZ solves asset distribution today; MPEG-GSC will solve codec interop for broadcast/streaming.
Need
Format
Smallest, browser-delivery, per-scene OK
PlayCanvas .sog / SOGS
Standards-friendly glTF pipeline, simple decode
.spz / SPZ4 via glTF KHR_gaussian_splatting_compression_spz
Three.js viewer, decode speed first
.ksplat
Broadcast streaming (future)
MPEG-GSC
Research / leaderboard
Method-specific binaries (HAC, ContextGS, etc.)
PART IXFrontier 2025-2026
§9.1Frontier 2025-2026 — 30 months in
Aug 20233D Gaussian Splatting (Kerbl et al., SIGGRAPH 2023) The starting point. Scenes ~1.4 GB.
Nov 2023LightGaussian · Compact3D (Navaneet) · Compact-3DGS (Lee) · EAGLES · SOG Four months in, basic directions already mapped. Sizes drop to ~20–60 MB.
Mar 2024Scaffold-GS · HAC Anchor + entropy combination crystallizes. HAC pushes to ~15 MB at no quality loss.
Oct 2024FCGS — feed-forward compression The amortization moment. Compression becomes inference, not optimization.
Jan 2025HAC++ · CodecGS · Splatpress · SG-Splatting Sub-10 MB scenes become routine. Khronos and MPEG start meeting.
Mar 2025PCGS (AAAI 2026 Oral) — progressive 3DGS "Progressive JPEG" for splats. One bitstream, multiple qualities.
Aug–Sep 2025EntropyGS · ExGS / Zip-GS · MEGS² Three new branches: parametric entropy, diffusion-assisted restoration, mobile-targeted.
Dec 2025Smol-GS · Splatwizard · RAVE SOTA at 4.87 MB on Mip-NeRF 360. Unified benchmarking toolkit. Variable-bitrate single-model decoder.
Feb 2026NiFi — 1000× via diffusion · glTF KHR_gaussian_splatting released Compression and standardization hitting maturity simultaneously.
May 2026SPZ 4 · MPEG-GSC exploration ongoing The field moved from "how small can we make a scene?" to "how do we ship it?"
Direction 1: Feed-forward / amortized codecs
Until late 2024, every 3DGS compressor required per-scene training. FCGS broke that. Going forward, expect dominant codecs to be single pretrained networks that compress any scene in one forward pass.
FCGS (ICLR 2025, arXiv 2410.08017) — first feed-forward 3DGS compressor. ∼20× compression in seconds.
FCGS+ / Long-Context FCGS (arXiv 2512.00877, 2025) — Morton serialization to build thousands-of-Gaussian context windows. SOTA among generalizable codecs.
D-FCGS (arXiv 2507.05859, 2025) — feedforward dynamic-3DGS for free-viewpoint video.
Why it matters: per-scene training is the bottleneck for capture-to-share workflows. Seconds, not 10 minutes, qualitatively changes UX.
Direction 2: Diffusion-assisted restoration
If you can repair a poorly-rendered image after the fact, you can compress your scene more aggressively. The decompression pipeline becomes:
Key idea Push to 1000× by destroying most detail, then resurrecting with an artifact-aware one-step diffusion decoder. The line between compression and synthesis blurs.
Direction 3: 4D / dynamic compression
Once 4DGS / 3DGStream made dynamic scenes possible, the natural question: how to compress a video of splats? Video codecs do this for pixels; the splat analog is active research.
4DGC (arXiv 2503.18421) — rate-aware streamable, ∼16× smaller than 3DGStream
Conceptual pattern across all of them: canonical-space + deformation. Store the scene once at t=0, then store low-bandwidth deformation fields (or anchor motion) per frame. Same as the MPEG I-frame + P-frame story.
Direction 4: Mobile / on-device
Most current SOTA assumes a 24 GB datacenter GPU. This direction is good 3DGS rendering on phones, with batteries:
FlexGaussian (ACM MM 2025) — INT8/INT4 mixed-precision, deployable in seconds
Real-Time On-Device 3DGS with Reuse (arXiv 2511.12930)
Note: these papers headline "watts per FPS, DRAM bytes, per-frame render budget" rather than PSNR — a different optimization regime.
Direction 5: Tooling & benchmarks
The field is starting to grow up. 3DGS.zip (Bagdasarian et al., 2025) is a live leaderboard pinning down cross-paper comparisons. Two toolkits are converging on a standard harness:
All interactive demos from this survey, collected here for convenience. Each is already embedded in its chapter. All pure Canvas2D, zero dependencies — gauss-engine.js≈280 lines, easy to fork.
Demos used in this survey (in order of appearance):
Anatomy of a single Gaussian — §1.1, six sliders deforming an anisotropic Gaussian.
Radiance lobe at each SH degree — §1.3, degree 3 → 0 visual change.
Compression recipe composer — §1.5, pruning + bits + VQ + SH all at once, watch size and PSNR estimate.
Pruning under different scoring criteria — PART III, opacity / volume / Hessian-ish, etc.
SOG before/after sort — PART VIII, from unstructured to 2D grid.
Size–PSNR Pareto scatter — §2.2, every method on Mip-NeRF 360.