用一个生活中的例子来介绍什么是颜色混合。
我们拿两块透明有色玻璃叠在一起,透过两块玻璃可以发现叠加的颜色跟两种颜色都不一样,它是一种新的颜色,这就是颜色混合。OpenGL中的颜色混合原理也是这样的,通过不同的颜色和对应的透明度计算出最终的颜色和透明度。如下图所示:
1. iOS中的应用
CALayer有个alpha属性,同时颜色值RGBA中的A就是alpha,他们归根结底都是用到了颜色混合。当alpha为1时,也就是不透明,这种情况下,OpenGL会自动过滤该控件下层控件的颜色计算,因为他们本来就被上层的控件遮挡了。所以,能不用alpha就尽量不用,这样能减少GPU的开销。
2. 离屏渲染
这里引入一个家喻户晓的概念,离屏渲染。关于离屏渲染的理解,笔者在网上看到了一篇文章对其进行详细介绍,附上地址:关于iOS离屏渲染
3. 实现原理
在一般情况下,OpenGL在渲染时把颜色值存放在颜色缓冲区中,把每个片段(像素)的深度值存放在深度缓冲区中。当深度检测被关闭时,新的颜色值简单地覆盖颜色缓冲区中已经存在的颜色值;当深度检测被打开时,新的颜色值只有当它比原来的颜色更接近临近的裁剪平面时才会替换原来的颜色。当然,这是在OpenGL的混合功能被关闭的情况下。当混合功能被启用时,新的颜色会与颜色缓冲区中原有的颜色进行组合。通过对这些颜色进行不同的组合,可以产生许多种不同的效果。
目标颜色:已经存储在颜色缓冲区中的颜色称为目标颜色;
源颜色:当前渲染命令的结果进入颜色缓冲区中的颜色称为源颜色;
我们正是通过对目标颜色和源颜色进行不同的组合操作,来实现颜色混合的功能
当混合功能被启用时,源颜色和目标颜色的组合方式是由混合方程式来控制的。在默认情况下,使用的混合方程式如下所示:
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background-image: none; background-size: auto; background-attachment: scroll; background-origin: padding-box; background-clip: border-box; background-color: rgba(0, 0, 0, 0); background-position: 0% 0%; background-repeat: repeat repeat;">
//Cf -- 最终组合的颜色值 //Cd:源颜色 -- 当前渲染命令传入的颜色值 //CS:目标颜色 -- 颜色缓冲区中已经存在的颜色值 //S:源混合因子 //D:目标混合因子 Cf = (Cs * S) + (Cd * D)</pre>
这两个混合因子可以通过下面的这个函数进行设置:
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background-image: none; background-size: auto; background-attachment: scroll; background-origin: padding-box; background-clip: border-box; background-color: rgba(0, 0, 0, 0); background-position: 0% 0%; background-repeat: repeat repeat;">
枚举类型可能的值为: GL_ZERO: 表示使用0.0作为因子,实际上相当于不使用这种颜色参与混合运算。 GL_ONE: 表示使用1.0作为因子,相当于完全的使用了这种颜色参与混合运算。 GL_SRC_ALPHA:表示使用源颜色的alpha值来作为因子。 GL_DST_ALPHA:表示使用目标颜色的alpha值来作为因子。 GL_ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子。 GL_ONE_MINUS_DST_ALPHA:表示用1.0减去目标颜色的alpha值来作为因子。 glBlendFunc(GLenum S, GLenum D);</pre>
4. 使用
要使用OpenGL的混合功能:
glEnable(GL_BLEND);
要关闭OpenGL的混合功能:
glDisable(GL_BLEND);
设置混合因子:
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);