Texture reduces when you apply the blur effect

After

Before


Class Game1

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    private const int BLUR_RADIUS = 7;
    private const float BLUR_AMOUNT = 2.0f;

 
    private SpriteFont spriteFont;
    private Texture2D texture;
    private RenderTarget2D renderTarget1;
    private RenderTarget2D renderTarget2;
    private Vector2 fontPos;
    private KeyboardState currentKeyboardState;
    private KeyboardState prevKeyboardState;
    private GaussianBlur gaussianBlur;
    private int windowWidth;
    private int windowHeight;
    private int renderTargetWidth;
    private int renderTargetHeight;
    private int frames;
    private int framesPerSecond;
    private TimeSpan elapsedTime = TimeSpan.Zero;
    private bool displayHelp;
    private bool enableGaussianBlur;
    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        Window.Title = "XNA 4.0 Gaussian Blur";
        IsMouseVisible = true;
        IsFixedTimeStep = false;
    }
       
    protected override void Initialize()
    {
        // Setup the window to be a quarter the size of the desktop.

        windowWidth = GraphicsDevice.DisplayMode.Width / 2;
        windowHeight = GraphicsDevice.DisplayMode.Height / 2;

        // Setup frame buffer.
        
        graphics.SynchronizeWithVerticalRetrace = false;
        graphics.PreferredBackBufferWidth = windowWidth;
        graphics.PreferredBackBufferHeight = windowHeight;
        graphics.ApplyChanges();

        // Position the text.
        
        fontPos = new Vector2(1.0f, 1.0f);

        // Setup the initial input states.
        
        currentKeyboardState = Keyboard.GetState();
                    
        // Create the Gaussian blur filter kernel.
        
        gaussianBlur = new GaussianBlur(this);
        gaussianBlur.ComputeKernel(BLUR_RADIUS, BLUR_AMOUNT);
                    
        base.Initialize();
    }

    private void InitRenderTargets()
    {
        // Since we're performing a Gaussian blur on a texture image the
        // render targets are half the size of the source texture image.
        // This will help improve the blurring effect.

        renderTargetWidth = texture.Width / 2;
        renderTargetHeight = texture.Height / 2;

        renderTarget1 = new RenderTarget2D(GraphicsDevice,
            renderTargetWidth, renderTargetHeight, false,
            GraphicsDevice.PresentationParameters.BackBufferFormat,
            DepthFormat.None);

        renderTarget2 = new RenderTarget2D(GraphicsDevice,
            renderTargetWidth, renderTargetHeight, false,
            GraphicsDevice.PresentationParameters.BackBufferFormat,
            DepthFormat.None);

        // The texture offsets used by the Gaussian blur shader depends
        // on the dimensions of the render targets. The offsets need to be
        // recalculated whenever the render targets are recreated.

        gaussianBlur.ComputeOffsets(renderTargetWidth, renderTargetHeight);
    }

    private bool KeyJustPressed(Keys key)
    {
        return currentKeyboardState.IsKeyDown(key) && prevKeyboardState.IsKeyUp(key);
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        spriteFont = Content.Load<SpriteFont>(@"Fonts\DemoFont");

        texture = Content.Load<Texture2D>(@"Textures\lena");

        InitRenderTargets();
    }

    private void ProcessKeyboard()
    {
        prevKeyboardState = currentKeyboardState;
        currentKeyboardState = Keyboard.GetState();

        if (KeyJustPressed(Keys.Escape))
            this.Exit();

        if (KeyJustPressed(Keys.Space))
            enableGaussianBlur = !enableGaussianBlur;

        if (KeyJustPressed(Keys.H))
            displayHelp = !displayHelp;

        if (currentKeyboardState.IsKeyDown(Keys.LeftAlt) ||
            currentKeyboardState.IsKeyDown(Keys.RightAlt))
        {
            if (KeyJustPressed(Keys.Enter))
                ToggleFullScreen();
        }
    }

    private void ToggleFullScreen()
    {
        int newWidth = 0;
        int newHeight = 0;

        graphics.IsFullScreen = !graphics.IsFullScreen;

        if (graphics.IsFullScreen)
        {
            newWidth = GraphicsDevice.DisplayMode.Width;
            newHeight = GraphicsDevice.DisplayMode.Height;
        }
        else
        {
            newWidth = windowWidth;
            newHeight = windowHeight;
        }

        graphics.PreferredBackBufferWidth = newWidth;
        graphics.PreferredBackBufferHeight = newHeight;
        graphics.ApplyChanges();
    }

    protected override void UnloadContent()
    {
        renderTarget1.Dispose();
        renderTarget1 = null;

        renderTarget2.Dispose();
        renderTarget2 = null;
    }

    protected override void Update(GameTime gameTime)
    {
        if (!IsActive)
            return;

        ProcessKeyboard();
        UpdateFrameRate(gameTime);

        base.Update(gameTime);
    }

    private void UpdateFrameRate(GameTime gameTime)
    {
        elapsedTime += gameTime.ElapsedGameTime;

        if (elapsedTime > TimeSpan.FromSeconds(1))
        {
            elapsedTime -= TimeSpan.FromSeconds(1);
            framesPerSecond = frames;
            frames = 0;
        }
    }

    private void IncrementFrameCounter()
    {
        ++frames;
    }

    private void DrawText()
    {
        StringBuilder buffer = new StringBuilder();

        if (displayHelp)
        {
            buffer.AppendLine("Press SPACE to enable/disable Gaussian blur");
            buffer.AppendLine("Press ALT and ENTER to toggle full screen");
            buffer.AppendLine("Press ESCAPE to exit");
            buffer.AppendLine();
            buffer.AppendLine("Press H to hide help");
        }
        else
        {
            buffer.AppendFormat("FPS: {0}\n", framesPerSecond);
            buffer.AppendLine();
            buffer.AppendFormat("Radius: {0}\n", gaussianBlur.Radius);
            buffer.AppendFormat("Sigma: {0}\n", gaussianBlur.Sigma.ToString("f2"));
            buffer.AppendLine();
            buffer.AppendLine("Press H to display help");
        }

        spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
        spriteBatch.DrawString(spriteFont, buffer.ToString(), fontPos, Color.Yellow);
        spriteBatch.End();
    }

    protected override void Draw(GameTime gameTime)
    {
        if (!IsActive)
            return;

        if (enableGaussianBlur)
        {
            Texture2D result = gaussianBlur.PerformGaussianBlur(texture, renderTarget1, renderTarget2, spriteBatch);
            Rectangle rectangle = new Rectangle(0, 0, texture.Width, texture.Height);

            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(result, rectangle, Color.White);
            spriteBatch.End();
        }
        else
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(texture, new Rectangle(0, 0, texture.Width, texture.Height), Color.White);
            spriteBatch.End();
        }

        DrawText();
        base.Draw(gameTime);
        IncrementFrameCounter();
    }

