Gaussian Blur with Depth Preservation


This post will show a simple implementation of a gaussian blur effect with edge preservation.

Sometimes (like in fluid rendering) we need to perform a gaussian blur but we also need to still with edge preservation. The following code shows how to achieve this.

First, we need to calculate the Gaussian Blur Kernel and sent them to the GPU:

   
private float sigma;
        private float[] kernel;
        private Vector2[] offsetsHoriz;
        private Vector2[] offsetsVert;
        private int radius;
        private float amount;
        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;
        }
        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);
            }
        }       

We call both funtions in Intialization time passing the parameters: blurRadius = something ranging from 2 to 15 (the Kernel width), blurAmount = blur scale parameter, textureWidth = width of the texture that will be blured, textureHeight = same for height.

Here is the shader that Performs the Gaussian Blur (the RADIUS value must be defined in Compilation time, it must have the same value used in CPU side)

#define RADIUS  15
#define KERNEL_SIZE (RADIUS * 2 + 1)
float weights[KERNEL_SIZE];
float2 offsets[KERNEL_SIZE];

float2 GBufferPixelSize; ///half pixel size of the origin render target(0.5f /width , 0.5f/height)
float2 TempBufferRes; ///destiny buffer size
float blurDepthFalloff;

sampler2D depthSampler : register(s0);
sampler2D ssaoSampler : register(s1);

struct VertexShaderInput
{
    float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
	float4 TexCoord : TEXCOORD0;
};

VertexShaderOutput VertexShaderBlur(VertexShaderInput input)
{
    VertexShaderOutput output = (VertexShaderOutput)0;

	output.Position = input.Position;
	output.TexCoord.xy = input.TexCoord + GBufferPixelSize;
	output.TexCoord.zw = input.TexCoord + 0.5f / TempBufferRes;
	return output;
}

/////////////////////////////////// bilateral

float4 PS_GaussianBlurTriple(float4 texCoord : TEXCOORD0) : COLOR0
{
    float3 color = 0;

    float depth = tex2D(depthSampler, texCoord.xy).x;	

    float s=0;
    for (int i = 0; i < KERNEL_SIZE; ++i)
	{
		float3 im = tex2D(ssaoSampler, texCoord.zw + offsets[i] );
		float d = tex2D(depthSampler, texCoord.xy + offsets[i] ).x;
		float r2 = abs(depth - d) * blurDepthFalloff;
		float g = exp(-r2*r2);
		color +=  im* weights[i] * g;
		s+=g* weights[i];
	}
	color = color/s;
	return float4(color,1);
}

technique GAUSSTriple
{
    pass p0
    {
	VertexShader = compile vs_3_0 VertexShaderBlur();
        PixelShader = compile ps_3_0 PS_GaussianBlurTriple();
    }
}

//////////////////////////////////////

float4 PS_GaussianBlurSingle(float4 texCoord : TEXCOORD0) : COLOR0
{
    float color = 0;
    float depth = tex2D(depthSampler, texCoord.xy).x;	

	float s=0;
    for (int i = 0; i < KERNEL_SIZE; ++i)
	{
		float im = tex2D(ssaoSampler, texCoord.zw + offsets[i] ).x;
		float d = tex2D(depthSampler, texCoord.xy + offsets[i] ).x;
		float r2 = abs(depth - d) * blurDepthFalloff;
		float g = exp(-r2*r2);
		color +=  im* weights[i] * g;
		s+=g* weights[i];
	}
	color = color/s;
	return float4(color,0,0,1);
}

technique GAUSSSingle
{
    pass p0
    {
		VertexShader = compile vs_3_0 VertexShaderBlur();
        PixelShader = compile ps_3_0 PS_GaussianBlurSingle();
    }
}

I included two version of the pixel shader, one for Color Texture and another for float point textures (used in fluid rendering for example).
The blurDepthFalloff is a artistic/adjustment parameter
The DepthTexture is a texture containing the depth of the Scene (in z/w form). See this article for more details about how to generate it.

To render the Scene (Post Effect) we use Render a Quad using the previous shader and the avaluated parameters.

            rHelper.PushRenderTarget(RenderTarget2D);
            effect.Parameters["blurDepthFalloff"].SetValue(blurDepthFalloff);
            effect.Parameters["weights"].SetValue(kernel);
            effect.Parameters["offsets"].SetValue(offsetsHoriz);
            effect.Parameters["GBufferPixelSize"].SetValue(new Vector2(1f / ImageToProcess.Width, 1f / ImageToProcess.Height));
            effect.Parameters["TempBufferRes"].SetValue(destinySize.Value);
            rHelper.Textures[0] = rHelper[PrincipalConstants.DephRT];
            rHelper.Textures[1] = ImageToProcess;
            SamplerState s0 = rHelper.SetSamplerState(SamplerState.PointClamp, 0);
            SamplerState s1 = rHelper.SetSamplerState(ImageSamplerState, 1);
            rHelper.RenderFullScreenQuadVertexPixel(effect);

            rHelper.PopRenderTarget();

            effect.Parameters["offsets"].SetValue(offsetsVert);
            rHelper.Textures[1] = RenderTarget2D;
            rHelper.RenderFullScreenQuadVertexPixel(effect);

            rHelper.SetSamplerState(s0, 0);
            rHelper.SetSamplerState(s1, 1);

Quite Simple !
The Gaussian Blur with edge preservation is not Separable (we cant perform a Y and a X pass independentely) but for performance we normally dont care about this.

