3DGS Renderer Bench
Spark · SuperSplat · Gaussian Splat Lite
Rendering, sorting and memory measured on the same original PLY files, with matching cameras and full models at the MacBook Pro 14 Retina resolution. Each renderer uses its default rendering parameters and camera-axis depth sorting.
Current scene
ms · Lower is betterGreen highlighting marks the lowest displayed value in each comparable metric; ties are shared. Rankings follow the current filters.
Bars show the median of the independent run statistics; P95 is computed within each run first. Native GPU queries measure the first-to-last GPU pass span on WebGPU and elapsed GPU time on WebGL2. Frame completion also includes submission and query readback, with one frame in flight. Neither measurement is the display refresh interval.
Where sorting runs
Worker sorting runs asynchronously; GPU sorting is ordered within the GPU command stream. Async completion includes preparation, transfers, sorting and handing back the result. A separate diagnostic measures the first-to-last radix pass span. Each run alternates between two camera directions, with 4 warm-up iterations and 16 measured samples.
The Gaussian Splat Lite WebGPU diagnostic separates projection and radix into two compute passes; the main frame chart retains its original combined path. SuperSplat keeps its native pass boundaries. Visible counts, key precision and culling differ, so these are renderer pipeline measurements, not equal-input sorting algorithm benchmarks.
Sorting precision, explained
All sorted tests use camera-axis depth. Source encoding, depth-key precision and sort latency are separate properties. A wider key preserves more depth distinctions, while an asynchronous result may still lag behind the current camera.
| Renderer | Depth key | Execution | Precision and trade-off |
|---|---|---|---|
| Spark · WebGL2 | 32-bit float depth, all bits retained | GPU depth readback → Worker/WASM; 2 × 16-bit radix digits | No extra truncation of the float32 depth key. GPU readback and Worker transfers contribute to async completion latency. |
| SuperSplat · WebGPU | 20-bit integer, uniformly quantized across near…far | GPU compaction + radix; 5 × 4-bit radix digits | 1,048,576 depth levels. Bin spacing depends on the clip range; narrowing that range improves depth discrimination. |
| Gaussian Splat Lite · default | Upper 24 bits of the float32 key; lowest 8 bits removed | WebGL2: Worker/WASM, 1 × 24-bit counting pass. WebGPU: 6 × 4-bit radix digits. | 15 fraction bits remain. Depth spacing grows with distance. Fewer scatter passes; WebGL2 uses a 64 MiB count table. |
| Gaussian Splat Lite · full precision | All 32 bits of the float32 key retained | WebGL2: Worker/WASM, 2 × 16-bit radix digits. WebGPU: 8 × 4-bit radix digits. | Preserves all 23 float32 fraction bits. Separates depths merged by the default mode, with more sorting work. |
For this near = 0.1, far = 3000 setup, SuperSplat’s nominal depth bin is ≈0.002861 model units. At depth 100, Gaussian Splat Lite default spacing is ≈0.001953, versus ≈0.00000763 for a full float32 key; at depth 1000, those spacings are ≈0.015625 and ≈0.0000610. These are encoding intervals, not measured image errors. Thus “24 bit” does not always resolve finer depths than “20 bit.”
Nearly coincident splats can share a quantized key, changing alpha-blend results. Full-precision sorting preserves the computed float32 center depths; it does not remove floating-point rounding or provide per-pixel ordering for intersecting Gaussians. Switching Gaussian Splat Lite sorting leaves source positions, SH data and model count unchanged. Spark uses extended source and accumulator encoding in both timing and image tests.
Spark sort source · SuperSplat depth keys · Gaussian Splat Lite Worker sort source · Gaussian Splat Lite GPU depth keys
JS heap and GPU allocation
For each run, take the largest post-GC snapshot across the static, close and moving sorted cases, then report the median across three runs. Gaussian Splat Lite includes caches retained after both sorting modes; this is not memory for each mode in isolation. Stochastic render targets are excluded. MiB = 2²⁰ bytes.
JS heap · main thread · MiB
Explicit GPU allocation · MiB
JS heap is the page’s main-thread V8 used heap after garbage collection, measured with Chrome Runtime.getHeapUsage. It excludes Worker JS heaps and is not the complete CPU memory footprint. Large model arrays are mainly outside that heap: main-thread ArrayBuffer/external-string backing storage and live Worker WASM linear-memory capacity are reported separately. These scopes may overlap and must not be summed into a total.
Explicit GPU allocation tracks buffer, texture and renderbuffer capacity, excluding measurement-query buffers, driver overhead, alignment and the swapchain. It is allocated resource capacity, not physical VRAM usage; Apple uses unified memory. Browser process-tree RSS includes unrelated browser/GPU-process memory and can double-count shared pages, so it is retained only as raw diagnostics, not used for the memory comparison.
Image comparison
Fixed matching cameras, 3024 × 1964 captures. HotelFareza is framed around the building façade. Click a render to inspect the original. Gaussian Splat Lite WebGPU uses the viewer’s sRGB working space, matching WebGL’s sRGB blending. Native SH decoding and projection remain unchanged. Spatial resolve has temporal accumulation disabled; no TAA pass is used.
MAE (RGB 0–255) and PSNR compare each backend with its own normal-sorting capture. They quantify image change, not subjective image quality or a ranking between renderers.
Measurement scope
Full inputs, fixed resolutionElevator: 2,796,503 splats; HotelFareza: 12,202,010. Canvas dimensions follow the built-in screen’s logical size and default DPR. Headless Chrome uses the real Metal GPU without display-rate throttling. FOV 45°, near 0.1, far 3000, black background. Matching world-space cameras; native frustum, opacity and size culling remain active.
Spark source precisionBoth source and accumulator use extended encoding, with runtime assertions. Base records are 32 bytes with float32 positions; “extended” does not mean every field is float32. Neither uses PackedSplats. SH3 is retained. The 32-byte source record and the 32-bit sort key describe different things.
Gaussian Splat Lite source and accumulatorGaussian Splat Lite 1.1.5 uses 32-byte base records: float32 positions; float16 RGB, alpha and log-scale; a 10/10-bit octahedral rotation axis plus a 12-bit angle. SH3 remains enabled; each RGB coefficient uses 32 bits (8-bit channel magnitudes, 3 sign bits and a shared 5-bit exponent). WebGL2 uses highp shader arithmetic and a 32-byte accumulator with the same attribute layout.
Gaussian Splat Lite WebGPU precisionNative WebGPU computes projection in float32 and stores 32-byte projected records: screen centers use 16-bit signed normalized values; axes, axis ratio and RGB use float16; view depth, alpha, support radius and kernel power use float32. Full-precision sorting retains the complete 32-bit depth key; it does not change source encoding or projection-cache precision.
SuperSplat implementationOriginal SuperSplat Editor 3.4.2 ProjectedSplatRenderer, EditorSplatResource, shaders, GPU radix and spatial resolve, with PlayCanvas 2.22.4. Normal blending uses RGBA16F. Stochastic uses its native RGBA8 target, linear filtering and resolve to RGBA16F. Its stochastic rendering mode enables occlusion culling; it is lossy, but delivers a substantial performance improvement in large scenes.
Caching and motionStatic tests still draw every frame and retain internal projection caches. Moving tests use matching camera sequences; asynchronous backends may draw with a previous ordering. Frame time therefore does not include waiting for the newest sort. Motion advances per frame, so results do not claim equal-time interactive FPS.
Supported featuresSpark 2.2.0 has no native stochastic path; those entries are unavailable. A dash means the metric is not applicable. Results describe this machine, these views, inputs and pinned versions. A different GPU, camera or color configuration can change the relative performance.
Versions, data and sources
Spark renderer · ExtSplats · SuperSplat source · Gaussian Splat Lite v1.1.5 · Layout / protocol reference