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
|
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#define CRYPTOMATTE_LEVELS_MAX 16
void cryptomatte_load_samples(ivec2 texel, int layer, out vec2 samples[CRYPTOMATTE_LEVELS_MAX])
{
int pass_len = divide_ceil(cryptomatte_samples_per_layer, 2);
int layer_id = layer * pass_len;
/* Read all samples from the cryptomatte layer. */
for (int p = 0; p < pass_len; p++) {
vec4 pass_sample = imageLoad(cryptomatte_img, ivec3(texel, p + layer_id));
samples[p * 2] = pass_sample.xy;
samples[p * 2 + 1] = pass_sample.zw;
}
for (int i = pass_len * 2; i < CRYPTOMATTE_LEVELS_MAX; i++) {
samples[i] = vec2(0.0);
}
}
void cryptomatte_sort_samples(inout vec2 samples[CRYPTOMATTE_LEVELS_MAX])
{
/* Sort samples. Lame implementation, can be replaced with a more efficient algorithm. */
for (int i = 0; i < cryptomatte_samples_per_layer - 1 && samples[i].y != 0.0; i++) {
int highest_index = i;
float highest_weight = samples[i].y;
for (int j = i + 1; j < cryptomatte_samples_per_layer && samples[j].y != 0.0; j++) {
if (samples[j].y > highest_weight) {
highest_index = j;
highest_weight = samples[j].y;
}
};
if (highest_index != i) {
vec2 tmp = samples[i];
samples[i] = samples[highest_index];
samples[highest_index] = tmp;
}
}
}
void cryptomatte_normalize_weight(float total_weight, inout vec2 samples[CRYPTOMATTE_LEVELS_MAX])
{
for (int i = 0; i < CRYPTOMATTE_LEVELS_MAX; i++) {
samples[i].y /= total_weight;
}
}
void cryptomatte_store_samples(ivec2 texel, int layer, in vec2 samples[CRYPTOMATTE_LEVELS_MAX])
{
int pass_len = divide_ceil(cryptomatte_samples_per_layer, 2);
int layer_id = layer * pass_len;
/* Store samples back to the cryptomatte layer. */
for (int p = 0; p < pass_len; p++) {
vec4 pass_sample;
pass_sample.xy = samples[p * 2];
pass_sample.zw = samples[p * 2 + 1];
imageStore(cryptomatte_img, ivec3(texel, p + layer_id), pass_sample);
}
}
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
for (int layer = 0; layer < cryptomatte_layer_len; layer++) {
vec2 samples[CRYPTOMATTE_LEVELS_MAX];
cryptomatte_load_samples(texel, layer, samples);
cryptomatte_sort_samples(samples);
/* Repeat texture coordinates as the weight can be optimized to a small portion of the film. */
float weight = imageLoad(
weight_img,
ivec3(texel % imageSize(weight_img).xy, FILM_WEIGHT_LAYER_ACCUMULATION))
.x;
cryptomatte_normalize_weight(weight, samples);
cryptomatte_store_samples(texel, layer, samples);
}
}
|