1#ifdef HARDWARE_SHADOWS
2    #define SHADOWMAP sampler2DShadow
3    #define SHADOWCOMPARE(tex,coord) shadow2DProj(tex, coord).r
4#else
5    #define SHADOWMAP sampler2D
6    #define SHADOWCOMPARE(tex,coord) step(coord.z, texture2DProj(tex, coord).r)
7#endif
8
9#if FILTER_MODE == 0
10    #define GETSHADOW Shadow_DoShadowCompare
11    #define KERNEL 1.0
12#elif FILTER_MODE == 1
13    #ifdef HARDWARE_SHADOWS
14        #define GETSHADOW Shadow_DoShadowCompare
15    #else
16        #define GETSHADOW Shadow_DoBilinear_2x2
17    #endif
18    #define KERNEL 1.0
19#elif FILTER_MODE == 2
20    #define GETSHADOW Shadow_DoDither_2x2
21    #define KERNEL 1.0
22#elif FILTER_MODE == 3
23    #define GETSHADOW Shadow_DoPCF
24    #define KERNEL 4.0
25#elif FILTER_MODE == 4
26    #define GETSHADOW Shadow_DoPCF
27    #define KERNEL 8.0
28#endif
29
30uniform SHADOWMAP m_ShadowMap0;
31uniform SHADOWMAP m_ShadowMap1;
32uniform SHADOWMAP m_ShadowMap2;
33uniform SHADOWMAP m_ShadowMap3;
34
35uniform vec4 m_Splits;
36
37uniform float m_ShadowIntensity;
38
39varying vec4 projCoord0;
40varying vec4 projCoord1;
41varying vec4 projCoord2;
42varying vec4 projCoord3;
43
44varying float shadowPosition;
45
46const float texSize = 1024.0;
47const float pixSize = 1.0 / texSize;
48const vec2 pixSize2 = vec2(pixSize);
49
50float Shadow_DoShadowCompareOffset(in SHADOWMAP tex, in vec4 projCoord, in vec2 offset){
51    vec4 coord = vec4(projCoord.xy + offset.xy * pixSize2, projCoord.zw);
52    return SHADOWCOMPARE(tex, coord);
53}
54
55float Shadow_DoShadowCompare(in SHADOWMAP tex, vec4 projCoord){
56    return SHADOWCOMPARE(tex, projCoord);
57}
58
59float Shadow_BorderCheck(in vec2 coord){
60    // Fastest, "hack" method (uses 4-5 instructions)
61    vec4 t = vec4(coord.xy, 0.0, 1.0);
62    t = step(t.wwxy, t.xyzz);
63    return dot(t,t);
64}
65
66float Shadow_DoDither_2x2(in SHADOWMAP tex, in vec4 projCoord){
67    float shadow = 0.0;
68    vec2 o = mod(floor(gl_FragCoord.xy), 2.0);
69    shadow += Shadow_DoShadowCompareOffset(tex,projCoord,vec2(-1.5,  1.5) + o);
70    shadow += Shadow_DoShadowCompareOffset(tex,projCoord,vec2( 0.5,  1.5) + o);
71    shadow += Shadow_DoShadowCompareOffset(tex,projCoord,vec2(-1.5, -0.5) + o);
72    shadow += Shadow_DoShadowCompareOffset(tex,projCoord,vec2( 0.5, -0.5) + o);
73    shadow *= 0.25 ;
74    return shadow;
75}
76
77float Shadow_DoBilinear_2x2(in SHADOWMAP tex, in vec4 projCoord){
78    vec4 gather = vec4(0.0);
79    gather.x = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(0.0, 0.0));
80    gather.y = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(1.0, 0.0));
81    gather.z = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(0.0, 1.0));
82    gather.w = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(1.0, 1.0));
83
84    vec2 f = fract( projCoord.xy * texSize );
85    vec2 mx = mix( gather.xz, gather.yw, f.x );
86    return mix( mx.x, mx.y, f.y );
87}
88
89float Shadow_DoPCF(in SHADOWMAP tex, in vec4 projCoord){
90    float shadow = 0.0;
91    float bound = KERNEL * 0.5 - 0.5;
92    bound *= PCFEDGE;
93    for (float y = -bound; y <= bound; y += PCFEDGE){
94        for (float x = -bound; x <= bound; x += PCFEDGE){
95            shadow += clamp(Shadow_DoShadowCompareOffset(tex,projCoord,vec2(x,y)) +
96                            Shadow_BorderCheck(projCoord.xy),
97                            0.0, 1.0);
98        }
99    }
100
101    shadow = shadow / (KERNEL * KERNEL);
102    return shadow;
103}
104
105void main(){
106    vec4 shadowPerSplit = vec4(0.0);
107    shadowPerSplit.x = GETSHADOW(m_ShadowMap0, projCoord0);
108    shadowPerSplit.y = GETSHADOW(m_ShadowMap1, projCoord1);
109    shadowPerSplit.z = GETSHADOW(m_ShadowMap2, projCoord2);
110    shadowPerSplit.w = GETSHADOW(m_ShadowMap3, projCoord3);
111
112    vec4 less = step( shadowPosition, m_Splits );
113    vec4 more = vec4(1.0) - step( shadowPosition, vec4(0.0, m_Splits.xyz) );
114    float shadow = dot(shadowPerSplit, less * more );
115    
116    shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);
117    gl_FragColor = vec4(shadow, shadow, shadow, 1.0);
118}
119
120