Your problem is that you're blurring a texture which has had its alpha pre-multiplied into its color channels. That is, the rgba of a 100% transparent white pixel is stored as {0,0,0,0}
, and the rgba color of a 50% transparent white pixel is {0.5,0.5,0.5,0.5}
. Which means that when you're using that pixel as part of your blur, you're not blurring half-strength white; you're blurring half-strength 50% grey.
Which means that even when you correct for varying alpha levels, the source color of the pixels has already been darkened before your shader ever got there, and so you're still not getting the overall blur brightness level that you were expecting.
The simple answer is: don't use textures with pre-multiplied alpha; make sure that your 100% transparent white pixels are encoded as {1,1,1,0}
instead of {0,0,0,0}
. There are some plausible arguments for using pre-multiplied alpha in certain situations (mostly to do with simple compositing operations), but they really cause severe problems any time you want to do non-trivial processing on textures, such generating mipmaps, or such as performing the blur operation that you're doing.
The more complicated answer is: if you really want to keep using premultiplied textures, you can un-premultiply the pixel colors inside your fragment shader. Basically, you ignore any pixel with an alpha of 0, and any other pixel, you adjust its rgb color by multiplying by 1.0 / alpha. So in the case of a 50% transparent white pixel, which from your premultiplied alpha texture contains rgba of {0.5,0.5,0.5,0.5}
, your blur shader multiplies the rgb values by 1.0 / alpha
== 1.0 / 0.5
== 2.0
, to recover the original pixel color from before the alpha premultiplication was applied -- {1.0,1.0,1.0.0.5}
. You can then use that pixel color for the blurring calculation.
But really, you want to use the simple approach. It's much faster and easier and better in every way.