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
|
uniform sampler2D u_ScreenDepthMap;
uniform sampler2D u_ShadowMap;
#if defined(USE_SHADOW_CASCADE)
uniform sampler2D u_ShadowMap2;
uniform sampler2D u_ShadowMap3;
#endif
uniform mat4 u_ShadowMvp;
#if defined(USE_SHADOW_CASCADE)
uniform mat4 u_ShadowMvp2;
uniform mat4 u_ShadowMvp3;
#endif
uniform vec3 u_ViewOrigin;
uniform vec4 u_ViewInfo; // zfar / znear, zfar
varying vec2 var_DepthTex;
varying vec3 var_ViewDir;
// depth is GL_DEPTH_COMPONENT24
// so the maximum error is 1.0 / 2^24
#define DEPTH_MAX_ERROR 0.000000059604644775390625
// Input: It uses texture coords as the random number seed.
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
// Author: Michael Pohoreski
// Copyright: Copyleft 2012 :-)
// Source: http://stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader
float random( const vec2 p )
{
// We need irrationals for pseudo randomness.
// Most (all?) known transcendental numbers will (generally) work.
const vec2 r = vec2(
23.1406926327792690, // e^pi (Gelfond's constant)
2.6651441426902251); // 2^sqrt(2) (Gelfond-Schneider constant)
//return fract( cos( mod( 123456789., 1e-7 + 256. * dot(p,r) ) ) );
return mod( 123456789., 1e-7 + 256. * dot(p,r) );
}
float PCF(const sampler2D shadowmap, const vec2 st, const float dist)
{
float mult;
float scale = 2.0 / r_shadowMapSize;
#if defined(USE_SHADOW_FILTER)
float r = random(var_DepthTex.xy);
float sinr = sin(r) * scale;
float cosr = cos(r) * scale;
mat2 rmat = mat2(cosr, sinr, -sinr, cosr);
mult = step(dist, texture2D(shadowmap, st + rmat * vec2(-0.7055767, 0.196515)).r);
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.3524343, -0.7791386)).r);
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.2391056, 0.9189604)).r);
#if defined(USE_SHADOW_FILTER2)
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.07580382, -0.09224417)).r);
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.5784913, -0.002528916)).r);
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.192888, 0.4064181)).r);
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.6335801, -0.5247476)).r);
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.5579782, 0.7491854)).r);
mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.7320465, 0.6317794)).r);
mult *= 0.11111;
#else
mult *= 0.33333;
#endif
#else
mult = step(dist, texture2D(shadowmap, st).r);
#endif
return mult;
}
float getLinearDepth(sampler2D depthMap, vec2 tex, float zFarDivZNear)
{
float sampleZDivW = texture2D(depthMap, tex).r;
sampleZDivW -= DEPTH_MAX_ERROR;
return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
}
void main()
{
float result;
float depth = getLinearDepth(u_ScreenDepthMap, var_DepthTex, u_ViewInfo.x);
float sampleZ = u_ViewInfo.y * depth;
vec4 biasPos = vec4(u_ViewOrigin + var_ViewDir * (depth - 0.5 / u_ViewInfo.x), 1.0);
vec4 shadowpos = u_ShadowMvp * biasPos;
#if defined(USE_SHADOW_CASCADE)
const float fadeTo = 1.0;
result = fadeTo;
#else
result = 0.0;
#endif
if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
{
shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
result = PCF(u_ShadowMap, shadowpos.xy, shadowpos.z);
}
#if defined(USE_SHADOW_CASCADE)
else
{
shadowpos = u_ShadowMvp2 * biasPos;
if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
{
shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
result = PCF(u_ShadowMap2, shadowpos.xy, shadowpos.z);
}
else
{
shadowpos = u_ShadowMvp3 * biasPos;
if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
{
shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
result = PCF(u_ShadowMap3, shadowpos.xy, shadowpos.z);
float fade = clamp(sampleZ / r_shadowCascadeZFar * 10.0 - 9.0, 0.0, 1.0);
result = mix(result, fadeTo, fade);
}
}
}
#endif
gl_FragColor = vec4(vec3(result), 1.0);
}
|