LibGDX - make motion blur for 2D game

I made a 2D game, with basic shaders and now i wish to add motion blur, i am beginner with shaders so i have hard time to implement it.

My shaders -
Vertex shader :

attribute vec4 a_color;
    attribute vec2 a_position;
    attribute vec2 a_texCoord0;

    uniform mat4 u_projTrans;

    varying vec4 v_color;
    varying vec2 v_texCoord0;

    void main() {
	    v_color = a_color;
	    v_texCoord0 = a_texCoord0;
	    gl_Position =  u_projTrans * vec4(a_position, 0.0f, 1.0f);	
    }

Fragment shader :

 varying vec4 v_color;
    varying vec2 v_texCoord0;

    uniform vec2 screenSize;

    uniform sampler2D u_texture;
    uniform vec4 v_time;

    const float RADIUS = 0.75;

    const float SOFTNESS = 0.6;

    void main() {
    	vec4 texColor = texture2D(u_texture, v_texCoord0);
        vec4 timedColor = (v_color + v_time);

	    vec2 position = (gl_FragCoord.xy / screenSize.xy) - vec2(0.5);
	    float len = length(position);

	    float vignette = smoothstep(RADIUS, RADIUS-SOFTNESS, len);

	    texColor.rgb = mix(texColor.rgb, texColor.rgb * vignette, 0.5);

	    gl_FragColor = vec4(texColor.rgb * timedColor.rgb, texColor.a);
    }

What should I add to the shaders to create the motion blur effect?
Or maybe I can create the motion blur effect in libgdx without the shaders?

Any ideas?
Thanks in advance

You should google first. You should look into Accumulation Buffer. You also might want to learn what’s FBO (Frame Buffer Object) You could keep old FBOs and render them on top of your current frame with alpha that is lower the older the buffer. Might create sorta motion blur idk.

I don’t know anything about shaders and am still a noob…But if I was trying to create the same effect, I would render an image of the object a few times a few pixels behind the object each time and lower the alpha of the image a little more then the one before it. Should give you the same effect…But like I said, i’m a noob…There’s probably an easier way of doing it that pertains to what you’re doing.

@Bassex96 that’s exactly what trollwarrior1 was saying to do with fbos. :wink:

Motion blur is rather an advanced effect, eg you have to be very comfortable with matrices and more in depth stuff than LibGDX normally has you use.

Here’s where I learned mine:

However, that’s for 3D games. For 2D it may be very simple, such as trollwarrior said, just keeping a virtual image of the last couple frames. The only problem with such an approach is that it is dependent on framerate, eg, the lower the FPS, the lower quality the “blur”.

The basic principle is this: You get the last frame’s position in worldspace and then you blur along a vector to the current world space.

Bruteforce motion blur is rather simple. You just take avarage of multiple drawed sub frames.

I gonna answer my own question

I changed only the fragment shader -

 varying vec4 vColor;
    varying vec2 vTexCoord;

    uniform vec2 screenSize;

    uniform sampler2D u_texture;
    uniform vec4 v_time;

    const float RADIUS = 0.75;

    const float SOFTNESS = 0.6;

    const float blurSize = 1.0/1000.0;

    void main() {

	    vec4 texColor = vec4(0.0); // texture2D(u_texture, vTexCoord)
	    texColor += texture2D(u_texture, vTexCoord - 4.0*blurSize) * 0.05;
   	    texColor += texture2D(u_texture, vTexCoord - 3.0*blurSize) * 0.09;
  	    texColor += texture2D(u_texture, vTexCoord - 2.0*blurSize) * 0.12;
   	    texColor += texture2D(u_texture, vTexCoord - blurSize) * 0.15;
   	    texColor += texture2D(u_texture, vTexCoord) * 0.16;
   	    texColor += texture2D(u_texture, vTexCoord + blurSize) * 0.15;
   	    texColor += texture2D(u_texture, vTexCoord + 2.0*blurSize) * 0.12;
   	    texColor += texture2D(u_texture, vTexCoord + 3.0*blurSize) * 0.09;
   	    texColor += texture2D(u_texture, vTexCoord + 4.0*blurSize) * 0.05;

        vec4 timedColor = (vColor + v_time);

	    vec2 position = (gl_FragCoord.xy / screenSize.xy) - vec2(0.5);
	    float len = length(position);

	    float vignette = smoothstep(RADIUS, RADIUS-SOFTNESS, len);

	    texColor.rgb = mix(texColor.rgb, texColor.rgb * vignette, 0.5);
		
	    gl_FragColor = vec4(texColor.rgb * timedColor.rgb, texColor.a);
    }

The actual blur effect is written here -


    	vec4 texColor = vec4(0.0); // texture2D(u_texture, vTexCoord)
	    texColor += texture2D(u_texture, vTexCoord - 4.0*blurSize) * 0.05;
   	    texColor += texture2D(u_texture, vTexCoord - 3.0*blurSize) * 0.09;
  	    texColor += texture2D(u_texture, vTexCoord - 2.0*blurSize) * 0.12;
   	    texColor += texture2D(u_texture, vTexCoord - blurSize) * 0.15;
   	    texColor += texture2D(u_texture, vTexCoord) * 0.16;
   	    texColor += texture2D(u_texture, vTexCoord + blurSize) * 0.15;
   	    texColor += texture2D(u_texture, vTexCoord + 2.0*blurSize) * 0.12;
   	    texColor += texture2D(u_texture, vTexCoord + 3.0*blurSize) * 0.09;
   	    texColor += texture2D(u_texture, vTexCoord + 4.0*blurSize) * 0.05;

For more information - http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/

see ya out there programmers :slight_smile: