01 Quick reference: start with the big picture
Start with this table to get a feel for all eight formats. Each has its own section below, and the byte-level technical details are tucked into a collapsible "Inside the spec" block in each section.
| Format | In one line | Extension | Compression | Supported tools | Best for |
|---|---|---|---|---|---|
| PLY | The full original. Huge | .ply | Uncompressed by default | Nearly all tools | Data exchange, compatibility priority |
| SPLAT | Early simplified format. Skip it today | .splat | SH coefficients dropped + quantized | Mainly early web viewers | Compatibility with older viewers (not recommended for new work) |
| KSPLAT | One viewer's private format | .ksplat | Chunked + two-tier compression | GaussianSplats3D only | Custom viewers with progressive display |
| SPZ | The go-to compressed format. 1/10 of PLY | .spz | v1-3 = gzip / v4 = zstd | Scaniverse, splat-transform, Spark, etc. | General-purpose compact format for distribution/storage |
| SOG | Image-compression tricks, smallest class | Folder + meta.json | Attribute sort + WebP (~20x) | PlayCanvas-ecosystem tools | Web delivery / streaming |
| RAD | Built for streaming giant scenes | .rad + .radc | 16 bytes/Gaussian + chunked delivery | Spark only | Ultra-large streaming beyond 100M points |
| LCC / LCC2 | A container for whole cities | .lcc2 + SOG/SPZ | Follows internal format | XGRIDS SDK, splat-transform (read) | City-scale LOD switching |
| glTF (GLB) | The standards-track future | .glb / .gltf | SPZ-based KHR compression extension | Cesium family, gsbox (expanding) | Standard-format storage, geospatial delivery |
02 PLY (original, uncompressed)
This is the de facto common language of 3DGS — the format the original Inria paper outputs directly. Each Gaussian records position (x, y, z), scale, rotation (quaternion), opacity, and color. Color is stored as spherical harmonics (SH) coefficients, and using degree 3 requires 45 coefficients per Gaussian (3 channels × 15) — which makes PLY the largest file size of any format here.
| Item | Details |
|---|---|
| Extension | .ply |
| Compression | Uncompressed by default (a "Compressed PLY" variant supported by tools like splat-transform also exists) |
| Supported tools | Readable by nearly every DCC, viewer, and conversion tool |
| Best for | Exchanging data between tools and importing into a DCC. When compatibility is the top priority |
Inside the spec (for the nerds)
Inside the spec ── The header is plain ASCII text: ply, then format binary_little_endian 1.0, then element vertex N followed by the property lines. In the standard SH-degree-3 layout, one gaussian is 62 properties × float32 = 248 bytes: position x,y,z / normals nx,ny,nz (unused in 3DGS) / f_dc_0..2 (SH degree 0 = base color) / f_rest_0..44 (SH degrees 1–3) / opacity / scale_0..2 / rot_0..3. Values are stored in the raw training-time representation, so at display time you run opacity through a sigmoid, scale through an exponential, and normalize the quaternion. Open the header in a text editor and you can read the property layout directly — a quick first check of whether a given tool will load the file.
In the wild ── This is the exact output of the official Inria implementation, and the exports from Polycam, Luma AI, and XGRIDS LCC Studio follow the same layout. SuperSplat reads and writes it directly, which makes PLY the hub for editing too.
03 SPLAT (antimatter15)
A simple fixed-length binary format created for splat (antimatter15), one of the earliest web viewers. Each Gaussian is a fixed 32 bytes (position, scale, color, covariance) and carries no SH coefficients for view-dependent color, so files end up roughly half the size of PLY.
| Item | Details |
|---|---|
| Extension | .splat |
| Compression | Lightweighted by dropping SH coefficients and quantizing values (not codec-style compression) |
| Supported tools | Mainly early web viewers. There's no formal spec — the layout is settled by convention |
| Best for | When you just want to get something on the web quickly. View-dependent effects like reflections and gloss are lost |
Inside the spec (for the nerds)
Inside the spec ── There is no header: the file is a run of fixed 32-byte records, one per gaussian — position float32×3 (12 bytes) + scale float32×3 (12 bytes) + RGBA color at 8 bits each (4 bytes) + quaternion at 8 bits per component (4 bytes). File size ÷ 32 gives you the point count. SH coefficients are discarded after baking the degree-0 color into RGBA, which is why view-dependent shading is lost. There is no formal spec — the antimatter15 repository's implementation and README are the de facto definition.
04 KSPLAT (mkkellogg/GaussianSplats3D)
A compression format built specifically for the Three.js library GaussianSplats3D. Data is split into chunks and designed for progressive streaming, rendering each chunk as it arrives — even a scene over 100MB can show its first frame in 0.5-1 seconds. You can choose the compression level, including a setting that compresses SH coefficients down to 8 bits.
| Item | Details |
|---|---|
| Extension | .ksplat |
| Compression | Chunked splitting plus two compression levels (level 2 also compresses SH to 8 bits) |
| Supported tools | GaussianSplats3D only (a dedicated format). A PLY/SPLAT conversion tool ships with it |
| Best for | When building a custom GaussianSplats3D-based viewer and you want large scenes to load progressively |
Inside the spec (for the nerds)
Inside the spec ── Three compression levels: 0 = uncompressed (float32) / 1 = position, scale, rotation, and SH quantized from float32 to 16-bit / 2 = level 1 plus SH coefficients down to 8-bit. Space is partitioned into blocks (default 5.0) and stored in buckets (default 256 gaussians), and that structure doubles as the unit of progressive loading. Convert with the bundled node util/create-ksplat.js [in] [out] [compression] …, which also takes the SH degree (0–2) to preserve.
05 SPZ (Niantic Spatial)
A compression format developed by Niantic Spatial (Scaniverse) that's becoming something of an industry standard. It was also adopted as the compression method for glTF's KHR_gaussian_splatting compression extension (09). v1 through v3 used gzip compression; the latest v4 switched to zstd compression plus a plain 32-byte header. The v4 header starts with the magic bytes "NGSP" and exposes the Gaussian count, SH degree, version, and more as directly readable text, so you can peek at the point count just by reading the header — no need to decode the whole file.
| Item | Details |
|---|---|
| Extension | .spz |
| Compression | v1-3 = gzip / v4 = zstd (higher compression ratio) |
| Supported tools | Broad support: Scaniverse, splat-transform, Spark, UnityGaussianSplatting, 3ds Max 2027.2, and more |
| Best for | As a general-purpose compact format for distribution and storage. A leading candidate for the future de facto standard |
Inside the spec (for the nerds)
Inside the spec (v4) ── A 32-byte plaintext header (magic NGSP = 0x5053474E, gaussian count, SH degree 0–4, fractional bits, antialiasing flag, stream count, TOC offset) is followed by independently zstd-compressed streams, one per attribute. Independent streams are the point of v4 — they decompress in parallel (v1–3 used a single gzip stream). Quantization is tuned per attribute:
| Attribute | Quantization |
|---|---|
| Position | 24-bit fixed point per coordinate |
| Scale | 8-bit (log domain) |
| Rotation | Smallest-three: 2-bit index of the largest component + three 10-bit components |
| Color / opacity | 8-bit each |
| SH coefficients | Degree 1 = 5-bit, degree 2+ = 4-bit (defaults) |
In the wild ── Scaniverse exports SPZ, and Niantic open-sourced it under MIT (nianticlabs/spz). The stated compression is roughly 1/10 the size of the equivalent PLY.
06 SOG (PlayCanvas)
Developed by PlayCanvas and sometimes described as "WebP for Gaussian Splatting." Gaussians are sorted by attributes such as position, scale, and color, then each attribute is compressed as a WebP image and linked together via meta.json. Because similar Gaussians end up adjacent before image compression is applied, the compression is highly efficient — there are reports of a 1GB PLY shrinking to around 55MB (roughly 20x).
| Item | Details |
|---|---|
| Extension | A folder + meta.json (not a single file) |
| Compression | Attribute sorting plus WebP image compression. Measured at roughly 20x |
| Supported tools | SuperSplat, splat-transform, Spark, and other PlayCanvas-ecosystem tools |
| Best for | Delivery and streaming in the browser. When file size is the top priority |
Inside the spec (for the nerds)
Inside the spec ── One scene is meta.json plus a set of WebP images (5 required files, plus 2 optional files for higher-order SH). The core convention: the same pixel coordinate (x, y) refers to the same gaussian across every image:
| File | Contents |
|---|---|
| means_l / means_u.webp | Position. 16-bit values quantized in log domain, split into low/high 8-bit images (RGB = xyz) |
| quats.webp | Rotation. Smallest-three (3 components × 8-bit + index of the dropped component) |
| scales.webp | Scale. 8-bit codebook indices (log domain) |
| sh0.webp | Base color. RGB = codebook indices, A = opacity |
| shN_centroids / shN_labels.webp | Higher-order SH. K-means palette of up to 65,536 entries, referenced by 16-bit labels |
The WebPs must be lossless to preserve the quantized values. A single-file .sog — all assets zipped together — is also defined. The spec is published in the official PlayCanvas documentation.
07 RAD (Spark)
A streaming-only format that Spark, the Three.js renderer, added in 2.0, capable of storing an LOD tree as-is. You build and save the LOD tree ahead of time with the build-lod command, and at viewing time only the chunks (.radc) you need are fetched via HTTP Range Requests. It's a "coarse-to-fine" design: a rough version appears instantly, and more detail streams in as the viewpoint moves. Locahun 3D's own viewer builds its custom parallel decoding and LOD control around this RAD format as well.
| Item | Details |
|---|---|
| Extension | .rad (header, LOD tree) + .radc (chunk data) |
| Compression | Internally defaults to 16 bytes/Gaussian PackedSplats. Delivered per-chunk over HTTP Range requests |
| Supported tools | Spark (loaded with paged:true). Support elsewhere is currently limited |
| Best for | When streaming an ultra-large scene with over 100 million points while staying within GPU memory |
In the wild ── Our own viewer streams a 934MB, 49.4-million-gaussian RAD to first render in about 6 seconds (after that, camera moves hit the resident cache with no wait). The only primary sources for the format are Spark's documentation and source code — there is no standalone spec document like SPZ's or SOG's yet.
08 LCC / LCC2 (XGRIDS)
A container format developed by XGRIDS for handling city-scale scenes with LOD (level of detail). Rather than a single file, it's made up of JSON metadata (an octree-style LOD tree) and a data/3dgs/ folder holding the actual data. The underlying data is stored as either SOG or SPZ, and adjacent nodes are merged into a single file. PortalCam scans also include this: LCC Studio's export contains a Lcc2/lcc2-result/ folder (3dgs as SOG, mesh as PLY).
| Item | Details |
|---|---|
| Extension | .lcc2 (metadata) + SOG or SPZ under data/3dgs |
| Compression | Follows the compression ratio of whichever SOG/SPZ is used internally |
| Supported tools | XGRIDS's own SDK (UE5/Unity/Web), splat-transform (read-only), SuperSplat, 3ds Max 2027.2 (read) |
| Best for | For large-scale scenes such as an entire city district, when you want LOD switching based on camera distance |
09 glTF (KHR_gaussian_splatting)
The official Khronos extension, currently being standardized, for storing 3DGS inside glTF/GLB. A release candidate (RC) was published in February 2026 and it's now in the final stages toward formal ratification. Compression uses the SPZ-based extension donated by Niantic Spatial (KHR_gaussian_splatting_compression_spz). Its biggest significance is the shift away from a proliferation of proprietary formats toward building on top of glTF, a general-purpose 3D standard. Cesium adopted it as a payload to support hierarchical LOD streaming in 3D Tiles (April 2026), making it possible to deliver city-scale 3DGS with geographic coordinates. Conversion CLIs like gsbox also support PLY⇄GLB.
| Item | Details |
|---|---|
| Extension | .glb / .gltf (KHR_gaussian_splatting extension) |
| Compression | SPZ-based compression extension (up to 90% smaller than PLY) |
| Supported tools | CesiumJS, Cesium for Unreal, Cesium ion, gsbox. Still an RC, so support is expanding |
| Best for | Long-term storage and distribution on a standard format. City-scale geospatial delivery combined with 3D Tiles |
Inside the spec (for the nerds)
Inside the spec (RC) ── On a mesh primitive, alongside POSITION, the extension defines prefixed attributes: KHR_gaussian_splatting:ROTATION (VEC4, unit quaternion) / :SCALE (VEC3) / :OPACITY (SCALAR, 0–1) / :SH_DEGREE_0_COEF_0 (VEC3). Higher-order SH goes up to degree 3 (45 coefficients total) with a hierarchy rule: if you include a degree, you must include all lower degrees. Display color derives from the degree-0 coefficient as Color = SH0 × 0.282095 + 0.5. In proper standards fashion, you can also include a COLOR_0 attribute so viewers without 3DGS support can fall back to point-cloud rendering. Read the spec in the Khronos glTF repository.
10 So which one should you use?
One core principle first. Compressed formats like SPZ, SOG, and KSPLAT quantize the data, and once compressed, the original quality cannot be recovered. Whatever you pick for delivery, keep the PLY straight out of training as your master and derive per-use-case copies from it. Format selection is not about choosing a master — it's about choosing how you deliver and hand off.
With that in place, here's a rough guide by use case. Use it together with our comparison of 3DGS-capable software and tools to decide which format to use with which software.
- Passing data to another DCC (Houdini, Blender, etc.) ── PLY. More tools now read SPZ directly (3ds Max 2027.2, for one), but PLY is still the only format every tool is guaranteed to open
- Publishing and sharing on the web ── Decide by what your viewer supports. If you're displaying through the PlayCanvas family (SuperSplat, Spark), go SOG for maximum compression (note it's a folder, not a single file). If you need one file to hand around, or you can't predict the recipient's setup, SPZ is the safe pick
- Switching LOD in a city-scale scene ── LCC2 if you're on XGRIDS' SDKs (UE5/Unity); Cesium's 3D Tiles + glTF (09) if you want an open standard with geospatial coordinates. Remember to check LCC2's proprietary license
- Streaming an ultra-large scene with over 100 million points ── RAD. Spark-only, but it's currently the only format that delivers the whole LOD tree over HTTP Range requests
- Building a custom viewer with GaussianSplats3D ── KSPLAT. Gets the benefit of progressive display
- Long-term storage and distribution on a standard ── glTF (KHR_gaussian_splatting) is where this is heading, but it's still at the RC stage. For archival today, the reliable setup is a PLY master plus compressed derivatives
As for SPLAT: there's little reason to adopt it for new work. It has no formal spec and drops the SH coefficients — even for "just want a quick look" cases, tossing the PLY straight into a viewer like SuperSplat is faster and safer.
Converting between formats is mostly covered in one place by splat-transform.
If you want to handle huge 3DGS data without worrying about the format
Locahun 3D's own viewer is built on Spark, which supports the major formats including SOG and SPZ, and is developed to handle huge 3DGS data offline, in the browser alone. Try a sample scene with no download or sign-up required.
Try a sample scene in your browser →
