首先说到混合模式,简单理解,混合模式就是同一像素上有两个颜色需要混合成一个使用的模式。
这里的两个像素点,我们把原先已经存在的,也就是下面的像素点颜色定义为目标颜色。把新加上来的,也就是上面的像素点颜色定义为源颜色。
颜色的混合过程是把目标颜色和源颜色各乘上一个系数然后相加。这里把与目标颜色相乘的系数定义为目标因子,与源颜色相乘的系数定义为源因子。
假设
源颜色(Rsrc, Gsrc, Bsrc, Asrc)
源因子(Sr, Sg, Sb, Sa)
目标颜色(Rdst, Gdst, Bdst, Adst)
目标因子(Dr, Dg, Db, Da)
那么两种颜色相乘之后的结果颜色就是:
RGBAresult = (Rsrc*Sr + Rdst*Dr, Gsrc*Sg + Gdst*Dg, Bsrc*Sb + Bdst*Db, Asrc*Sa+ Adst*Da)
于是乎,设置不同的目标因子和源因子就能实现一些不同的效果。
而我们一般使用的混合因子是
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc函数中前者是源因子,后者是混合因子。也就是把源颜色的alpha值作为源因子,1-源颜色的alpha值作为目标因子。简单来说就是把目标颜色看作不透明的,源颜色是透明的。
(一些混合因子设置效果)
再说到预乘,预乘的是为了解决当纹理缩小,两个临近的像素需要合并成一个像素时出现的问题。
举一个简单的例子:
假设有一个像素颜色是红色不透明(255, 0, 0, 1)
旁边是一个绿色0.1透明度(0, 255, 0, 0.1)
当图片缩小时,需要经过Texture Filtering(纹理过滤),把两个像素的颜色合成为1个。
以线性插值方法为例,合成后的像素是((255 + 0)/ 2, (0 + 255)/ 2, 0, (1 + 0.1) / 2)=
(127, 127, 0, 0.55)
这里的绿色像素其实是有透明度的,他真正展示的绿色并不是255,而应该是255*0.1,而相乘这个操作其实就是预乘。也就是说如果这里的颜色没有经过预乘,直接拿255去参与颜色合并的过程,错误的数值会占据比较大的比重。
经过预乘后的像素:
(0 * 0.1, 255 * 0.1, 0 * 0.1, 0.1) = (0, 25, 0, 0.1)
再线性插值的结果:
(255 + 0)/ 2,(0 + 25)/ 2, 0, (1 + 0.1) / 2)= (127, 12, 0, 0.55)
整体颜色会偏红色,看起来更合理一些。