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
|
/**
* Tile dilate pass: Takes the 8x8 Tiles buffer and converts dilates the tiles with large CoC to
* their neighborhood. This pass is repeated multiple time until the maximum CoC can be covered.
*/
#pragma BLENDER_REQUIRE(effect_dof_lib.glsl)
/* 1/16th of fullres. */
uniform sampler2D cocTilesFgBuffer;
uniform sampler2D cocTilesBgBuffer;
uniform int ringCount;
uniform int ringWidthMultiplier;
uniform bool dilateSlightFocus;
/* 1/16th of fullres. Same format as input. */
layout(location = 0) out vec4 outFgCoc;
layout(location = 1) out vec3 outBgCoc;
const float tile_to_fullres_factor = float(DOF_TILE_DIVISOR);
/* Error introduced by the random offset of the gathering kernel's center. */
const float bluring_radius_error = 1.0 + 1.0 / (gather_ring_count + 0.5);
void main()
{
ivec2 center_tile_pos = ivec2(gl_FragCoord.xy);
CocTile ring_buckets[DOF_DILATE_RING_COUNT];
for (int ring = 0; ring < ringCount && ring < DOF_DILATE_RING_COUNT; ring++) {
ring_buckets[ring] = dof_coc_tile_init();
int ring_distance = ring + 1;
for (int sample_id = 0; sample_id < 4 * ring_distance; sample_id++) {
ivec2 offset = dof_square_ring_sample_offset(ring_distance, sample_id);
offset *= ringWidthMultiplier;
for (int i = 0; i < 2; i++) {
ivec2 adj_tile_pos = center_tile_pos + ((i == 0) ? offset : -offset);
CocTile adj_tile = dof_coc_tile_load(cocTilesFgBuffer, cocTilesBgBuffer, adj_tile_pos);
#ifdef DILATE_MODE_MIN_MAX
/* Actually gather the "absolute" biggest coc but keeping the sign. */
ring_buckets[ring].fg_min_coc = min(ring_buckets[ring].fg_min_coc, adj_tile.fg_min_coc);
ring_buckets[ring].bg_max_coc = max(ring_buckets[ring].bg_max_coc, adj_tile.bg_max_coc);
if (dilateSlightFocus) {
ring_buckets[ring].fg_slight_focus_max_coc = dof_coc_max_slight_focus(
ring_buckets[ring].fg_slight_focus_max_coc, adj_tile.fg_slight_focus_max_coc);
}
#else /* DILATE_MODE_MIN_ABS */
ring_buckets[ring].fg_max_coc = max(ring_buckets[ring].fg_max_coc, adj_tile.fg_max_coc);
ring_buckets[ring].bg_min_coc = min(ring_buckets[ring].bg_min_coc, adj_tile.bg_min_coc);
/* Should be tight as possible to reduce gather overhead (see slide 61). */
float closest_neighbor_distance = length(max(abs(vec2(offset)) - 1.0, 0.0)) *
tile_to_fullres_factor;
ring_buckets[ring].fg_max_intersectable_coc = max(
ring_buckets[ring].fg_max_intersectable_coc,
adj_tile.fg_max_intersectable_coc + closest_neighbor_distance);
ring_buckets[ring].bg_min_intersectable_coc = min(
ring_buckets[ring].bg_min_intersectable_coc,
adj_tile.bg_min_intersectable_coc + closest_neighbor_distance);
#endif
}
}
}
/* Load center tile. */
CocTile out_tile = dof_coc_tile_load(cocTilesFgBuffer, cocTilesBgBuffer, center_tile_pos);
/* Dilate once. */
if (dilateSlightFocus) {
out_tile.fg_slight_focus_max_coc = dof_coc_max_slight_focus(
out_tile.fg_slight_focus_max_coc, ring_buckets[0].fg_slight_focus_max_coc);
}
for (int ring = 0; ring < ringCount && ring < DOF_DILATE_RING_COUNT; ring++) {
float ring_distance = float(ring + 1);
ring_distance = (ring_distance * ringWidthMultiplier - 1) * tile_to_fullres_factor;
/* NOTE(fclem): Unsure if both sides of the inequalities have the same unit. */
#ifdef DILATE_MODE_MIN_MAX
if (-ring_buckets[ring].fg_min_coc * bluring_radius_error > ring_distance) {
out_tile.fg_min_coc = min(out_tile.fg_min_coc, ring_buckets[ring].fg_min_coc);
}
if (ring_buckets[ring].bg_max_coc * bluring_radius_error > ring_distance) {
out_tile.bg_max_coc = max(out_tile.bg_max_coc, ring_buckets[ring].bg_max_coc);
}
#else /* DILATE_MODE_MIN_ABS */
/* Find minimum absolute CoC radii that will be intersected for the previously
* computed maximum CoC values. */
if (-out_tile.fg_min_coc * bluring_radius_error > ring_distance) {
out_tile.fg_max_coc = max(out_tile.fg_max_coc, ring_buckets[ring].fg_max_coc);
out_tile.fg_max_intersectable_coc = max(out_tile.fg_max_intersectable_coc,
ring_buckets[ring].fg_max_intersectable_coc);
}
if (out_tile.bg_max_coc * bluring_radius_error > ring_distance) {
out_tile.bg_min_coc = min(out_tile.bg_min_coc, ring_buckets[ring].bg_min_coc);
out_tile.bg_min_intersectable_coc = min(out_tile.bg_min_intersectable_coc,
ring_buckets[ring].bg_min_intersectable_coc);
}
#endif
}
dof_coc_tile_store(out_tile, outFgCoc, outBgCoc);
}
|