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.
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.
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 <= t <= 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























