aboutsummaryrefslogtreecommitdiff
path: root/engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM15.frag
blob: 0dc1ddfde4225192ed7d7ff63649609dcd5dc7e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Because gpu_shader5 is actually where those
// gather functions are declared to work on shadowmaps
#extension GL_ARB_gpu_shader5 : enable

#ifdef HARDWARE_SHADOWS
    #define SHADOWMAP sampler2DShadow
    #define SHADOWCOMPAREOFFSET(tex,coord,offset) textureProjOffset(tex, coord, offset)
    #define SHADOWCOMPARE(tex,coord) textureProj(tex, coord)
    #define SHADOWGATHER(tex,coord) textureGather(tex, coord.xy, coord.z)
#else
    #define SHADOWMAP sampler2D
    #define SHADOWCOMPAREOFFSET(tex,coord,offset) step(coord.z, textureProjOffset(tex, coord, offset).r)
    #define SHADOWCOMPARE(tex,coord) step(coord.z, textureProj(tex, coord).r)
    #define SHADOWGATHER(tex,coord) step(coord.z, textureGather(tex, coord.xy))
#endif


#if FILTER_MODE == 0
    #define GETSHADOW SHADOWCOMPARE
    #define KERNEL 1
#elif FILTER_MODE == 1
    #ifdef HARDWARE_SHADOWS
        #define GETSHADOW SHADOWCOMPARE
    #else
        #define GETSHADOW Shadow_DoBilinear_2x2
    #endif
    #define KERNEL 1
#elif FILTER_MODE == 2
    #define GETSHADOW Shadow_DoDither_2x2
    #define KERNEL 1
#elif FILTER_MODE == 3
    #define GETSHADOW Shadow_DoPCF
    #define KERNEL 4
#elif FILTER_MODE == 4
    #define GETSHADOW Shadow_DoPCF
    #define KERNEL 8
#endif

out vec4 outFragColor;

uniform SHADOWMAP m_ShadowMap0;
uniform SHADOWMAP m_ShadowMap1;
uniform SHADOWMAP m_ShadowMap2;
uniform SHADOWMAP m_ShadowMap3;

uniform vec4 m_Splits;
uniform float m_ShadowIntensity;

in vec4 projCoord0;
in vec4 projCoord1;
in vec4 projCoord2;
in vec4 projCoord3;
in float shadowPosition;

float Shadow_BorderCheck(in vec2 coord){
    // Fastest, "hack" method (uses 4-5 instructions)
    vec4 t = vec4(coord.xy, 0.0, 1.0);
    t = step(t.wwxy, t.xyzz);
    return dot(t,t);
}

float Shadow_DoDither_2x2(in SHADOWMAP tex, in vec4 projCoord){
    float border = Shadow_BorderCheck(projCoord.xy);
    if (border > 0.0)
        return 1.0;

    ivec2 texSize = textureSize(tex, 0);
    vec2 pixSize = 1.0 / vec2(texSize);

    float shadow = 0.0;
    ivec2 o = ivec2(mod(floor(gl_FragCoord.xy), 2.0));
    shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2(-1.5, 1.5)+o), projCoord.zw));
    shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2( 0.5, 1.5)+o), projCoord.zw));
    shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2(-1.5, -0.5)+o), projCoord.zw));
    shadow += SHADOWCOMPARE(tex, vec4(projCoord.xy+pixSize*(vec2( 0.5, -0.5)+o), projCoord.zw));
    shadow *= 0.25;
    return shadow;
}

float Shadow_DoBilinear_2x2(in SHADOWMAP tex, in vec4 projCoord){
    float border = Shadow_BorderCheck(projCoord.xy);
    if (border > 0.0)
        return 1.0;

    ivec2 texSize = textureSize(tex, 0);
    #ifdef GL_ARB_gpu_shader5
        vec4 coord = vec4(projCoord.xyz / projCoord.www,0.0);
        vec4 gather = SHADOWGATHER(tex, coord);
    #else
        vec4 gather = vec4(0.0);
        gather.x = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(0, 0));
        gather.y = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(1, 0));
        gather.z = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(0, 1));
        gather.w = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(1, 1));
   #endif

   vec2 f = fract( projCoord.xy * texSize );
   vec2 mx = mix( gather.xz, gather.yw, f.x );
   return mix( mx.x, mx.y, f.y );
}

float Shadow_DoPCF(in SHADOWMAP tex, in vec4 projCoord){
    float pixSize = 1.0 / textureSize(tex,0).x;

    float shadow = 0.0;
    float border = Shadow_BorderCheck(projCoord.xy);
    if (border > 0.0)
        return 1.0;

    float bound = KERNEL * 0.5 - 0.5;
    bound *= PCFEDGE;
    for (float y = -bound; y <= bound; y += PCFEDGE){
        for (float x = -bound; x <= bound; x += PCFEDGE){
            vec4 coord = vec4(projCoord.xy + vec2(x,y) * pixSize, projCoord.zw);
            shadow += SHADOWCOMPARE(tex, coord);
        }
    }

    shadow = shadow / (KERNEL * KERNEL);
    return shadow;
}

void main(){
    float shadow = 0.0;

    if(shadowPosition < m_Splits.x){
        shadow = GETSHADOW(m_ShadowMap0, projCoord0);
    }else if( shadowPosition <  m_Splits.y){
        shadow = GETSHADOW(m_ShadowMap1, projCoord1);
    }else if( shadowPosition <  m_Splits.z){
        shadow = GETSHADOW(m_ShadowMap2, projCoord2);
    }else if( shadowPosition <  m_Splits.w){
        shadow = GETSHADOW(m_ShadowMap3, projCoord3);
    }
    
    shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);
    outFragColor = vec4(shadow, shadow, shadow, 1.0);
}