PrivatetslPersistent TSL leaf nodes — single source of truth for the
shader's primitive/vec inputs. Kept across rebuildGraph() so
mutations stay live after a defines change.
Private Optional_Explicit depthTest / transparent overrides from the constructor
config. Every rebuildGraph() re-applies the factory tail's
MODE-DERIVED blending state (depthTest/transparent included), so an
override honored only once in the constructor tail would silently
revert on the first later rebuild (e.g. the guaranteed
placeholder→real updateSplatTexture rebuild at first commit). The
GLSL twin never rebuilds, so its constructor-tail overrides stick;
persisting them here and re-applying at the end of rebuildGraph
keeps the two backends contract-identical. An explicit later
applyBlendingMode() call CLEARS both (a runtime mode switch takes
full ownership of the blending state — matching the GLSL twin,
where applyBlendingStateToMaterial overwrites both fields
unconditionally).
Private Optional_PrivatebuildConstruct the IUniform-shaped getter/setter proxies over the
current tslNodes set. Called from the constructor and from any
setter that adds/removes a colormap node.
PrivaterebuildRe-run the TSL factory and attach nodes. Drives useColormap
from defines.USE_COLORMAP (mirrors GLSL behaviour; uniform
presence is not the source of truth — see PointTSLMaterial for
the in-depth note).
Blending state is applied by the factory tail: normal gets the
gsplat-specific getGSplatNormalBlendingState() (the fragment
emits a real premultiplied coverage alpha in that mode — see
shader-tsl.ts), every other mode gets the shared
getCompleteBlendingState(mode) — now the SAME sources of truth
the GLSL wrapper uses, so the two backends are state-identical.
AdditiveBlending's SrcAlpha factor is the identity under the
shader's alpha = 1.0 contract. No separate alpha-channel blend
state anywhere (it trips gl.getError() under WebGPURenderer's
WebGL2 bridge; its historical HalfFloat-overflow-guard purpose is
handled by the raw-scene-hdr capture sanitization).
(max mode goes through the same factory path and gets
CustomBlending + MaxEquation + OneFactor straight from
getCompleteBlendingState — that's what gsplat actually
needs for max projection.)
Update camera-dependent uniforms (viewport, projection kind, near cull).
Push again after a resize, a projection-kind flip, a near-cull change or a pixel-ratio change. An FOV or ortho-zoom change needs no push.
Viewport resolution in pixels
OptionalnearCull: number
Near-fade start distance in world units (consumed by all four geometry materials via the shared perspectiveNearFade)
Physical render-target pixels per CSS pixel; screen-space appearance constants scale with it above 1×
Current opacity multiplier (the LOD cross-fade snapshots this as its fade base).
Update the absorption coefficient κ (volumetric mode only — a plain uniform write, no rebuild; inert in every other mode).
Current absorption coefficient κ.
Declare whether the committed dataset's colors carry a per-splat alpha channel (RGBA). Plain uniform write — no graph rebuild (the volumetric branch gates the alpha → optical-depth mapping with a runtime mix on this uniform).
Private_Same toggle helper as GSplatMaterial._refreshNoGOGDefine — see there.
Rebind the splat data texture. TSL texture() captures the
THREE.Texture at factory time, so an identity change needs a
fresh node + graph rebuild (exact mirror of the colormap
texture lifecycle). No-op when the texture is unchanged — the
common per-commit case.
The currently bound splat data texture (mirrors getPointTexture/getLineTexture).
Apply a Luxar blending mode at runtime. Same source of truth as
the factory tail in rebuildGraph — normal via
getGSplatNormalBlendingState() (premultiplied coverage-alpha
output; see shader-tsl.ts), everything else via the shared
getCompleteBlendingState — so subsequent rebuilds (e.g. colormap
toggles) don't strand the material in a divergent state.
State-identical with the GLSL wrapper (both draw from the same
two helpers). max gets CustomBlending + MaxEquation + OneFactor
from getCompleteBlendingState; the gsplat-normal state is
bridge-safe (symmetric alpha channel; separate alpha-equation
state would trip gl.getError() under the WebGPU→WebGL2 bridge).
Also sets uProjectionMode — peak (1) for surface modes
(max/normal/opaque, usesPeakProjection), sum (0) for emissive
(additive/luminous/volumetric). In TSL the uniform is decorative (the graph
JS-branches on the mode); the crossing is what triggers
rebuildGraph() below.
Returns a new material with copied values from this instance.
A clone of this instance.
Bind a colormap LUT texture (or null to disable colormap mode).
When texture is non-null, the USE_COLORMAP define is added
and the uniforms (uColormapTex, uScalarMin, uScalarScale)
are allocated with neutral defaults if they don't exist yet.
When texture is null, the define is removed and the uniform
values are cleared so a subsequent clone() doesn't resurrect
a stale colormap.
No-op when called on a material whose shader path doesn't
include USE_COLORMAP-guarded uniforms.
Update the scalar range [min, max] the colormap maps over.
Encoded as uScalarMin = min and uScalarScale = 1/max(1e-10, max-min)
for the shader. No-op when colormap mode is not active (uniforms
are absent until setColormapTexture has been called once).
Public uniforms table, same shape as
GSplatMaterial.uniforms. Each entry is a getter/setter that forwards to the underlyingUniformNode.value(see module preamble +proxyIUniform).