Welcome to mirror list, hosted at ThFree Co, Russian Federation.

shadow_copy_frag.glsl « shaders « eevee « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 67b0fc2bdfcf28b3c6875e4b2b037eb1ee062f8a (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* Copy the depth only shadowmap into another texture while converting
 * to linear depth (or other storage method) and doing a 3x3 box filter. */

layout(std140) uniform shadow_render_block {
	mat4 ShadowMatrix[6];
	mat4 FaceViewMatrix[6];
	vec4 lampPosition;
	float cubeTexelSize;
	float storedTexelSize;
	float nearClip;
	float farClip;
	int shadowSampleCount;
	float shadowInvSampleCount;
};

#ifdef CSM
uniform sampler2DArray shadowTexture;
uniform int cascadeId;
#else
uniform samplerCube shadowTexture;
uniform int faceId;
#endif
uniform float shadowFilterSize;

out vec4 FragColor;

float linear_depth(float z)
{
	return (nearClip  * farClip) / (z * (nearClip - farClip) + farClip);
}

vec4 linear_depth(vec4 z)
{
	return (nearClip  * farClip) / (z * (nearClip - farClip) + farClip);
}

#ifdef CSM
vec4 get_world_distance(vec4 depths, vec3 cos[4])
{
	/* Background case */
	vec4 is_background = step(vec4(0.99999), depths);
	depths *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */
	depths += 1e1 * is_background;
	return depths;
}

float get_world_distance(float depth, vec3 cos)
{
	/* Background case */
	float is_background = step(0.9999, depth);
	depth *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */
	depth += 1e1 * is_background;
	return depth;
}
#else /* CUBEMAP */
vec4 get_world_distance(vec4 depths, vec3 cos[4])
{
	vec4 is_background = step(vec4(1.0), depths);
	depths = linear_depth(depths);
	depths += vec4(1e1) * is_background;
	cos[0] = normalize(abs(cos[0]));
	cos[1] = normalize(abs(cos[1]));
	cos[2] = normalize(abs(cos[2]));
	cos[3] = normalize(abs(cos[3]));
	vec4 cos_vec;
	cos_vec.x = max(cos[0].x, max(cos[0].y, cos[0].z));
	cos_vec.y = max(cos[1].x, max(cos[1].y, cos[1].z));
	cos_vec.z = max(cos[2].x, max(cos[2].y, cos[2].z));
	cos_vec.w = max(cos[3].x, max(cos[3].y, cos[3].z));
	return depths / cos_vec;
}

float get_world_distance(float depth, vec3 cos)
{
	float is_background = step(1.0, depth);
	depth = linear_depth(depth);
	depth += 1e1 * is_background;
	cos = normalize(abs(cos));
	float cos_vec = max(cos.x, max(cos.y, cos.z));
	return depth / cos_vec;
}
#endif

/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */
float ln_space_prefilter(float w0, float x, float w1, float y)
{
    return x + log(w0 + w1 * exp(y - x));
}

#define SAMPLE_WEIGHT 0.11111

#ifdef ESM
void prefilter(vec4 depths, inout float accum)
{
	accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.x);
	accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.y);
	accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.z);
	accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.w);
}
#else /* VSM */
void prefilter(vec4 depths, inout vec2 accum)
{
	vec4 depths_sqr = depths * depths;
	accum += vec2(dot(vec4(1.0), depths), dot(vec4(1.0), depths_sqr)) * SAMPLE_WEIGHT;
}
#endif

#ifdef CSM
vec3 get_texco(vec2 uvs, vec2 ofs)
{
	return vec3(uvs + ofs, float(cascadeId));
}
#else /* CUBEMAP */
const vec3 minorAxisX[6] = vec3[6](
	vec3(0.0f, 0.0f, -1.0f),
	vec3(0.0f, 0.0f, 1.0f),
	vec3(1.0f, 0.0f, 0.0f),
	vec3(1.0f, 0.0f, 0.0f),
	vec3(1.0f, 0.0f, 0.0f),
	vec3(-1.0f, 0.0f, 0.0f)
);

const vec3 minorAxisY[6] = vec3[6](
	vec3(0.0f, -1.0f, 0.0f),
	vec3(0.0f, -1.0f, 0.0f),
	vec3(0.0f, 0.0f, 1.0f),
	vec3(0.0f, 0.0f, -1.0f),
	vec3(0.0f, -1.0f, 0.0f),
	vec3(0.0f, -1.0f, 0.0f)
);

const vec3 majorAxis[6] = vec3[6](
	vec3(1.0f, 0.0f, 0.0f),
	vec3(-1.0f, 0.0f, 0.0f),
	vec3(0.0f, 1.0f, 0.0f),
	vec3(0.0f, -1.0f, 0.0f),
	vec3(0.0f, 0.0f, 1.0f),
	vec3(0.0f, 0.0f, -1.0f)
);

vec3 get_texco(vec2 uvs, vec2 ofs)
{
	uvs += ofs;
	return majorAxis[faceId] + uvs.x * minorAxisX[faceId] + uvs.y * minorAxisY[faceId];
}
#endif

void main() {
	/* Copy the depth only shadowmap into another texture while converting
	 * to linear depth and do a 3x3 box blur. */

#ifdef CSM
	vec2 uvs = gl_FragCoord.xy * storedTexelSize;
#else /* CUBEMAP */
	vec2 uvs = gl_FragCoord.xy * cubeTexelSize * 2.0 - 1.0;
#endif

	/* Center texel */
	vec3 co = get_texco(uvs, vec2(0.0));
	float depth = texture(shadowTexture, co).r;
	depth = get_world_distance(depth, co);

	if (shadowFilterSize == 0.0) {
#ifdef ESM
		FragColor = vec4(depth);
#else /* VSM */
		FragColor = vec2(depth, depth * depth).xyxy;
#endif
		return;
	}

#ifdef ESM
	float accum = ln_space_prefilter(0.0, 0.0, SAMPLE_WEIGHT, depth);
#else /* VSM */
	vec2 accum = vec2(depth, depth * depth) * SAMPLE_WEIGHT;
#endif

#ifdef CSM
	vec3 ofs = vec3(1.0, 0.0, -1.0) * shadowFilterSize;
#else /* CUBEMAP */
	vec3 ofs = vec3(1.0, 0.0, -1.0) * shadowFilterSize;
#endif

	vec3 cos[4];
	cos[0] = get_texco(uvs, ofs.zz);
	cos[1] = get_texco(uvs, ofs.yz);
	cos[2] = get_texco(uvs, ofs.xz);
	cos[3] = get_texco(uvs, ofs.zy);

	vec4 depths;
	depths.x = texture(shadowTexture, cos[0]).r;
	depths.y = texture(shadowTexture, cos[1]).r;
	depths.z = texture(shadowTexture, cos[2]).r;
	depths.w = texture(shadowTexture, cos[3]).r;
	depths = get_world_distance(depths, cos);
	prefilter(depths, accum);

	cos[0] = get_texco(uvs, ofs.xy);
	cos[1] = get_texco(uvs, ofs.zx);
	cos[2] = get_texco(uvs, ofs.yx);
	cos[3] = get_texco(uvs, ofs.xx);
	depths.x = texture(shadowTexture, cos[0]).r;
	depths.y = texture(shadowTexture, cos[1]).r;
	depths.z = texture(shadowTexture, cos[2]).r;
	depths.w = texture(shadowTexture, cos[3]).r;
	depths = get_world_distance(depths, cos);
	prefilter(depths, accum);

	FragColor = vec2(accum).xyxy;
}