5
\$\begingroup\$

How do I perform a circular/rotational/spin blur on an image - using DirectX9.0 and HLSL?

For example:

Radial Blur - Courtesy Apple.com

\$\endgroup\$
0

2 Answers 2

3
\$\begingroup\$

You will need to work in Polar Coordinates. In order to convert Cartesian Coordinates into Polar you use the following:

r = sqrt(x * x + y * y);
theta = atan2(y, x);

This will get the coordinates around {0, 0} - so we need to change the Cartesian origin before converting:

float mx = x - 0.5;
float my = y - 0.5;
float r = sqrt(mx * mx + my * my);
float theta = atan2(y, x);

Once you have the polar coordinates you can use a typical multi-tap blur to perform the blur.

const int SAMPLES = 15;
extern float PARAM_RadialBlurLength = 0.01f; // In radians

float2 offsetCoord = inputTexCoord - float2(0.5, 0.5);
float r = length(offsetCoord);
float theta = atan2(offsetCoord.y, offsetCoord.x);

float4 sum = (float4)0;
float2 tapCoords = (float2)0;
for(float i = 0; i < SAMPLES; i++)
{
  float tapTheta = theta + i * (PARAM_radialBlurLength / SAMPLES);
  float tapR = r; // If you alter this according to 'i' you will get a swirl.

  // Remember we need to invert the origin offset we 
  // used to create the co-ordinates, the the + 0.5 on each.
  tapCoords.x = tapR * cos(tapTheta) + 0.5;
  tapCoords.y = tapR * sin(tapTheta) + 0.5;

  sum += tex2D(inputSampler, tapCoords);
}
sum /= SAMPLES;
return sum;
\$\endgroup\$
3
  • \$\begingroup\$ I don't have XNA here, so YMMV with that code - but it should be correct as far as pseudo-code goes. \$\endgroup\$ Nov 15, 2011 at 13:45
  • \$\begingroup\$ Hi , This is perfect and mind blowing solution . Its work fine and exactly what I want. \$\endgroup\$
    – Emon
    Nov 16, 2011 at 3:55
  • \$\begingroup\$ @Ajit remember to mark it as your chosen answer if it works. \$\endgroup\$ Nov 16, 2011 at 8:13
4
\$\begingroup\$

A blur just uses temporal coherence. It doesn't really matter what technology you're using to implement it, so long as you know how to do alpha, you're all good to go.

loop
{
lastRotation = currentRotation
++currentRotation;

draw image texture at lastRotation with some degree of alpha (eg. 50%, this is the blur)
draw image texture at currentRotation with full alpha (the actual image that is spinning)
}

Of course, you needn't just have one lastRotation, you can have an array of them, such that you can have an extensive blur behind your actual spinning image. Each one will reflect the rotation as it was further back in time.

HTH.

\$\endgroup\$
3
  • \$\begingroup\$ He could also just accumulate the previous textures in a back buffer (this is how temporal blurring works). \$\endgroup\$ Nov 15, 2011 at 13:28
  • \$\begingroup\$ @JonathanDickinson. I've kept the answer general rather than specific to be a useful resource for others. Not every graphics API uses the backbuffer paradigm. \$\endgroup\$
    – Engineer
    Nov 15, 2011 at 13:48
  • 2
    \$\begingroup\$ Maybe add it as a potential solution for the APIs that do (his one certainly does). \$\endgroup\$ Nov 15, 2011 at 13:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .