@playcanvas/splat-transform
Version:
Library and CLI tool for 3D Gaussian splat format conversion and transformation
51 lines (50 loc) • 2.31 kB
TypeScript
import { GraphicsDevice } from 'playcanvas';
import { type RenderCamera } from './camera';
import { DataTable } from '../data-table';
/**
* Max gaussians per GPU dispatch. Bounds per-render input/projection
* buffer sizes and the granularity of the depth-ordered chunked path.
*
* Each chunk dispatches its own project + rasterize-accumulate.
* Running state persists across chunks; saturated pixels (T < 1e-4)
* short-circuit on subsequent chunks via the rasterize shader's T
* early-out.
*/
declare const CHUNK_CAP = 200000;
interface BackgroundRGBA {
r: number;
g: number;
b: number;
a: number;
}
/**
* Render a splat scene to an RGBA byte buffer.
*
* Whole-image pipeline:
*
* 1. Linear frustum cull — one pass over all splats, testing each
* centre against the camera frustum in camera-space. No BVH or
* per-splat AABB precomputation.
* 2. Sort visible splats globally by camera-space z (front-to-back).
* 3. Split image into a grid of sub-frames (each ≤ MAX_SUB_FRAME_TILES
* in either dimension) and render each independently. The rasterizer
* retains its per-sub-frame running state; the project shader's
* group-AABB cull skips splats outside the current sub-frame. The
* CPU depth sort is global, so depth ordering is consistent across
* sub-frames and there are no boundary seams.
*
* Per-chunk (GPU tile-bin pipeline, fully GPU-resident): project (writes
* per-splat tile coverage) → prefix-sum (writes emitOffsets + totalPairs)
* → emit-pairs → prepare-indirect → radix sortIndirect (key + value:
* tile keys sorted, splat indices reordered) → init-tile-offsets →
* find-boundaries (atomicMin) → rasterize each tile's slice in depth
* order. No per-chunk CPU readbacks.
*
* @param device - PlayCanvas WebGPU graphics device.
* @param dataTable - Gaussian splat data in PlayCanvas-identity space.
* @param camera - Camera parameters.
* @param background - RGBA background composited under residual transmittance.
* @returns RGBA byte array of length `camera.width × camera.height × 4`.
*/
declare const renderRasterPass: (device: GraphicsDevice, dataTable: DataTable, camera: RenderCamera, background: BackgroundRGBA) => Promise<Uint8Array>;
export { renderRasterPass, CHUNK_CAP };