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

effect_dof_dilate_tiles_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: 22e6f929f36e68278c9fa2b90a04b972a125a4f4 (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

/**
 * 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);
}