Search code examples
directxhlslpixel-shaderpost-processing

HLSL: Gaussian Blur Effect


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?


Solution

  • 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