Premultiplied alpha results in less color depth, though. If my alpha is 10%, then my possible RGB values become 0-25. Even if I multiply by 10, I still lose the maximum possible values 251-255, and only values 0, 10, 20, 30... 250, are possible.
The correct solution is to pay close attention to all of the factors... and to be ESPECIALLY aware of pixel scaling. Provide your RGBA textures at the 1:1 pixel scale they will be rendered (or higher!) if at all possible.
> Premultiplied alpha results in less color depth, though.
That doesn't matter unless you color-scale the image (like multiply by 2 to make it brighter) before displaying it. Otherwise, the depth is at the correct resolution for display.
And premultiplied alpha should be used for final display, not just for the halo-ing reasons demonstrated here, but for lots of reasons.
Artists should generally be working in un-premultiplied alpha though, and the premultiplication is something that should happen right before an artist image is used. Artists shouldn't work in premultiplied images (and they generally don't) because of the color depth issue, and because it's crazy to paint premultiplied transparency manually.
> that doesn't matter unless you color-scale the image (like multiply by 2 to make it brighter) before displaying it.
It does if you stack several image layers. Let's say I have a particular color tone. Then I use that as background color. And I also stack 10 layers of the same color with alpha 0.05 on top of that. If you use premultiplied colors then this will actually result in a different color.
Due to rounding those colors often tend to be more greyish too. So if draw some vector graphics and have multiple basic shapes with semi-transparent edges (aliasing!) stacked on top of each other you can get some ugly fringes.
Yeah true, I suppose there is rounding error. Is this something that has actually happened to you, or are you saying it's a problem in theory? I'd be hard pressed to come up with a real-world use case for 10 of the same color being comped. For this to be a problem, the visible elements being comped would have to be exactly the same color, without any gradient or noise at all...
Even if it did happen, the error is bounded - with 10 layers of the same color, the maximum error in any channel is 5, and the average error is 2.5. It's pretty hard to say it would be wildly and noticeably different to most people even with 8 bit color channels, but I certainly have met some film directors and CG supervisors who were very color sensitive. It would be literally invisible in anything higher than 8 bits.
I'm curious -- why do you say the rounded colors would tend toward gray? Rounding error can happen in both directions, so I would expect rounding errors to cause a uniformly distributed error -- some colors would get slightly more saturated, some less, some of them would shift hue, and some would be unaffected.
You lost me on the edges part & aliasing. Rounding errors will not be visible as fringes, so if you're seeing fringes, you have some other problem... perhaps failure to pre-multiply! ;) Tell me more about stacking shapes and getting fringes. Is this stacking 10 of the same shape in the same place, or at the edge crossings of different shapes? What kind of fringes are you seeing?
Anyway, I've never witnessed a case in 20 years of film & game production where rounding errors caused a visible, detectable problem, but I'd love to know if there real cases where it's an issue!
> Is this something that has actually happened to you
In a toy project where I tried to automatically generate SVG shapes and rendering them to a html canvas (which uses 8bit per channel premultiplied alpha). The assembled shapes occasionally overlapped and it did lead to visible color inconsistencies.
It's also a problem when working with PNGs. When you put your PNG pixels into a premultiplied space and pull them out again you actually lost information to rounding, which negates the benefits of a lossless format.
> You lost me on the edges part & aliasing. Rounding errors will not be visible as fringes, so if you're seeing fringes, you have some other problem... perhaps failure to pre-multiply! ;)
Well, if you got a solid shape then there's no alpha. But the aliasing at the edges introduces partially transparent pixels. If you then pull out the pixel data and apply it to a different canvas you get mismatched colors.
I only spent a few hours on it, so I don't recall all the details, but my conclusion was that it is inadequate for image manipulation since it is lossy and lacks precision.
The article suggests why 1:1 won't be adequate, there will still be interpolation when the position isn't on a pixel boundary.
In practical applications the reduced color gamut isn't a problem, your ability to discriminate the colors goes down as the transparency goes up. It would only be a problem if you were trying to convert the pixels to something less transparent than they started.
If you were just doing image compositing would this be an issue? I can easily imagine how that would adversely effect a 3d game where the images are used as texture maps and the values of the diffuse texture map may change from other lighting contributions and shaders. It seems like in that case doing some kind of HDR/higher precision texturing would be good right?
Disclaimer: not a graphics programmer just a hobbyist seeking clarification. :)
In practice it's the other way around. Pre-multiplying alpha adversely affects image editing more than 3d rendering.
For image editing, the problem is that you might send the same pixel through many different operations, and if you flatten something and further manipulate, then the rounding error will continue to accumulate. So losing granularity early in the process due to alpha can result in accumulated rounding error.
In 3d graphics, the texture typically goes through a very predictable and short number of transformations, and they will rarely need to "stretch" the color range of the transparent pixel. When you alpha blend with pre-multiplied alpha, you're literally just adding the whole color value. And then you're slapping a whole lot of other colors onto it in the lighting/shadow/other passes, so the subtle nuances of that mostly transparent window get lost in the bustle.
Interesting! Thanks for clearing that up. I suppose if you have a strange shader that does some non-linear stuff it also might be more obvious to the programmer to use something higher precision or tweak how the math is done.
If you need to scale that up for some reason or are working with 10-bit displays then just use RGBA16F textures. No reason to stick to 32-bit here. GPUs are perfectly happy to work with half-float textures.
Although if you want to keep 32-bit textures you also shouldn't be doing linear premultiplication like the article suggests, you should be using sRGB instead.
The correct solution is to pay close attention to all of the factors... and to be ESPECIALLY aware of pixel scaling. Provide your RGBA textures at the 1:1 pixel scale they will be rendered (or higher!) if at all possible.