<@if not SHADOW_SLH@> <@def SHADOW_SLH@> // the shadow texture uniform sampler2DShadow shadowMap; // Fetching it float fetchShadow(vec3 texcoord) { <@if GPU_FEATURE_PROFILE == GPU_CORE @> return texture(shadowMap, texcoord); <@else@> return shadow2D(shadowMap, texcoord).r; <@endif@> } // 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 vec3 shadowTexcoord = vec3(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position)); return vec4(shadowTexcoord, 0.0); } vec4 evalCascadedShadowTexcoord(vec4 position) { // 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(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), dot(gl_EyePlaneR[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); } vec3 debugShadowMap(float shadowAttenuation, vec4 shadowTexcoord) { vec3 colorArray[4]; colorArray[0].xyz = vec3(1.0, 1.0, 1.0); colorArray[1].xyz = vec3(1.0, 0.0, 0.0); colorArray[2].xyz = vec3(0.0, 1.0, 0.0); colorArray[3].xyz = vec3(0.0, 0.0, 1.0); vec2 offsetArray[4]; offsetArray[0] = vec2(0.0, 0.0); offsetArray[1] = vec2(0.5, 0.0); offsetArray[2] = vec2(0.0, 0.5); offsetArray[3] = vec2(0.5, 0.5); return shadowAttenuation * colorArray[int(shadowTexcoord.w)]; // return shadowAttenuation * vec3(2.0*(shadowTexcoord.xy - offsetArray[int(shadowTexcoord.w)]), 0); } <@endif@>