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

effect_dof_resolve_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: 688ae4915e16796bdf1a8d54b13abf5ceef91e10 (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
211
212

/**
 * Recombine Pass: Load separate convolution layer and composite with self slight defocus
 * convolution and in-focus fields.
 *
 * The halfres gather methods are fast but lack precision for small CoC areas. To fix this we
 * do a bruteforce gather to have a smooth transition between in-focus and defocus regions.
 */

#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(effect_dof_lib.glsl)

uniform sampler2D fullResColorBuffer;
uniform sampler2D fullResDepthBuffer;

uniform sampler2D bgColorBuffer;
uniform sampler2D bgWeightBuffer;
uniform sampler2D bgTileBuffer;

uniform sampler2D fgColorBuffer;
uniform sampler2D fgWeightBuffer;
uniform sampler2D fgTileBuffer;

uniform sampler2D holefillColorBuffer;
uniform sampler2D holefillWeightBuffer;

uniform sampler2D bokehLut;

uniform float bokehMaxSize;

in vec4 uvcoordsvar;

out vec4 fragColor;

void dof_slight_focus_gather(float radius, out vec4 out_color, out float out_weight)
{
  /* offset coord to avoid correlation with sampling pattern. */
  vec4 noise = texelfetch_noise_tex(gl_FragCoord.xy + 7.0);

  DofGatherData fg_accum = GATHER_DATA_INIT;
  DofGatherData bg_accum = GATHER_DATA_INIT;

  int i_radius = clamp(int(radius + 0.5), 0, int(layer_threshold));
  const int resolve_ring_density = DOF_SLIGHT_FOCUS_DENSITY;
  ivec2 texel = ivec2(gl_FragCoord.xy);

  bool first_ring = true;

  for (int ring = i_radius; ring > 0; ring--) {
    DofGatherData fg_ring = GATHER_DATA_INIT;
    DofGatherData bg_ring = GATHER_DATA_INIT;

    int ring_distance = ring;
    int ring_sample_count = resolve_ring_density * ring_distance;
    for (int sample_id = 0; sample_id < ring_sample_count; sample_id++) {
      int s = sample_id * (4 / resolve_ring_density) +
              int(noise.y * float((4 - resolve_ring_density) * ring_distance));

      ivec2 offset = dof_square_ring_sample_offset(ring_distance, s);
      float ring_dist = length(vec2(offset));

      DofGatherData pair_data[2];
      for (int i = 0; i < 2; i++) {
        ivec2 sample_offset = ((i == 0) ? offset : -offset);
        ivec2 sample_texel = texel + sample_offset;
        /* OPTI: could precompute the factor. */
        vec2 sample_uv = (vec2(sample_texel) + 0.5) / vec2(textureSize(fullResDepthBuffer, 0));
        float depth = textureLod(fullResDepthBuffer, sample_uv, 0.0).r;
        pair_data[i].color = safe_color(textureLod(fullResColorBuffer, sample_uv, 0.0));
        pair_data[i].coc = dof_coc_from_zdepth(depth);
        pair_data[i].dist = ring_dist;
#ifdef DOF_BOKEH_TEXTURE
        /* Contains subpixel distance to bokeh shape. */
        pair_data[i].dist = texelFetch(bokehLut, sample_offset + DOF_MAX_SLIGHT_FOCUS_RADIUS, 0).r;
#endif
        pair_data[i].coc = clamp(pair_data[i].coc, -bokehMaxSize, bokehMaxSize);
      }

      float bordering_radius = ring_dist + 0.5;
      const float isect_mul = 1.0;
      dof_gather_accumulate_sample_pair(
          pair_data, bordering_radius, isect_mul, first_ring, false, false, bg_ring, bg_accum);

#ifdef DOF_BOKEH_TEXTURE
      /* Swap distances in order to flip bokeh shape for foreground. */
      float tmp = pair_data[0].dist;
      pair_data[0].dist = pair_data[1].dist;
      pair_data[1].dist = tmp;
#endif
      dof_gather_accumulate_sample_pair(
          pair_data, bordering_radius, isect_mul, first_ring, false, true, fg_ring, fg_accum);
    }

    dof_gather_accumulate_sample_ring(
        bg_ring, ring_sample_count * 2, first_ring, false, false, bg_accum);
    dof_gather_accumulate_sample_ring(
        fg_ring, ring_sample_count * 2, first_ring, false, true, fg_accum);

    first_ring = false;
  }

  /* Center sample. */
  vec2 sample_uv = uvcoordsvar.xy;
  float depth = textureLod(fullResDepthBuffer, sample_uv, 0.0).r;
  DofGatherData center_data;
  center_data.color = safe_color(textureLod(fullResColorBuffer, sample_uv, 0.0));
  center_data.coc = dof_coc_from_zdepth(depth);
  center_data.coc = clamp(center_data.coc, -bokehMaxSize, bokehMaxSize);
  center_data.dist = 0.0;

  /* Slide 38. */
  float bordering_radius = 0.5;

  dof_gather_accumulate_center_sample(
      center_data, bordering_radius, i_radius, false, true, fg_accum);
  dof_gather_accumulate_center_sample(
      center_data, bordering_radius, i_radius, false, false, bg_accum);

  vec4 bg_col, fg_col;
  float bg_weight, fg_weight;
  vec2 unused_occlusion;

  int total_sample_count = dof_gather_total_sample_count(i_radius + 1, resolve_ring_density);
  dof_gather_accumulate_resolve(total_sample_count, bg_accum, bg_col, bg_weight, unused_occlusion);
  dof_gather_accumulate_resolve(total_sample_count, fg_accum, fg_col, fg_weight, unused_occlusion);

  /* Fix weighting issues on perfectly focus > slight focus transitionning areas. */
  if (abs(center_data.coc) < 0.5) {
    bg_col = center_data.color;
    bg_weight = 1.0;
  }

  /* Alpha Over */
  float alpha = 1.0 - fg_weight;
  out_weight = bg_weight * alpha + fg_weight;
  out_color = bg_col * bg_weight * alpha + fg_col * fg_weight;
}

void dof_resolve_load_layer(sampler2D color_tex,
                            sampler2D weight_tex,
                            out vec4 out_color,
                            out float out_weight)
{
  vec2 pixel_co = gl_FragCoord.xy / 2.0;
  vec2 uv = pixel_co / vec2(textureSize(color_tex, 0).xy);
  out_color = textureLod(color_tex, uv, 0.0);
  out_weight = textureLod(weight_tex, uv, 0.0).r;
}

void main(void)
{
  ivec2 tile_co = ivec2(gl_FragCoord.xy / float(DOF_TILE_DIVISOR));
  CocTile coc_tile = dof_coc_tile_load(fgTileBuffer, bgTileBuffer, tile_co);
  CocTilePrediction prediction = dof_coc_tile_prediction_get(coc_tile);

  fragColor = vec4(0.0);
  float weight = 0.0;

  vec4 layer_color;
  float layer_weight;

  if (!no_holefill_pass && prediction.do_holefill) {
    dof_resolve_load_layer(holefillColorBuffer, holefillWeightBuffer, layer_color, layer_weight);
    fragColor = layer_color * safe_rcp(layer_weight);
    weight = float(layer_weight > 0.0);
  }

  if (!no_background_pass && prediction.do_background) {
    dof_resolve_load_layer(bgColorBuffer, bgWeightBuffer, layer_color, layer_weight);
    /* Always prefer background to holefill pass. */
    layer_color *= safe_rcp(layer_weight);
    layer_weight = float(layer_weight > 0.0);
    /* Composite background. */
    fragColor = fragColor * (1.0 - layer_weight) + layer_color;
    weight = weight * (1.0 - layer_weight) + layer_weight;
    /* Fill holes with the composited background. */
    fragColor *= safe_rcp(weight);
    weight = float(weight > 0.0);
  }

  if (!no_slight_focus_pass && prediction.do_slight_focus) {
    dof_slight_focus_gather(coc_tile.fg_slight_focus_max_coc, layer_color, layer_weight);
    /* Composite slight defocus. */
    fragColor = fragColor * (1.0 - layer_weight) + layer_color;
    weight = weight * (1.0 - layer_weight) + layer_weight;
  }

  if (!no_focus_pass && prediction.do_focus) {
    layer_color = safe_color(textureLod(fullResColorBuffer, uvcoordsvar.xy, 0.0));
    layer_weight = 1.0;
    /* Composite in focus. */
    fragColor = fragColor * (1.0 - layer_weight) + layer_color;
    weight = weight * (1.0 - layer_weight) + layer_weight;
  }

  if (!no_foreground_pass && prediction.do_foreground) {
    dof_resolve_load_layer(fgColorBuffer, fgWeightBuffer, layer_color, layer_weight);
    /* Composite foreground. */
    fragColor = fragColor * (1.0 - layer_weight) + layer_color;
  }

  /* Fix float precision issue in alpha compositing. */
  if (fragColor.a > 0.99) {
    fragColor.a = 1.0;
  }

#if 0 /* Debug */
  if (coc_tile.fg_slight_focus_max_coc >= 0.5) {
    fragColor.rgb *= vec3(1.0, 0.1, 0.1);
  }
#endif
}