Skip to content

@gameable/splat ​

Classes ​

AnimatedSplat ​

A dynamic splat: SplatSink plus lifecycle.

Implements ​

Constructors ​

Constructor ​
ts
new AnimatedSplat(renderer, options): AnimatedSplat;

Use createAnimatedSplat; the GPU buffers must be acquired before the object is usable, and that needs an initialised renderer.

Parameters ​
ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer, on WebGPU or the WebGL2 fallback.
optionsCreateAnimatedSplatOptionsCapacity, bounds and draw order.
Returns ​

AnimatedSplat

Properties ​

capacity ​
ts
readonly capacity: number;

Total gaussians this sink can hold. Fixed for its lifetime.

Implementation of ​

SplatSink.capacity

nodes ​
ts
readonly nodes: SplatStorageNodes;

The four buffers as writable TSL storage nodes, on either backend.

Implementation of ​

SplatSink.nodes

shBuffers ​
ts
readonly shBuffers: readonly GPUBuffer[];

One GPUBuffer per spherical-harmonics band asked for (shDegree): band 1 is 3 words a gaussian, band 2 is 4, band 3 is 6, in three's packing, storageCapacity gaussians each. Empty without bands, and on the WebGL fallback.

splat ​
ts
readonly splat: AnimatedGaussianSplat;

The fork instance. Typed as the fork, not as Object3D, for object3D consumers.

storageCapacity ​
ts
readonly storageCapacity: number;

Elements actually allocated per buffer: capacity padded up to the WebGL fallback's PBO texture shape. The slots past capacity are never handed out and stay invisible. A compute on the fallback dispatches exactly this many invocations.

Implementation of ​

SplatSink.storageCapacity

Accessors ​

available ​
Get Signature ​
ts
get available(): number;

Slots not handed out. Named available, because free is the method above.

Returns ​

number

The count.

buffers ​
Get Signature ​
ts
get buffers(): SplatGPUBuffers;

The four GPU buffers. WebGPU only.

Throws ​

On the WebGL fallback, which has no GPUBuffers; use nodes.

Returns ​

SplatGPUBuffers

The buffers, acquired at construction.

The four GPU buffers, in the layout documented in backendBuffers.ts. WebGPU only: on the WebGL fallback reading this throws; write through SplatSink.nodes instead.

Implementation of ​

SplatSink.buffers

largestFree ​
Get Signature ​
ts
get largestFree(): number;

The longest run of free slots, the most one allocate can give.

Returns ​

number

The count.

object3D ​
Get Signature ​
ts
get object3D(): Object3D;

The scene object.

Returns ​

Object3D

The fork instance, which is an ordinary Object3D.

The scene object. Add it to a scene, move it, parent it — it is an ordinary Object3D.

Implementation of ​

SplatSink.object3D

used ​
Get Signature ​
ts
get used(): number;

Slots currently handed out.

Returns ​

number

The count.

Methods ​

allocate() ​
ts
allocate(count): SlotRange;

Reserve a contiguous run of slots.

Parameters ​
ParameterTypeDescription
countnumberHow many gaussians.
Returns ​

SlotRange

The range.

Implementation of ​

SplatSink.allocate

clearSlots() ​
ts
clearSlots(range?): void;

Zero a slot range, which makes it invisible: a colour word of 0 is alpha 0.

This is a queue.writeBuffer of zeros, which is allowed here precisely because it is not a per-frame operation — it runs when a branch is allocated or retired. A producer must never upload gaussian data this way; that is what the compute pass is for.

Parameters ​
ParameterTypeDescription
range?SlotRangeThe range to clear. Defaults to the whole capacity.
Returns ​

void

Nothing.

dispose() ​
ts
dispose(): void;

Detach from the scene and release the geometry, material and every storage buffer.

