2
\$\begingroup\$

I want to blur image with Gaussian blur algorithm. And I use the following shaders:

Vertex shader

attribute vec4 position;
attribute vec4 inputTextureCoordinate;

const int GAUSSIAN_SAMPLES = 9;

uniform float texelWidthOffset;
uniform float texelHeightOffset;

varying vec2 textureCoordinate;
varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];

void main()
{
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;

    // Calculate the positions for the blur
    int multiplier = 0;
    vec2 blurStep;
   vec2 singleStepOffset = vec2(texelHeightOffset, texelWidthOffset);

    for (int i = 0; i < GAUSSIAN_SAMPLES; i++)
   {
        multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));
       // Blur in x (horizontal)
       blurStep = float(multiplier) * singleStepOffset;
        blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;
    }
}

Fragment shader

uniform sampler2D inputImageTexture;

const lowp int GAUSSIAN_SAMPLES = 9;

varying highp vec2 textureCoordinate;
varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];

void main()
{
    lowp vec3 sum = vec3(0.0);
   lowp vec4 fragColor=texture2D(inputImageTexture,textureCoordinate);

    sum += texture2D(inputImageTexture, blurCoordinates[0]).rgb * 0.05;
    sum += texture2D(inputImageTexture, blurCoordinates[1]).rgb * 0.09;
    sum += texture2D(inputImageTexture, blurCoordinates[2]).rgb * 0.12;
    sum += texture2D(inputImageTexture, blurCoordinates[3]).rgb * 0.15;
    sum += texture2D(inputImageTexture, blurCoordinates[4]).rgb * 0.18;
    sum += texture2D(inputImageTexture, blurCoordinates[5]).rgb * 0.15;
    sum += texture2D(inputImageTexture, blurCoordinates[6]).rgb * 0.12;
    sum += texture2D(inputImageTexture, blurCoordinates[7]).rgb * 0.09;
    sum += texture2D(inputImageTexture, blurCoordinates[8]).rgb * 0.05;

    gl_FragColor = vec4(sum,fragColor.a);
}

This produces an image with a lot of blurred squares.

enter image description here

But. How to get something like this? enter image description here

\$\endgroup\$
  • \$\begingroup\$ You need to blur in both X and Y directions, yet your code seem to blur only along one diagonal. \$\endgroup\$ – Kromster Nov 18 '15 at 13:56
  • \$\begingroup\$ How can I do it? \$\endgroup\$ – Semyon Tikhonenko Nov 18 '15 at 14:00
  • 1
    \$\begingroup\$ Basically your code should sample by X and by Y axis. for i = 0 to N-1 do for k = 0 to N - 1 do sum += sample[i,k] * multiplier. Don't do this like that though, use 2 pass blur, it's faster cos of sequential memory access. \$\endgroup\$ – Kromster Nov 18 '15 at 14:03
  • \$\begingroup\$ @ Semyon Tikhonenko had you get the right way for blur? i.stack.imgur.com/Bc8fM.jpg \$\endgroup\$ – isuker Sep 27 '17 at 9:53
1
\$\begingroup\$

The kind of artefacts you're seeing - the squares - are often caused by not sampling some pixels within the blur range. Since you're only using 9 samples, and your blur is quite soft, this is likely the case here. You're effectively blurring a lower-resolution image, but the next fragment over is blurring a slightly different lower-resolution image, and so on.

There are many approaches to blurring, but since you specifically mention Gaussian blur, I present two options without changing the blurring algorithm:

  1. Use more samples within your blur range, so that you're not skipping over pixels in the original image; or
  2. Downsample the image first, so that, at the resolution you're blurring, you're not skipping pixels.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.