Class GaussianBlur

  public class GaussianBlur
  {
        private Game game;
        private Effect effect;
        private int radius;
        private float amount;
        private float sigma;
        private float[] kernel;
        private Vector2[] offsetsHoriz;
        private Vector2[] offsetsVert;

    /// <summary>
    /// Returns the radius of the Gaussian blur filter kernel in pixels.
    /// </summary>


    public int Radius
    {
        get { return radius; }
    }

    /// <summary>
    /// Returns the blur amount. This value is used to calculate the
    /// Gaussian blur filter kernel's sigma value. Good values for this
    /// property are 2 and 3. 2 will give a more blurred result whilst 3
    /// will give a less blurred result with sharper details.
    /// </summary>
    public float Amount
    {
        get { return amount; }
    }

    /// <summary>
    /// Returns the Gaussian blur filter's standard deviation.
    /// </summary>
    public float Sigma
    {
        get { return sigma; }
    }

    /// <summary>
    /// Returns the Gaussian blur filter kernel matrix. Note that the
    /// kernel returned is for a 1D Gaussian blur filter kernel matrix
    /// intended to be used in a two pass Gaussian blur operation.
    /// </summary>
    public float[] Kernel
    {
        get { return kernel; }
    }

    /// <summary>
    /// Returns the texture offsets used for the horizontal Gaussian blur
    /// pass.
    /// </summary>
    public Vector2[] TextureOffsetsX
    {
        get { return offsetsHoriz; }
    }

    /// <summary>
    /// Returns the texture offsets used for the vertical Gaussian blur
    /// pass.
    /// </summary>
    public Vector2[] TextureOffsetsY
    {
        get { return offsetsVert; }
    }

    /// <summary>
    /// Default constructor for the GaussianBlur class. This constructor
    /// should be called if you don't want the GaussianBlur class to use
    /// its GaussianBlur.fx effect file to perform the two pass Gaussian
    /// blur operation.
    /// </summary>
    public GaussianBlur()
    {
    }

    /// <summary>
    /// This overloaded constructor instructs the GaussianBlur class to
    /// load and use its GaussianBlur.fx effect file that implements the
    /// two pass Gaussian blur operation on the GPU. The effect file must
    /// be already bound to the asset name: 'Effects\GaussianBlur' or
    /// 'GaussianBlur'.
    /// </summary>
    public GaussianBlur(Game game)
    {
        this.game = game;

        try
        {
            effect = game.Content.Load<Effect>(@"Effects\GaussianBlur");
        }
        catch (ContentLoadException)
        {
            effect = game.Content.Load<Effect>("GaussianBlur");
        }
    }

    /// <summary>
    /// Calculates the Gaussian blur filter kernel. This implementation is
    /// ported from the original Java code appearing in chapter 16 of
    /// "Filthy Rich Clients: Developing Animated and Graphical Effects for
    /// Desktop Java".
    /// </summary>
    /// <param name="blurRadius">The blur radius in pixels.</param>
    /// <param name="blurAmount">Used to calculate sigma.</param>
    public void ComputeKernel(int blurRadius, float blurAmount)
    {
        radius = blurRadius;
        amount = blurAmount;

        kernel = null;
        kernel = new float[radius * 2 + 1];
        sigma = radius / amount;

        float twoSigmaSquare = 2.0f * sigma * sigma;
        float sigmaRoot = (float)Math.Sqrt(twoSigmaSquare * Math.PI);
        float total = 0.0f;
        float distance = 0.0f;
        int index = 0;

        for (int i = -radius; i <= radius; ++i)
        {
            distance = i * i;
            index = i + radius;
            kernel[index] = (float)Math.Exp(-distance / twoSigmaSquare) / sigmaRoot;
            total += kernel[index];
        }

        for (int i = 0; i < kernel.Length; ++i)
            kernel[i] /= total;
    }

    /// <summary>
    /// Calculates the texture coordinate offsets corresponding to the
    /// calculated Gaussian blur filter kernel. Each of these offset values
    /// are added to the current pixel's texture coordinates in order to
    /// obtain the neighboring texture coordinates that are affected by the
    /// Gaussian blur filter kernel. This implementation has been adapted
    /// from chapter 17 of "Filthy Rich Clients: Developing Animated and
    /// Graphical Effects for Desktop Java".
    /// </summary>
    /// <param name="textureWidth">The texture width in pixels.</param>
    /// <param name="textureHeight">The texture height in pixels.</param>
    public void ComputeOffsets(float textureWidth, float textureHeight)
    {
        offsetsHoriz = null;
        offsetsHoriz = new Vector2[radius * 2 + 1];

        offsetsVert = null;
        offsetsVert = new Vector2[radius * 2 + 1];

        int index = 0;
        float xOffset = 1.0f / textureWidth;
        float yOffset = 1.0f / textureHeight;

        for (int i = -radius; i <= radius; ++i)
        {
            index = i + radius;
            offsetsHoriz[index] = new Vector2(i * xOffset, 0.0f);
            offsetsVert[index] = new Vector2(0.0f, i * yOffset);
        }
    }

    /// <summary>
    /// Performs the Gaussian blur operation on the source texture image.
    /// The Gaussian blur is performed in two passes: a horizontal blur
    /// pass followed by a vertical blur pass. The output from the first
    /// pass is rendered to renderTarget1. The output from the second pass
    /// is rendered to renderTarget2. The dimensions of the blurred texture
    /// is therefore equal to the dimensions of renderTarget2.
    /// </summary>
    /// <param name="srcTexture">The source image to blur.</param>
    /// <param name="renderTarget1">Stores the output from the horizontal blur pass.</param>
    /// <param name="renderTarget2">Stores the output from the vertical blur pass.</param>
    /// <param name="spriteBatch">Used to draw quads for the blur passes.</param>
    /// <returns>The resulting Gaussian blurred image.</returns>
    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;
    }

}


File GaussianBlur.fx

#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_4_0_level_9_1 PS_GaussianBlur();
    }
}

Could this be the problem? You’re initialising your rendertargets to half the width and height of the original texture instead of the full width and height.

I already tried to change it but it still stays the same, only bigger

Odd, it shouldn’t be drawing bigger as both times you’re specifying the exact same rectangle area to draw it in. Stick a breakpoint into the code and check the width and height of “texture” and "result after performing the blur.

Why do you use outputTexture as colormap instead of setting it as rendertarget while doing the horizontal pass?
And use rendertarget1 from the horizontal pass. Or do you want separated blur direction?