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

eevee_depth_of_field_scatter_vert.glsl « shaders « eevee « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8b02f91951223e4bb5b7184fefc319ae4dfe8698 (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

/**
 * Scatter pass: Use sprites to scatter the color of very bright pixel to have higher quality blur.
 *
 * We only scatter one triangle per sprite and one sprite per 4 pixels to reduce vertex shader
 * invocations and overdraw.
 **/

#pragma BLENDER_REQUIRE(eevee_depth_of_field_lib.glsl)

/* Load 4 Circle of confusion values. texel_co is centered around the 4 taps. */
vec4 fetch_cocs(vec2 texel_co)
{
  /* TODO(@fclem): The `textureGather(sampler, co, comp)` variant isn't here on some
   * implementations.
   */
#if 0  // GPU_ARB_texture_gather
  vec2 uvs = texel_co / vec2(textureSize(coc_tx, 0));
  /* Reminder: Samples order is CW starting from top left. */
  cocs = textureGather(coc_tx, uvs, isForegroundPass ? 0 : 1);
#else
  ivec2 texel = ivec2(texel_co - 0.5);
  vec4 cocs;
  cocs.x = texelFetchOffset(coc_tx, texel, 0, ivec2(0, 1)).r;
  cocs.y = texelFetchOffset(coc_tx, texel, 0, ivec2(1, 1)).r;
  cocs.z = texelFetchOffset(coc_tx, texel, 0, ivec2(1, 0)).r;
  cocs.w = texelFetchOffset(coc_tx, texel, 0, ivec2(0, 0)).r;
#endif

  if (DOF_FOREGROUND_PASS) {
    cocs *= -1.0;
  }

  cocs = max(vec4(0.0), cocs);
  /* We are scattering at half resolution, so divide CoC by 2. */
  return cocs * 0.5;
}

void vertex_discard()
{
  /* Don't produce any fragments */
  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}

void main()
{
  ivec2 tex_size = textureSize(coc_tx, 0);

  int t_id = gl_VertexID / 3; /* Triangle Id */

  /* Some math to get the target pixel. */
  ivec2 texelco = ivec2(t_id % dof_buf.scatter_sprite_per_row,
                        t_id / dof_buf.scatter_sprite_per_row) *
                  2;

  /* Center sprite around the 4 texture taps. */
  spritepos = vec2(texelco) + 1.0;

  cocs = fetch_cocs(spritepos);

  /* Early out from local CoC radius. */
  if (all(lessThan(cocs, vec4(0.5)))) {
    vertex_discard();
    return;
  }

  vec2 input_texel_size = 1.0 / vec2(tex_size);
  vec2 quad_center = spritepos * input_texel_size;
  vec4 colors[4];
  bool no_color = true;
  for (int i = 0; i < 4; i++) {
    vec2 sample_uv = quad_center + quad_offsets[i] * input_texel_size;

    colors[i] = textureLod(color_tx, sample_uv, 0.0);
    no_color = no_color && all(equal(colors[i].rgb, vec3(0.0)));
  }

  /* Early out from no color to scatter. */
  if (no_color) {
    vertex_discard();
    return;
  }

  weights = dof_layer_weight(cocs) * dof_sample_weight(cocs);
  /* Filter NaNs. */
  weights = mix(weights, vec4(0.0), equal(cocs, vec4(0.0)));

  color1 = colors[0] * weights[0];
  color2 = colors[1] * weights[1];
  color3 = colors[2] * weights[2];
  color4 = colors[3] * weights[3];

  /* Extend to cover at least the unit circle */
  const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0;
  /* Crappy diagram
   * ex 1
   *    | \
   *    |   \
   *  1 |     \
   *    |       \
   *    |         \
   *  0 |     x     \
   *    |   Circle    \
   *    |   Origin      \
   * -1 0 --------------- 2
   *   -1     0     1     ex
   */

  /* Generate Triangle : less memory fetches from a VBO */
  int v_id = gl_VertexID % 3;                     /* Vertex Id */
  gl_Position.x = float(v_id / 2) * extend - 1.0; /* int divisor round down */
  gl_Position.y = float(v_id % 2) * extend - 1.0;
  gl_Position.z = 0.0;
  gl_Position.w = 1.0;

  spritesize = max_v4(cocs);

  /* Add 2.5 to max_coc because the max_coc may not be centered on the sprite origin
   * and because we smooth the bokeh shape a bit in the pixel shader. */
  gl_Position.xy *= spritesize * dof_buf.bokeh_anisotropic_scale + 2.5;
  /* Position the sprite. */
  gl_Position.xy += spritepos;
  /* NDC range [-1..1]. */
  gl_Position.xy = gl_Position.xy * dof_buf.texel_size * 2.0 - 1.0;

  /* Add 2.5 for the same reason but without the ratio. */
  spritesize += 2.5;
}