预乘alpha
概念:预乘alpha就是预先将颜色的rgb通道乘以α:(a * α,b * α,c * α,α);
在alpha混合的时候,一般的混合方法是:
- Cres’ = Csrc * Asrc + (Cdes * Ades) *(1 - Asrc) (res为结果,src为需要混合上去的颜色,des为原来的颜色),可见最终颜色由两种颜色共同贡献,C * A为一种颜色对最终颜色的贡献,而Asrc决定了两种颜色对于最终颜色的贡献强度,其为1则说明Csrc贡献全部强度,为0则说明Cdes贡献全部强度
- Ares = Asrc + Ades *(1 - Asrc)
而预乘alpha实际上就是预先将C*A计算好了:
- Cres’ = Csrc’ + Cdes’ * (1 - Asrc);(Cres’ = Cres * Ares)
- Ares = Asrc + Ades * (1 - Asrc);
在unity中默认使用 SrcAlpha, oneMinusSrcAlpha的方式进行透明度混合:Cres’ = Csrc * Asrc + Cdes * (1 - Asrc) ,Ares = Asrc * Asrc + Ades * (1 - Asrc),其将des的alpha默认为1,即不透明,预乘alpha后则为:Cres’ = Csrc’ + Cdes’ * (1 - Asrc),并且,当Ades始终为1时,Ares == 1,即不透明的颜色混合上半透明物体后仍然是不透明。并且由于结果始终为不透明,所以混合后的a值是没有意义的值(计算的结果也是错误的),可以利用其位置储存其他的值。
预乘alpha会使得相近的颜色更加相近(乘以alpha后会使得颜色之间的差值更小)会导致失真
预乘alpha可以减少纹理过滤产生的失真:假设有两个颜色:(1,0,0,1),(0,1,0,0.1)不透明红色和透明绿色,如果没有使用预乘alpha将其进行双线性过滤:(Ca + Cb) / 2 = (0.5, 0.5 ,0 , 0.55)可以发现,透明度仅为0.1的绿色却和不透明的红色贡献了相同的颜色强度,这显然是不正确的。而使用了预乘alpha后两个颜色(1,0,0,1),(0,0.1,0,0.1),再将其进行双线性过滤得到的结果为(0.5,0.05,0,0.55)这次绿色贡献的颜色强度就远不如红色了,这显然更加符合现实。
参考资料
网络