混合通常是指实现物品的透明度的一种技术。可以理解为调色,例如:红色加蓝色之后出现的颜色是紫色或品红这样的。就是两种物品通过透明度把两种颜色混合起来的一种技术。
一个物体的透明度是通过它颜色的aplha值来决定的,Alpha颜色值是颜色向量的第四个分量。
丢弃片段
有些图片不需要半透明,只想要一部分的时候。你就可以抛弃这部分。通过alpha等于0来将其抛弃。
草的形状和2D四边形的形状并不完全相同,所以你只想显示草纹理的某些部分,而忽略剩下的部分。
传入数据到着色器,通过着色器去判断透明度的值,抛弃不需要的值。
precision mediump float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap; //2d纹理采样器,默认的激活纹理单元(0),没有分配值
uniform sampler2D colorMap2;
void main()
{
vec4 texColor = texture2D(colorMap, varyTextCoord);
if (texColor.a < 0.1) {
discard;
}
gl_FragColor = texColor;
}
因为草的的图像,就只有白色和绿色之分。我们把白色的部分都丢弃后,就只留下绿色的部分,这样就把草给抠图一般扣出来。
混合
虽然直接丢弃片段很好,但它不能让我们渲染半透明的图像。我们要么渲染一个片段,要么完全丢弃它。要想渲染有多个透明度级别的图像,我们需要启用混合(Blending)。和OpenGL大多数的功能一样,我们可以启用GL_BLEND来启用混合:
glEnable(GL_BLEND);
OpenGL中的混合是通过下面这个方程来实现的:
片段着色器运行完成后,并且所有的测试都通过之后,这个混合方程(Blend Equation)才会应用到片段颜色输出与当前颜色缓冲中的值(当前片段之前储存的之前片段的颜色)上。源颜色和目标颜色将会由OpenGL自动设定,但源因子和目标因子的值可以由我们来决定。我们先来看一个简单的例子:
我们有两个方形,我们希望将这个半透明的绿色方形绘制在红色方形之上。红色的方形将会是目标颜色(所以它应该先在颜色缓冲中),我们将要在这个红色方形之上绘制这个绿色方形。
问题来了:我们将因子值设置为什么?嘛,我们至少想让绿色方形乘以它的alpha值,所以我们想要将Fsrc设置为源颜色向量的alpha值,也就是0.6。接下来就应该清楚了,目标方形的贡献应该为剩下的alpha值。如果绿色方形对最终颜色贡献了60%,那么红色方块应该对最终颜色贡献了40%,即1.0 - 0.6。所以我们将Fdestination设置为1减去源颜色向量的alpha值。这个方程变成了:
结果就是重叠方形的片段包含了一个60%绿色,40%红色的一种脏兮兮的颜色:
最终的颜色将会被储存到颜色缓冲中,替代之前的颜色。
这样子很不错,但我们该如何让OpenGL使用这样的因子呢?正好有一个专门的函数,叫做
glBlendFunc
。glBlendFunc(GLenum sfactor, GLenum dfactor)
函数接受两个参数,来设置源和目标因子。OpenGL为我们定义了很多个选项,我们将在下面列出大部分最常用的选项。为了获得之前两个方形的混合结果,我们需要使用源颜色向量的alpha作为源因子,使用1−alpha作为目标因子。这将会产生以下的glBlendFunc:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
也可以使用glBlendFuncSeparate为RGB和alpha通道分别设置不同的选项:
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
OpenGL甚至给了我们更多的灵活性,允许我们改变方程中源和目标部分的运算符。当前源和目标是相加的,但如果愿意的话,我们也可以让它们相减。glBlendEquation(GLenum mode)
允许我们设置运算符,它提供了三个选项:
通常我们都可以省略调用
glBlendEquation
,因为GL_FUNC_ADD
对大部分的操作来说都是我们希望的混合方程,但如果你真的想打破主流,其它的方程也可能符合你的要求。