const MOTION_BLUR: &str = r#"
uniform sampler2D u_prev;
uniform sampler2D u_next;
uniform float u_frames;
uniform vec2 u_motion;
void main() {
vec2 uv = gl_FragCoord.xy / u_res;
vec4 src = texture(tex, uv);
float sh = clamp(p0, 0.0, 360.0) / 360.0;
int n = int(clamp(p1, 2.0, 32.0));
vec4 acc = vec4(0.0);
vec4 prev = src;
vec4 next = src;
if (u_frames > 0.5) {
prev = texture(u_prev, uv);
next = u_frames > 1.5 ? texture(u_next, uv) : prev;
for (int i = 0; i < 32; i++) {
if (i >= n) break;
float o = ((float(i) + 0.5) / float(n) - 0.5) * sh;
acc += o < 0.0 ? mix(src, prev, clamp(-o, 0.0, 1.0)) : mix(src, next, clamp(o, 0.0, 1.0));
}
} else {
vec2 d = u_motion / u_res * sh;
for (int i = 0; i < 32; i++) {
if (i >= n) break;
acc += texture(tex, uv + d * ((float(i) + 0.5) / float(n) - 0.5));
}
}
vec4 res = acc / float(n);
if (p2 >= 0.5 && u_frames > 0.5) {
float mv = length(prev.rgb - src.rgb) + length(next.rgb - src.rgb);
res = mix(src, res, clamp(mv * 4.0, 0.0, 1.0));
}
float m = u_has_mask > 0.5 ? texture(u_mask, uv).r : 1.0;
out_color = mix(src, res, m);
}
"#;Expand description
Shutter-window average of the frames gpu.rs supplies.
Extra uniforms gpu.rs must bind (this kind reports EffectKind::needs_motion()):
sampler2D u_prev / u_next the layer one frame before / after (bind tex when missing)
float u_frames how many of those are real: 0, 1 (prev only) or 2
vec2 u_motion the layer’s motion in layer pixels per frame, for the 0-frame fallback