Thanks for the explanation. 
In fact, in the "real" implementation, I also used a texture lookup to store kernel values (see GPU gems 24) and read them when needed.
I was trying to normalize my kernel before storing it but your code is easier to use.

For visvis, you might be interested in the different weight functions (I translated those of the antigrain library that are used in matplotlib):

Thanks again, you made my day !


On Sep 3, 2011, at 22:27 , Almar Klein wrote:

I've been playing with gaussian texture filtering using shaders and I obtained a strange "grid" effect on a completely uniform texture. Since all fragments get the same processing and same neighbouring values,I wonder if the grid is the result of some kind of artifact with floating points or the way texture coordinates are interpolated. Or I missed something completely obvious…

The Gaussian kernel is in theory infinite. Of course you need to cut it off somewhere, but you should normalize the kernel such that its sum is 1.0. I'm guessing that the fact that your kernel is asymetric does not help either.

The code below fixes the pattern:

filter( float x, vec4 c0, vec4 c1, vec4 c2, vec4 c3 )
float w;

w = gaussian(x+1.0); // h.x;
float w_sum = w;
vec4 r = c0 * w;

w = gaussian(x+0.0); // h.y;
w_sum += w;
r += c1 * w;

w = gaussian(1.0-x); // h.z;
w_sum += w;
r += c2 * w;

w = gaussian(2.0-x); // h.w;
w_sum += w;
r += c3 * w;

return r/w_sum;

Also a suggestion. I'm doing something similar in visvis to anti-alias 2D images. I also use a vec4 to represent the kernel, but I make use of the fact that the Gaussian kernel is symetric: kernel[0] is the center element, and kernel[1] to kernel[3] are the 3 elements on each side of the center. This way I get a kernel of effectively 7 elements. Further, I calculate (and normalize) the kernel beforehand in Python, and pass it as a uniform vec4. This way, it does not have to be calculated for each pixel. I'm not sure how significant this is for the speed, but there is a costly exp call in there ...