1// Because gpu_shader5 is actually where those 2// gather functions are declared to work on shadowmaps 3#extension GL_ARB_gpu_shader5 : enable 4 5#ifdef HARDWARE_SHADOWS 6 #define SHADOWMAP sampler2DShadow 7 #define SHADOWCOMPAREOFFSET(tex,coord,offset) textureProjOffset(tex, coord, offset) 8 #define SHADOWCOMPARE(tex,coord) textureProj(tex, coord) 9 #define SHADOWGATHER(tex,coord) textureGather(tex, coord.xy, coord.z) 10#else 11 #define SHADOWMAP sampler2D 12 #define SHADOWCOMPAREOFFSET(tex,coord,offset) step(coord.z, textureProjOffset(tex, coord, offset).r) 13 #define SHADOWCOMPARE(tex,coord) step(coord.z, textureProj(tex, coord).r) 14 #define SHADOWGATHER(tex,coord) step(coord.z, textureGather(tex, coord.xy)) 15#endif 16 17 18#if FILTER_MODE == 0 19 #define GETSHADOW SHADOWCOMPARE 20 #define KERNEL 1 21#elif FILTER_MODE == 1 22 #ifdef HARDWARE_SHADOWS 23 #define GETSHADOW SHADOWCOMPARE 24 #else 25 #define GETSHADOW Shadow_DoBilinear_2x2 26 #endif 27 #define KERNEL 1 28#elif FILTER_MODE == 2 29 #define GETSHADOW Shadow_DoDither_2x2 30 #define KERNEL 1 31#elif FILTER_MODE == 3 32 #define GETSHADOW Shadow_DoPCF 33 #define KERNEL 4 34#elif FILTER_MODE == 4 35 #define GETSHADOW Shadow_DoPCF 36 #define KERNEL 8 37#endif 38 39out vec4 outFragColor; 40 41uniform SHADOWMAP m_ShadowMap0; 42uniform SHADOWMAP m_ShadowMap1; 43uniform SHADOWMAP m_ShadowMap2; 44uniform SHADOWMAP m_ShadowMap3; 45 46uniform vec4 m_Splits; 47uniform float m_ShadowIntensity; 48 49in vec4 projCoord0; 50in vec4 projCoord1; 51in vec4 projCoord2; 52in vec4 projCoord3; 53in float shadowPosition; 54 55float Shadow_BorderCheck(in vec2 coord){ 56 // Fastest, "hack" method (uses 4-5 instructions) 57 vec4 t = vec4(coord.xy, 0.0, 1.0); 58 t = step(t.wwxy, t.xyzz); 59 return dot(t,t); 60} 61 62float Shadow_DoDither_2x2(in SHADOWMAP tex, in vec4 projCoord){ 63 float border = Shadow_BorderCheck(projCoord.xy); 64 if (border > 0.0) 65 return 1.0; 66 67 ivec2 texSize = textureSize(tex, 0); 68 vec2 pixSize = 1.0 / vec2(texSize); 69 70 float shadow = 0.0; 71 ivec2 o = ivec2(mod(floor(gl_FragCoord.xy), 2.0)); 72 shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2(-1.5, 1.5)+o), projCoord.zw)); 73 shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2( 0.5, 1.5)+o), projCoord.zw)); 74 shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2(-1.5, -0.5)+o), projCoord.zw)); 75 shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2( 0.5, -0.5)+o), projCoord.zw)); 76 shadow *= 0.25; 77 return shadow; 78} 79 80float Shadow_DoBilinear_2x2(in SHADOWMAP tex, in vec4 projCoord){ 81 float border = Shadow_BorderCheck(projCoord.xy); 82 if (border > 0.0) 83 return 1.0; 84 85 ivec2 texSize = textureSize(tex, 0); 86 #ifdef GL_ARB_gpu_shader5 87 vec4 coord = vec4(projCoord.xyz / projCoord.www,0.0); 88 vec4 gather = SHADOWGATHER(tex, coord); 89 #else 90 vec4 gather = vec4(0.0); 91 gather.x = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(0, 0)); 92 gather.y = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(1, 0)); 93 gather.z = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(0, 1)); 94 gather.w = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(1, 1)); 95 #endif 96 97 vec2 f = fract( projCoord.xy * texSize ); 98 vec2 mx = mix( gather.xz, gather.yw, f.x ); 99 return mix( mx.x, mx.y, f.y ); 100} 101 102float Shadow_DoPCF(in SHADOWMAP tex, in vec4 projCoord){ 103 float pixSize = 1.0 / textureSize(tex,0).x; 104 105 float shadow = 0.0; 106 float border = Shadow_BorderCheck(projCoord.xy); 107 if (border > 0.0) 108 return 1.0; 109 110 float bound = KERNEL * 0.5 - 0.5; 111 bound *= PCFEDGE; 112 for (float y = -bound; y <= bound; y += PCFEDGE){ 113 for (float x = -bound; x <= bound; x += PCFEDGE){ 114 vec4 coord = vec4(projCoord.xy + vec2(x,y) * pixSize, projCoord.zw); 115 shadow += SHADOWCOMPARE(tex, coord); 116 } 117 } 118 119 shadow = shadow / (KERNEL * KERNEL); 120 return shadow; 121} 122 123void main(){ 124 float shadow = 0.0; 125 126 if(shadowPosition < m_Splits.x){ 127 shadow = GETSHADOW(m_ShadowMap0, projCoord0); 128 }else if( shadowPosition < m_Splits.y){ 129 shadow = GETSHADOW(m_ShadowMap1, projCoord1); 130 }else if( shadowPosition < m_Splits.z){ 131 shadow = GETSHADOW(m_ShadowMap2, projCoord2); 132 }else if( shadowPosition < m_Splits.w){ 133 shadow = GETSHADOW(m_ShadowMap3, projCoord3); 134 } 135 136 shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity); 137 outFragColor = vec4(shadow, shadow, shadow, 1.0); 138} 139 140