153 lines
5.6 KiB
C
153 lines
5.6 KiB
C
|
#ifndef SLB_SHADOW_OPTIMIZED_PCF_H
|
||
|
#define SLB_SHADOW_OPTIMIZED_PCF_H
|
||
|
|
||
|
/// Source https://github.com/TheRealMJP/Shadows/blob/master/Shadows/Mesh.hlsl
|
||
|
|
||
|
float SLB_Shadow_OptimizedPCF_Sample(in float2 base_uv, in float u, in float v, in float depth) {
|
||
|
float2 shadowMapSize = float2(int2(SMAP_size, SMAP_size));
|
||
|
float2 shadowMapSizeInv = 1.0 / shadowMapSize;
|
||
|
|
||
|
float2 uv = base_uv + float2(u, v) * shadowMapSizeInv;
|
||
|
|
||
|
const float compare_window = 0.0001;
|
||
|
{
|
||
|
float4 depths = SLB_Shadow_Gather(uv);
|
||
|
float4 notblockers = saturate((depths - depth + compare_window)/compare_window);
|
||
|
#ifdef SLB_GLSL
|
||
|
notblockers = depths;
|
||
|
#endif
|
||
|
|
||
|
float s1 = notblockers.x;
|
||
|
float s2 = notblockers.y;
|
||
|
float s3 = notblockers.z;
|
||
|
float s4 = notblockers.w;
|
||
|
|
||
|
float2 fract = frac(uv*float(SMAP_size)+0.5);
|
||
|
float notblocker = lerp(lerp(s4, s3, fract.x), lerp(s1, s2, fract.x), fract.y);
|
||
|
|
||
|
return notblocker;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float SLB_Shadow_OptimizedPCF(float4 tc) {
|
||
|
const int filter_size = 7;
|
||
|
|
||
|
float2 shadowMapSize = float2(int2(SMAP_size, SMAP_size));
|
||
|
float2 shadowMapSizeInv = 1.0 / shadowMapSize;
|
||
|
float2 shadowPos = tc.xy;
|
||
|
float lightDepth = tc.z;
|
||
|
|
||
|
float2 uv = shadowPos.xy * shadowMapSize; // 1 unit - 1 texel
|
||
|
|
||
|
float2 base_uv;
|
||
|
base_uv.x = floor(uv.x + 0.5);
|
||
|
base_uv.y = floor(uv.y + 0.5);
|
||
|
|
||
|
float s = (uv.x + 0.5 - base_uv.x);
|
||
|
float t = (uv.y + 0.5 - base_uv.y);
|
||
|
|
||
|
base_uv -= float2(0.5, 0.5);
|
||
|
base_uv *= shadowMapSizeInv;
|
||
|
|
||
|
float sum = 0;
|
||
|
|
||
|
if(filter_size == 2) {
|
||
|
return SLB_Shadow_SampleCmp(shadowPos.xy, lightDepth);
|
||
|
} else if(filter_size == 3) {
|
||
|
float uw0 = (3 - 2 * s);
|
||
|
float uw1 = (1 + 2 * s);
|
||
|
|
||
|
float u0 = (2 - s) / uw0 - 1;
|
||
|
float u1 = s / uw1 + 1;
|
||
|
|
||
|
float vw0 = (3 - 2 * t);
|
||
|
float vw1 = (1 + 2 * t);
|
||
|
|
||
|
float v0 = (2 - t) / vw0 - 1;
|
||
|
float v1 = t / vw1 + 1;
|
||
|
|
||
|
sum += uw0 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v0, lightDepth);
|
||
|
sum += uw1 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v0, lightDepth);
|
||
|
sum += uw0 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v1, lightDepth);
|
||
|
sum += uw1 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v1, lightDepth);
|
||
|
|
||
|
return sum * 1.0f / 16;
|
||
|
} else if(filter_size == 5) {
|
||
|
float uw0 = (4 - 3 * s);
|
||
|
float uw1 = 7;
|
||
|
float uw2 = (1 + 3 * s);
|
||
|
|
||
|
float u0 = (3 - 2 * s) / uw0 - 2;
|
||
|
float u1 = (3 + s) / uw1;
|
||
|
float u2 = s / uw2 + 2;
|
||
|
|
||
|
float vw0 = (4 - 3 * t);
|
||
|
float vw1 = 7;
|
||
|
float vw2 = (1 + 3 * t);
|
||
|
|
||
|
float v0 = (3 - 2 * t) / vw0 - 2;
|
||
|
float v1 = (3 + t) / vw1;
|
||
|
float v2 = t / vw2 + 2;
|
||
|
|
||
|
sum += uw0 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v0, lightDepth);
|
||
|
sum += uw1 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v0, lightDepth);
|
||
|
sum += uw2 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v0, lightDepth);
|
||
|
|
||
|
sum += uw0 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v1, lightDepth);
|
||
|
sum += uw1 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v1, lightDepth);
|
||
|
sum += uw2 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v1, lightDepth);
|
||
|
|
||
|
sum += uw0 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v2, lightDepth);
|
||
|
sum += uw1 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v2, lightDepth);
|
||
|
sum += uw2 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v2, lightDepth);
|
||
|
|
||
|
return sum * 1.0f / 144;
|
||
|
} else if(filter_size == 7) {
|
||
|
float uw0 = (5 * s - 6);
|
||
|
float uw1 = (11 * s - 28);
|
||
|
float uw2 = -(11 * s + 17);
|
||
|
float uw3 = -(5 * s + 1);
|
||
|
|
||
|
float u0 = (4 * s - 5) / uw0 - 3;
|
||
|
float u1 = (4 * s - 16) / uw1 - 1;
|
||
|
float u2 = -(7 * s + 5) / uw2 + 1;
|
||
|
float u3 = -s / uw3 + 3;
|
||
|
|
||
|
float vw0 = (5 * t - 6);
|
||
|
float vw1 = (11 * t - 28);
|
||
|
float vw2 = -(11 * t + 17);
|
||
|
float vw3 = -(5 * t + 1);
|
||
|
|
||
|
float v0 = (4 * t - 5) / vw0 - 3;
|
||
|
float v1 = (4 * t - 16) / vw1 - 1;
|
||
|
float v2 = -(7 * t + 5) / vw2 + 1;
|
||
|
float v3 = -t / vw3 + 3;
|
||
|
|
||
|
sum += uw0 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v0, lightDepth);
|
||
|
sum += uw1 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v0, lightDepth);
|
||
|
sum += uw2 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v0, lightDepth);
|
||
|
sum += uw3 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v0, lightDepth);
|
||
|
|
||
|
sum += uw0 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v1, lightDepth);
|
||
|
sum += uw1 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v1, lightDepth);
|
||
|
sum += uw2 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v1, lightDepth);
|
||
|
sum += uw3 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v1, lightDepth);
|
||
|
|
||
|
sum += uw0 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v2, lightDepth);
|
||
|
sum += uw1 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v2, lightDepth);
|
||
|
sum += uw2 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v2, lightDepth);
|
||
|
sum += uw3 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v2, lightDepth);
|
||
|
|
||
|
sum += uw0 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v3, lightDepth);
|
||
|
sum += uw1 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v3, lightDepth);
|
||
|
sum += uw2 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v3, lightDepth);
|
||
|
sum += uw3 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v3, lightDepth);
|
||
|
|
||
|
return sum * 1.0f / 2704;
|
||
|
} else {
|
||
|
return 1.0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif /// SLB_SHADOW_OPTIMIZED_PCF_H
|