"Every storage buffer" is nine of them (more with bands, rest points or a place's projected squares): the four gaussian buffers, the spherical-harmonics contribution buffer if the pre-pass ever ran, and the four the sort holds. Three frees none of them on its own — BufferAttribute.dispose() dispatches an event nothing listens for on a storage attribute — so a despawned character used to leak about 2 MB of GPU memory.

Idempotent, and every mutating method throws afterwards.

Returns ​

void

Nothing.

free() ​
ts
free(range): void;

Give a range back.

Parameters ​
ParameterTypeDescription
rangeSlotRangeA range from AnimatedSplat.allocate.
Returns ​

void

Nothing.

Implementation of ​

SplatSink.free

markGaussiansChanged() ​
ts
markGaussiansChanged(): void;

Force a re-sort on the next frame.

On the WebGL fallback this asks for a readback of the centres instead (at most one every 50 ms); the sort runs when it lands. Calls while one is in flight coalesce into the next.

Returns ​

void

Nothing.

Implementation of ​

SplatSink.markGaussiansChanged

releaseCpuCopies() ​
ts
releaseCpuCopies(): object;

Let go of the CPU copies three keeps of buffers the GPU already holds: the zero-filled arrays the capacity was uploaded from, the sort's, the colour pass's. A producer that writes the GPU buffers itself never needs them, and at millions of gaussians they are hundreds of megabytes. Buffers not yet on the GPU (the sort's before its first frame) stay: call again after a frame until waiting is 0. Nothing happens on the WebGL fallback, whose transform feedback and readback keep the arrays.

Returns ​

object

Bytes freed now, and how many buffers are still waiting for their first frame.

bytes ​
ts
bytes: number;
waiting ​
ts
waiting: number;
restPoints() ​
ts
restPoints(): GPUBuffer;

The GPU buffer of each point's rest centre and group, for a point hook (AnimatedGaussianSplat.setPointHook): a vec4 a slot, xyz the rest centre in the splat's own space, w the group. Allocated on the first call (16 bytes a slot); the producer writes it with device.queue.writeBuffer. WebGPU only: on the WebGL fallback it throws (the hook reads center for the rest centre there).

Returns ​

GPUBuffer

The buffer.

Throws ​

On the WebGL fallback.

Example ​
ts
const rest = sink.restPoints();
device.queue.writeBuffer(rest, range.offset * 16, restData);
Implementation of ​

SplatSink.restPoints

setBoundingSphere() ​
ts
setBoundingSphere(center, radius): void;

Declare where the gaussians are, in local space.

Parameters ​
ParameterTypeDescription
centerVec3TupleLocal-space centre.
radiusnumberLocal-space radius.
Returns ​

void

Nothing.

Implementation of ​

SplatSink.setBoundingSphere

setColorScale() ​
ts
setColorScale(
   r, 
   g, 
   b
): void;

Multiply every gaussian's colour, in linear light after the colour-space decode: a tint and an exposure, to fit a character into a scene's light. (1, 1, 1) is the file's colour. Set it as often as you like (a uniform).

Parameters ​
ParameterTypeDescription
rnumberRed multiplier.
gnumberGreen multiplier.
bnumberBlue multiplier.
Returns ​

void

Nothing.

setFragmentAlpha() ​
ts
setFragmentAlpha(builder): void;

Scale each fragment's opacity by a node built from the splat's view-space centre, or pass null to draw as before. See the fork's edit 15.

Parameters ​
ParameterTypeDescription
builder((view) => Node) | nullReturns a float node from the view-space centre (a vec3 node).
Returns ​

void

Nothing.


SlotAllocationError ​

An allocation request that cannot be satisfied.

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new SlotAllocationError(
   message, 
   requested, 
   largestFree
): SlotAllocationError;

Build a slot allocation error.

Parameters ​
ParameterTypeDescription
messagestringWhat went wrong.
requestednumberSlots requested.
largestFreenumberLargest free run at the time.
Returns ​

SlotAllocationError

Overrides ​
ts
Error.constructor

Properties ​

largestFree ​
ts
readonly largestFree: number;

The largest run available at the time.

requested ​
ts
readonly requested: number;

Slots that were asked for.


SplatLoadError ​

A splat file that could not be decoded.

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new SplatLoadError(
   url, 
   message, 
   options?
): SplatLoadError;

Build a splat load error.

Parameters ​
ParameterTypeDescription
urlstringThe URL that failed.
messagestringWhat went wrong.
options?ErrorOptionsStandard Error options, used to keep the cause.
Returns ​

SplatLoadError

Overrides ​
ts
Error.constructor

Properties ​

url ​
ts
readonly url: string;

The URL that failed.


SplatPlace ​

A streaming place in the scene.

Constructors ​

Constructor ​
ts
new SplatPlace(
   renderer, 
   index, 
   source, 
   options?, 
   ready?
): SplatPlace;

Use loadSplatPlace.

Parameters ​
ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer on the WebGPU backend.
indexPlaceIndexThe place's index.
sourcePlaceSourceWhere its files come from.
optionsSplatPlaceOptionsBudget and the rest.
ready{ metas?: ReadonlyMap<number, SogMeta>; pool?: SogWorkerPool; }Workers already started and metas already fetched (by loadSplatPlace, so they get going while the index is read and before this constructor makes the splat's buffers).
ready.metas?ReadonlyMap<number, SogMeta>Files' metas by file index.
ready.pool?SogWorkerPoolThe decode workers.
Returns ​

SplatPlace

Properties ​

index ​
ts
readonly index: PlaceIndex;

The place's index (lod-meta.json).

sink ​
ts
readonly sink: AnimatedSplat;

The splat every piece is drawn in.

stats ​
ts
readonly stats: SplatPlaceStats;

Live numbers.

Accessors ​

budget ​
Get Signature ​
ts
get budget(): number;

Gaussians shown at most.

Returns ​

number

The budget.

Set Signature ​
ts
set budget(value): void;

Change the budget (capped by the capacity the place was made with).

Parameters ​
ParameterTypeDescription
valuenumberGaussians.
Returns ​

void

firstPicture ​
Get Signature ​
ts
get firstPicture(): Promise<void>;

Resolves once the coarsest level of every leaf is on screen (the first picture).

Returns ​

Promise<void>

The promise.

object3D ​
Get Signature ​
ts
get object3D(): Object3D;

The scene object.

Returns ​

Object3D

The splat; add it to the scene, move it, turn it.

Methods ​

dispose() ​
ts
dispose(): void;

Remove from the scene, stop the workers, free the splat's buffers.

Returns ​

void

Nothing.


WebglSkinnedSplat ​

A dynamic splat fed by a gaussian source and an owner's order, for the WebGL fallback.

Example ​

ts
import { createWebglSkinnedSplat } from 'gameable/splat';
import { vec3, vec4 } from 'three/tsl';

const splat = createWebglSkinnedSplat(renderer, { capacity: 144_492, colorSpace: 'srgb' });
splat.setGaussianSource(({ index }) => ({ center: vec3(0), covA: vec4(0.01, 0, 0, 0.01), covB: vec4(0, 0.01, 0, 0), color: vec4(1) }));
scene.add(splat.object3D);

Constructors ​

Constructor ​
ts
new WebglSkinnedSplat(renderer, options): WebglSkinnedSplat;

Use createWebglSkinnedSplat.

Parameters ​
ParameterTypeDescription
rendererWebGPURendererAn initialised renderer on the WebGL fallback.
optionsCreateWebglSkinnedSplatOptionsCapacity, bounds, draw order and colour space.
Returns ​

WebglSkinnedSplat

Properties ​

capacity ​
ts
readonly capacity: number;
splat ​
ts
readonly splat: AnimatedGaussianSplat;

The fork instance.

storageCapacity ​
ts
readonly storageCapacity: number;

Slots the fork really holds: capacity padded to the fallback's texture shape (fork edit 17, padStorageCapacity). The source is asked for the first capacity only; an order from the owner may cover capacity or all of these.

Accessors ​

object3D ​
Get Signature ​
ts
get object3D(): Object3D;

The scene object.

Returns ​

Object3D

The fork instance, an ordinary Object3D.

Methods ​

dispose() ​
ts
dispose(): void;

Detach from the scene and release the geometry, the material and every attribute (its WebGL buffer and the float texture the fallback reads it through). Idempotent.

Returns ​

void

Nothing.

setBoundingSphere() ​
ts
setBoundingSphere(center, radius): void;

Declare where the gaussians are, in local space.

Parameters ​
ParameterTypeDescription
centerreadonly [number, number, number]Local-space centre.
radiusnumberLocal-space radius.
Returns ​

void

Nothing.

setFragmentAlpha() ​
ts
setFragmentAlpha(builder): void;

Scale each fragment's opacity by a node built from the view-space centre (fork edit 15).

Parameters ​
ParameterTypeDescription
builder((view) => Node) | nullReturns a float node, or null to draw as before.
Returns ​

void

Nothing.

setGaussianSource() ​
ts
setGaussianSource(builder): void;

The gaussian source: where each gaussian's centre, covariance and colour come from.

Parameters ​
ParameterTypeDescription
builderSplatGaussianSourceBuilder | nullThe source, or null to draw nothing (the buffers are zero).
Returns ​

void

Nothing.

setSortOrder() ​
ts
setSortOrder(order, camera): void;

The draw order, from the owner's CPU sort (far first).

Parameters ​
ParameterTypeDescription
orderUint32Arraycapacity slot indices (or storageCapacity; the padding goes last by itself).
cameraCameraThe camera the order was made for.
Returns ​

void

Nothing.

sortViewMoved() ​
ts
sortViewMoved(camera): boolean;

Whether the view turned past the sort's threshold since the last order.

Parameters ​
ParameterTypeDescription
cameraCameraThe camera.
Returns ​

boolean

True when a new order is due for the camera alone.

Interfaces ​

CreateAnimatedSplatOptions ​

Options accepted by createAnimatedSplat.

Properties ​

autoSort? ​
ts
readonly optional autoSort?: boolean;

Sort in onBeforeRender. Defaults to true, which is what a producer wants: paired with markGaussiansChanged it gives exactly one sort per frame.

boundingSphere? ​
ts
readonly optional boundingSphere?: object;

Where the gaussians will be, in local space. Defaults to a unit sphere at the origin, which is almost certainly wrong; set it as soon as the producer knows.

center ​
ts
readonly center: Vec3Tuple;
radius ​
ts
readonly radius: number;
capacity ​
ts
readonly capacity: number;

Gaussians to allocate. Fixed for the object's lifetime.

colorSpace? ​
ts
readonly optional colorSpace?: "linear" | "srgb";

What the producer's packed colour bytes mean. 'srgb' (the default) is what nearly every splat holds, a character trained against photographs among them: drawn only by gameable/core's attachSrgbPass (which the engine and gameable/three attach), blending on its sRGB values as it was trained; without a pass it draws nothing and warns once. 'linear' is for a splat trained in linear light: three's convention, drawn in the app's own pass.

kernel? ​
ts
readonly optional kernel?: "three" | "studio";

The gaussian kernel, the fork's edit 18: 'three' is three's (cut at 2 sigma, opacity reduced as the 2D blur grows) and 'studio' the Gameable studio's, which exported characters were made on (cut at 2.83 sigma with the tail subtracted, the trained opacity kept, a 0.075 px² blur): less washed-out thin details (lashes, hair) and no grain from the hard 2-sigma edge. The same switch as CreateAnimatedSplatOptions.pointShape: 'studio' is pointShape: 'studio', 'three' is 'engine'; a pointShape wins when both are given.

pointShape? ​
ts
readonly optional pointShape?: "studio" | "engine" | "full-opacity" | "trained" | "size-aware";

How each point is drawn (the fork's edits 18, 21, 26 and 27). 'engine' (the default) keeps three's 2-sigma point with its small-point fade (the dilation's opacity compensation); 'studio' draws each point as the Gameable studio draws it (the studio kernel above); 'full-opacity' is the studio's first rule alone (a small point keeps its whole opacity) on the engine's point; 'size-aware' gives a point the engine's soft shape while it is small on screen and the studio's once it is large, blended across a band of sizes (setSizeAwareBand): the look Isaac chose for every character on the looks sheet of 30 Sep 2026, which the character bridge asks for; 'trained' draws it as the training renderer did (the whole opacity capped at 0.999, a square to the major axis reaching 3 sigma of it, fragments under 1/255 not drawn): the align lab's measuring switch only, rejected for characters by Isaac on 30 Sep 2026; no package, manifest or bridge may ask for it.

renderOrder? ​
ts
readonly optional renderOrder?: number;

Draw order. Defaults to SPLAT_RENDER_ORDER.

shDegree? ​
ts
readonly optional shDegree?: number;

Spherical-harmonics bands, 0 (the default) to 3: the splat then has shBuffers, one per band, storageCapacity gaussians of three's packed words each (3, 4 and 6 words a gaussian), for the producer to write with the gaussians. A streaming place uses it; a character does not. WebGPU only (the buffers are GPUBuffers).


CreateSplatObjectOptions ​

Options accepted by createSplatObject.

Properties ​

autoSort? ​
ts
readonly optional autoSort?: boolean;

Re-sort in onBeforeRender when the camera turns far enough. Defaults to true. Turn it off only if you drive updateSort yourself.

colorSpace? ​
ts
readonly optional colorSpace?: "linear" | "srgb";

What the file's colour bytes mean. 'srgb' (the default) is what nearly every splat holds: trained against photographs read as they are stored, blending sRGB values. It draws through the fork (AnimatedGaussianSplat) in the sRGB pass (gameable/core's attachSrgbPass, which the engine attaches; without one it draws nothing and warns once). 'linear' is for a splat trained in linear light: three's own GaussianSplat, in the app's pass. The choice marks the asset's geometry (userData.colorSpace), so every object made from it agrees; a SOG asset's geometry says 'srgb' when decoded. Inside the engine, where the splats add up is createEngine's renderer.splatBlend (the layer, the pass, or linear light).

environmentLighting? ​
ts
readonly optional environmentLighting?: SplatEnvironmentLighting;

Opt into diffuse lighting; omitted keeps the native, unlit splat path.

receiveShadows? ​
ts
readonly optional receiveShadows?: boolean;

Make it the maintained fork, which can receive shadows (setShadowReceiver); it draws exactly as three's own until one is switched on. Defaults to false here; the splat service's add passes true.

renderOrder? ​
ts
readonly optional renderOrder?: number;

Draw order. Defaults to SPLAT_RENDER_ORDER.


CreateWebglSkinnedSplatOptions ​

Options accepted by createWebglSkinnedSplat.

Properties ​

boundingSphere? ​
ts
readonly optional boundingSphere?: object;

Where the gaussians will be, in local space (the owner's promise; culling is off).

center ​
ts
readonly center: readonly [number, number, number];
radius ​
ts
readonly radius: number;
capacity ​
ts
readonly capacity: number;

Gaussians to allocate. Fixed for the object's lifetime.

colorSpace? ​
ts
readonly optional colorSpace?: "linear" | "srgb";

What the source's colour bytes mean; 'srgb' decodes each gaussian before blending (fork edit 14).

pointShape? ​
ts
readonly optional pointShape?: "studio" | "engine" | "full-opacity" | "trained" | "size-aware";

How each point is drawn (fork edits 18, 21, 26 and 27), the same names as createAnimatedSplat takes: the look a character gets on the WebGPU path is the look it gets here, so the head reads the same on both.

renderOrder? ​
ts
readonly optional renderOrder?: number;

Draw order. Defaults to SPLAT_RENDER_ORDER.


EnvironmentProbeOptions ​

Shared mesh environment and Gaussian probe settings. SH must already be in world space.

Properties ​

enabled? ​
ts
optional enabled?: boolean;

Set false to temporarily attach no mesh environment. Default true.

intensity? ​
ts
optional intensity?: number;

Shared brightness multiplier. Default 1.

radianceSH ​
ts
radianceSH: readonly readonly [number, number, number][];

Nine RGB radiance coefficients, already rotated to match the scene.

yaw? ​
ts
optional yaw?: number;

Panorama yaw in radians; does not rotate the supplied world-space SH.


GaussianCloud ​

Gaussians of a place, for panoramaFromGaussians.

Properties ​

colors ​
ts
readonly colors: ArrayLike<number>;

RGBA per gaussian (alpha = opacity), multiplied by colorScale to reach 0..1.

colorScale? ​
ts
readonly optional colorScale?: number;

Multiplier on colors. Defaults to 1/255.

colorSpace? ​
ts
readonly optional colorSpace?: "linear" | "srgb";

'srgb' decodes the colours before any sum. Defaults to 'srgb' (a place trained on photographs).

matrixWorld? ​
ts
readonly optional matrixWorld?: ArrayLike<number>;

Column-major 4x4 from the cloud's space to the world (three's Matrix4.elements). Defaults to identity.

positions ​
ts
readonly positions: ArrayLike<number>;

Centres, three per gaussian, in the cloud's own space.


GaussianPanoramaOptions ​

Options for panoramaFromGaussians.

Properties ​

maxSamples? ​
ts
readonly optional maxSamples?: number;

Upper bound on gaussians visited; the rest are skipped evenly. Defaults to 600 000.

minDistance? ​
ts
readonly optional minDistance?: number;

Gaussians nearer than this to the probe are skipped (the character's own space). Defaults to 0.35 m.

minOpacity? ​
ts
readonly optional minOpacity?: number;

Gaussians fainter than this opacity are skipped. Defaults to 0.3.

width? ​
ts
readonly optional width?: number;

Pixels across; the height is half. Defaults to 64.


GltfLoaderLike ​

The subset of GLTFLoader this package needs, so the loader itself is not imported.

Methods ​

register() ​
ts
register(callback): unknown;

three's plugin hook.

Parameters ​
ParameterTypeDescription
callback(parser) => unknownBuilds the plugin from the parser.
Returns ​

unknown

The loader, for chaining.


JoinedGaussians ​

A layer's gaussians in the joined object's own frame, in the layout of the object's buffers.

Extended by ​

Properties ​

center ​
ts
readonly center: Float32Array;

Four floats each: the centre, then 1.

color ​
ts
readonly color: Uint32Array;

One word each: red, green, blue, opacity, a byte apiece, red lowest.

count ​
ts
readonly count: number;

How many.

covA ​
ts
readonly covA: Float32Array;

Four floats each: the covariance's c00, c01, c02, c11.

covB ​
ts
readonly covB: Float32Array;

Four floats each: c12, c22, 0, 0.

max ​
ts
readonly max: [number, number, number];

The high corner of the centres.

min ​
ts
readonly min: [number, number, number];

The low corner of the centres.


JoinedLayer ​

One layer in a joined splat.

Properties ​

count ​
ts
readonly count: number;

How many gaussians it has.

done ​
ts
readonly done: Promise<void>;

Resolves when all of it is drawn; rejects when it is removed first.

uploaded ​
ts
readonly uploaded: number;

How many are in the object so far.


JoinedSplat ​

Several layers of points as one splat.

Properties ​

capacity ​
ts
readonly capacity: number;

Gaussians the layers may hold at once (less than asked for when the card binds less).

incremental ​
ts
readonly incremental: boolean;

True on WebGPU: layers are written into the one object; false on the WebGL fallback.

object ​
ts
readonly object: Object3D<Object3DEventMap> | null;

The scene object now, or null before the WebGL fallback has its first layer.

parts ​
ts
readonly parts: SplatPartsIn | null;

The moving parts, bound to the object, or null (none asked for, or the WebGL fallback).

uploadPerFrame ​
ts
uploadPerFrame: number;

Gaussians written to the card in a frame at most, on WebGPU. Change it at any time.

used ​
ts
readonly used: number;

Gaussians the layers in it hold now.

Methods ​

add() ​
ts
add(gaussians): JoinedLayer | null;

Add a layer. Its gaussians are already in the object's frame.

Parameters ​
ParameterTypeDescription
gaussiansJoinedGaussiansThe layer.
Returns ​

JoinedLayer | null

The layer in the object, or null when there is not room for it.

dispose() ​
ts
dispose(): void;

Take the object out of the scene and free what it holds.

Returns ​

void

Nothing.

remove() ​
ts
remove(layer): void;

Take a layer out: it is drawn no more and its room is free.

Parameters ​
ParameterTypeDescription
layerJoinedLayerA layer from add.
Returns ​

void

Nothing.

update() ​
ts
update(camera): void;

One frame's work: write the next piece of a layer that is arriving, sort again when the view has moved, move the parts. Call it once a frame, before the render.

Parameters ​
ParameterTypeDescription
cameraCameraThe camera the frame is drawn with.
Returns ​

void

Nothing.


JoinedSplatOptions ​

Options for createJoinedSplat.

Properties ​

bounds ​
ts
readonly bounds: object;

A sphere, in the object's own frame, that holds every layer there will ever be: the sort's depth range is built from it, so it is told before anything arrives.

center ​
ts
readonly center: readonly [number, number, number];
radius ​
ts
readonly radius: number;
capacity ​
ts
readonly capacity: number;

Gaussians the layers may hold at once, all together.

colorSpace? ​
ts
readonly optional colorSpace?: "linear" | "srgb";

What the colour bytes mean. Defaults to 'srgb'.

onObject? ​
ts
readonly optional onObject?: (object) => void;

Told each time the scene object is made anew (the WebGL fallback does at every change).

Parameters ​
ParameterType
objectObject3D
Returns ​

void

parts? ​
ts
readonly optional parts?: readonly number[];

Room for moving parts (loose things that come as points): gaussians each. WebGPU only.

renderOrder? ​
ts
readonly optional renderOrder?: number;

Draw order. Defaults to one before SPLAT_RENDER_ORDER: a place draws first.

sortNearScale? ​
ts
readonly optional sortNearScale?: number;

Depth, in the object's units, below which the sort's bins stay nearly even (the fork's setSortDepthCurve): one object spans a whole world, and even bins across hundreds of metres are too coarse for two surfaces a hand apart near the eye. Defaults to 1.


KeyLightEstimate ​

A key light's direction and balance.

Properties ​

azimuth ​
ts
readonly azimuth: number;

Degrees around y, from +z toward +x.

confidence ​
ts
readonly confidence: number;

0 when there is no single key to find (flat light), 1 for a clear one.

direction ​
ts
readonly direction: readonly [number, number, number];

Unit vector from the scene toward the light, y up.

elevation ​
ts
readonly elevation: number;

Degrees above the horizon.

keyToFill ​
ts
readonly keyToFill: number;

Light on a surface facing the key over light on a surface facing away from it.

shadowStrength ​
ts
readonly shadowStrength: number;

How dark the key's shadow is, 0 to 1: the key's share of the light on a surface facing it, 1 - 1 / keyToFill, held at 0.9 or below.


LightProbeGrid ​

Samples a LightProbeGridData anywhere inside it.

Methods ​

sample() ​
ts
sample(
   x, 
   y, 
   z, 
   out
): Float32Array;

The light at a point, blended from the nearest probes.

Parameters ​
ParameterTypeDescription
xnumberPlace-frame x.
ynumberPlace-frame y.
znumberPlace-frame z.
outFloat32Array27 numbers, written in place.
Returns ​

Float32Array

out.


LightProbeGridData ​

The baked grid, as its JSON file holds it.

Properties ​

bounds ​
ts
readonly bounds: object;

The grid's box, in the place's frame.

max ​
ts
readonly max: readonly number[];
min ​
ts
readonly min: readonly number[];
dims ​
ts
readonly dims: object;

Probes across (x) and deep (z) per layer.

nx ​
ts
readonly nx: number;
nz ​
ts
readonly nz: number;
layerYs ​
ts
readonly layerYs: readonly number[];

Height of each layer, in the place's frame.

probes ​
ts
readonly probes: readonly object[];

Layer by layer, row by row (z), then x: { p: position, sh: 27 numbers }.

spacing ​
ts
readonly spacing: number;

Metres between neighbouring probes of a layer.


LoadedSplatLayer ​

A layer as it came from its file: the gaussians, and how large the file was.

Extends ​

Properties ​

bytes ​
ts
readonly bytes: number;

The file's size, bytes.

center ​
ts
readonly center: Float32Array;

Four floats each: the centre, then 1.

Inherited from ​

JoinedGaussians.center

color ​
ts
readonly color: Uint32Array;

One word each: red, green, blue, opacity, a byte apiece, red lowest.

Inherited from ​

JoinedGaussians.color

count ​
ts
readonly count: number;

How many.

Inherited from ​

JoinedGaussians.count

covA ​
ts
readonly covA: Float32Array;

Four floats each: the covariance's c00, c01, c02, c11.

Inherited from ​

JoinedGaussians.covA

covB ​
ts
readonly covB: Float32Array;

Four floats each: c12, c22, 0, 0.

Inherited from ​

JoinedGaussians.covB

max ​
ts
readonly max: [number, number, number];

The high corner of the centres.

Inherited from ​

JoinedGaussians.max

min ​
ts
readonly min: [number, number, number];

The low corner of the centres.

Inherited from ​

JoinedGaussians.min


LoadSplatOptions ​

Options accepted by loadSplat.

Properties ​

fetch? ​
ts
readonly optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Replaces globalThis.fetch, for tests and for an asset-manager transport.

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputURL | RequestInfo
init?RequestInit
Returns ​

Promise<Response>

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputstring | URL | Request
init?RequestInit
Returns ​

Promise<Response>

format? ​
ts
readonly optional format?: SplatFormatOption;

Force a decoder instead of sniffing. Defaults to 'auto'.

maxShDegree? ​
ts
readonly optional maxShDegree?: number;

Highest spherical-harmonics band a SOG keeps, 0 to 3 (default 3, all the file has).

signal? ​
ts
readonly optional signal?: AbortSignal;

Aborts the fetch. The decode itself is synchronous and is not interruptible.


LodMetaJson ​

lod-meta.json.

Properties ​

count? ​
ts
readonly optional count?: number;

Gaussians across every level.

counts? ​
ts
readonly optional counts?: readonly number[];

Gaussians per level.

filenames ​
ts
readonly filenames: readonly string[];

Each file's meta.json, relative to the bundle.

lodLevels ​
ts
readonly lodLevels: number;

Levels of detail.

tree ​
ts
readonly tree: LodNodeJson;

The octree.

version? ​
ts
readonly optional version?: number;

Format version (1).


Panorama ​

An equirectangular picture in three's orientation: the top row looks up, u = 0.5 looks along +x.

Properties ​

channels? ​
ts
readonly optional channels?: 4 | 1 | 3;

Numbers per pixel: 1 (luminance), 3 (RGB) or 4 (RGBA). Defaults to 4.

colorSpace? ​
ts
readonly optional colorSpace?: "linear" | "srgb";

'srgb' decodes each number before any sum (a photograph); 'linear' uses it as is. Defaults to 'linear'.

data ​
ts
readonly data: ArrayLike<number>;

Row-major from the top row, channels numbers per pixel.

height ​
ts
readonly height: number;

Pixels down (180°).

scale? ​
ts
readonly optional scale?: number;

Multiplier that brings a stored number to 0..1 (1/255 for bytes). Defaults to 1.

width ​
ts
readonly width: number;

Pixels across (360°).

yaw? ​
ts
readonly optional yaw?: number;

Degrees added to every azimuth read from the picture, for a picture whose middle column does not look along +x (three's orientation). A World Labs place's own panorama looks along -z in its middle column: pass 90, plus the place's own turn. Defaults to 0.


PanoramaKeyLightOptions ​

Options for estimateKeyLightFromPanorama.

Properties ​

clipBoost? ​
ts
readonly optional clipBoost?: number;

How much brighter than white a clipped pixel is taken to be (an 8-bit picture stores a lamp or the sun as white): values above 0.8 are raised by up to 1 + clipBoost times, as the studio's place-light reader does. Defaults to 24 for an sRGB picture, 0 for a linear one.

holdAbove? ​
ts
readonly optional holdAbove?: number;

The key found is then lifted to at least this elevation, keeping its azimuth (a lamp at eye height still throws a floor shadow a camera can see). Defaults to minElevation.

keyCone? ​
ts
readonly optional keyCone?: number;

Half-width of the key's cone, in degrees, for the confidence. Defaults to 25.

minElevation? ​
ts
readonly optional minElevation?: number;

The key is searched no lower than this, in degrees above the horizon. Defaults to 0.


ParseSplatOptions ​

Options accepted by parseSplat, beyond the format.

Properties ​

decodeImage? ​
ts
readonly optional decodeImage?: SogImageDecoder;

Turns a SOG's image files into exact RGBA texels. Defaults to a pool of workers decoding through WebGL2; tests and hosts with their own image path pass one.

fetch? ​
ts
readonly optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Fetches a SOG folder's images when the buffer is its meta.json. Defaults to globalThis.fetch.

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputURL | RequestInfo
init?RequestInit
Returns ​

Promise<Response>

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputstring | URL | Request
init?RequestInit
Returns ​

Promise<Response>

maxShDegree? ​
ts
readonly optional maxShDegree?: number;

Highest spherical-harmonics band a SOG keeps, 0 to 3 (default 3).

signal? ​
ts
readonly optional signal?: AbortSignal;

Aborts those fetches.


PlaceIndex ​

A streaming place's index.

Properties ​

bounds ​
ts
readonly bounds: Float32Array;

Per leaf: min x, y, z, max x, y, z (the place's own space).

box ​
ts
readonly box: object;

The leaves' union box.

max ​
ts
readonly max: readonly number[];
min ​
ts
readonly min: readonly number[];
files ​
ts
readonly files: readonly object[];

Each file: its meta.json URL (resolved), its level, and the gaussians the leaves take from it.

leafCount ​
ts
readonly leafCount: number;

Leaves in the octree.

levelCounts ​
ts
readonly levelCounts: readonly number[];

Gaussians per level, summed over the leaves.

levels ​
ts
readonly levels: number;

Levels of detail; 0 is the finest.

sliceCount ​
ts
readonly sliceCount: Int32Array;

Per leaf and level: gaussians (0 when none).

sliceFile ​
ts
readonly sliceFile: Int32Array;

Per leaf and level (leaf * levels + level): file index, or -1 when the leaf has none there.

sliceOffset ​
ts
readonly sliceOffset: Int32Array;

Per leaf and level: first gaussian in the file.


ShadowCasterSpot ​

Where a character stands, as clusterShadowCasters needs it.

Properties ​

radius ​
ts
readonly radius: number;

Metres around the origin its shadow covers.

x ​
ts
readonly x: number;

World x of its origin.

z ​
ts
readonly z: number;

World z of its origin.


ShadowCharacter ​

A character, as the shadows need it.

Properties ​

captured? ​
ts
readonly optional captured?: KeyLightEstimate | null;

The light its colours were captured under, in the character's own space (see estimateKeyLightFromSurfels).

footBones? ​
ts
readonly optional footBones?: readonly string[];

The foot joints, for the contact shadow. Defaults to l_foot/r_foot, then foot_l/foot_r.

headBone? ​
ts
readonly optional headBone?: string;

The head joint: it and its children are left out of the character's own shadow. Defaults to c_head, then head.

holder ​
ts
readonly holder: Object3D;

Its origin stands on the floor between the feet.

radius? ​
ts
readonly optional radius?: number;

Metres from the holder's origin to cover around the character. Defaults to 1.

rig ​
ts
readonly rig: Object3D;

Its rig: every skinned mesh under it casts.

splat? ​
ts
readonly optional splat?: AnimatedGaussianSplat | null;

Its gaussians, which receive; null for a mesh-only character.


ShadowDeviceHints ​

What defaultShadowQuality looks at; each field defaults to the browser's own answer.

Properties ​

coarsePointer? ​
ts
readonly optional coarsePointer?: boolean;

A touch screen is the main pointer.

deviceMemory? ​
ts
readonly optional deviceMemory?: number;

navigator.deviceMemory in GB (Chrome's rounded answer; Safari has none).

shortSide? ​
ts
readonly optional shortSide?: number;

The screen's shorter side in CSS pixels.


ShadowInfo ​

What the shadows are doing, for a debug readout.

Properties ​

azimuth ​
ts
readonly azimuth: number;

Degrees around y from +z toward +x, where the light comes from.

characters ​
ts
readonly characters: number;

Characters casting.

confidence ​
ts
readonly confidence: number;

How sure the chosen source was, 0 to 1.

elevation ​
ts
readonly elevation: number;

Degrees above the horizon.

ground ​
ts
readonly ground: boolean;

Whether the see-through ground is drawing (no place).

keyToFill ​
ts
readonly keyToFill: number;

Light facing the key over light facing away, as read.

places ​
ts
readonly places: number;

Places receiving.

quality ​
ts
readonly quality: ShadowQuality;

The level in use.

rendered ​
ts
readonly rendered: boolean;

Whether the last update drew the depth maps again (false: nothing in them had moved).

renders ​
ts
readonly renders: number;

How many times the depth maps have been drawn since the start.

route ​
ts
readonly route: KeyLightRoute;

Which source decided the light.

sources ​
ts
readonly sources: readonly object[];

Every source that answered, in the order they are preferred, with its answer.

strength ​
ts
readonly strength: number;

How dark the place's shadow is, 0 to 1.

tiles ​
ts
readonly tiles: number;

Light cameras (atlas tiles) in use: 1 when every character stands together, up to 4.

updateMs ​
ts
readonly updateMs: number;

Milliseconds of CPU the last update took, depth passes included.


ShadowPlace ​

A place, as the shadows need it; every field is optional.

Properties ​

collider? ​
ts
readonly optional collider?: Object3D<Object3DEventMap> | null;

Its collider mesh: casts onto characters only, never onto the place itself.

colliderReach? ​
ts
readonly optional colliderReach?: number;

How far toward the light, in metres from the characters, the collider still casts. Only its faces that face the light cast, so a room's own shell never shades the room. Defaults to 8.

compareRoutes? ​
ts
readonly optional compareRoutes?: boolean;

Read every source this place has, not only the first, and list them in info.sources (for a readout; the place's own gaussians cost a tenth of a second more at load). Defaults to false.

lightProbes? ​
ts
readonly optional lightProbes?: LightProbeGridData | null;

A baked light-probe grid, positions and light in world space.

panorama? ​
ts
readonly optional panorama?: Panorama | null;

Its own 360° picture, directions in world space (pass yaw to align it).


ShadowQualityPreset ​

What a level draws.

Properties ​

characterMap ​
ts
readonly characterMap: boolean;

A second map for the characters themselves: their own shadow (an arm on the body) and the place's collider on them. A second depth pass, so only the top level has it.

contact ​
ts
readonly contact: boolean;

A soft dark patch under each foot.

mapSize ​
ts
readonly mapSize: number;

The key light's depth map, texels per side; 0 draws no cast shadow.

taps ​
ts
readonly taps: readonly number[];

The edge filter: flat [dx, dy, weight, ...] in texels.


SlotAllocator ​

Hands out and reclaims slot ranges inside a fixed capacity.

Properties ​

available ​
ts
readonly available: number;

Slots not handed out. Equals capacity - used.

Named available rather than free because free is the method next to it, and a property cannot be both.

capacity ​
ts
readonly capacity: number;

Total slots.

freeRuns ​
ts
readonly freeRuns: readonly SlotRange[];

The free runs, low offset first. Exposed for tests and for the debug overlay.

largestFree ​
ts
readonly largestFree: number;

The largest range allocate could satisfy right now.

used ​
ts
readonly used: number;

Slots currently handed out.

Methods ​

allocate() ​
ts
allocate(count): SlotRange;

Take the first free run large enough.

Parameters ​
ParameterTypeDescription
countnumberHow many slots. Must be a positive integer.
Returns ​

SlotRange

The range.

Throws ​

When nothing is large enough, or RangeError when count is not a positive integer.

free() ​
ts
free(range): void;

Give a range back, coalescing with either neighbour.

Parameters ​
ParameterTypeDescription
rangeSlotRangeA range from allocate.
Returns ​

void

Nothing.

Throws ​

When the range was not allocated, or was already freed.

reset() ​
ts
reset(): void;

Drop every allocation and return to one free run.

Returns ​

void

Nothing.


SlotRange ​

A contiguous run of gaussian slots.

Properties ​

count ​
ts
readonly count: number;

How many slots. Always at least 1.

offset ​
ts
readonly offset: number;

Index of the first slot.


SplatAsset ​

A decoded splat file.

Properties ​

boundingSphere ​
ts
readonly boundingSphere: Sphere;

Bounds of the centres, in the file's own coordinate system.

count ​
ts
readonly count: number;

Gaussians in the file.

format ​
ts
readonly format: SplatFormat;

Which decoder ran.

geometry ​
ts
readonly geometry: BufferGeometry;

Geometry with position (f32x3), covariance (f32x6), color (u8x4) and optional SH.

shDegree ​
ts
readonly shDegree: number;

Spherical-harmonics degree, 0 to 3. Degree 0 is flat colour.

url ​
ts
readonly url: string;

Where it came from.


SplatGPUBuffers ​

The four storage buffers behind a GaussianSplat, as real GPUBuffers.

Properties ​

center ​
ts
readonly center: GPUBuffer;

array<vec4<f32>>: xyz = centre in local space, w unused.

color ​
ts
readonly color: GPUBuffer;

array<u32>: pack4x8unorm(vec4(r, g, b, a)).

covarianceA ​
ts
readonly covarianceA: GPUBuffer;

array<vec4<f32>>: (c00, c01, c02, c11).

covarianceB ​
ts
readonly covarianceB: GPUBuffer;

array<vec4<f32>>: (c12, c22, 0, 0).


SplatLayerLoader ​

Fetches layers and puts them in a joined object's frame, off the page's own thread.

Methods ​

dispose() ​
ts
dispose(): void;

Stop the workers; loads still out never answer.

Returns ​

void

Nothing.

load() ​
ts
load(url, matrix): Promise<LoadedSplatLayer>;

Fetch a layer's file and unpack it into the joined object's frame.

Parameters ​
ParameterTypeDescription
urlstringThe file (.spz).
matrixArrayLike<number> | nullSixteen numbers, column by column, from the file's frame to the object's.
Returns ​

Promise<LoadedSplatLayer>

The gaussians and the file's size.


SplatModuleOptions ​

Options accepted by splat.

Properties ​

format? ​
ts
readonly optional format?: SplatFormat;

Force a decoder for every splat asset instead of sniffing each one. Leave unset unless your assets are served from URLs with no useful extension.


SplatParts ​

Parts that move inside one splat.

Extends ​

Properties ​

asset ​
ts
readonly asset: SplatAsset;

The base asset grown by room for the parts: make the object from this one.

ranges ​
ts
readonly ranges: readonly SlotRange[];

Where each part's gaussians are in the object, in the order the counts were given.

Inherited from ​

SplatPartsIn.ranges

Methods ​

bind() ​
ts
bind(object): void;

Name the object the parts are written into. Call once, with the object made from SplatParts.asset (or, for createSplatPartsIn, the object that has the room).

Parameters ​
ParameterTypeDescription
objectobjectThe splat object.
Returns ​

void

Nothing.

Inherited from ​

SplatPartsIn.bind

dispose() ​
ts
dispose(): void;

Let go of the rest buffers. The object is the caller's to dispose.

Returns ​

void

Nothing.

Inherited from ​

SplatPartsIn.dispose

fill() ​
ts
fill(part, asset): number;

Give a part its gaussians, at rest in the part's own frame. More than the part has room for are left out; the part stays hidden until SplatParts.show.

Parameters ​
ParameterTypeDescription
partnumberWhich part.
assetSplatAssetThe part's gaussians (spherical-harmonics bands are not carried).
Returns ​

number

How many gaussians were taken.

Inherited from ​

SplatPartsIn.fill

flush() ​
ts
flush(renderer): boolean;

Write what changed since the last call. Call once a frame, before the render.

Parameters ​
ParameterTypeDescription
rendererWebGPURendererThe renderer the object is drawn with.
Returns ​

boolean

True when a pass ran.

Inherited from ​

SplatPartsIn.flush

move() ​
ts
move(part, matrix): void;

Put a part somewhere.

Parameters ​
ParameterTypeDescription
partnumberWhich part.
matrixMatrix4From the part's own frame to the object's local frame. Copied.
Returns ​

void

Nothing.

Inherited from ​

SplatPartsIn.move

show() ​
ts
show(part, shown): void;

Show or hide a part.

Parameters ​
ParameterTypeDescription
partnumberWhich part.
shownbooleanTrue to draw it.
Returns ​

void

Nothing.

Inherited from ​

SplatPartsIn.show


SplatPartsIn ​

Parts that move inside a splat that already has room for them (createSplatPartsIn).

Extended by ​

Properties ​

ranges ​
ts
readonly ranges: readonly SlotRange[];

Where each part's gaussians are in the object, in the order the counts were given.

Methods ​

bind() ​
ts
bind(object): void;

Name the object the parts are written into. Call once, with the object made from SplatParts.asset (or, for createSplatPartsIn, the object that has the room).

Parameters ​
ParameterTypeDescription
objectobjectThe splat object.
Returns ​

void

Nothing.

dispose() ​
ts
dispose(): void;

Let go of the rest buffers. The object is the caller's to dispose.

Returns ​

void

Nothing.

fill() ​
ts
fill(part, asset): number;

Give a part its gaussians, at rest in the part's own frame. More than the part has room for are left out; the part stays hidden until SplatParts.show.

Parameters ​
ParameterTypeDescription
partnumberWhich part.
assetSplatAssetThe part's gaussians (spherical-harmonics bands are not carried).
Returns ​

number

How many gaussians were taken.

flush() ​
ts
flush(renderer): boolean;

Write what changed since the last call. Call once a frame, before the render.

Parameters ​
ParameterTypeDescription
rendererWebGPURendererThe renderer the object is drawn with.
Returns ​

boolean

True when a pass ran.

move() ​
ts
move(part, matrix): void;

Put a part somewhere.

Parameters ​
ParameterTypeDescription
partnumberWhich part.
matrixMatrix4From the part's own frame to the object's local frame. Copied.
Returns ​

void

Nothing.

show() ​
ts
show(part, shown): void;

Show or hide a part.

Parameters ​
ParameterTypeDescription
partnumberWhich part.
shownbooleanTrue to draw it.
Returns ​

void

Nothing.


SplatPlaceOptions ​

Options for loadSplatPlace.

Properties ​

behindPenalty? ​
ts
readonly optional behindPenalty?: number;

A leaf straight behind the camera counts this many times as far. Defaults to 5 (SuperSplat's).

budget? ​
ts
readonly optional budget?: number;

Gaussians shown at most. Defaults to DESKTOP_PLACE_BUDGET, or PHONE_PLACE_BUDGET on a phone or tablet (a touch device whose user agent says so).

coarsestFirst? ​
ts
readonly optional coarsestFirst?: boolean;

The first picture from the coarsest level only, then the full range (SuperSplat's way). Defaults to true.

colorSpace? ​
ts
readonly optional colorSpace?: "linear" | "srgb";

What the colour bytes mean. Defaults to 'srgb' (a SOG's colours are its photographs').

concurrentLoads? ​
ts
readonly optional concurrentLoads?: number;

Files fetched and decoded at once. Defaults to 4.

cooldownMs? ​
ts
readonly optional cooldownMs?: number;

A file no piece needs is dropped after this cooldown (ms) once the files held pass holdBytes. Defaults to 3000.

fetch? ​
ts
readonly optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Replaces globalThis.fetch.

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputURL | RequestInfo
init?RequestInit
Returns ​

Promise<Response>

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputstring | URL | Request
init?RequestInit
Returns ​

Promise<Response>

headroom? ​
ts
readonly optional headroom?: number;

Capacity above the budget, as a fraction of it, for pieces in transition. Defaults to 0.15.

holdBytes? ​
ts
readonly optional holdBytes?: number;

Decoded files the workers may keep (bytes of texels and tables), so a piece the camera comes back to need not be fetched again. Past it, files no piece needs go, the longest unneeded first. Defaults to 512 MB on a desktop, 128 MB on a phone.

lodUpdateAngle? ​
ts
readonly optional lodUpdateAngle?: number;

...or turned this far (degrees). Defaults to 90 (SuperSplat's).

lodUpdateDistance? ​
ts
readonly optional lodUpdateDistance?: number;

Re-choose the levels when the camera has moved this far (world units). Defaults to 1.

log? ​
ts
readonly optional log?: (message) => void;

Told what the place does (loads, drops, first picture), for a debug overlay or the console.

Parameters ​
ParameterType
messagestring
Returns ​

void

minContribution? ​
ts
readonly optional minContribution?: number;

With the projected draw, a point adding less than this many pixels' worth of full coverage (opacity x 2 pi x its footprint) is not drawn: PlayCanvas's minContribution, 1 in SuperSplat's viewer. Defaults to 0 (every point): at 1 the street drew 25 % faster standing still, but the room seen close lost its faint points (the rug's soft weave turned speckled; 10 % of the pixels moved by more than 16 grey levels).

projectedDraw? ​
ts
readonly optional projectedDraw?: boolean;

Project each gaussian once a frame in a compute pass and draw from that (fork edit 36), instead of working out each corner of its square in the vertex stage. Defaults to true.

shDegree? ​
ts
readonly optional shDegree?: number;

Highest spherical-harmonics band drawn, 0 to 3. Defaults to 3.

sortNearScale? ​
ts
readonly optional sortNearScale?: number;

Depth (world units) below which the sort's bins stay nearly even (fork edit 33). Defaults to 1.

sortRadius? ​
ts
readonly optional sortRadius?: number;

How far from the camera the sort orders finely (world units); beyond, one bin. Defaults to 200.

uploadPerFrame? ​
ts
readonly optional uploadPerFrame?: number;

Gaussians uploaded per frame at most (one piece always goes, however big). Defaults to 300,000.

uploadPerSecond? ​
ts
readonly optional uploadPerSecond?: number;

Gaussians uploaded per second at most, after the first picture (about 104 bytes each with three bands). The browser copies every upload into the graphics process; past what it can carry, a frame waits for it (measured on a desktop with the frame rate uncapped: 300,000 a frame stalled frames for up to 1.1 s). Defaults to 2,000,000.

workers? ​
ts
readonly optional workers?: number;

Decode workers. Defaults to half the processors, 2 to 6.


SplatPlaceStats ​

What a place is doing, updated every frame (read it, do not keep it).

Properties ​

budget ​
ts
budget: number;

The budget.

capacity ​
ts
capacity: number;

Gaussians the splat can hold.

fetchedBytes ​
ts
fetchedBytes: number;

Bytes fetched so far.

filesHeld ​
ts
filesHeld: number;

Files decoded and held in the workers now.

filesLoading ​
ts
filesLoading: number;

Files being fetched and decoded.

firstPictureMs ​
ts
firstPictureMs: number | null;

When (ms on the page's clock) the coarsest level was all on screen.

gpuBytes ​
ts
gpuBytes: number;

Graphics memory of the splat's buffers (bytes): gaussians, bands, colour pass, sort.

heldBytes ​
ts
heldBytes: number;

Their bytes (texels and tables).

leavesEmpty ​
ts
leavesEmpty: number;

Leaves showing nothing yet.

leavesPerLevel ​
ts
readonly leavesPerLevel: number[];

Leaves showing each level.

loads ​
ts
loads: number;

Files ever loaded, and ever dropped.

lodUpdates ​
ts
lodUpdates: number;

Level choices made so far.

perLevel ​
ts
readonly perLevel: number[];

Gaussians drawn per level (0 the finest).

queued ​
ts
queued: number;

Pieces decoded and waiting for their upload.

releasedCpuBytes ​
ts
releasedCpuBytes: number;

Page memory freed from three's copies of those buffers.

shown ​
ts
shown: number;

Gaussians drawn now.

slowestTickMs ​
ts
slowestTickMs: number;

The longest a frame's place work took (ms).

startedMs ​
ts
startedMs: number;

When the place was asked for.

unloads ​
ts
unloads: number;
uploadedLastFrame ​
ts
uploadedLastFrame: number;

Gaussians uploaded in the last frame.

wanted ​
ts
wanted: number;

Gaussians the chosen levels add up to.


SplatService ​

What engine.get('splat') returns.

Properties ​

added ​
ts
readonly added: readonly (AnimatedGaussianSplat | GaussianSplat)[];

Every object add has put in the scene, in order (an object removed from the scene stays listed; its parent is null). The character bridge reads it to find the places that receive shadows.

loaded ​
ts
readonly loaded: ReadonlyMap<string, SplatAsset>;

Every splat asset loaded through the registry, by asset id.

Assets are cached by the registry, so this is a view of it, not a second cache.

Methods ​

add() ​
ts
add(id, options?): AnimatedGaussianSplat | GaussianSplat;

Add a loaded asset to the scene as a GaussianSplat, with the right draw order.

It receives shadows unless receiveShadows: false is passed: the object is then the maintained fork (AnimatedGaussianSplat), which draws exactly as three's own until a shadow is switched on.

Parameters ​
ParameterTypeDescription
idstring | SplatAssetAsset id, as declared in assets.json; or an asset made in code (a place grown by createSplatParts), which is in no manifest.
options?CreateSplatObjectOptions-
Returns ​

AnimatedGaussianSplat | GaussianSplat

The object that was added.

addBuilt() ​
ts
addBuilt(
   id, 
   options?, 
   place?
): Promise<AnimatedGaussianSplat | GaussianSplat>;

SplatService.add, with the drawing built before the first sight: the object goes in hidden, the card builds its programs off the frame (renderer.compileAsync), and it shows once they are built, so a place never freezes the picture when it first appears.

Parameters ​
ParameterTypeDescription
idstring | SplatAssetAsset id, as declared in assets.json, or an asset made in code.
options?CreateSplatObjectOptionsAs for add.
place?(object) => voidCalled with the object before the build, to put it where it goes.
Returns ​

Promise<AnimatedGaussianSplat | GaussianSplat>

The object, showing.

adopt() ​
ts
adopt(object): void;

List a splat made elsewhere (a world's joined places, createJoinedSplat) among the objects add put in the scene, so it receives shadows as they do. The object is the caller's: in the scene already, and the caller's to take out.

Parameters ​
ParameterTypeDescription
objectobjectThe splat object.
Returns ​

void

Nothing.


SplatShadows ​

The running shadows of one scene.

Properties ​

info ​
ts
readonly info: ShadowInfo;

What the shadows are doing.

quality ​
ts
readonly quality: ShadowQuality;

The level in use.

Methods ​

addCharacter() ​
ts
addCharacter(key, character): void;

Add a character: its rig casts, its gaussians receive, its colours suggest the light.

Parameters ​
ParameterTypeDescription
keyobjectAny object that names it (the caller's own record).
characterShadowCharacterThe character.
Returns ​

void

Nothing.

addPlace() ​
ts
addPlace(splat, place?): void;

Add a place: its gaussians receive, its data suggests the light.

Parameters ​
ParameterTypeDescription
splatAnimatedGaussianSplatThe place's gaussians (the fork class).
place?ShadowPlaceIts collider, panorama or light probes.
Returns ​

void

Nothing.

dispose() ​
ts
dispose(): void;

Release every map, material and receiver.

Returns ​

void

removeCharacter() ​
ts
removeCharacter(key): void;

Remove a character.

Parameters ​
ParameterTypeDescription
keyobjectThe key it was added with.
Returns ​

void

Nothing.

removePlace() ​
ts
removePlace(splat): void;

Remove a place.

Parameters ​
ParameterTypeDescription
splatAnimatedGaussianSplatThe place's gaussians.
Returns ​

void

Nothing.

setKeyLight() ​
ts
setKeyLight(light): void;

Set the light yourself, or null to go back to reading it from the scene.

Parameters ​
ParameterTypeDescription
lightKeyLightEstimate | nullThe light, world space.
Returns ​

void

Nothing.

setQuality() ​
ts
setQuality(quality): void;

Change the level; 'auto' picks by device. Rebuilds the receivers' shaders once.

Parameters ​
ParameterTypeDescription
quality"auto" | ShadowQualityThe level.
Returns ​

void

Nothing.

update() ​
ts
update(dt): void;

Draw the depth maps. Call once a frame after the characters are posed, before the frame renders. When nothing in them moved since the last draw, the maps are kept as they are (info.rendered says which).

Parameters ​
ParameterTypeDescription
dtnumberSeconds since the last call.
Returns ​

void

Nothing.


SplatShadowsOptions ​

Options for createSplatShadows.

Properties ​

characterBias? ​
ts
readonly optional characterBias?: number;

Metres along the light a character's gaussian may sit behind its own rig mesh and still count as lit. Its gaussians sit on and a little inside the smooth rig mesh that casts (loose cloth, folds): at 0.02 a character lit from the front comes out blotched grey. An arm this far or more in front of the body still shades it. Defaults to 0.12.

ground? ​
ts
readonly optional ground?: boolean;

A see-through ground under the characters when no place receives. Defaults to true.

placeBias? ​
ts
readonly optional placeBias?: number;

The same for the place's gaussians and the see-through ground. Defaults to 0.03.

placeSpread? ​
ts
readonly optional placeSpread?: boolean;

Read a place's shadow at each corner of its points' squares instead of once a point (fork edit 38): softer on a place whose points are centimetres across, where one value a point makes a shadow of blobs, but fainter too. In test since 3 Oct 2026; defaults to false, the shadow as shipped.

quality? ​
ts
readonly optional quality?: "auto" | ShadowQuality;

A level, or 'auto' (the default) for defaultShadowQuality.

turnSeconds? ​
ts
readonly optional turnSeconds?: number;

Seconds a later, better light takes to turn in. Defaults to 1.


SplatSink ​

What a producer writes into.

Deliberately small and three-free: a lift shader needs slots, buffers and a way to say the gaussians moved, and nothing else.

Properties ​

buffers ​
ts
readonly buffers: SplatGPUBuffers;

The four GPU buffers, in the layout documented in backendBuffers.ts. WebGPU only: on the WebGL fallback reading this throws; write through SplatSink.nodes instead.

capacity ​
ts
readonly capacity: number;

Total gaussians this sink can hold. Fixed for its lifetime.

nodes ​
ts
readonly nodes: SplatStorageNodes;

The four buffers as writable TSL storage nodes, on either backend.

object3D ​
ts
readonly object3D: Object3D;

The scene object. Add it to a scene, move it, parent it — it is an ordinary Object3D.

storageCapacity ​
ts
readonly storageCapacity: number;

Elements actually allocated per buffer: capacity padded up to the WebGL fallback's PBO texture shape. The slots past capacity are never handed out and stay invisible. A compute on the fallback dispatches exactly this many invocations.

Methods ​

allocate() ​
ts
allocate(count): SlotRange;

Reserve a contiguous run of slots.

Parameters ​
ParameterTypeDescription
countnumberHow many gaussians.
Returns ​

SlotRange

The range, as { offset, count }.

free() ​
ts
free(range): void;

Give a range back. The slots are not cleared; call clearSlots first if the caller is not about to overwrite them.

Parameters ​
ParameterTypeDescription
rangeSlotRangeA range from allocate.
Returns ​

void

Nothing.

markGaussiansChanged() ​
ts
markGaussiansChanged(): void;

Tell the splat its gaussians moved, so the next frame re-sorts.

Call it once per frame after the compute pass. Without it the sort only runs when the camera turns more than about 1.81 degrees, and a moving avatar seen from a still camera renders in a stale depth order.

Returns ​

void

Nothing.

restPoints()? ​
ts
optional restPoints(): GPUBuffer;

The rest centre and group of every slot (a vec4 each), for a point hook; allocated on the first call. Optional: a sink that cannot keep them leaves it out and producers skip the rest points.

Returns ​

GPUBuffer

setBoundingSphere() ​
ts
setBoundingSphere(center, radius): void;

Declare where the gaussians are, in the object's local space.

The sort quantises depth into 4096 bins across this sphere, so a sphere that does not contain the splats costs precision, and frustum culling is off precisely because this value is a promise rather than a measurement.

Parameters ​
ParameterTypeDescription
centerVec3TupleLocal-space centre.
radiusnumberLocal-space radius.
Returns ​

void

Nothing.


SplatStorageNodes ​

The four gaussian buffers as writable TSL storage nodes, storageCapacity elements each.

Layout as in backendBuffers.ts. A compute node that assigns to element(instanceIndex) of these writes the splat on WebGPU and on the WebGL fallback alike. On the fallback the compute runs as transform feedback, which has two consequences a producer must respect: invocation i writes element i (no offsets, no scattered writes), and each dispatch must cover the whole storageCapacity, once per frame — a partial dispatch leaves elements from two frames back, because three double-buffers the attribute and swaps after every pass.

Properties ​

center ​
ts
readonly center: StorageBufferNode<"vec4">;

vec4: xyz = centre in local space, w written 1.

color ​
ts
readonly color: StorageBufferNode<"uint">;

uint: pack4x8unorm(vec4(r, g, b, a)).

covarianceA ​
ts
readonly covarianceA: StorageBufferNode<"vec4">;

vec4: (c00, c01, c02, c11).

covarianceB ​
ts
readonly covarianceB: StorageBufferNode<"vec4">;

vec4: (c12, c22, 0, 0).


SurfelKeyLightOptions ​

Options for estimateKeyLightFromSurfels.

Properties ​

elevationRange? ​
ts
readonly optional elevationRange?: readonly [number, number];

The elevation is kept inside this range, in degrees. Defaults to [25, 70].

minGroupLuminance? ​
ts
readonly optional minGroupLuminance?: number;

Groups darker than this mean luminance are ignored (black carries no shading). Defaults to 0.01.

minGroupSize? ​
ts
readonly optional minGroupSize?: number;

Groups with fewer samples are ignored. Defaults to 24.


SurfelSamples ​

The light a character's colours carry, one sample per gaussian.

Properties ​

count ​
ts
readonly count: number;

Samples.

groups? ​
ts
readonly optional groups?: ArrayLike<number>;

Which patch of the same material each sample belongs to (a body part and a colour), so a dark coat and a pale face are compared only with themselves. Defaults to one group.

luminance ​
ts
readonly luminance: ArrayLike<number>;

Linear luminance per sample.

normals ​
ts
readonly normals: ArrayLike<number>;

Outward unit normals, three per sample.

weights? ​
ts
readonly optional weights?: ArrayLike<number>;

Weight per sample (opacity). Defaults to 1.

Type Aliases ​

KeyLightRoute ​

ts
type KeyLightRoute = 
  | "game"
  | "light probe"
  | "panorama"
  | "place gaussians"
  | "character"
  | "default";

Which source decided the key light's direction.


ShadowQuality ​

ts
type ShadowQuality = "off" | "contact" | "simple" | "soft";

How much shadow to draw.


SplatFileFormat ​

ts
type SplatFileFormat = SplatFormat | "ssog";

What sniffSplatFormat can recognise: every SplatFormat, plus 'ssog', a streaming place (lod-meta.json and SOG tiles), which is not one geometry and opens with loadSplatPlace.


SplatFormat ​

ts
type SplatFormat = "spz" | "ply" | "splat" | "ksplat" | "sog";

Container formats loadSplat understands.


SplatFormatOption ​

ts
type SplatFormatOption = SplatFormat | "auto";

SplatFormat, or 'auto' to sniff.


Vec3Tuple ​

ts
type Vec3Tuple = [number, number, number];

A centre as a plain triple, so producers need no three import.

Variables ​

BYTES_PER_GAUSSIAN ​

ts
const BYTES_PER_GAUSSIAN: number;

Bytes one gaussian occupies across the four storage buffers.


DEFAULT_KEY_LIGHT ​

ts
const DEFAULT_KEY_LIGHT: KeyLightEstimate;

The light used when nothing can be read: above and to the front-right of a character facing +z.


DESKTOP_PLACE_BUDGET ​

ts
const DESKTOP_PLACE_BUDGET: 6000000 = 6_000_000;

The budget on a desktop, in gaussians shown.


PACKAGE ​

ts
const PACKAGE: "@gameable/splat";

Package identity marker.

Example ​

ts
import { PACKAGE } from 'gameable/splat';

console.log(PACKAGE); // 'gameable/splat'

PHONE_PLACE_BUDGET ​

ts
const PHONE_PLACE_BUDGET: 1500000 = 1_500_000;

The budget on a phone or tablet.


SHADOW_QUALITIES ​

ts
const SHADOW_QUALITIES: readonly ShadowQuality[];

Every level, lowest first.


SPLAT_RENDER_ORDER ​

ts
const SPLAT_RENDER_ORDER: 1000 = 1000;

Splats draw after opaque geometry.

The material is transparent with depthWrite: false, so three already puts it in the transparent pass; the render order pins splats after ordinary transparent meshes, because a splat cloud has no single depth to sort by and would otherwise be interleaved by its object centre.


SUPPORTED_THREE_VERSION ​

ts
const SUPPORTED_THREE_VERSION: "0.186.0" = '0.186.0';

The three version this file's private-surface knowledge was written against.

Functions ​

acquireSplatGPUBuffers() ​

ts
function acquireSplatGPUBuffers(renderer, splat): SplatGPUBuffers;

Materialise a splat's four storage attributes as real GPUBuffers and hand them back.

Idempotent in both directions: createStorageAttribute early-returns when the buffer already exists, and the same GPUBuffer objects come back on every call for the lifetime of the splat. The buffers are owned by three — do not destroy them; dispose the splat.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer.
splatobjectA GaussianSplat or AnimatedGaussianSplat.

Returns ​

SplatGPUBuffers

The four buffers, in the layout documented at the top of this file.

Throws ​

When the backend is WebGL, the renderer is not initialised, or three's internals moved.

Example ​

ts
const buffers = acquireSplatGPUBuffers(renderer, splat);
console.log(buffers.center.size / 16); // gaussian capacity

acquireStorageGPUBuffer() ​

ts
function acquireStorageGPUBuffer(renderer, attribute): GPUBuffer;

Materialise one StorageBufferAttribute as a real GPUBuffer and hand it back.

For a producer that writes a buffer from its own compute pass which a three material then reads through storage(attribute, …) — a character's mouth writes its mesh this way. The same private surface as acquireSplatGPUBuffers, for any storage attribute. The buffer is owned by three; give it back with releaseStorageAttribute.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer.
attributeobjectA StorageBufferAttribute.

Returns ​

GPUBuffer

Its GPUBuffer, with STORAGE | COPY_DST usage.

Throws ​

When the backend is WebGL, the renderer is not initialised, or three's internals moved.

Example ​

ts
const attribute = new StorageBufferAttribute(new Float32Array(1024 * 4), 4);
const buffer = acquireStorageGPUBuffer(renderer, attribute);
device.queue.writeBuffer(buffer, 0, new Float32Array(1024 * 4));

anglesFromDirection() ​

ts
function anglesFromDirection(direction): [number, number];

Azimuth and elevation of a direction.

Parameters ​

ParameterTypeDescription
directionArrayLike<number>Any non-zero vector, y up.

Returns ​

[number, number]

[azimuth, elevation] in degrees.


backendKind() ​

ts
function backendKind(renderer): "webgpu" | "webgl";

Which backend an initialised renderer ended up on.

Unlike isWebGPUBackend, this refuses to answer for a renderer that has not been initialised, because before init there is no backend to ask and "not WebGPU" would be a guess.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer.

Returns ​

"webgpu" | "webgl"

'webgpu', or 'webgl' for the WebGL2 fallback.

Throws ​

When the renderer has not been initialised.

Example ​

ts
await renderer.init();
if (backendKind(renderer) === 'webgl') console.info('WebGL2 fallback: CPU sort from readback');

clampElevation() ​

ts
function clampElevation(
   direction, 
   min, 
   max
): [number, number, number];

The same direction with its elevation held inside a range.

Parameters ​

ParameterTypeDescription
directionArrayLike<number>Unit direction.
minnumberLowest elevation, degrees.
maxnumberHighest elevation, degrees.

Returns ​

[number, number, number]

The adjusted unit direction.


clusterShadowCasters() ​

ts
function clusterShadowCasters(
   spots, 
   previous?, 
   out?
): number[];

Group characters for the shadow's light cameras: those standing together share one, those standing apart get one each, at most four groups. Two groups join when their circles overlap, or when joining leaves no texel coarser (one group has the whole map; two to four share it as a 2 x 2 atlas, half the texels per side each). Groups that were together last frame (previous) stay together a little longer, so a walk past a limit does not flicker. With more than four groups the two with the smallest circle around both join. Groups are numbered by their first member, so a lone character is always group 0.

Parameters ​

ParameterTypeDefault valueDescription
spotsreadonly ShadowCasterSpot[]undefinedWhere each character stands.
previousreadonly number[][]Each spot's group last frame, -1 for a new one; empty for none.
outnumber[][]An array to fill and return, to spare an allocation per frame.

Returns ​

number[]

Each spot's group, 0 to 3.

Example ​

ts
import { clusterShadowCasters } from 'gameable/splat';
// Two people side by side, a third across the room.
clusterShadowCasters([
  { x: 0, z: 0, radius: 1 },
  { x: 1, z: 0, radius: 1 },
  { x: 8, z: 0, radius: 1 },
]); // [0, 0, 1]

createAnimatedSplat() ​

ts
function createAnimatedSplat(renderer, options): Promise<AnimatedSplat>;

Build a dynamic splat on an initialised renderer.

Asynchronous by contract rather than by need: acquiring the buffers is synchronous today, but the call sits on the boundary where a backend could have to be asked for something, and every caller already awaits.

Works on WebGPU and on the WebGL2 fallback. On the fallback there are no GPUBuffers: write through sink.nodes with a TSL compute node dispatched over sink.storageCapacity.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer.
optionsCreateAnimatedSplatOptionsCapacity, bounds and draw order.

Returns ​

Promise<AnimatedSplat>

The sink, with its GPU buffers already acquired on WebGPU.

Throws ​

When the renderer is not initialised.

Example ​

ts
import { createAnimatedSplat } from 'gameable/splat';

const sink = await createAnimatedSplat(renderer, {
  capacity: 250_000,
  boundingSphere: { center: [0, 1, 0], radius: 1.4 },
});
scene.add(sink.object3D);

const head = sink.allocate(120_000);
// ... compute pass writes sink.buffers.* over [head.offset, head.offset + head.count)
sink.markGaussiansChanged();

// Either backend: a TSL compute node over the storage nodes, one invocation per slot.
import { Fn, instanceIndex, vec4 } from 'three/tsl';
const lift = Fn(() => {
  sink.nodes.center.element(instanceIndex).assign(vec4(0, 1, 0, 1));
})().compute(sink.storageCapacity);
renderer.compute(lift);
sink.markGaussiansChanged();

createEnvironmentProbe() ​

ts
function createEnvironmentProbe(
   scene, 
   renderer, 
   panorama, 
   options
): object;

Filter a caller-owned panorama for mesh IBL and scale its world-space Gaussian probe. Dispose restores the previous scene environment if this helper still owns it. The input texture remains caller-owned. No assets or network requests are created.

Parameters ​

ParameterTypeDescription
sceneSceneScene receiving mesh IBL.
rendererRendererInitialized engine renderer.
panoramaTextureLinear HDR equirectangular panorama.
optionsEnvironmentProbeOptionsProbe and matching mesh intensity/orientation.

Returns ​

object

Shared SH coefficients and idempotent cleanup.

radianceSH ​
ts
radianceSH: [number, number, number][];
dispose() ​
ts
dispose(): void;
Returns ​

void

Example ​

ts
const lighting = createEnvironmentProbe(engine.scene, engine.renderer, panorama, {
  radianceSH: probe.radianceSH, intensity: 0.95, yaw: probe.yaw,
});
splat.setEnvironmentLighting({ radianceSH: lighting.radianceSH });
// On shutdown: lighting.dispose(); panorama.dispose();

createJoinedSplat() ​

ts
function createJoinedSplat(
   renderer, 
   parent, 
   options
): JoinedSplat;

Several layers of points as one splat: one object, one sort.

On WebGPU the object is there at once, empty, with room for capacity gaussians and the parts; each layer is written into it a piece a frame. On the WebGL fallback the object is built again from every layer whenever one comes or goes.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererThe renderer, initialised.
parentObject3DWhere the object goes (the scene).
optionsJoinedSplatOptionsThe room, the bounds, the colour space.

Returns ​

JoinedSplat

The joined splat.

Example ​

ts
import { createJoinedSplat, createSplatLayerLoader } from 'gameable/splat';

const joined = createJoinedSplat(renderer, scene, {
  capacity: 6_000_000,
  bounds: { center: [60, 20, 90], radius: 180 },
});
const loader = createSplatLayerLoader();
const court = joined.add(await loader.load('/worlds/estate/places/court/place.spz', courtMatrix));
// each frame, before the render: joined.update(camera)
await court?.done;

createLightProbeGrid() ​

ts
function createLightProbeGrid(data): LightProbeGrid;

Check a baked grid and build its sampler.

Parameters ​

ParameterTypeDescription
dataLightProbeGridDataThe parsed JSON.

Returns ​

LightProbeGrid

The sampler.

Throws ​

When the grid's sizes do not match its probes.


createSlotAllocator() ​

ts
function createSlotAllocator(capacity): SlotAllocator;

Build a slot allocator over capacity slots.

Parameters ​

ParameterTypeDescription
capacitynumberTotal slots. Must be a positive integer.

Returns ​

SlotAllocator

An allocator with one free run covering everything.

Example ​

ts
import { createSlotAllocator } from 'gameable/splat';

const slots = createSlotAllocator(1000);
const head = slots.allocate(400);
console.log(head.offset, head.count); // 0 400
slots.free(head);
console.log(slots.available); // 1000

createSplatLayerLoader() ​

ts
function createSplatLayerLoader(options?): SplatLayerLoader;

A loader for the layers of a joined splat: each file is fetched, unpacked and put through its matrix in a worker, so the page's own thread does none of it. A file the worker cannot read (not an .spz of version 2 or 3, or no workers here) is read on the page's thread instead, by the package's own loader.

Parameters ​

ParameterTypeDescription
options{ workers?: number; }workers: how many (default 2).
options.workers?number-

Returns ​

SplatLayerLoader

The loader.

Example ​

ts
import { createSplatLayerLoader } from 'gameable/splat';

const loader = createSplatLayerLoader();
const layer = await loader.load('/worlds/estate/places/court/place.spz', null);
console.log(layer.count, layer.bytes);
loader.dispose();

createSplatObject() ​

ts
function createSplatObject(asset, options?): AnimatedGaussianSplat | GaussianSplat;

Turn a decoded asset into a scene object.

Uses three's own GaussianSplat unless lighting or shadows are asked for; then the maintained fork, which on a real geometry takes upstream's own path (the same one-time repack) and only adds the switches.

Parameters ​

ParameterTypeDescription
assetSplatAssetA decoded asset.
optionsCreateSplatObjectOptionsSort behaviour and draw order.

Returns ​

AnimatedGaussianSplat | GaussianSplat

The object, with its bounds computed and its render order set.

Example ​

ts
attachSrgbPass(renderer, scene); // from gameable/core: sRGB splats draw in its pass
const splat = createSplatObject(asset, { autoSort: true });
splat.position.y = -1;
scene.add(splat);

createSplatParts() ​

ts
function createSplatParts(base, counts): SplatParts;

Grow a splat asset by room for parts that move.

The object made from the result draws the base as before; each part is a group of gaussians appended to it, filled from an asset of its own, moved by a matrix and sorted with the rest. WebGPU only (check isWebGPUBackend(renderer) first).

Parameters ​

ParameterTypeDescription
baseSplatAssetThe splat the parts stand in (a place). Its geometry is copied, not changed.
countsreadonly number[]How many gaussians each part has room for.

Returns ​

SplatParts

The parts, with the grown asset to make the object from.

Example ​

ts
import { createSplatObject, createSplatParts } from 'gameable/splat';

const parts = createSplatParts(place, [trunk.count]);
const object = createSplatObject(parts.asset, { receiveShadows: true });
scene.add(object);
parts.bind(object);
parts.fill(0, trunk);
parts.show(0, true);
parts.move(0, trunkToPlace); // then, each frame: parts.flush(renderer)

createSplatPartsIn() ​

ts
function createSplatPartsIn(first, counts): SplatPartsIn;

Parts that move inside a splat that already has room for them: the same as createSplatParts, for an object whose own slots from first on are kept free for the parts (a dynamic splat made with the capacity, say: the joined places of a world). WebGPU only (check isWebGPUBackend(renderer) first).

Parameters ​

ParameterTypeDescription
firstnumberThe object's first slot kept for the parts; the parts follow one another from it.
countsreadonly number[]How many gaussians each part has room for.

Returns ​

SplatPartsIn

The parts; bind them to the object.

Example ​

ts
import { createAnimatedSplat, createSplatPartsIn } from 'gameable/splat';

const sink = await createAnimatedSplat(renderer, { capacity: 1_000_000 + trunk.count });
const parts = createSplatPartsIn(1_000_000, [trunk.count]);
parts.bind(sink.splat);
parts.fill(0, trunk);
parts.show(0, true); // then, each frame: parts.flush(renderer)

createSplatShadows() ​

ts
function createSplatShadows(
   renderer, 
   scene, 
   options?
): SplatShadows;

Start shadows for one scene. Nothing is drawn until a character is added; on the WebGL fallback everything is a no-op.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererThe engine's renderer.
sceneObject3DThe scene the ground (when there is no place) is added to.
optionsSplatShadowsOptionsThe level, the ground switch, how fast a new light turns in and the biases.

Returns ​

SplatShadows

The shadows.

Example ​

ts
import { createSplatShadows } from 'gameable/splat';
const shadows = createSplatShadows(engine.renderer, engine.scene, { characterBias: 0.08 });
shadows.addCharacter(record, { rig, holder, splat });
// Every frame, after the characters are posed and before the frame renders:
shadows.update(dt);
console.log(shadows.info.tiles, shadows.info.rendered);

createWebglSkinnedSplat() ​

ts
function createWebglSkinnedSplat(renderer, options): WebglSkinnedSplat;

Build a dynamic splat for the WebGL fallback, fed by a gaussian source.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised renderer on the WebGL fallback.
optionsCreateWebglSkinnedSplatOptionsCapacity, bounds, draw order and colour space.

Returns ​

WebglSkinnedSplat

The splat.

Throws ​

When the renderer is on WebGPU (use createAnimatedSplat there).

Example ​

ts
import { createWebglSkinnedSplat } from 'gameable/splat';

const splat = createWebglSkinnedSplat(renderer, {
  capacity: 144_492,
  boundingSphere: { center: [0, 0.9, 0], radius: 1.2 },
  colorSpace: 'srgb',
});
scene.add(splat.object3D);

decodeSpzGaussians() ​

ts
function decodeSpzGaussians(bytes, matrix): JoinedGaussians;

Unpack an .spz file (already gunzipped; versions 2 and 3) straight into a joined object's layout, each gaussian put through a matrix on the way: its centre as a point, its covariance as A S A^T (A the matrix's turn and scale).

The numbers are three's own SPZLoader's (the same tables for size and colour, the same turn), so a place drawn through here is the place the loader would have drawn. View-dependent colour is not carried: a made place has none. The function stands by itself (no imports, no outer names) because it also runs inside a worker, from its own source text.

Parameters ​

ParameterTypeDescription
bytesUint8ArrayThe file after gunzip.
matrixArrayLike<number> | nullSixteen numbers, column by column, from the file's frame to the object's; null leaves the gaussians where the file has them.

Returns ​

JoinedGaussians

The gaussians.

Throws ​

When the bytes are not an .spz of version 2 or 3.

Example ​

ts
import { decodeSpzGaussians } from 'gameable/splat';

const stream = new Blob([file]).stream().pipeThrough(new DecompressionStream('gzip'));
const bytes = new Uint8Array(await new Response(stream).arrayBuffer());
const layer = decodeSpzGaussians(bytes, null);
console.log(layer.count, layer.min, layer.max);

defaultShadowQuality() ​

ts
function defaultShadowQuality(hints?): ShadowQuality;

The level a device starts at: soft on a computer, simple on a phone, the contact shadow alone on a phone with 2 GB of memory or less.

Parameters ​

ParameterTypeDescription
hintsShadowDeviceHintsWhat is known about the device; the browser is asked for anything missing.

Returns ​

ShadowQuality

The level.


directionFromAngles() ​

ts
function directionFromAngles(azimuth, elevation): [number, number, number];

A unit direction from azimuth and elevation.

Parameters ​

ParameterTypeDescription
azimuthnumberDegrees around y from +z toward +x.
elevationnumberDegrees above the horizon.

Returns ​

[number, number, number]

The unit vector, y up.


estimateKeyLightFromPanorama() ​

ts
function estimateKeyLightFromPanorama(panorama, options?): KeyLightEstimate;

Find the key light in a 360° picture: the brightest compact region above the horizon.

The picture is reduced to at most 128 x 64, every direction above minElevation is scored by the light inside a narrow lobe around it (a 12° half-width), and the best is refined to the centroid of the light near it. The balance follows from irradiance: keyToFill compares a surface facing the key with one facing away, and shadowStrength is the key's share of the light on the surface facing it, the share its shadow takes away. An 8-bit picture clips a sun at white, so its key reads weaker than it was and the shadow comes out lighter.

Parameters ​

ParameterTypeDescription
panoramaPanoramaThe picture, three's equirectangular orientation.
optionsPanoramaKeyLightOptionsSearch limits.

Returns ​

KeyLightEstimate

The key light; confidence near 0 for an evenly lit (overcast) picture.


estimateKeyLightFromSH() ​

ts
function estimateKeyLightFromSH(sh, options?): KeyLightEstimate;

Read the key light from a light probe: nine radiance coefficients of the light arriving at one point, in three's SphericalHarmonics3 order, either nine RGB triples (the engine's radianceSH) or 27 flat numbers (a baked probe grid's sh).

The first band's direction is where the most light comes from; keyToFill compares the irradiance facing it with the irradiance facing away. A probe is smooth by nature: it finds the side the light comes from, not a small lamp's exact position.

Parameters ​

ParameterTypeDescription
sh| ArrayLike<number> | readonly readonly [number, number, number][]The probe.
options{ minElevation?: number; }The key is held no lower than minElevation degrees (default 20).
options.minElevation?number-

Returns ​

KeyLightEstimate

The key light; confidence near 0 for light that is the same from every side.


estimateKeyLightFromSurfels() ​

ts
function estimateKeyLightFromSurfels(samples, options?): KeyLightEstimate & object;

Find the light a character was captured under from its own colours.

The capture-lighting idea (brightness against surface normal) with one change that matters for a clothed person: within each group of samples of one material (one body part, one colour), brightness relative to the group's mean is fitted against the normal's offset from the group's mean normal, L / mean(L) - 1 = d . (n - mean(n)), so a dark coat on the back and a pale face on the front do not read as light from the front. The fitted d points at the key; its length is the key's strength against the ambient light.

Parameters ​

ParameterTypeDescription
samplesSurfelSamplesOne sample per gaussian: outward normal, luminance, weight and group.
optionsSurfelKeyLightOptionsGroup filters and the elevation range.

Returns ​

KeyLightEstimate & object

The key light in the samples' own space; confidence near 0 when the colours carry no shading.


getGPUDevice() ​

ts
function getGPUDevice(renderer): GPUDevice;

The one GPUDevice in the process — the renderer's.

AGENTS.md hard rule 7: nothing calls navigator.gpu.requestAdapter(). The device only exists after await renderer.init(), and the backend object is replaced when the renderer falls back to WebGL, so never cache either across init.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer.

Returns ​

GPUDevice

The device the renderer owns.

Throws ​

When the renderer is not initialised, or fell back to WebGL.

Example ​

ts
await renderer.init();
const device = getGPUDevice(renderer);
device.createShaderModule({ code });

initCountingSortPatch() ​

ts
function initCountingSortPatch(target?): boolean;

Patch CountingSort.prototype.compute so a sort is one renderer.compute([...]) call.

Idempotent. gameable/splat applies it from the splat() module's init, from createSplatObject and from createAnimatedSplat, so a game never has to; it is exported for hosts that build splats some other way.

Parameters ​

ParameterTypeDescription
target?objectPrototype to patch. Tests pass a fake; production never sets it.

Returns ​

boolean

True when the prototype carries the patch after the call.

Example ​

ts
import { initCountingSortPatch } from 'gameable/splat';

initCountingSortPatch(); // before the first frame that sorts a splat

isCountingSortPatched() ​

ts
function isCountingSortPatched(target?): boolean;

Whether a prototype already carries the counting-sort patch.

Parameters ​

ParameterTypeDescription
target?objectPrototype to check. Defaults to CountingSort.prototype.

Returns ​

boolean

True when initCountingSortPatch has run against it.

Example ​

ts
import { initCountingSortPatch, isCountingSortPatched } from 'gameable/splat';

initCountingSortPatch();
console.log(isCountingSortPatched()); // true

isWebGPUBackend() ​

ts
function isWebGPUBackend(renderer): boolean;

Whether this renderer got a real WebGPU backend rather than the WebGL fallback.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererA renderer, initialised or not.

Returns ​

boolean

True for the WebGPU backend.

Example ​

ts
await renderer.init();
if (!isWebGPUBackend(renderer)) console.warn('static splats only');

loadSplat() ​

ts
function loadSplat(url, options?): Promise<SplatAsset>;

Fetch and decode a splat file.

Parameters ​

ParameterTypeDescription
urlstringSPZ, PLY, SPLAT, KSPLAT, a .sog or a SOG folder's meta.json.
optionsLoadSplatOptionsFormat override, abort signal, custom fetch.

Returns ​

Promise<SplatAsset>

The decoded asset.

Throws ​

On a non-2xx response, an unrecognised format or a decoder failure.

Example ​

ts
import { createSplatObject, loadSplat } from 'gameable/splat';

const asset = await loadSplat('/models/arena.spz');
attachSrgbPass(renderer, scene); // from gameable/core: sRGB splats draw in its pass
scene.add(createSplatObject(asset));

loadSplatPlace() ​

ts
function loadSplatPlace(
   renderer, 
   url, 
   options?
): Promise<SplatPlace>;

Open a streaming place: SuperSplat's tiled bundle with levels of detail, by its lod-meta.json URL (the files beside it are fetched as the camera needs them) or as a .ssog / .zip (fetched whole, then decoded piece by piece).

The returned place draws itself: add place.object3D to the scene and every frame it is drawn it chooses each leaf's level for that camera, loads the files the chosen pieces need, uploads them nearest first and drops files no piece needs after a cooldown. A SuperSplat scene's up is -y: turn it (object3D.rotation.z = Math.PI) as SuperSplat's viewer does.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer on the WebGPU backend. A single SOG (a .sog, or a folder's meta.json) opens the same way, as a place of one level: it streams in piece by piece and is drawn after the view test, but it has nothing coarser to show, so it holds all its gaussians whatever the budget.
urlstringThe bundle's lod-meta.json, or a .ssog / .zip of the bundle; or a single SOG.
optionsSplatPlaceOptionsBudget (desktop 6 M, phone 1.5 M by default) and the rest.

Returns ​

Promise<SplatPlace>

The place; its firstPicture resolves when the coarsest level is all on screen.


moveNeedsSort() ​

ts
function moveNeedsSort(
   x, 
   y, 
   z, 
   scaleX, 
   scaleY
): boolean;

Whether a joined splat must be sorted again after the view has moved (without turning: a turn sorts by itself).

Two things are worked out when the object is sorted and go stale as the eye moves: which centres are in view (the rest are not drawn), and the depth bins, finest at the eye. A move towards a point that is on the screen brings nothing new into view (the view is a cone, and a cone moved along a line inside itself stays inside itself) and keeps the order, so it only coarsens the bins near the eye, slowly: such a move is let run two metres. Any other move (sideways, back) sorts again after a quarter of a metre. At racing speed this is the difference between a sort every frame and one every sixth.

Parameters ​

ParameterTypeDescription
xnumberThe move since the last sort in the camera's own frame: to its right.
ynumberUp.
znumberTowards the viewer (a move straight on is negative).
scaleXnumberThe projection's x scale (projectionMatrix.elements[0]).
scaleYnumberThe projection's y scale (projectionMatrix.elements[5]).

Returns ​

boolean

True when a sort is due.

Example ​

ts
import { moveNeedsSort } from 'gameable/splat';

console.log(moveNeedsSort(0, 0, -1, 1, 1.8)); // false: a metre straight on
console.log(moveNeedsSort(0.3, 0, 0, 1, 1.8)); // true: 30 cm to the side

panoramaFromGaussians() ​

ts
function panoramaFromGaussians(
   cloud, 
   at, 
   options?
): Panorama & object;

Draw a small panorama of a place's gaussians as seen from one point: each pixel takes the colour of the nearest surface in its direction (the front layer of gaussians), so a lamp behind a wall is not seen and a window beside the character is. Feed the result to estimateKeyLightFromPanorama; it is the place's light probe at that point.

Parameters ​

ParameterTypeDescription
cloudGaussianCloudThe place's gaussians.
atArrayLike<number>The probe point in world space (a character's chest height is a good one).
optionsGaussianPanoramaOptionsSize and filters.

Returns ​

Panorama & object

A linear RGB panorama, width x width / 2.


parseShadowQuality() ​

ts
function parseShadowQuality(value): "auto" | ShadowQuality | null;

Read a quality from untrusted text (a URL switch, a saved setting).

Parameters ​

ParameterTypeDescription
valuestring | null | undefinedThe text.

Returns ​

"auto" | ShadowQuality | null

The level, 'auto', or null when the text is neither.


parseSplat() ​

ts
function parseSplat(
   buffer, 
   url, 
   format?, 
   options?
): Promise<SplatAsset>;

Decode a buffer that has already been fetched.

Separated from loadSplat so tests can drive every decoder from memory, and so an asset pipeline that already holds the bytes does not fetch twice. A SOG is either its .sog zip or a folder's meta.json, whose images are then fetched from beside url.

Parameters ​

ParameterTypeDefault valueDescription
bufferArrayBufferundefinedThe file.
urlstringundefinedWhere it came from, for sniffing, a SOG folder's images and error messages.
formatSplatFormatOption'auto'Decoder to use, or 'auto'.
optionsParseSplatOptions{}SOG bands, and the fetch a SOG folder's images come through.

Returns ​

Promise<SplatAsset>

The decoded asset.

Throws ​

When the file is a streaming place ('ssog'), which is not one geometry.

Example ​

ts
import { parseSplat } from 'gameable/splat';

const asset = await parseSplat(bytes, 'arena.spz');
console.log(asset.count, asset.shDegree);

placeGaussians() ​

ts
function placeGaussians(
   position, 
   covariance, 
   color, 
   matrix
): JoinedGaussians;

Put decoded gaussians (a splat asset's own arrays) through a matrix, into a joined object's layout: each centre as a point, each covariance as A S A^T.

Parameters ​

ParameterTypeDescription
positionArrayLike<number>Centres, three floats each.
covarianceArrayLike<number>Covariances, six floats each: c00, c01, c02, c11, c12, c22.
colorArrayLike<number>Colours, four bytes each: red, green, blue, opacity.
matrixArrayLike<number> | nullSixteen numbers, column by column, to the object's frame; null leaves them.

Returns ​

JoinedGaussians

The gaussians.

Example ​

ts
import { placeGaussians } from 'gameable/splat';

const g = asset.geometry;
const layer = placeGaussians(
  g.getAttribute('position').array,
  g.getAttribute('covariance').array,
  g.getAttribute('color').array,
  [2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 10, 0, 0, 1], // twice the size, ten metres along x
);

readPlaceIndex() ​

ts
function readPlaceIndex(json, baseUrl): PlaceIndex;

Read lod-meta.json into a PlaceIndex.

Parameters ​

ParameterTypeDescription
jsonLodMetaJsonThe parsed file.
baseUrlstringWhere it came from: file names resolve against it.

Returns ​

PlaceIndex

The index.

Throws ​

When the file is not a streaming bundle's index.


registerGltfSplatExtension() ​

ts
function registerGltfSplatExtension(gltfLoader): void;

Teach a GLTFLoader to read KHR_gaussian_splatting.

Register it before the first load; meshes carrying the extension then come back as GaussianSplat nodes inside the glTF scene graph. Their render order is not set for you, because the glTF author owns that graph — walk the result and set SPLAT_RENDER_ORDER if splats are interleaving with your transparent meshes.

Parameters ​

ParameterTypeDescription
gltfLoaderGltfLoaderLikeThe loader to extend.

Returns ​

void

Nothing.

Example ​

ts
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { registerGltfSplatExtension } from 'gameable/splat';

const loader = new GLTFLoader();
registerGltfSplatExtension(loader);
const gltf = await loader.loadAsync('/models/scene.glb');

releaseStorageAttribute() ​

ts
function releaseStorageAttribute(renderer, attribute): boolean;

Destroy the GPUBuffer behind one storage attribute.

The counterpart to acquireSplatGPUBuffers, and the reason this file exists: three creates a storage attribute's buffer through backend.createStorageAttribute and destroys it through backend.destroyAttribute, and neither is reachable from the public API. BufferAttribute.dispose() only dispatches a dispose event, which Geometries.js listens for on vertex and index attributes but never on storage ones — so without this call every disposed dynamic splat leaks its buffers for the lifetime of the page.

Safe to call more than once and on an attribute that was never uploaded: it returns false rather than letting destroyAttribute dereference a missing buffer.

Parameters ​

ParameterTypeDescription
rendererWebGPURendererThe renderer that materialised the attribute.
attributeobjectA StorageBufferAttribute (or any BufferAttribute).

Returns ​

boolean

True when a GPU buffer was destroyed.

Example ​

ts
for (const attribute of splat.storageAttributes()) releaseStorageAttribute(renderer, attribute);

releaseStorageCopies() ​

ts
function releaseStorageCopies(renderer, attributes): object;

Drop the CPU copy of storage attributes the GPU already holds, and say how many bytes that freed.

three keeps every StorageBufferAttribute's array after uploading it. A dynamic splat's arrays are zeros the owner never reads again (it writes the GPU buffers directly), and for a streaming place of millions of gaussians they are hundreds of megabytes of page memory. An attribute the backend has a GPUBuffer for gets an empty array of the same type in place of its copy; three only reads array again when the attribute's version changes (needsUpdate), which a dynamic splat never asks for. Its memory accounting (renderer.info.memory) kept the size at creation. An attribute not yet on the GPU (the sort's buffers before the first sort) is left alone: call again after a frame. On the WebGL fallback nothing is released (its transform feedback, PBO textures and readback read the arrays).

Parameters ​

ParameterTypeDescription
rendererWebGPURendererAn initialised WebGPURenderer on the WebGPU backend.
attributesIterable<object>The attributes, e.g. splat.storageAttributes().

Returns ​

object

Bytes released, and how many attributes are still waiting for their GPU buffer.

bytes ​
ts
bytes: number;
waiting ​
ts
waiting: number;

Example ​

ts
const { bytes, waiting } = releaseStorageCopies(renderer, sink.splat.storageAttributes());
if (waiting > 0) requestAnimationFrame(() => releaseStorageCopies(renderer, sink.splat.storageAttributes()));

shadowQualityPreset() ​

ts
function shadowQualityPreset(quality): ShadowQualityPreset;

What a quality level draws.

Parameters ​

ParameterTypeDescription
qualityShadowQualityThe level.

Returns ​

ShadowQualityPreset

Its map size, filter and contact switch.


sniffSplatFormat() ​

ts
function sniffSplatFormat(url, bytes): SplatFileFormat;

Guess the container format from the URL and the first bytes.

The extension wins when it is one we know, because .ksplat has no magic number and .splat has no header at all. Content sniffing is the fallback, and it can only recognise the formats that are self-describing: SPZ (gzip, or NGSP for v4), PLY (ply\n), a SOG (a zip holding meta.json, or that meta.json itself) and a streaming place, 'ssog' (a zip with lod-meta.json at its top, or that lod-meta.json). A zip is told apart by its central directory when bytes is the whole file, else by its first entry's name.

Parameters ​

ParameterTypeDescription
urlstringThe URL the bytes came from. Query and hash are ignored.
bytesUint8ArrayAt least the first 8 bytes of the file (the whole file tells zips apart best).

Returns ​

SplatFileFormat

The format.

Throws ​

When neither the extension nor the content identifies it.

Example ​

ts
import { sniffSplatFormat } from 'gameable/splat';

sniffSplatFormat('/models/arena.spz', new Uint8Array(8)); // 'spz'
sniffSplatFormat('/places/room.sog', new Uint8Array(8)); // 'sog'

splat() ​

ts
function splat(options?): EngineModule;

The splat EngineModule.

Registers the splat asset type, so { "id": "arena", "type": "splat", "src": "arena.spz" } in assets.json resolves to a SplatAsset, and publishes a small service for putting one in the scene.

Parameters ​

ParameterTypeDescription
optionsSplatModuleOptionsOptional format override.

Returns ​

EngineModule

The module, to be passed in createEngine({ modules }).

Example ​

ts
import { createEngine } from 'gameable/core';
import { splat } from 'gameable/splat';

const engine = await createEngine({ canvas, manifest: '/assets.json', modules: [splat()] });
engine.get('splat').add('arena');
engine.start();

strengthOf() ​

ts
function strengthOf(keyToFill): number;

How dark a shadow of the key is: the key's share of the light on a surface facing it.

Parameters ​

ParameterTypeDescription
keyToFillnumberKey over fill, 1 or more.

Returns ​

number

0 to 0.9.


takeSlotRuns() ​

ts
function takeSlotRuns(slots, count): SlotRange[] | null;

Take room for a number of gaussians from an allocator, in as many runs as it needs: a layer let go leaves a run a larger layer does not fit, and a layer is written a piece at a time anyway, so it need not be in one run.

Parameters ​

ParameterTypeDescription
slots{ available: number; largestFree: number; allocate: SlotRange; }The allocator.
slots.availablenumber-
slots.largestFreenumber-
slots.allocate-
countnumberHow many gaussians.

Returns ​

SlotRange[] | null

The runs, in the order the layer fills them; null (nothing taken) when there is not room for all of it.

Example ​

ts
import { createSlotAllocator, takeSlotRuns } from 'gameable/splat';

const slots = createSlotAllocator(1000);
const runs = takeSlotRuns(slots, 400);
console.log(runs); // [{ offset: 0, count: 400 }]