<@if not SHADOW_SLH@> <@def SHADOW_SLH@> // the shadow texture uniform sampler2DShadow shadowMap; struct EyePlanes { vec4 _S[1]; vec4 _T[1]; vec4 _R[1]; vec4 _Q[1]; }; uniform eyePlanes { EyePlanes _eyePlanes; }; EyePlanes getEyePlanes() { return _eyePlanes; } // Fetching it float fetchShadow(vec3 texcoord) { return texture(shadowMap, texcoord); } // the distances to the cascade sections uniform vec3 shadowDistances; // the inverse of the size of the shadow map uniform float shadowScale; uniform mat4 shadowMatrices[4]; vec2 samples[8] = vec2[8]( vec2(-2.0, -2.0), vec2(2.0, -2.0), vec2(2.0, 2.0), vec2(-2.0, 2.0), vec2(1.0, 0.0), vec2(0.0, 1.0), vec2(-1.0, 0.0), vec2(0.0, -1.0) ); vec4 evalShadowTexcoord(vec4 position) { // compute the corresponding texture coordinates EyePlanes eyePlanes = getEyePlanes(); vec3 shadowTexcoord = vec3(dot(eyePlanes._S[0], position), dot(eyePlanes._T[0], position), dot(eyePlanes._R[0], position)); return vec4(shadowTexcoord, 0.0); } vec4 evalCascadedShadowTexcoord(vec4 position) { EyePlanes eyePlanes = getEyePlanes(); // compute the index of the cascade to use and the corresponding texture coordinates int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); vec3 shadowTexcoord = vec3( dot(eyePlanes._S[shadowIndex], position), dot(eyePlanes._T[shadowIndex], position), dot(eyePlanes._R[shadowIndex], position)); return vec4(shadowTexcoord, shadowIndex); } float evalShadowAttenuationPCF(vec4 shadowTexcoord) { float radiusScale = (shadowTexcoord.w + 1.0); float shadowAttenuation = (0.25 * ( fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) )); if ((shadowAttenuation > 0) && (shadowAttenuation < 1.0)) { radiusScale *= 0.5; shadowAttenuation = 0.5 * shadowAttenuation + (0.125 * ( fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[4], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[5], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[6], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[7], 0.0)) )); } return shadowAttenuation; } float evalShadowAttenuationBasic(vec4 shadowTexcoord) { float radiusScale = 0.5; float shadowAttenuation = (0.25 * ( fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) )); return shadowAttenuation; } float evalShadowAttenuation(vec4 shadowTexcoord) { return evalShadowAttenuationBasic(shadowTexcoord); } <@endif@>