This topic is 1073 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

1. I implemented Gaussian Blur and trying to turn the entire scene blurry gradually (not all of sudden)

Now I'm getting weird edges:

[attachment=30128:blur_effect.png]

Here is what I'm doing in Pixel Shader:

// Pixel Shader
const float Pixels[13] =
{
-6,
-5,
-4,
-3,
-2,
-1,
0,
1,
2,
3,
4,
5,
6
};

const float BlurWeights[13] =
{
0.002216,
0.008764,
0.026995,
0.064759,
0.120985,
0.176033,
0.199471,
0.176033,
0.120985,
0.064759,
0.026995,
0.008764,
0.002216,
};

float blur = 20.0f; // The higher the more blurry
float4 color = float4(0.0f, 0.0f, 0.0f, 1.0f);

// Horizontal
float pixelWidth = (1.0f / screenWidth) * blur;
for (int i = 0; i < 13; i++)
{
color += Tex.Sample(SampleType, IN.UV + float2(Pixels[i] * pixelWidth, 0.0f)) * BlurWeights[i];
}

// Vertical
float pixelHeight = (1.0f / screenHeight) * blur;
for (int i = 0; i < 13; i++)
{
color += Tex.Sample(SampleType, IN.UV + float2(0.0f, Pixels[i] * pixelWidth)) * BlurWeights[i];
}

return color / 2;

2. Should I do the blur effect in two different shader passes (one for Horizontal and one for Vertical) or both in one single function call like the above code?

What if I'm doing Horizontal and vertical calculation in the same Pixel Shader function, is that a good way?

3. In the above example I'm not doing any down sample, If I do down sample and the blur is not too high, I see undesired jagged edges, which make things look unrealistic when I do gradual blur.

4. In the above example the kernel size is 13, when should I increase or decrease that number?

##### Share on other sites

You need to do this as two separate passes, one horizontal then one vertical (or vice versa).  What you currently have is blurring each pixel in a cross shape instead of as the full area around the pixel.

In other words, your current setup is blurring like below for each pixel, where the middle pixel (P) is the current one.  Separating these into two passes and blurring the first pass into a temporary buffer to be used as the input for the second pass will give you a blur that includes the pixels in the area surrounding the center point, also.

        *
*
*
*
********P*******
*
*
*
*


##### Share on other sites

@WFP: Thanks! Now it's better, however I have few questions:

1. If I don't do any down sample something looks weird (click on the image below to make it larger and see inside the red squares), how do I get rid of that without doing down sample?

[attachment=30141:blur_2.png]

2. If I want to do gradual blur, how should I do it?

What I was thinking about is that I down sample the screen to quarter of it's size and then apply blur effect, then gradually change the variable float blur; inside the shader from 0.1 to 2.0f, what do you think? (I want to make sure that the scene will look smooth all the time)

3. When should I change the kernel? What is the difference?

Edited by Medo3337

##### Share on other sites
I'm not positive but my first guess is that it's because of the additional space you're taking between blur taps. Try it by just taking neighboring pixels and not using the below value. You can just set it to 1.0f for testing before removing it.

float blur = 20.0f; // The higher the more blurry

I'm on mobile at the moment, so I'll try to get to your other questions later if no one else has yet.

##### Share on other sites

@WFP: If I remove float blur = 20.0f; How can I increase/decrease the blur?

##### Share on other sites

You need to recalculate the weights and pixel locations such that there aren't any source pixels that don't contribute to the blurred destination. So if you have a NxN pixel wide blur kernel, you might sample N different locations with N weights, one for each source pixel. In your case:

float pixelWidth = (1.0f / screenWidth) * blur;

pixelWidth is a misnomer because this variable doesn't represent the width of a pixel, it represents the texture space distance you step over.

const float Pixels[13]

This means your kernel is only suited for a 13x13 blur, and you can't do more than that unless you're going to get fancy with filtering.

Edited by Dingleberry

##### Share on other sites

One way to do a variable strength blur is to set up a filter kernel (i.e. array of weights) big enough for the maximum blur quantity you need.

You can pass that weights array as a parameter to the shader, and change the blur amount by adjusting the weights, and padding with zeros.

Making some numbers up, you could set up a 5 tap blur, with weights of say { 0.1, 0.2, 0.4, 0.2, 0.1 } and convert it to a 3 tap blur by setting the weights as say {0, 0.25, 0.5, 0.25, 0}

Obviously you'd need to calculate those weights on the CPU and upload them to the shader, and you'd probably want much more than a 5 tap shader.

##### Share on other sites

Adam_42's way to increase the blur is one approach.  Another approach is to simply run the result of the first blur pass through the blur technique again.  In pseudo-code it would look something like this:

int numPasses = 3;
for(int i = 0; i < numPasses; ++i)
{
setInputImage(imageToBlur);
setRenderTarget(tempBuffer);
blurVertical();
setInputImage(tempBuffer);
setRenderTarget(imageToBlur);
blurHorizontal();
}


If you were using a 7-tap blur in your shader and ran it through that loop 3 times, you would have the same result as running a 21-tap blur.

1. 1
2. 2
3. 3
Rutin
13
4. 4
5. 5

• 26
• 10
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633696
• Total Posts
3013394
×