This effect shows how a radial blur can be used to render beams of shining spherical objects like a star. A radial blur is simulated by blurring along radial lines as if zooming in or out of an image. An obvious way to achieve a radial blur is to transform the image from cartesian to polar coordinates, do a horizontal blur (or vertical blur depending on which axis corresponds to r after the transformation) and finally transform the result back to cartesian coordinates. The problem with this approach is that pixel read-backs required for the transformations are still a big performance bottle neck on current 3D hardware (let alone regenerating the mip-map chain if required). Fortunately there is another way to do the very same thing that is particularly well suited for hardware accelerated rendering.
What we do is calculate the weighted sum of a series of zoomed-in versions of the same image. Therefore we need two textures we can render to - a source and a destination texture. The source texture contains the image for the radial blur. In Meshuggah this texture will be updated every frame with a new animation frame of a star. The destination texture functions as an accumulation buffer for the radial blur. The following code snippet shows how the radial blur is done.
- Clear( destTexture );
SetRenderTarget( destTexture );- SetTexture( srcTexture );
EnableAlphaBlending( true );
SetDestinationAlpha( 1.0 );
for i = 1 to NumRadialBlurSteps
{
fUVOffset = i * 0.0075f;
SetSourceAlpha( 1/8 * ( NumRadialBlurSteps - i ) / NumRadialBlurSteps );
struct
{
x, y
u, v
} TexVertex2D;- w = viewPort.width;
- h = viewPort.height;
TexVertex2D vQuad[ 4 ] =
{
{ 0, 0, fUVOffset, fUVOffset },
{ w, 0, 1 - fUVOffset, fUVOffset },
{ w, h, 1 - fUVOffset, 1 - fUVOffset },
{ 0, h, fUVOffset, 1 - fUVOffset }
}
DrawScreenQuad( vQuad );
}
It draws a number of quads to the destination texture. They are all the same size, covering the entire viewport of the destination texture. The only difference is that with every new quad the range of the source texture is more and more limited to the center, thus resulting in a zoomed-in version of the previous quad. By additively blending the individual quads together we get a radial blur effect. The source factor used for blending is set to gradually fall down to zero. This is to fade out the beams. When finished blurring we can use the destination texture to blit/stretch the result to the screen.
The last thing of interest is how the star is rendered into the source texture for the radial blur. To render the star we set the source texture as the render target and draw a textured sphere. The only trick here is to find an appropriate texture to represent a star. For Meshuggah real sun pictures taken from SOHO (EIT304) were used and preprocessed to fit its needs. To animate the sun surface this texture as well as the texture coordinate set of the sphere is reused four times. In the vertex shader four individual texture coordinate sets are created by using the spheres original texture coordinate set and adding a texture offset - defined by an arbitrary function of time - every frame. Those four functions defining the texture offsets should return values which at all times are different one another. The pixel shader fetches four colors from the sun texture and calculates the weighted sum 0.25 * ( c1 + c2 + c3 + c4 ) of them. This will result in a complex motion of the sun surface.
Note when rendering the star to the source texture the aspect ratio should be set to match the screen - not the texture. This ensures that the star will appear as a spherical and not as an elliptical object when the result of the radial blur is to be copied to the screen.