Back to all works & blog
3DGSFormatsReference 2026-08-09Updated 2026-08-11~13 min read

Sorting Out 3DGS File Formats

Even for the same scene, 3D Gaussian Splatting (3DGS) file size and tool compatibility change depending on the storage format. This article sorts out the major formats — PLY, SPLAT, KSPLAT, SPZ, SOG, RAD, and LCC/LCC2 — by compression method, supported tools, and use case. Read it alongside our comparison of 3DGS-capable software and tools to make it easier to decide which format to use with which software.

This article reflects information as of August 20263DGS formats are being actively updated. Check each project's repository for the latest specifications.
Spark (sparkjsdev) logo
Niantic Spatial logo
PlayCanvas logo
XGRIDS logo

The four organizations behind the main formats covered in this article. Each logo is a trademark of its respective owner and is shown here for the purpose of identifying and comparing formats.

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.

FormatIn one lineExtensionCompressionSupported toolsBest for
PLYThe full original. Huge.plyUncompressed by defaultNearly all toolsData exchange, compatibility priority
SPLATEarly simplified format. Skip it today.splatSH coefficients dropped + quantizedMainly early web viewersCompatibility with older viewers (not recommended for new work)
KSPLATOne viewer's private format.ksplatChunked + two-tier compressionGaussianSplats3D onlyCustom viewers with progressive display
SPZThe go-to compressed format. 1/10 of PLY.spzv1-3 = gzip / v4 = zstdScaniverse, splat-transform, Spark, etc.General-purpose compact format for distribution/storage
SOGImage-compression tricks, smallest classFolder + meta.jsonAttribute sort + WebP (~20x)PlayCanvas-ecosystem toolsWeb delivery / streaming
RADBuilt for streaming giant scenes.rad + .radc16 bytes/Gaussian + chunked deliverySpark onlyUltra-large streaming beyond 100M points
LCC / LCC2A container for whole cities.lcc2 + SOG/SPZFollows internal formatXGRIDS SDK, splat-transform (read)City-scale LOD switching
glTF (GLB)The standards-track future.glb / .gltfSPZ-based KHR compression extensionCesium 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.

ItemDetails
Extension.ply
CompressionUncompressed by default (a "Compressed PLY" variant supported by tools like splat-transform also exists)
Supported toolsReadable by nearly every DCC, viewer, and conversion tool
Best forExchanging 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.

ItemDetails
Extension.splat
CompressionLightweighted by dropping SH coefficients and quantizing values (not codec-style compression)
Supported toolsMainly early web viewers. There's no formal spec — the layout is settled by convention
Best forWhen 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.

ItemDetails
Extension.ksplat
CompressionChunked splitting plus two compression levels (level 2 also compresses SH to 8 bits)
Supported toolsGaussianSplats3D only (a dedicated format). A PLY/SPLAT conversion tool ships with it
Best forWhen 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.

ItemDetails
Extension.spz
Compressionv1-3 = gzip / v4 = zstd (higher compression ratio)
Supported toolsBroad support: Scaniverse, splat-transform, Spark, UnityGaussianSplatting, 3ds Max 2027.2, and more
Best forAs 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:

AttributeQuantization
Position24-bit fixed point per coordinate
Scale8-bit (log domain)
RotationSmallest-three: 2-bit index of the largest component + three 10-bit components
Color / opacity8-bit each
SH coefficientsDegree 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).

ItemDetails
ExtensionA folder + meta.json (not a single file)
CompressionAttribute sorting plus WebP image compression. Measured at roughly 20x
Supported toolsSuperSplat, splat-transform, Spark, and other PlayCanvas-ecosystem tools
Best forDelivery 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:

FileContents
means_l / means_u.webpPosition. 16-bit values quantized in log domain, split into low/high 8-bit images (RGB = xyz)
quats.webpRotation. Smallest-three (3 components × 8-bit + index of the dropped component)
scales.webpScale. 8-bit codebook indices (log domain)
sh0.webpBase color. RGB = codebook indices, A = opacity
shN_centroids / shN_labels.webpHigher-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.

ItemDetails
Extension.rad (header, LOD tree) + .radc (chunk data)
CompressionInternally defaults to 16 bytes/Gaussian PackedSplats. Delivered per-chunk over HTTP Range requests
Supported toolsSpark (loaded with paged:true). Support elsewhere is currently limited
Best forWhen 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).

ItemDetails
Extension.lcc2 (metadata) + SOG or SPZ under data/3dgs
CompressionFollows the compression ratio of whichever SOG/SPZ is used internally
Supported toolsXGRIDS's own SDK (UE5/Unity/Web), splat-transform (read-only), SuperSplat, 3ds Max 2027.2 (read)
Best forFor large-scale scenes such as an entire city district, when you want LOD switching based on camera distance
A note on licensingLCC/LCC2 is covered by XGRIDS's own proprietary license. We believe the impact is small for a custom loader that only reads the format, but if you're considering serious commercial use or redistribution, check the license terms in the official whitepaper beforehand.

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.

ItemDetails
Extension.glb / .gltf (KHR_gaussian_splatting extension)
CompressionSPZ-based compression extension (up to 90% smaller than PLY)
Supported toolsCesiumJS, Cesium for Unreal, Cesium ion, gsbox. Still an RC, so support is expanding
Best forLong-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.

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.

Locahun3D Viewer

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 →
Credits / Production

Credit

Kou Nakamura
Kou Nakamura
Founder, Locahun 3D / Research & Writing

Founder of Locahun 3D (LOCAHUN 3D). Researches and tests capture workflows that combine 3DGS scanning with game engines and AI.

Follow @Kou45388803 →