Shadow Receiver Glsl
Reusable GLSL fragments concatenated into every shadow receiver's fragment shader.
Receiver vertex shader must emit:
varying vec3 worldPos— camera-relative world position (worldVertex - cameraPoint), computed from uniforms the drawable composed against the camera point in double precision on the CPU. A raw ECEF position quantizes to ~0.5 m in a float32 varying — enough to erase street-scale shadow structure entirely.varying float viewDepth— positive distance to the camera plane (gl_Position.w)
Receiver contract - one lighting model engine-wide (see earth.worldwind.render.program.LightingGlsl): shadows attenuate only the direct sun term, never the ambient term, so material Lambert and the cascade term can't double-darken the same fragment.
Lit receivers call
shadowLitFactor(lambert, worldPos, viewDepth, worldNormal)- the whole lighting multiplier with the sun term shadow-attenuated. Emitted when fragmentDeclarations is built withlit = true; requiresLightingGlsl.DECLARATIONSearlier in the shader. A zero normal degrades to depth-only sampling.Unlit receivers (terrain imagery, photogrammetry, points) call
shadowAlbedoFactor(worldPos, viewDepth)- the shadow term is their only sun shading, so it darkens the whole albedo towardambientShadow.shadowSunVisibilityoverloads expose the raw[0, 1]visibility; the normal-aware overload adds a normal-offset receiver bias scaled by the active cascade's texel world size. All short-circuit to 1.0 whenapplyShadowis false.
Occlusion resolve is a single hardware depth-compare tap by default (its free 2x2 bilinear PCF softens the edge by one texel), or a bilinear-weighted 3x3 nine-tap kernel when DrawContext.SOFT_SHADOWS is set. Stable under camera motion thanks to the cascade texel snapping.
Properties
Number of cascades the shader code is unrolled for. Matches ShadowState.DEFAULT_CASCADE_COUNT.
Receiver-side constant depth bias for opaque primitives (shapes, 3D-Tile meshes, models), in world metres — normalized per cascade on the CPU (metres / depth range) so a caster-inflated depth window can't balloon the bias and detach contact shadows. Small because the caster pass already applies slope-scaled polygon offset.
Switches the occlusion resolves (cascades AND the sightline cube) to hardware depth-compare samplers (sampler2DShadow / samplerCubeShadow).
Toggled by each receiver program's shadowsEnabled flag.
Receiver-side constant depth bias for terrain-draped receivers, in world metres — larger than the primitive bias because terrain triangles are big and often nearly light-parallel.
Functions
Builds the fragment-shader declaration block. lit additionally emits shadowLitFactor for receivers with a lighting model (requires LightingGlsl.DECLARATIONS above this block).
#version + define prefix for receiver programs. Shadow-capable variants compile as modern GLSL with hardware depth-compare samplers where the platform supports them (earth.worldwind.util.kgl.Kgl.hasShadowSamplers) - which also makes GLES3 depth-texture reads spec-defined; everything else keeps the platform's legacy default.