Skip to main content

SplatLayer

SplatLayer renders prepared, anisotropic 3D Gaussians ("splats"), instanced per data row. Rows can share one immutable source while keeping their own position, transform, color and picking. Distant instances can use coarser levels of a hierarchy within a Gaussian budget. It runs on WebGL2 and WebGPU, and TreeLayer uses it for foliage.

SplatLayer draws decoded Gaussians only. File loading, training, streaming and spherical harmonics are out of scope.

Usage​

import {SplatLayer, type SplatSource} from '@deck.gl-community/layers';

const source: SplatSource = {
positions: new Float32Array([0, 0, 0]),
scales: new Float32Array([0.3, 0.12, 0.02]),
rotations: new Float32Array([1, 0, 0, 0]), // WXYZ
colors: new Uint8Array([80, 160, 50, 255]),
opacities: new Float32Array([0.85])
};

new SplatLayer({
id: 'splats',
data: objects,
getSource: source,
getPosition: d => d.position,
getScale: d => d.scale,
pickable: true
});

data can also be a single source, and getSource can select a source per row:

// One source at one position.
new SplatLayer({data: source, getPosition: [longitude, latitude, 0]});

// A different source per row.
new SplatLayer({data: objects, getSource: d => templates[d.kind]});

Levels of detail​

Build a hierarchy once with createSplatHierarchy and pass it alongside the source:

import {createSplatHierarchy} from '@deck.gl-community/layers';

const asset = {
type: 'prepared-splats' as const,
source,
hierarchy: createSplatHierarchy(source, [0.2, 0.5, 1])
};

new SplatLayer({data: objects, getSource: asset, maxSplats: 50_000});

createSplatHierarchy(source, cellSizes, minimumSplats = 1) merges Gaussians into increasingly coarse spatial cells. Each visible instance uses the coarsest level that stays within pixelError. A finite maxSplats gives detail to the instances that gain the most, and level changes crossfade.

Properties​

Inherits all CompositeLayer properties. Picking and highlightedObjectIndex use the source row. Use updateTriggers when an accessor's result changes without new data, and replace a source object instead of mutating its arrays.

Data​

PropertyDefaultDescription
data[]Instance rows, or one prepared source.
getSourced => d.splatsA SplatSource or prepared asset, constant or per row.
getPositiond => d.positionInstance position.
getOrientation[0, 0, 0]Pitch, yaw and roll in degrees.
getScale[1, 1, 1]XYZ scale.
getTranslation[0, 0, 0]Offset after orientation and scale. Metres in geospatial views.
getTransformMatrixnullAffine 4×4 matrix. Replaces orientation, scale and translation.
getColorwhiteRGBA tint. Alpha multiplies opacity.
getCoverageWeight1Opacity multiplier, for fading instances in and out.

Rendering​

PropertyDefaultDescription
transparency'weighted'Unsorted blending, or 'sorted' for exact alpha blending at extra cost.
materialPhongLighting, using the source normals.
kernelVariance0.3Anti-aliasing blur added to each Gaussian, in pixels.
support3Gaussian extent in standard deviations, 1–6.
alphaCutoff1/255Fragments below this opacity are discarded.

Level of detail​

PropertyDefaultDescription
pixelError0.75Allowed screen error in pixels when choosing a hierarchy level.
maxSplatsInfinitySplat budget for this layer. Visible instances keep their coarsest level.
maxTotalSplatsInfinityBudget shared by all SplatLayers in a deck. The strictest value wins.
maxRenderPixelsInfinityPixel cap for splat rendering. Lower values trade sharpness for speed.
foveationStrength00–1. Under a budget, favors instances near the screen center.

Budgets count submitted Gaussians, not GPU memory.

Deformation​

PropertyDefaultDescription
getDeformation[1, 0, 0]Per-instance [height, phase, flex] for wind bending.
deformationStrength0Bend as a fraction of instance height.
deformationTimenullSeconds. null follows deck.gl's animation timeline.

Types​

SplatSource​

All arrays describe the same number of Gaussians and are Float32Arrays, except colors. Invalid sources throw before upload.

FieldDescription
positionsXYZ centers.
scalesPositive XYZ one-sigma radii.
rotationsUnit WXYZ quaternions.
colorsRGBA bytes (Uint8Array) or linear RGBA floats.
opacitiesPeak opacity, 0–1.
opticalDepthsOptional optical density. Overrides opacities to keep dense aggregates opaque.
normalsOptional XYZ normals for lighting.

Statistics​

After initialization, layer.splatStats reports sourceCount, visibleInstances, renderedSplats, coverageFloor and refiningInstances.

Limitations​

  • Supports MapView, GlobeView and Cartesian views. With MapView.repeat, splats render in the primary world copy only.
  • On GlobeView, owner-local metres point east, north and up, so a pose is unchanged when the view switches to Web Mercator above zoom 12. Gaussians behind the sea-level horizon are hidden. Positions resolve about 0.4 m at the surface, like deck.gl's own globe layers.
  • deck.gl 9.4 shadow maps do not fit GlobeView: a _shadow: true light darkens every layer on it.
  • deck.gl LightingEffect shadows work on WebGL2 only.
  • Place opaque layers before splat layers so that they occlude splats.
  • Weighted transparency approximates alpha blending. Overlapping colors can differ from a depth-sorted renderer.
  • Requires renderable RGBA16F and R16F textures.
  • On WebGPU, View.clear is not supported.

Source​

modules/layers/src/splat-layer