<@if not SHADOW_CORE_SLH@> <@def SHADOW_CORE_SLH@> <@include Shadows_shared.slh@> LAYOUT_STD140(binding=RENDER_UTILS_BUFFER_SHADOW_PARAMS) uniform shadowTransformBuffer { ShadowParameters shadow; }; int getShadowCascadeCount() { return shadow.cascadeCount; } float getShadowCascadeInvBlendWidth() { return shadow.invCascadeBlendWidth; } float evalShadowFalloff(float depth) { return clamp((shadow.maxDistance-depth) * shadow.invFalloffDistance, 0.0, 1.0); } mat4 getShadowReprojection(int cascadeIndex) { return shadow.cascades[cascadeIndex].reprojection; } float getShadowScale() { return shadow.invMapSize; } float getShadowFixedBias(int cascadeIndex) { return shadow.cascades[cascadeIndex].fixedBias; } float getShadowSlopeBias(int cascadeIndex) { return shadow.cascades[cascadeIndex].slopeBias; } // Compute the texture coordinates from world coordinates vec4 evalShadowTexcoord(int cascadeIndex, vec4 position) { vec4 shadowCoord = getShadowReprojection(cascadeIndex) * position; return vec4(shadowCoord.xyz, 1.0); } bool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) { bvec2 greaterThanZero = greaterThan(cascadeTexCoords.xy, vec2(0)); bvec2 lessThanOne = lessThan(cascadeTexCoords.xy, vec2(1)); return all(greaterThanZero) && all(lessThanOne); } int getFirstShadowCascadeOnPixel(int startCascadeIndex, vec4 worldPosition, out vec4 cascadeShadowCoords) { int cascadeIndex; startCascadeIndex = min(startCascadeIndex, getShadowCascadeCount()-1); for (cascadeIndex=startCascadeIndex ; cascadeIndex