Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a compact work buffer format for GSplat rendering that reduces memory and bandwidth usage by 37.5% (from 32 to 20 bytes per splat) compared to the existing format. The compact format uses advanced encoding techniques including 11+11+10 bit RGB color (supporting [0,4] range), half-angle quaternion projection for rotation (3 components instead of 4), and log-encoded scale values covering e^-12 to e^9 range. The format is runtime-switchable via the scene.gsplat.dataFormat property, with GSPLATDATA_COMPACT as the new default and GSPLATDATA_LARGE available for full precision when needed.
The PR also unifies the rendering code path by using instanced draws for all splats (both octree and non-octree), eliminating the zero-fill code path that was previously needed for non-LOD splats. This simplification removes redundant uniforms (uActiveSplats, uViewportWidth) and ensures consistent behavior across all rendering scenarios.
Changes:
- Added compact 20 bytes/splat format with specialized encoding (half-angle quaternion, log-encoded scale, packed RGB)
- Created format-specific read/write shader interfaces for both GLSL and WGSL
- Unified instanced draw path for all splats, removing conditional rendering logic
- Added runtime format switching capability with automatic work buffer recreation
- Updated viewer and lod-streaming examples with compact format toggle (defaulting to enabled)
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/scene/constants.js | Added GSPLATDATA_COMPACT and GSPLATDATA_LARGE constants for format selection |
| src/scene/gsplat-unified/gsplat-params.js | Implemented format creation and runtime switching logic, defaulting to compact format |
| src/scene/gsplat-unified/gsplat-manager.js | Added handleFormatChange() to detect and handle format changes, ensuring work buffer recreation |
| src/scene/gsplat-unified/gsplat-work-buffer-render-pass.js | Removed conditional intervals logic, unified to always use instanced draws |
| src/scene/gsplat-unified/gsplat-renderer.js | Extracted setOrderData() method for reuse after work buffer changes |
| src/scene/gsplat-unified/gsplat-info.js | Synthesizes full-range interval when none exist to ensure unified instanced path |
| src/scene/gsplat/gsplat-format.js | Added setWriteCode/getWriteCode methods for format-specific write encoding |
| src/scene/gsplat/gsplat-resource-base.js | Integrated format-specific write code injection, removed useIntervals parameter |
| src/scene/shader-lib/wgsl/chunks/gsplat/vert/formats/containerCompactRead.js | WGSL read functions for compact format with half-angle quaternion and log-scale decoding |
| src/scene/shader-lib/wgsl/chunks/gsplat/frag/formats/containerCompactWrite.js | WGSL write functions for compact format with specialized encoding |
| src/scene/shader-lib/wgsl/chunks/gsplat/frag/formats/containerPackedWrite.js | WGSL write functions for large format, extracted from copy shader |
| src/scene/shader-lib/wgsl/chunks/gsplat/frag/gsplatCopyToWorkbuffer.js | Unified shader logic, removed zero-fill path, uses format-specific writeSplat() |
| src/scene/shader-lib/glsl/chunks/gsplat/vert/formats/containerCompactRead.js | GLSL read functions for compact format (parallel to WGSL version) |
| src/scene/shader-lib/glsl/chunks/gsplat/frag/formats/containerCompactWrite.js | GLSL write functions for compact format (parallel to WGSL version) |
| src/scene/shader-lib/glsl/chunks/gsplat/frag/formats/containerPackedWrite.js | GLSL write functions for large format, extracted from copy shader |
| src/scene/shader-lib/glsl/chunks/gsplat/frag/gsplatCopyToWorkbuffer.js | Unified shader logic (parallel to WGSL version) |
| src/scene/shader-lib/wgsl/collections/gsplat-chunks-wgsl.js | Removed containerPackedRead from collection (now imported directly where needed) |
| src/scene/shader-lib/glsl/collections/gsplat-chunks-glsl.js | Removed containerPackedRead from collection (now imported directly where needed) |
| examples/src/examples/gaussian-splatting/viewer.example.mjs | Added compact toggle control, defaults to enabled |
| examples/src/examples/gaussian-splatting/viewer.controls.mjs | Added UI control for compact format toggle |
| examples/src/examples/gaussian-splatting/lod-streaming.example.mjs | Added compact toggle control, defaults to enabled |
| examples/src/examples/gaussian-splatting/lod-streaming.controls.mjs | Added UI control for compact format toggle |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adds a compact 20 bytes/splat work buffer format (
GSPLATDATA_COMPACT) as the new default,reducing memory and bandwidth by 37.5% compared to the existing 32 bytes/splat format.
(f32 position + half-angle quaternion), R32U scale/alpha (3x8-bit log-encoded scale + 8-bit alpha)
scene.gsplat.dataFormatpropertyzero-fill code path and redundant uniforms
writeSplat()shader interface decoupling the copy shader fromindividual format encodings