Clamp the wrapped-diffuse exponent to a safe range, supplying the default when
undefined.
The same class of hazard clampGamma exists for, and the same 0.001 bound. The
shade term computes pow(wrap, exponent) where wrap = saturate(N·L · 0.5 + 0.5),
and wrap is exactly 0 for any fragment whose normal faces directly away from
the key light (N·L == -1, which remains reachable for valid surface normals).
GLSL leaves pow(0, y)
undefined for y <= 0, so an author setting shadeExponent = 0 — a perfectly
plausible "I want no gradient" value — produces driver-dependent output (1, 0 or
NaN) for those face-away fragments.
Clamping keeps that fragment DEFINED and sensible: at exponent = 0.001,
pow(0, 0.001) is 0, so a face-away fragment shades at ambient — which is what
the ambient floor means. The honest way to ask for no gradient at all is
ambient = 1, which collapses the mix and is documented as such.
Lives here rather than in _shared/uniform-helpers.ts because that module states
its own scope as helpers "that already appear in every material constructor", and
mesh is the only shaded type.
Clamp the wrapped-diffuse exponent to a safe range, supplying the default when undefined.
The same class of hazard
clampGammaexists for, and the same0.001bound. The shade term computespow(wrap, exponent)wherewrap = saturate(N·L · 0.5 + 0.5), andwrapis exactly 0 for any fragment whose normal faces directly away from the key light (N·L == -1, which remains reachable for valid surface normals). GLSL leavespow(0, y)undefined fory <= 0, so an author settingshadeExponent = 0— a perfectly plausible "I want no gradient" value — produces driver-dependent output (1, 0 or NaN) for those face-away fragments.Clamping keeps that fragment DEFINED and sensible: at
exponent = 0.001,pow(0, 0.001)is 0, so a face-away fragment shades atambient— which is what the ambient floor means. The honest way to ask for no gradient at all isambient = 1, which collapses themixand is documented as such.Lives here rather than in
_shared/uniform-helpers.tsbecause that module states its own scope as helpers "that already appear in every material constructor", and mesh is the only shaded type.