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