2D Selective Gaussian Blur
- by Joshua Thomas
I am attempting to use Gaussian blur on a 2D platform game, selectively blurring specific types of platforms with different amounts. I am currently just messing around with simple test code, trying to get it to work correctly. What I need to eventually do is create three separate render targets, leave one normal, blur one slightly, and blur the last heavily, then recombine on the screen. Where I am now is I have successfully drawn into a new render target and performed the gaussian blur on it, but when I draw it back to the screen everything is purple aside from the platforms I drew to the target.
This is my .fx file:
#define RADIUS 7
#define KERNEL_SIZE (RADIUS * 2 + 1)
//-----------------------------------------------------------------------------
// Globals.
//-----------------------------------------------------------------------------
float weights[KERNEL_SIZE];
float2 offsets[KERNEL_SIZE];
//-----------------------------------------------------------------------------
// Textures.
//-----------------------------------------------------------------------------
texture colorMapTexture;
sampler2D colorMap = sampler_state
{
Texture = <colorMapTexture>;
MipFilter = Linear;
MinFilter = Linear;
MagFilter = Linear;
};
//-----------------------------------------------------------------------------
// Pixel Shaders.
//-----------------------------------------------------------------------------
float4 PS_GaussianBlur(float2 texCoord : TEXCOORD) : COLOR0
{
float4 color = float4(0.0f, 0.0f, 0.0f, 0.0f);
for (int i = 0; i < KERNEL_SIZE; ++i)
color += tex2D(colorMap, texCoord + offsets[i]) * weights[i];
return color;
}
//-----------------------------------------------------------------------------
// Techniques.
//-----------------------------------------------------------------------------
technique GaussianBlur
{
pass
{
PixelShader = compile ps_2_0 PS_GaussianBlur();
}
}
This is the code I'm using for the gaussian blur:
public Texture2D PerformGaussianBlur(Texture2D srcTexture,
RenderTarget2D renderTarget1,
RenderTarget2D renderTarget2,
SpriteBatch spriteBatch)
{
if (effect == null)
throw new InvalidOperationException("GaussianBlur.fx effect not loaded.");
Texture2D outputTexture = null;
Rectangle srcRect = new Rectangle(0, 0, srcTexture.Width, srcTexture.Height);
Rectangle destRect1 = new Rectangle(0, 0, renderTarget1.Width, renderTarget1.Height);
Rectangle destRect2 = new Rectangle(0, 0, renderTarget2.Width, renderTarget2.Height);
// Perform horizontal Gaussian blur.
game.GraphicsDevice.SetRenderTarget(renderTarget1);
effect.CurrentTechnique = effect.Techniques["GaussianBlur"];
effect.Parameters["weights"].SetValue(kernel);
effect.Parameters["colorMapTexture"].SetValue(srcTexture);
effect.Parameters["offsets"].SetValue(offsetsHoriz);
spriteBatch.Begin(0, BlendState.Opaque, null, null, null, effect);
spriteBatch.Draw(srcTexture, destRect1, Color.White);
spriteBatch.End();
// Perform vertical Gaussian blur.
game.GraphicsDevice.SetRenderTarget(renderTarget2);
outputTexture = (Texture2D)renderTarget1;
effect.Parameters["colorMapTexture"].SetValue(outputTexture);
effect.Parameters["offsets"].SetValue(offsetsVert);
spriteBatch.Begin(0, BlendState.Opaque, null, null, null, effect);
spriteBatch.Draw(outputTexture, destRect2, Color.White);
spriteBatch.End();
// Return the Gaussian blurred texture.
game.GraphicsDevice.SetRenderTarget(null);
outputTexture = (Texture2D)renderTarget2;
return outputTexture;
}
And this is the draw method affected:
public void Draw(SpriteBatch spriteBatch)
{
device.SetRenderTarget(maxBlur);
spriteBatch.Begin();
foreach (Brick brick in blueBricks)
brick.Draw(spriteBatch);
spriteBatch.End();
blue = gBlur.PerformGaussianBlur((Texture2D) maxBlur, helperTarget, maxBlur, spriteBatch);
spriteBatch.Begin();
device.SetRenderTarget(null);
foreach (Brick brick in redBricks)
brick.Draw(spriteBatch);
foreach (Brick brick in greenBricks)
brick.Draw(spriteBatch);
spriteBatch.Draw(blue, new Rectangle(0, 0, blue.Width, blue.Height), Color.White);
foreach (Brick brick in purpleBricks)
brick.Draw(spriteBatch);
spriteBatch.End();
}
I'm sorry about the massive brick of text and images(or not....new user, I tried, it said no), but I wanted to get my problem across clearly as I have been searching for an answer to this for quite a while now. As a side note, I have seen the bloom sample. Very well commented, but overly complicated since it deals in 3D; I was unable to take what I needed to learn form it. Thanks for any and all help.