Skip to main content

Class: LightClusterGrid

The world-space clustered light layer: selects the highest-importance registered lights around the camera (deterministically, with hysteresis), bins them into a camera-centered world-aligned cell grid, and packs both into two small data textures every chunk material samples.

All per-frame work runs on preallocated scratch; a frame in which neither the registry nor the camera cell changed does nothing at all.

Constructors

constructor

new LightClusterGrid(registry, options): LightClusterGrid

Parameters

NameType
registryLightSourceRegistry
optionsObject
options.analyticRadiusnumber
options.fluidSpecularStrengthnumber
options.gridCellSizenumber
options.gridDims[number, number, number]
options.maskKneenumber
options.maxClusteredLightsnumber
options.maxLightsPerCellnumber
options.selectionHysteresisnumber

Returns

LightClusterGrid

Properties

selectedCount

selectedCount: number = 0


selectedIndices

Readonly selectedIndices: Uint32Array<ArrayBufferLike>

Selected registry slot per rank; selectedCount entries are live.


shadowProvider

shadowProvider: (index: number) => ShadowTexelRecord = null

Shadow-slot data source, wired by the facade once the shadow scheduler exists. Null keeps every record unshadowed (Engine PR A behavior).

Type declaration

▸ (index): ShadowTexelRecord

Parameters
NameType
indexnumber
Returns

ShadowTexelRecord


uniforms

Readonly uniforms: Object

Type declaration

NameTypeDescription
clusteredCount{ value: number = 0 }-
clusteredCount.valuenumber-
debugMode{ value: number = 0 }-
debugMode.valuenumber-
emissiveLevels{ value: Vector4 }-
emissiveLevels.valueVector4-
gridCellSize{ value: number = 8 }-
gridCellSize.valuenumber-
gridDims{ value: Vector3 }-
gridDims.valueVector3-
gridOrigin{ value: Vector3 }-
gridOrigin.valueVector3-
lightData{ value: DataTexture }-
lightData.valueDataTexture-
lightGrid{ value: DataTexture }-
lightGrid.valueDataTexture-
maskKnee{ value: number }-
maskKnee.valuenumber-
ownership{ value: number = 1 }0..1: how strongly analytic claims suppress the baked flood term.
ownership.valuenumber-
specularStrength{ value: number = 1 }-
specularStrength.valuenumber-

Methods

dispose

dispose(): void

Returns

void


markTexturesDirty

markTexturesDirty(): void

Re-upload GPU state after a restored context; CPU data is authoritative.

Returns

void


refreshShadowTexels

refreshShadowTexels(stats): void

Rewrite only the shadow-facing data (flags bit 2 + texels 4–5) of every packed record. Runs when shadow slots change on a frame where the main pack did not — a ≤ 32 KB re-upload, counted in stats.

Parameters

NameType
statsLocalLightStats

Returns

void


resetHysteresis

resetHysteresis(): void

A camera jump larger than the analytic radius means the previous selection belongs to somewhere else entirely; hysteresis must not drag it across the map.

Returns

void


sampleIrradiance

sampleIrradiance(point, out, options?): number

CPU mirror of the shader's light response, for entities and particles: accumulates the falloff-weighted color of every selected light in range of the point, with the same spot/capsule shaping, shader-matched flicker, and — when the caller supplies its local flood level — the same occlusion mask the world surfaces use, so an entity behind a wall stops tinting from the light the wall blocks. Mirrors the chunk shader's per-fragment structure exactly: only lights present in the point's grid cell contribute — color and claim alike — so a point outside the window or in an overflowed cell keeps its flood look on entities just as it does on blocks, and both the color and out.claim (the unoccluded luminance claim that drives the flood remainder) carry the same outer-two-cell window fade the shader applies, keeping the combined block light continuous across the rim. Zero allocation; the caller owns out and may reuse one options scratch object across calls (floodMask is the knee-mapped local flood level, 1 = fully open; timeMs drives the same flicker curve the shader evaluates).

Parameters

NameType
point[number, number, number]
outLocalLightSample
options?Object
options.floodMask?number
options.timeMs?number

Returns

number


setTierCaps

setTierCaps(caps): void

Parameters

NameType
capsObject
caps.analyticRadiusnumber
caps.blockLightOwnershipnumber
caps.fluidSpecularStrengthnumber
caps.maxClusteredLightsnumber
caps.maxLightsPerCellnumber

Returns

void


update

update(cameraX, cameraY, cameraZ, stats): void

Selection + binning + packing. Returns immediately when neither the registry nor the camera's grid cell moved since the last pass.

Parameters

NameType
cameraXnumber
cameraYnumber
cameraZnumber
statsLocalLightStats

Returns

void