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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl')
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl151
1 files changed, 151 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl
new file mode 100644
index 00000000000..0eb598521af
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl
@@ -0,0 +1,151 @@
+/**
+ * Shaders that down-sample velocity buffer,
+ *
+ * Based on:
+ * A Fast and Stable Feature-Aware Motion Blur Filter
+ * by Jean-Philippe Guertin, Morgan McGuire, Derek Nowrouzezahrai
+ *
+ * Adapted from G3D Innovation Engine implementation.
+ */
+
+uniform sampler2D velocityBuffer;
+uniform vec2 viewportSize;
+uniform vec2 viewportSizeInv;
+uniform ivec2 velocityBufferSize;
+
+out vec4 tileMaxVelocity;
+
+vec4 sample_velocity(ivec2 texel)
+{
+ texel = clamp(texel, ivec2(0), velocityBufferSize - 1);
+ vec4 data = texelFetch(velocityBuffer, texel, 0);
+ /* Decode data. */
+ return (data * 2.0 - 1.0) * viewportSize.xyxy;
+}
+
+vec4 encode_velocity(vec4 velocity)
+{
+ return velocity * viewportSizeInv.xyxy * 0.5 + 0.5;
+}
+
+#ifdef TILE_GATHER
+
+uniform ivec2 gatherStep;
+
+void main()
+{
+ vec4 max_motion = vec4(0.0);
+ float max_motion_len_sqr_prev = 0.0;
+ float max_motion_len_sqr_next = 0.0;
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ texel = texel * gatherStep.yx + texel * EEVEE_VELOCITY_TILE_SIZE * gatherStep;
+
+ for (int i = 0; i < EEVEE_VELOCITY_TILE_SIZE; ++i) {
+ vec4 motion = sample_velocity(texel + i * gatherStep);
+ float motion_len_sqr_prev = dot(motion.xy, motion.xy);
+ float motion_len_sqr_next = dot(motion.zw, motion.zw);
+
+ if (motion_len_sqr_prev > max_motion_len_sqr_prev) {
+ max_motion_len_sqr_prev = motion_len_sqr_prev;
+ max_motion.xy = motion.xy;
+ }
+ if (motion_len_sqr_next > max_motion_len_sqr_next) {
+ max_motion_len_sqr_next = motion_len_sqr_next;
+ max_motion.zw = motion.zw;
+ }
+ }
+
+ tileMaxVelocity = encode_velocity(max_motion);
+}
+
+#else /* TILE_EXPANSION */
+
+bool neighbor_affect_this_tile(ivec2 offset, vec2 velocity)
+{
+ /* Manhattan distance to the tiles, which is used for
+ * differentiating corners versus middle blocks */
+ float displacement = float(abs(offset.x) + abs(offset.y));
+ /**
+ * Relative sign on each axis of the offset compared
+ * to the velocity for that tile. In order for a tile
+ * to affect the center tile, it must have a
+ * neighborhood velocity in which x and y both have
+ * identical or both have opposite signs relative to
+ * offset. If the offset coordinate is zero then
+ * velocity is irrelevant.
+ **/
+ vec2 point = sign(offset * velocity);
+
+ float dist = (point.x + point.y);
+ /**
+ * Here's an example of the logic for this code.
+ * In this diagram, the upper-left tile has offset = (-1, -1).
+ * V1 is velocity = (1, -2). point in this case = (-1, 1), and therefore dist = 0,
+ * so the upper-left tile does not affect the center.
+ *
+ * Now, look at another case. V2 = (-1, -2). point = (1, 1), so dist = 2 and the tile
+ * does affect the center.
+ *
+ * V2(-1,-2) V1(1, -2)
+ * \ /
+ * \ /
+ * \/___ ____ ____
+ * (-1, -1)| | | |
+ * |____|____|____|
+ * | | | |
+ * |____|____|____|
+ * | | | |
+ * |____|____|____|
+ **/
+ return (abs(dist) == displacement);
+}
+
+/**
+ * Only gather neighborhood velocity into tiles that could be affected by it.
+ * In the general case, only six of the eight neighbors contribute:
+ *
+ * This tile can't possibly be affected by the center one
+ * |
+ * v
+ * ____ ____ ____
+ * | | ///|/// |
+ * |____|////|//__|
+ * | |////|/ |
+ * |___/|////|____|
+ * | //|////| | <--- This tile can't possibly be affected by the center one
+ * |_///|///_|____|
+ **/
+void main()
+{
+ vec4 max_motion = vec4(0.0);
+ float max_motion_len_sqr_prev = -1.0;
+ float max_motion_len_sqr_next = -1.0;
+
+ ivec2 tile = ivec2(gl_FragCoord.xy);
+ ivec2 offset = ivec2(0);
+ for (offset.y = -1; offset.y <= 1; ++offset.y) {
+ for (offset.x = -1; offset.x <= 1; ++offset.x) {
+ vec4 motion = sample_velocity(tile + offset);
+ float motion_len_sqr_prev = dot(motion.xy, motion.xy);
+ float motion_len_sqr_next = dot(motion.zw, motion.zw);
+
+ if (motion_len_sqr_prev > max_motion_len_sqr_prev) {
+ if (neighbor_affect_this_tile(offset, motion.xy)) {
+ max_motion_len_sqr_prev = motion_len_sqr_prev;
+ max_motion.xy = motion.xy;
+ }
+ }
+
+ if (motion_len_sqr_next > max_motion_len_sqr_next) {
+ if (neighbor_affect_this_tile(offset, motion.zw)) {
+ max_motion_len_sqr_next = motion_len_sqr_next;
+ max_motion.zw = motion.zw;
+ }
+ }
+ }
+ }
+
+ tileMaxVelocity = encode_velocity(max_motion);
+}
+
+#endif \ No newline at end of file