Make Gaussian Splats production‑ready.
Open-source CLI and viewer SDK that compresses real Gaussian-Splat assets 22× without losing what you can see, ships them through standards-aligned glTF + SPZ, and proves every claim with a deterministic visual-fidelity benchmark.
Bonsai scene · 1.16M splats · 273 MB → 12 MB at the
web-mobile preset.
Mean colour distance vs. the lossless baseline across 8 orbit frames. Below the 3% attentive-observer threshold.
Full optimize + pack pipeline on bonsai. Single-threaded Rust;
releases tagged with a deterministic BLAKE3 corpus hash.
Install
$cargo install splatforge $brew install splatforge $git clone https://github.com/montabano1/SplatForge && make build Quickstart
Four commands to go from a raw .ply to a SplatBench entry. Full
reference in the README.
-
Rust toolchain + a single cargo install. macOS, Linux, Windows.
cargo install splatforge -
Pick a preset. web-mobile is the everyday default; size-min squeezes harder.
splatforge optimize scene.ply --preset web-mobile --out scene.gltf -
The viewer SDK is a tiny TS package — WebGPU primary, WebGL2 fallback.
pnpm add @splatforge/viewer # then in your app: # new SplatForgeViewer({ canvas }).load('scene.gltf') -
Reproduce the leaderboard byte-for-byte on your machine — same corpus, same hashes.
make bench-splatbench
SplatBench · Leaderboard
16 scenes — 2 real
(Mip-NeRF 360 bonsai, bicycle) and 14
deterministic synthetic probes for per-class failure modes (texture, transparency,
motion, depth, banding, foliage, specular, lowlight, portrait, …) — run through the
full analyze → optimize → pack pipeline at each preset. Compression is
measured against the raw .ply; fidelity is mean CIE ΔE94 over 8
deterministic orbit frames rendered through @splatforge/viewer, scaled
0–1 against the published 3% perceptibility threshold. Every scene
is identified by a BLAKE3 hash of its canonical IR so runs reproduce byte-for-byte.
pro — splat-aware perceptual score
(catches floater + edge-loss artifacts ΔE94 misses).
premium — differentiable repack
PSNR delta vs naive opacity-prune at the same byte budget.
Negative cells (translucent volumes) are a known failure mode
where opacity-prune is structurally near-optimal; we publish them
honestly rather than tune them away.
Values are published; both columns require splatforge-pro to
reproduce.
| Scene | Class | Source | Splats | Input | SPZ out | Ratio | Fidelity (ΔE94) | ML Score pro | Repack ΔPSNR premium | analyze |
|---|---|---|---|---|---|---|---|---|---|---|
| splatbench_banding_proxy | smooth-color-gradient | synth | 10,000 | 2.4 MB | 91.1 KB | 26.60× | 0.03% | 95.17% | +4.78 dB | 29 ms |
| splatbench_floater_proxy | noisy-capture | synth | 250,000 | 59.1 MB | 2.3 MB | 25.84× | 0.07% | 92.66% | -0.56 dB | 248 ms |
| splatbench_texture_proxy | high-frequency-texture | synth | 15,000 | 3.5 MB | 142.6 KB | 25.48× | 0.09% | 94.26% | +8.37 dB | 32 ms |
| bicycle_mipnerf360_iter7k | outdoor-scene | REAL | 3,616,103 | 855.3 MB | 33.6 MB | 25.46× | 2.86% | 0.00% | +4.99 dB | 4.46 s |
| splatbench_depth_proxy | depth-bimodal | synth | 15,000 | 3.5 MB | 149.6 KB | 24.30× | 0.02% | 95.34% | +22.71 dB | 33 ms |
| bonsai_mipnerf360_iter7k | indoor-real-estate | REAL | 1,157,141 | 273.7 MB | 12.0 MB | 22.81× | 0.60% | 46.51% | +6.41 dB | 1.24 s |
| splatbench_portrait_proxy | salient-region-portrait | synth | 12,000 | 2.8 MB | 129.0 KB | 22.55× | 0.04% | 95.12% | +23.90 dB | 15 ms |
| splatbench_specular_proxy | specular-highlights | synth | 12,000 | 2.8 MB | 132.3 KB | 21.97× | 0.04% | 95.14% | +15.19 dB | 16 ms |
| splatbench_motion_proxy | anisotropic-streak | synth | 12,000 | 2.8 MB | 133.5 KB | 21.79× | 0.15% | 91.49% | +10.11 dB | 30 ms |
| splatbench_dense_proxy | dense-large-scene | synth | 2,000,000 | 473.0 MB | 21.7 MB | 21.75× | 0.00% | 95.54% | +6.74 dB | 2.18 s |
| splatbench_indoor_proxy | indoor-real-estate | synth | 100,000 | 23.7 MB | 1.1 MB | 20.58× | 0.03% | 95.12% | +7.15 dB | 105 ms |
| splatbench_product_proxy | product-scan | synth | 10,000 | 2.4 MB | 118.2 KB | 20.50× | 0.02% | 95.28% | +13.55 dB | 11 ms |
| splatbench_lowlight_proxy | low-light-dynamic-range | synth | 8,000 | 1.9 MB | 96.5 KB | 20.10× | 0.03% | 95.27% | +15.31 dB | 11 ms |
| splatbench_outdoor_proxy | outdoor-scene | synth | 500,000 | 118.3 MB | 6.0 MB | 19.67× | 0.02% | 95.16% | +5.50 dB | 483 ms |
| splatbench_transparency_proxy | volumetric-translucency | synth | 25,000 | 5.9 MB | 337.2 KB | 17.96× | 0.07% | 94.69% | -8.28 dB | 51 ms |
| splatbench_foliage_proxy | dense-translucency | synth | 30,000 | 7.1 MB | 412.3 KB | 17.63× | 0.09% | 93.96% | +10.13 dB | 34 ms |
Try it on your splat
Drop a Gaussian-splat scene and we'll run the full upload → optimize → download round-trip against the hosted API live .