2D Motion Blur

Adds directional motion blur to canvas items like Sprite. Direction, size, and quality of blur can be configured.

Shader code
shader_type canvas_item;
uniform vec2 dir = vec2(0,0);
uniform int quality = 4;

void vertex(){
	vec2 blurSize = abs(dir) * 2.0;
	VERTEX *= blurSize + 1.0;
	UV = (UV - 0.5) * (blurSize + 1.0) + 0.5;
}

float insideUnitSquare(vec2 v) {
    vec2 s = step(vec2(0.0), v) - step(vec2(1.0), v);
    return s.x * s.y;   
}

void fragment(){
	float inSquare = insideUnitSquare(UV);
	float numSamples = inSquare;
	COLOR = texture(TEXTURE, UV) * inSquare;
	vec2 stepSize = dir/(float(quality));
	vec2 uv;
	for(int i = 1; i <= quality; i++){
		uv = UV + stepSize * float(i);
		inSquare = insideUnitSquare(uv);
		numSamples += inSquare;
		COLOR += texture(TEXTURE, uv) * inSquare;
		
		uv = UV - stepSize * float(i);
		inSquare = insideUnitSquare(uv);
		numSamples += inSquare;
		COLOR += texture(TEXTURE, uv) * inSquare;
	}
	COLOR.rgb /= numSamples;
	COLOR.a /= float(quality)*2.0 + 1.0;
}
Live Preview
Tags
2d, blur, canvas
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from Hayden

Related shaders

Comments 4

  1. This is the best blur implementation I've seen for a single sprite. I am trying to figure out how to make this into a gaussian or box blur(I am not sure of the correct term) by have each pass go around the center vs just the one direction. Can you suggest how this might be modified to accomplish that?

    0
  2. Aleksandr

    Very nice shader. It doesn't work on Godot 3 with GLSL2 on HTML5 export. The issue is - it cannot loop with non-const condition. The solution is to change quality from uniform to const.

    3