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

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

/**
 * Dilate motion vector tiles until we covered maximum velocity.
 * Outputs the largest intersecting motion vector in the neighboorhod.
 *
 */

#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_motion_blur_lib.glsl)

#define DEBUG_BYPASS_DILATION 0

struct MotionRect {
  ivec2 bottom_left;
  ivec2 extent;
};

MotionRect compute_motion_rect(ivec2 tile, vec2 motion)
{
#if DEBUG_BYPASS_DILATION
  return MotionRect(tile, ivec2(1));
#endif
  /* Ceil to number of tile touched.*/
  ivec2 point1 = tile + ivec2(sign(motion) * ceil(abs(motion) / float(MOTION_BLUR_TILE_SIZE)));
  ivec2 point2 = tile;

  ivec2 max_point = max(point1, point2);
  ivec2 min_point = min(point1, point2);
  /* Clamp to bounds. */
  max_point = min(max_point, imageSize(in_tiles_img) - 1);
  min_point = max(min_point, ivec2(0));

  MotionRect rect;
  rect.bottom_left = min_point;
  rect.extent = 1 + max_point - min_point;
  return rect;
}

struct MotionLine {
  /** Origin of the line. */
  vec2 origin;
  /** Normal to the line direction. */
  vec2 normal;
};

MotionLine compute_motion_line(ivec2 tile, vec2 motion)
{
  vec2 dir = safe_normalize(motion);

  MotionLine line;
  line.origin = vec2(tile);
  /* Rotate 90° Counter-Clockwise. */
  line.normal = vec2(-dir.y, dir.x);
  return line;
}

bool is_inside_motion_line(ivec2 tile, MotionLine motion_line)
{
#if DEBUG_BYPASS_DILATION
  return true;
#endif
  /* NOTE: Everything in is tile unit. */
  float dist = point_line_projection_dist(vec2(tile), motion_line.origin, motion_line.normal);
  /* In order to be conservative and for simplicity, we use the tiles bounding circles.
   * Consider that both the tile and the line have bouding radius of M_SQRT1_2. */
  return abs(dist) < M_SQRT2;
}

void main()
{
  ivec2 src_tile = ivec2(gl_GlobalInvocationID.xy);
  if (any(greaterThanEqual(src_tile, imageSize(in_tiles_img)))) {
    return;
  }

  vec4 max_motion = imageLoad(in_tiles_img, src_tile);

  MotionPayload payload_prv = motion_blur_tile_indirection_pack_payload(max_motion.xy, src_tile);
  MotionPayload payload_nxt = motion_blur_tile_indirection_pack_payload(max_motion.zw, src_tile);
  if (true) {
    /* Rectangular area (in tiles) where the motion vector spreads. */
    MotionRect motion_rect = compute_motion_rect(src_tile, max_motion.xy);
    MotionLine motion_line = compute_motion_line(src_tile, max_motion.xy);
    /* Do a conservative rasterization of the line of the motion vector line. */
    for (int x = 0; x < motion_rect.extent.x; x++) {
      for (int y = 0; y < motion_rect.extent.y; y++) {
        ivec2 tile = motion_rect.bottom_left + ivec2(x, y);
        if (is_inside_motion_line(tile, motion_line)) {
          motion_blur_tile_indirection_store(tile_indirection_buf, MOTION_PREV, tile, payload_prv);
          /* FIXME: This is a bit weird, but for some reason, we need the store the same vector in
           * the motion next so that weighting in gather pass is better. */
          motion_blur_tile_indirection_store(tile_indirection_buf, MOTION_NEXT, tile, payload_nxt);
        }
      }
    }
  }

  if (true) {
    MotionPayload payload = motion_blur_tile_indirection_pack_payload(max_motion.zw, src_tile);
    /* Rectangular area (in tiles) where the motion vector spreads. */
    MotionRect motion_rect = compute_motion_rect(src_tile, max_motion.zw);
    MotionLine motion_line = compute_motion_line(src_tile, max_motion.zw);
    /* Do a conservative rasterization of the line of the motion vector line. */
    for (int x = 0; x < motion_rect.extent.x; x++) {
      for (int y = 0; y < motion_rect.extent.y; y++) {
        ivec2 tile = motion_rect.bottom_left + ivec2(x, y);
        if (is_inside_motion_line(tile, motion_line)) {
          motion_blur_tile_indirection_store(tile_indirection_buf, MOTION_NEXT, tile, payload_nxt);
          /* FIXME: This is a bit weird, but for some reason, we need the store the same vector in
           * the motion next so that weighting in gather pass is better. */
          motion_blur_tile_indirection_store(tile_indirection_buf, MOTION_PREV, tile, payload_prv);
        }
      }
    }
  }
}