理论
如果我们所拥有的是一个和屏幕大小一样并且和屏幕像素对齐的单一纹理,那么屏幕上每一个像素相当于纹理中的一个像素,纹理的最后一个像素也就是屏幕的最后一个像素。
如果我们有第二个纹理放在第一个纹理之上,然后GPU将会把第二个纹理合成到第一个纹理中。有很多种不同的合成方法,但是如果我们假定两个纹理的像素对齐,并且使用正常的混合模式,我们便可以用下面这个公式来计算每一个像素:
R = S + D * ( 1 – Sa )
结果的颜色是源色彩(顶端纹理)+目标颜色(低一层的纹理)*(1-源颜色的透明度)。在这个公式中所有的颜色都假定已经预先乘以了他们的透明度。
显然相当多的事情在这发生了。让我们进行第二个假定,两个纹理都完全不透明,比如 alpha=1.如果目标纹理(低一层的纹理)是蓝色(RGB=0,0,1),并且源纹理(顶层的纹理)颜色是红色(RGB=1,0,0),因为 Sa 为1,所以结果为:
R = S
结果是源颜色的红色。这正是我们所期待的(红色覆盖了蓝色)。
如果源颜色层为50%的透明,比如 alpha=0.5,既然 alpha 组成部分需要预先乘进 RGB 的值中,那么 S 的 RGB 值为(0.5, 0, 0),公式看起来便会像这样:
0.5 0 0.5
R = S + D * (1 - Sa) = 0 + 0 * (1 - 0.5) = 0
0 1 0.5
我们最终得到RGB值为(0.5, 0, 0.5),是一个紫色。这正是我们所期望将透明红色合成到蓝色背景上所得到的。
记住我们刚刚只是将纹理中的一个像素合成到另一个纹理的像素上。当两个纹理覆盖在一起的时候,GPU需要为所有像素做这种操作。正如你所知道的一样,许多程序都有很多层,因此所有的纹理都需要合成到一起。尽管GPU是一块高度优化的硬件来做这种事情,但这还是会让它非常忙碌。
代码示范
UIView *view1 = [[UIView alloc] init];
view1.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
view1.frame = CGRectMake(100, 100, 100, 100);
UIView *view2 = [[UIView alloc] init];
view2.backgroundColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:1];
view2.frame = CGRectMake(100, 100, 100, 100);
[self.view addSubview:view2];
[self.view addSubview:view1];
网友评论