1
votes

I recently implemented a linear sampled gaussian blur based on this article: Linear Sampled Gaussian Blur

It generally came out well, however it appears there is slight aliasing on text and thinner collections of pixels. I'm pretty stumped as to what is causing this, is it an issue with my shader or weight calculations or is it an inherit draw back of using this method?

I'd like to add that I don't run into this issue when I sample each pixel regularly instead of using bilinear filtering.

Any insights are much appreciated. Here's a code sample of how I work out my weights:

int support = int(sigma * 3.0f);

float total = 0.0f;

weights.push_back(exp(-(0*0)/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma));
total += weights.back();

offsets.push_back(0);

for (int i = 1; i <= support; i++)
{
  float w1 = exp(-(i*i)/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma);
  float w2 = exp(-((i+1)*(i+1))/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma);
  
  weights.push_back(w1 + w2);
  total += 2.0f * weights[i];
  
  offsets.push_back((i * w1 + (i + 1) * w2) / weights[i]);
}

for (int i = 0; i < support; i++)
{
  weights[i] /= total;
}

And here is the fragment shader (there is another vertical version of this shader too):

 void main()
 {
  vec3 acc = texture2D(tex_object, v_tex_coord.st).rgb*weights[0];
  for (int i = 1; i < NUM_SAMPLES; i++)
  {
    acc += texture2D(tex_object, (v_tex_coord.st+(vec2(offsets[i], 0.0)/tex_size))).rgb*weights[i];
    acc += texture2D(tex_object, (v_tex_coord.st-(vec2(offsets[i], 0.0)/tex_size))).rgb*weights[i];
  }
  gl_FragColor = vec4(acc, 1.0);

Here is a screenshot depicting the issue:

Linear Sample Gaussian Blur Issue

2
I implemented a gauss-filter before and also had these artifacts, when I tried to use floating-offsets. When I used integer-offsets (I mean only the centers of the texels) it looked more smooth, seemed to be a filtering issue.Gnietschow
I've observed similar results. When I sample each pixel once at it's centre using double sigma I get a smoother result.Aequitas
You could apply the gauss-filter a few times to achieve a higher blur, while working with the pixelcenters to get a smooth and highly blurred result. If the result gets to dark, you could add the passes together.Gnietschow
The purpose of using this method was to halve the sampling count. I already have a blur that looks fine, I'd like to optimise what I've already got working correctly.Aequitas

2 Answers

2
votes

This looks like a correct gaussian blur to me. The extent to which text is disrupted depends on your sigma. What value are you using?

Also I would check the scaling matrix for the projection you are using.

If you want to blur but without affecting text and thin pixel lines, you might think of

  • compositing the result with the output of a mild high-pass filter
  • use a smaller sigma
  • change the shape of the kernel so it's not gaussian: rather than exp(-i*i/s*s), you might try a function with higher excess kurtosis. You could try a linear up/down function, or one of the functions listed on this page instead: http://en.wikipedia.org/wiki/Kurtosis . They will all lead to blurs with varying degrees of disrupting fine detail.
0
votes

This is an inherent issue with the bilinear filtering. It's unavoidable.