,

  1. #1 by Business Service on 22 de junho de 2017 - 6:27 am

    Perfectly pent content, appreciate it for entropy. “You can do very little with faith, but you can do nothing without it.” by Samuel Butler.

  2. #2 by low car insurance on 22 de junho de 2017 - 6:37 am

    Muchos Gracias for your post.Thanks Again. Cool.

  3. #3 by Offshore hosting on 22 de junho de 2017 - 7:10 am

    I think this is a real great blog.Thanks Again. Want more.

  4. #4 by the four percent on 22 de junho de 2017 - 8:03 am

    Major thanks for the article.Really thank you! Really Cool.

  5. #5 by agen bandarq online on 22 de junho de 2017 - 9:14 am

    Hey there. I discovered your website by way of Google whilst searching for a comparable subject, your web site came up. It looks great. I’ve bookmarked it in my google bookmarks to come back then.

  6. #6 by پنجره 2 3 جداره on 22 de junho de 2017 - 9:14 am

    When some one searches for his necessary thing, therefore he/she needs to be available that in detail, therefore that thing is maintained over here.

  7. #7 by New Orleans fishing charters on 22 de junho de 2017 - 10:51 am

    check below, are some entirely unrelated internet sites to ours, on the other hand, they may be most trustworthy sources that we use

  8. #8 by web site on 22 de junho de 2017 - 10:59 am

    please go to the web-sites we adhere to, like this 1, because it represents our picks through the web

  9. #9 by pleasure whip on 22 de junho de 2017 - 11:06 am

    although websites we backlink to beneath are considerably not associated to ours, we feel they’re essentially really worth a go via, so possess a look

  10. #10 by situs bandarq on 22 de junho de 2017 - 11:28 am

    Awesome write-up. I’m a regular visitor of your website and appreciate you taking the time to maintain the nice site. I will be a frequent visitor for a long time.

  11. #11 by پنجره دوجداره وین تک on 22 de junho de 2017 - 11:54 am

    Some really quality blog posts on this website , saved to my bookmarks.

  12. #12 by Swords For Sale on 22 de junho de 2017 - 12:54 pm

    I am very pleased with this Musashi sword. It arrived quite sharp and with no issues such as warped blades. It included a cotton sword bag for storage and a certificate of authenticity. My sword had a slight rattle in the hilt. I was concerned that the hilt was loose, but, after removing the pegs, I was completely unable to budge the hilt. Turned out that the “rattle” was actually the Menuki, the little brass good luck charm that Samurai had placed under the wrappings. This is probably one of the best swords you can get in this price range.

  13. #13 by porn gifs on 22 de junho de 2017 - 1:03 pm

    I value the article.Really thank you! Much obliged.

  14. #14 by situs bandarq online on 22 de junho de 2017 - 1:12 pm

    Awesome write-up. I’m a regular visitor of your site and appreciate you taking the time to maintain the nice site. I will be a regular visitor for a long time.

  15. #15 by paket wisata pulau tidung on 22 de junho de 2017 - 1:53 pm

    Hi there. I discovered your web site via Google whilst searching for a comparable matter, your site got here up. It seems good. I’ve bookmarked it in my google bookmarks to visit then.

  16. #16 by bandarq online on 22 de junho de 2017 - 2:11 pm

    Hiya, I am really glad I have found this info. Nowadays bloggers publish only about gossip and web stuff and this is actually frustrating. A good web site with interesting content, this is what I need. Thank you for making this web site, and I’ll be visiting again. Do you do newsletters by email?

  17. #17 by My Music on 22 de junho de 2017 - 2:12 pm

    Thank you a lot for sharing this with all folks you really understand what you are speaking about! Bookmarked. Kindly also consult with my web site =). We will have a hyperlink exchange arrangement between us!

  18. #18 by jenny on 22 de junho de 2017 - 2:40 pm

    prescription diet pills drugs phentermine hydrochloride

  19. #19 by web Design on 22 de junho de 2017 - 3:14 pm

    I like the valuable info you provide in your articles. I will bookmark your blog and check again here regularly. I’m quite certain I’ll learn many new stuff right here! Good luck for the next!

  20. #20 by Travel and Leisure on 22 de junho de 2017 - 4:28 pm

    Great – I should certainly pronounce, impressed with your website. I had no trouble navigating through all the tabs as well as related information ended up being truly easy to do to access. I recently found what I hoped for before you know it in the least. Quite unusual. Is likely to appreciate it for those who add forums or something, web site theme . a tones way for your customer to communicate. Nice task.

  21. #21 by nike air max on 22 de junho de 2017 - 5:15 pm

    want to suggest you some interesting things or advice.

  22. #22 by best katana on 22 de junho de 2017 - 6:39 pm

    Although slow shipping, the sword was really nice looking and very shape :)

  23. #23 by best plumbing contractor on 22 de junho de 2017 - 6:39 pm

    The facts mentioned in the report are a number of the ideal obtainable

  24. #24 by other on 22 de junho de 2017 - 7:00 pm

    I simply want to say I’m all new to blogging and site-building and seriously loved this web site. Probably I’m want to bookmark your blog . You actually come with really good well written articles. Bless you for revealing your blog site.

  25. #25 by Education and Training on 22 de junho de 2017 - 7:10 pm

    Absolutely composed written content, thank you for selective information. “No human thing is of serious importance.” by Plato.

  26. #26 by Web Design on 22 de junho de 2017 - 7:11 pm

    We’re a group of volunteers and opening a new scheme in our community. Your web site offered us with valuable information to work on. You have done an impressive job and our whole community will be grateful to you.

1 317 318 319
(não será publicado)