7
votes

I wish to implement motion blur or perhaps gaussian blur using purely GLSL.
I've created a few basic shaders and I have already a few ideas in mind.

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);
}

Is it a good idea to create blur using purely GLSL? and does anyone has any ideas on how to do it?
I may as well answer my own question as I have a few ideas in mind.

1

1 Answers

5
votes

I am going to answer my own question.

Eventually, 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;

The effect makes a gaussian blur, purely with GLSL. You can always adjust the variables to your liking.