AlphaBlend细节
https://www.khronos.org/opengl/wiki/Blending
* Orgb = srgb * Srgb + drgb * Drgb
* Oa = sa * Sa + da * Da
The same goes for the two subtraction equations. This separates the RGB component computation from the alpha computation. So there are 4 possible blending parameters.
void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
The srcRGB value specifies the srgb parameter. dstRGB specifies drgb. srcAlpha is for sa, while dstAlpha specifies da.
AlphaPremultiply
If the result is the same, why bother with pre-multiplied alpha? The reason is texture filtering. When you take samples from a texture, unless you have disabled texture filtering, the hardware is blending neighboring texels together and returning a weighted average as a result.
在纹理点采样的情况下,普通的AlphaBlend跟AlphaPremultiply是一样的。关键就在对纹理filter的时候,只有AlphaPremultiply才能得到正确的结果。
普通的AlphaBlend
普通AlphaBlend的形式是,这同时也被称为 post-multipled alpha,但是它会导致错误的颜色
DestinationColor.rgb = (SourceColor.rgb * SourceColor.a) + (DestinationColor.rgb * (1 - SourceColor.a));
给定一张2个像素的纹理图
如果这个时候,我们想计算这个2x1纹理的下一级mip的1x1纹理,那么我们使用普通的AlphaBlend就会得到
通过图1和图2的比较,我们可以看到当我们计算mip的时候,结果就完全不对了。如果我们使用普通的AlphaBlend做图片想相乘的时候得到如图3所示结果。
![](https://i-blog.csdnimg.cn/blog_migrate/1d3ad2b84a5c202d0170e9f08c0dca3c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d76175afe47db1339ce7896309aee698.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4a4ee31e66c8bc6d8a6f11134e8e6bd3.png)
Alpha-Premultiply
https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre
在 Alpha-premultiply 下,我们首先要输入纹理的 rgb 与它的 alpha 乘到一块儿,并把 SourceColor.a 变成 1 。
DestinationColor.rgb = (SourceColor.rgb * One) + (DestinationColor.rgb * (1 - SourceColor.a));
如果我们使用普通的AlphaBlend做图片想相乘的时候得到如图所示结果。
![](https://i-blog.csdnimg.cn/blog_migrate/1d3ad2b84a5c202d0170e9f08c0dca3c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bcbee7edc6a843750062ab100b2adc7b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e285b10b345ce89323dbe52f62238da8.png)
所以我们看到,只要做了filtering,那么只有Alpha Premultiplied才能得到正确的表现效果。
SoftAddition
在游戏中,如果我们需要把UI单独的绘制到一个RenderTexture上,再把这个RenderTexture作为一个半透明的纹理绘制到Backbuffer中,那么就需要关注这个临时的RenderTexture的Alpha值了。
正常的AlphaBlend流程,我们不需要关注Backbuffer的Alpha到底是怎么样的值,因为这个Alpha根本不会参与任何运算。但是如果需要使用到这一Alpha值的时候,就需要确保这个Alpha值的区间是[0,1]。
那么一个可行的Alpha的Blend模式就是
Blend x x, OneMinusDstAlpha One
这样可以保证Alpha值的区间
引用
[1] https://www.khronos.org/opengl/wiki/Blending
[2]https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre