HLSL: Gaussian Blur Effect

Salah Alshaal picture Salah Alshaal · Mar 30, 2016 · Viewed 9.6k times · Source

I'm trying to achieve a gaussian blur using post-processing. I have two render passes; first pass renders the scene and the second is used for the effect.

This is my pixel shader code:

const float offset[] = {
    0.0, 1.0, 2.0, 3.0, 4.0
    };
    const float weight[] = {
      0.2270270270, 0.1945945946, 0.1216216216,
      0.0540540541, 0.0162162162
    };
    ppColour = SceneTexture.Sample(PointSample, ppIn.UV) * weight[0];
    float3 FragmentColor = float3(0.0f, 0.0f, 0.0f);

    for (int i = 1; i < 5; i++) {
        // Horizontal-pass
        FragmentColor +=
            SceneTexture.Sample(PointSample, ppIn.UV + float2(0.0f, offset[i]))*weight[i] +
            SceneTexture.Sample(PointSample, ppIn.UV - float2(0.0f, offset[i]))*weight[i];      
            // Vertical-pass
        FragmentColor +=
            SceneTexture.Sample(PointSample, ppIn.UV + float2(offset[i], 0.0f))*weight[i] +
            SceneTexture.Sample(PointSample, ppIn.UV - float2(offset[i], 0.0f))*weight[i];
        }
ppColour += FragmentColor;
return (ppColour,1.0);

I get a string-y look, as seen: enter image description here

What am I doing wrong?

Answer

Zamrony P. Juhara picture Zamrony P. Juhara · Mar 30, 2016

I think you need to render horizontal and vertical pass separately using shader code such as below but with different direction (See dir uniform variable). So you need 3 steps

  • Render scene to texture A using default shader
  • Render texture A to texture B using gaussion blur shader horizontally (dir={1.0,0.0})
  • Render texture B to screen using same gaussion blur shader vertically (dir={0.0,1.0})
uniform vec2 dir;

const float offset[] = {0.0, 1.0, 2.0, 3.0, 4.0};
const float weight[] = {
  0.2270270270, 0.1945945946, 0.1216216216,
  0.0540540541, 0.0162162162
};
ppColour = SceneTexture.Sample(PointSample, ppIn.UV) * weight[0];
float3 FragmentColor = float3(0.0f, 0.0f, 0.0f);

//(1.0, 0.0) -> horizontal blur
//(0.0, 1.0) -> vertical blur
float hstep = dir.x;
float vstep = dir.y;

for (int i = 1; i < 5; i++) {
    FragmentColor +=
        SceneTexture.Sample(PointSample, ppIn.UV + float2(hstep*offset[i], vstep*offset[i]))*weight[i] +
        SceneTexture.Sample(PointSample, ppIn.UV - float2(hstep*offset[i], vstep*offset[i]))*weight[i];      
    }
ppColour += FragmentColor;
return (ppColour,1.0);

See Efficient Gaussion Blur with Linear Sampling