Radial Blur Filter

Radial blur is an effect that is often used in racing games and FPS-games. In racing games it can give the feel of speed and in fps games it’s often used when something important has happened, for example the player has been hit by an enemy. Radial blur is one of many blur filters that can be created in a shader
The image below shows to the left the original image and to the right the radial blurred one.

Radial Blur in the right image. The left image is the original.

The effects work like the following. First render the scene normally to a texture, then draw a full-screen quad with the radial blur shader.

The radial blur shader blurs the image in the direction towards the center of the screen. When considering uv-mapping, the center of the screen is the coordinates 0.5,0.5 because the uv-mapping starts with 0,0 and ends with 1,1. When drawing a fragment, we know it’s current uv-mapping coordinates (this can be the black dot in the image below) since it’s passed down by the vertex shader. We can simply create the direction vector by subtracting the current fragments uv-coordinates from the center of the screen coordinates. This vector will have an distance which can be used when blurring so that the image is more blurred the further it’s away from the middle (like the image above). Of course you can also remove this distance check and do a constant radial blur over the whole screen.

Radial Blur

The GLSL vertex shader:

varying vec2  uv;
// this vertex shader is from AMD RenderMonkey
void main(void)
{
   gl_Position = vec4( gl_Vertex.xy, 0.0, 1.0 );
   gl_Position = sign( gl_Position );
   
   // Texture coordinate for screen aligned (in correct range):
   uv = (vec2( gl_Position.x, - gl_Position.y ) + vec2( 1.0 ) ) / vec2( 2.0 );
}

The GLSL fragment shader:

// This texture should hold the image to blur.
// This can perhaps be a previous rendered scene.
uniform sampler2D tex;
 
// texture coordinates passed from the vertex shader
varying vec2 uv;
 
// some const, tweak for best look
const float sampleDist = 1.0;
const float sampleStrength = 2.2; 
 
void main(void)
{
   // some sample positions
   float samples[10] =
   float[](-0.08,-0.05,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.05,0.08);
 
    // 0.5,0.5 is the center of the screen
    // so substracting uv from it will result in
    // a vector pointing to the middle of the screen
    vec2 dir = 0.5 - uv; 
 
    // calculate the distance to the center of the screen
    float dist = sqrt(dir.x*dir.x + dir.y*dir.y); 
 
    // normalize the direction (reuse the distance)
    dir = dir/dist; 
 
    // this is the original colour of this fragment
    // using only this would result in a nonblurred version
    vec4 color = texture2D(tex,uv); 
 
    vec4 sum = color;
 
    // take 10 additional blur samples in the direction towards
    // the center of the screen
    for (int i = 0; i < 10; i++)
    {
      sum += texture2D( tex, uv + dir * samples[i] * sampleDist );
    }
 
    // we have taken eleven samples
    sum *= 1.0/11.0;
 
    // weighten the blur effect with the distance to the
    // center of the screen ( further out is blurred more)
    float t = dist * sampleStrength;
    t = clamp( t ,0.0,1.0); //0 &lt;= t &lt;= 1
 
    //Blend the original color with the averaged pixels
    gl_FragColor = mix( color, sum, t );
} 

This shader is mostly inspired and copied from a CG-shader in Ogre3D.
www.ogre3D.org

Be Sociable, Share!

8 thoughts on “Radial Blur Filter

  1. Ilja

    There is a better way to do a zoom blur filter. Suppose you want to render 64 passes of zoom blur, only 6 passes are needed. First make a blended images between zoom factor 0 and 32 and render this to a texture. Then use this as the source of your next pass. In the next pass you render your image with a blend between zoom factor 0 and 16. The result of this second pass contains zoom factor 0, 16, 32 and 48. ect. This gives you a nice number of zoom factors in small number of passes.

    And, instead of zooming out, I would zoom in, that saves you from the annoying borders at the sides.

    Good luck, Ilja

    1. admin Post author

      Thanks for the input. But how would this compete with a shader that is done in one pass?
      You’re right about the borders. They are ugly when doing zooming in the way I described.

  2. Pingback: Light Shafts + Tone Mapping | J.Coluna

  3. Pingback: Unity Radial Blur Post Process Shader : Shallway Studio

  4. Pingback: Weird issue with GLSL Radial Blur | BlogoSfera

  5. camera

    It is appropriate time to make some plans for the longer term and it’s time to be happy. I have read this submit and if I could I want to counsel you some attention-grabbing issues or tips. Perhaps you could write next articles referring to this article. I wish to read even more things about it!

Comments are closed.