1
votes

I currently have implemented a gaussian blur shader in Opengl using C++. The gaussian blur works. However the results seems to be a bit displaced compared to the original image. The resulting blur image seems to be placed some what higher and placed some what to the left. And not centered on the same place as the original.

The gaussian blur which I am using is a two pass calculation. I based the gaussian calculation on demo code which I found on the web.

The gaussian kernel calculation looks like this:

    for(i = 0; i <= center; ++i)
    {
        result            = exp(-(i*i)/(double)(2*_sigma*_sigma));
        _kernel[center+i]  = _kernel[center-i] = (float)result;
        sum              += (float)result;
        if(i != 0) sum   += (float)result;

    }

    // normalize kernel
    for(i = 0; i <= center; ++i)
    {
        _kernel[center+i] = _kernel[center-i] /= sum;
    }

The offset calculation looks like this:

_offsets        = new float [_kernelSize * 2 + 1];
_offsetSize     = _kernelSize * 2 + 1;

float xInc      = 0;

if(_shaderType == S2DGaussianComponentBlurShaderHorizontal)
{
    xInc        = 1.0f / (float)_width;
}
else
{
    xInc        = 1.0f / (float)_height;
}

int   index     = 0;
for (int i = -_kernelSize; i < _kernelSize + 1; ++i)
{
    index            = i + _kernelSize;
    _offsets [index] = i * xInc;
}

The frag shader looks like this:

#version 120   \n                               \
uniform sampler2D texture;                      \
varying vec4 texcoord;                          \
                                                \
                                                \
uniform int kernelSize;                         \
uniform float weight[50];                       \
uniform float offsets[50];                      \
void main(void)                                 \
{                                               \
vec2 uv  = texcoord.xy;                         \
vec4 sum = vec4(0.0);                           \
for (int i = 0; i< kernelSize; i++)             \
{                                               \
vec4 tmp       = texture2D( texture,  uv + vec2(0.0, offsets[i]) ); \
sum           += tmp * weight[i];               \
}                                               \
                                                \
gl_FragColor = sum;                             \
}"

The texture input are using these:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

Any thoughts what might be wrong?

1
Kernel/shader code looks good. problem could be in the way you apply it - e.g. vertex shader or vertex positions/texture coordinates.kerim
@kerim I figured it out, please check answer below :)battleex

1 Answers

1
votes

I figured it out.

It seems that the '_offsets' must be the same size as the kernel. The main reason for this is that the center position of the offsets must be at the same position as the center position of the kernel. If you don't do this, then the gaussian will not be aligned properly with the texture.

One way of doing this is to make the '_offsets' the same size as the kernel.

I have been looking for this solution for days -_-'