Home | History | Annotate | Download | only in Shadow
      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 
     39 out vec4 outFragColor;
     40 
     41 uniform SHADOWMAP m_ShadowMap0;
     42 uniform SHADOWMAP m_ShadowMap1;
     43 uniform SHADOWMAP m_ShadowMap2;
     44 uniform SHADOWMAP m_ShadowMap3;
     45 
     46 uniform vec4 m_Splits;
     47 uniform float m_ShadowIntensity;
     48 
     49 in vec4 projCoord0;
     50 in vec4 projCoord1;
     51 in vec4 projCoord2;
     52 in vec4 projCoord3;
     53 in float shadowPosition;
     54 
     55 float 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 
     62 float 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 
     80 float 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 
    102 float 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 
    123 void 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