2
\$\begingroup\$

I'm trying to do a blur on a texture with an alpha channel. Using a typical approach (two-pass, gaussian weighting) I end up with a very dark blur. The reason is because the blurring does not properly account for the alpha channel. It happily blurs in the invisible part of the image, whcih happens to be black, and thus results in a very dark blur.

Is there a technique to blur that properly accounts for the alpha channel?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Sounds like you shouldn't divide with a constant factor based on the kernel size, but instead accumulate the alpha values from the samples and divide by that. \$\endgroup\$
    – msell
    May 28, 2014 at 8:44
  • \$\begingroup\$ @msell, I am now using a convolution that does that, but I still get problems (though a lot less). \$\endgroup\$ May 28, 2014 at 9:20
  • \$\begingroup\$ Can you describe the problems you still have, preferably with screenshots? \$\endgroup\$
    – msell
    May 28, 2014 at 10:10

1 Answer 1

2
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ My textures are not premultiplied. The solution I found was to actually do the blurring in the premultiplied domain -- I found some references for image convolution with an alpha channel. \$\endgroup\$ May 29, 2014 at 11:16
  • \$\begingroup\$ Some png saving tools write black to any fully-tansparent pixel. Working with TGA will often fix this, because the format doesn't assume that zero alpha is always 100% transparent and thus the colour unimportant. \$\endgroup\$
    – DMGregory
    May 29, 2014 at 11:37
  • \$\begingroup\$ I'm having the same issues. Care to link to the references to convolution with an alpha channel, @edA-qamort-ora-y? And: I'd like to do a Gaussian blur which isn't simply done using a convolution matrix. Any approach for this? GIMP, for instance, uses the alpha channel properly when blurring, meaning that the invisible "color" of a completely transparent pixel has no influence on the blur outcome. \$\endgroup\$
    – Alfe
    Feb 2, 2017 at 12:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .