views:

309

answers:

3
uniform sampler2D sampler0;
uniform vec2 tc_offset[9];
void blur()
{
  vec4 sample[9];
  for(int i = 0; i < 9; ++i)
    sample[i] = texture2D(sampler0, gl_TexCoord[0].st + tc_offset[i]);

  gl_FragColor = (sample[0] + (2.0 * sample[1]) + sample[2] +
      (2.0 * sample[3]) + sample[4] + 2.0 * sample[5] +
      sample[6] + 2.0 * sample[7] + sample[8] ) / 13.0;
}

How does the sample[i] = texture2D(sample0, ...) line work?

It seems like to blur an image, I have to first generate the image, yet here, I'm somehow trying to query the very iamge I'm generating. How does this work?

+3  A: 

It applies a blur kernel to the image. tc_offset needs to be properly initialized by the application to form a 3x3 area of sampling points around the actual texture coordinate:

0   0   0
0   x   0
0   0   0

(assuming x is the original coordinate). The offset for the upper-left sampling point would be -1/width,-1/height. The offset for the center point needs to be carefully aligned to texel center (the off-by-0.5 problem). Also, the hardware bilinear filter can be used to cheaply increase the amount of blur (by sampling between texels).

The rest of the shader scales the samples by their distance. Usually, this is precomputed as well:

for(int i = 0; i < NUM_SAMPLES; ++i) {
    result += texture2D(sampler,texcoord+offsetscaling[i].xy)*offsetscaling[i].z;
}
Alexander Gessler
+3  A: 

One way is to generate your original image to render to a texture, not to the screen. And then you draw a full screen quad using this shader and the texture as it's input to post-process the image.

John Burton
+3  A: 

As you note, in order to make a blurred image, you first need to make an image, and then blur it. This shader does (just) the second step, taking an image that was generated previously and blurring it. There needs to be additional code elsewhere to generate the original non-blurred image.

Chris Dodd