@aosengine/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
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | An initialised WebGPURenderer on the WebGPU backend. |
options | CreateAnimatedSplatOptions | Capacity, bounds and draw order. |
Returns
Properties
buffers
ts
readonly buffers: SplatGPUBuffers;The four GPU buffers, in the layout documented in backendBuffers.ts.
Implementation of
capacity
ts
readonly capacity: number;Total gaussians this sink can hold. Fixed for its lifetime.
Implementation of
splat
ts
readonly splat: AnimatedGaussianSplat;The fork instance. Typed as the fork, not as Object3D, for object3D consumers.
Accessors
available
Get Signature
ts
get available(): number;Slots not handed out. Named available, because free is the method above.
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
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
| Parameter | Type | Description |
|---|---|---|
count | number | How many gaussians. |
Returns
The range.
Implementation of
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
| Parameter | Type | Description |
|---|---|---|
range? | SlotRange | The 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: 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
| Parameter | Type | Description |
|---|---|---|
range | SlotRange | A range from AnimatedSplat.allocate. |
Returns
void
Nothing.
Implementation of
markGaussiansChanged()
ts
markGaussiansChanged(): void;Force a re-sort on the next frame.
Returns
void
Nothing.
Implementation of
SplatSink.markGaussiansChanged
setBoundingSphere()
ts
setBoundingSphere(center, radius): void;Declare where the gaussians are, in local space.
Parameters
| Parameter | Type | Description |
|---|---|---|
center | Vec3Tuple | Local-space centre. |
radius | number | Local-space radius. |
Returns
void
Nothing.
Implementation of
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
| Parameter | Type | Description |
|---|---|---|
builder | ((view) => Node) | null | Returns 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
| Parameter | Type | Description |
|---|---|---|
message | string | What went wrong. |
requested | number | Slots requested. |
largestFree | number | Largest free run at the time. |
Returns
Overrides
ts
Error.constructorProperties
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
| Parameter | Type | Description |
|---|---|---|
url | string | The URL that failed. |
message | string | What went wrong. |
options? | ErrorOptions | Standard Error options, used to keep the cause. |
Returns
Overrides
ts
Error.constructorProperties
url
ts
readonly url: string;The URL that failed.
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. 'linear' (the default) is what three assumes and encodes to sRGB in its output pass; 'srgb' says the bytes are already sRGB (a character trained against photographs), so each gaussian is decoded to linear in the vertex shader and the screen shows the file's own colours instead of a second encode.
renderOrder?
ts
readonly optional renderOrder?: number;Draw order. Defaults to SPLAT_RENDER_ORDER.
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. 'linear' (the default) is three's assumption, and the renderer's output pass encodes them to sRGB. 'srgb' is for a splat trained against photographs — a place from Gameable CC — whose colours are already sRGB: they are decoded per gaussian, so the page shows the file's own colours instead of a lifted, washed-out copy. Opting in draws through the fork (AnimatedGaussianSplat) and marks the asset's geometry (userData.colorSpace), so every object made from that asset agrees.
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.
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
| Parameter | Type | Description |
|---|---|---|
callback | (parser) => unknown | Builds the plugin from the parser. |
Returns
unknown
The loader, for chaining.
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
| Parameter | Type | Description |
|---|---|---|
x | number | Place-frame x. |
y | number | Place-frame y. |
z | number | Place-frame z. |
out | Float32Array | 27 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.
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>;Parameters
| Parameter | Type |
|---|---|
input | URL | RequestInfo |
init? | RequestInit |
Returns
Promise<Response>
Call Signature
ts
(input, init?): Promise<Response>;Parameters
| Parameter | Type |
|---|---|
input | string | URL | Request |
init? | RequestInit |
Returns
Promise<Response>
format?
ts
readonly optional format?: SplatFormatOption;Force a decoder instead of sniffing. Defaults to 'auto'.
signal?
ts
readonly optional signal?: AbortSignal;Aborts the fetch. The decode itself is synchronous and is not interruptible.
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.
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.
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.
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
| Parameter | Type | Description |
|---|---|---|
count | number | How many slots. Must be a positive integer. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
range | SlotRange | A 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).
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.
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
| Parameter | Type | Description |
|---|---|---|
id | string | Asset id, as declared in assets.json. |
options? | CreateSplatObjectOptions | - |
Returns
AnimatedGaussianSplat | GaussianSplat
The object that was added.
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
| Parameter | Type | Description |
|---|---|---|
key | object | Any object that names it (the caller's own record). |
character | ShadowCharacter | The character. |
Returns
void
Nothing.
addPlace()
ts
addPlace(splat, place?): void;Add a place: its gaussians receive, its data suggests the light.
Parameters
| Parameter | Type | Description |
|---|---|---|
splat | AnimatedGaussianSplat | The place's gaussians (the fork class). |
place? | ShadowPlace | Its 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
| Parameter | Type | Description |
|---|---|---|
key | object | The key it was added with. |
Returns
void
Nothing.
removePlace()
ts
removePlace(splat): void;Remove a place.
Parameters
| Parameter | Type | Description |
|---|---|---|
splat | AnimatedGaussianSplat | The 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
| Parameter | Type | Description |
|---|---|---|
light | KeyLightEstimate | null | The light, world space. |
Returns
void
Nothing.
setQuality()
ts
setQuality(quality): void;Change the level; 'auto' picks by device. Rebuilds the receivers' shaders once.
Parameters
| Parameter | Type | Description |
|---|---|---|
quality | "auto" | ShadowQuality | The 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.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | number | Seconds since the last call. |
Returns
void
Nothing.
SplatShadowsOptions
Options for createSplatShadows.
Properties
ground?
ts
readonly optional ground?: boolean;A see-through ground under the characters when no place receives. Defaults to true.
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.
capacity
ts
readonly capacity: number;Total gaussians this sink can hold. Fixed for its lifetime.
object3D
ts
readonly object3D: Object3D;The scene object. Add it to a scene, move it, parent it — it is an ordinary Object3D.
Methods
allocate()
ts
allocate(count): SlotRange;Reserve a contiguous run of slots.
Parameters
| Parameter | Type | Description |
|---|---|---|
count | number | How many gaussians. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
range | SlotRange | A 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.
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
| Parameter | Type | Description |
|---|---|---|
center | Vec3Tuple | Local-space centre. |
radius | number | Local-space radius. |
Returns
void
Nothing.
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.
SplatFormat
ts
type SplatFormat = "spz" | "ply" | "splat" | "ksplat";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.
PACKAGE
ts
const PACKAGE: "@aosengine/splat";Package identity marker.
Example
ts
import { PACKAGE } from '@aosengine/splat';
console.log(PACKAGE); // '@aosengine/splat'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
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | An initialised WebGPURenderer. |
splat | object | A GaussianSplat or AnimatedGaussianSplat. |
Returns
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 capacityacquireStorageGPUBuffer()
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
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | An initialised WebGPURenderer. |
attribute | object | A 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
| Parameter | Type | Description |
|---|---|---|
direction | ArrayLike<number> | Any non-zero vector, y up. |
Returns
[number, number]
[azimuth, elevation] in degrees.
clampElevation()
ts
function clampElevation(
direction,
min,
max
): [number, number, number];The same direction with its elevation held inside a range.
Parameters
| Parameter | Type | Description |
|---|---|---|
direction | ArrayLike<number> | Unit direction. |
min | number | Lowest elevation, degrees. |
max | number | Highest elevation, degrees. |
Returns
[number, number, number]
The adjusted unit direction.
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.
Parameters
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | An initialised WebGPURenderer on the WebGPU backend. |
options | CreateAnimatedSplatOptions | Capacity, bounds and draw order. |
Returns
Promise<AnimatedSplat>
The sink, with its GPU buffers already acquired.
Throws
When the renderer is not initialised or fell back to WebGL.
Example
ts
import { createAnimatedSplat } from '@aosengine/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();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
| Parameter | Type | Description |
|---|---|---|
scene | Scene | Scene receiving mesh IBL. |
renderer | Renderer | Initialized engine renderer. |
panorama | Texture | Linear HDR equirectangular panorama. |
options | EnvironmentProbeOptions | Probe 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();createLightProbeGrid()
ts
function createLightProbeGrid(data): LightProbeGrid;Check a baked grid and build its sampler.
Parameters
| Parameter | Type | Description |
|---|---|---|
data | LightProbeGridData | The parsed JSON. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
capacity | number | Total slots. Must be a positive integer. |
Returns
An allocator with one free run covering everything.
Example
ts
import { createSlotAllocator } from '@aosengine/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); // 1000createSplatObject()
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
| Parameter | Type | Description |
|---|---|---|
asset | SplatAsset | A decoded asset. |
options | CreateSplatObjectOptions | Sort behaviour and draw order. |
Returns
AnimatedGaussianSplat | GaussianSplat
The object, with its bounds computed and its render order set.
Example
ts
const splat = createSplatObject(asset, { autoSort: true });
splat.position.y = -1;
scene.add(splat);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
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | The engine's renderer. |
scene | Object3D | The scene the ground (when there is no place) is added to. |
options | SplatShadowsOptions | The level, the ground switch and how fast a new light turns in. |
Returns
The shadows.
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
| Parameter | Type | Description |
|---|---|---|
hints | ShadowDeviceHints | What is known about the device; the browser is asked for anything missing. |
Returns
The level.
directionFromAngles()
ts
function directionFromAngles(azimuth, elevation): [number, number, number];A unit direction from azimuth and elevation.
Parameters
| Parameter | Type | Description |
|---|---|---|
azimuth | number | Degrees around y from +z toward +x. |
elevation | number | Degrees 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
| Parameter | Type | Description |
|---|---|---|
panorama | Panorama | The picture, three's equirectangular orientation. |
options | PanoramaKeyLightOptions | Search limits. |
Returns
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
| Parameter | Type | Description |
|---|---|---|
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
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
| Parameter | Type | Description |
|---|---|---|
samples | SurfelSamples | One sample per gaussian: outward normal, luminance, weight and group. |
options | SurfelKeyLightOptions | Group 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
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | An 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. @aosengine/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
| Parameter | Type | Description |
|---|---|---|
target? | object | Prototype 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 '@aosengine/splat';
initCountingSortPatch(); // before the first frame that sorts a splatisCountingSortPatched()
ts
function isCountingSortPatched(target?): boolean;Whether a prototype already carries the counting-sort patch.
Parameters
| Parameter | Type | Description |
|---|---|---|
target? | object | Prototype to check. Defaults to CountingSort.prototype. |
Returns
boolean
True when initCountingSortPatch has run against it.
Example
ts
import { initCountingSortPatch, isCountingSortPatched } from '@aosengine/splat';
initCountingSortPatch();
console.log(isCountingSortPatched()); // trueisWebGPUBackend()
ts
function isWebGPUBackend(renderer): boolean;Whether this renderer got a real WebGPU backend rather than the WebGL fallback.
Parameters
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | A 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
| Parameter | Type | Description |
|---|---|---|
url | string | SPZ, PLY, SPLAT or KSPLAT. |
options | LoadSplatOptions | Format 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 '@aosengine/splat';
const asset = await loadSplat('/models/arena.spz');
scene.add(createSplatObject(asset));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
| Parameter | Type | Description |
|---|---|---|
cloud | GaussianCloud | The place's gaussians. |
at | ArrayLike<number> | The probe point in world space (a character's chest height is a good one). |
options | GaussianPanoramaOptions | Size 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
| Parameter | Type | Description |
|---|---|---|
value | string | null | undefined | The text. |
Returns
"auto" | ShadowQuality | null
The level, 'auto', or null when the text is neither.
parseSplat()
ts
function parseSplat(
buffer,
url,
format?
): 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.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
buffer | ArrayBuffer | undefined | The file. |
url | string | undefined | Where it came from, for sniffing and error messages. |
format | SplatFormatOption | 'auto' | Decoder to use, or 'auto'. |
Returns
Promise<SplatAsset>
The decoded asset.
Example
ts
import { parseSplat } from '@aosengine/splat';
const asset = await parseSplat(bytes, 'arena.spz');
console.log(asset.count, asset.shDegree);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
| Parameter | Type | Description |
|---|---|---|
gltfLoader | GltfLoaderLike | The loader to extend. |
Returns
void
Nothing.
Example
ts
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { registerGltfSplatExtension } from '@aosengine/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
| Parameter | Type | Description |
|---|---|---|
renderer | WebGPURenderer | The renderer that materialised the attribute. |
attribute | object | A StorageBufferAttribute (or any BufferAttribute). |
Returns
boolean
True when a GPU buffer was destroyed.
Example
ts
for (const attribute of splat.storageAttributes()) releaseStorageAttribute(renderer, attribute);shadowQualityPreset()
ts
function shadowQualityPreset(quality): ShadowQualityPreset;What a quality level draws.
Parameters
| Parameter | Type | Description |
|---|---|---|
quality | ShadowQuality | The level. |
Returns
Its map size, filter and contact switch.
sniffSplatFormat()
ts
function sniffSplatFormat(url, bytes): SplatFormat;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 two formats that are self-describing: SPZ (gzip, or NGSP for v4) and PLY (ply\n).
Parameters
| Parameter | Type | Description |
|---|---|---|
url | string | The URL the bytes came from. Query and hash are ignored. |
bytes | Uint8Array | At least the first 8 bytes of the file. |
Returns
The format.
Throws
When neither the extension nor the content identifies it.
Example
ts
import { sniffSplatFormat } from '@aosengine/splat';
sniffSplatFormat('/models/arena.spz', new Uint8Array(8)); // 'spz'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
| Parameter | Type | Description |
|---|---|---|
options | SplatModuleOptions | Optional format override. |
Returns
The module, to be passed in createEngine({ modules }).
Example
ts
import { createEngine } from '@aosengine/core';
import { splat } from '@aosengine/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
| Parameter | Type | Description |
|---|---|---|
keyToFill | number | Key over fill, 1 or more. |
Returns
number
0 to 0.9.