在OpenGL中,物体透明技术通常被叫做混合(Blending)。一个物体的透明度,被定义为它的颜色的alpha值。alpha颜色值是一个颜色向量的第四个元素。
我们之前所使用的纹理都是由3个颜色元素组成的:红、绿、蓝,但是有些纹理同样有一个内嵌的aloha通道,它为每个纹理像素(Texel)包含着一个alpha值。这个alpha值告诉我们纹理的哪个部分有透明度,以及这个透明度有多少。例如,下面图片玻璃部分的alpha值为0.25(它的颜色是完全红色,但是由于它有75的透明度,它会很大程度上反映出网站的背景色,看起来就不那么红了),角落部分alpha是0.0。
为了渲染出不同的透明度级别,我们需要开启混合(Blending)。像大多数OpenGL的功能一样,我们可以开启GL_BLEND
来启用混合(Blending)功能:
glEnable(GL_BLEND);
开启混合后,我们还需要告诉OpenGL它该如何混合。OpenGL以下面的方程进行混合:
- C¯source :源颜色向量。这是来自纹理的本来的颜色向量。
- C¯destination :目标颜色向量。这是储存在颜色缓冲中当前位置的颜色向量。
- Fsource :源因子。设置了对源颜色的alpha值影响。
- Fdestination :目标因子。设置了对目标颜色的alpha影响。
片段着色器运行完成并且所有的测试都通过以后,混合方程才能自由执行片段的颜色输出,当前它在颜色缓冲中(前面片段的颜色在当前片段之前储存)。源和目标颜色会自动被OpenGL设置,而源和目标因子可以让我们自由设置。我们来看一个简单的例子:
我们有两个方块,我们希望在红色方块上绘制绿色方块。红色方块会成为目标颜色(它会先进入颜色缓冲),我们将在红色方块上绘制绿色方块。
我们怎样来设置因子呢?我们起码要把绿色方块乘以它的alpha值,所以我们打算把 Fsrc 设置为源颜色向量的alpha值:0.6。接着,让目标方块的浓度等于剩下的alpha值。如果最终的颜色中绿色方块的浓度为60%,我们就把红色的浓度设为40%(1.0 – 0.6)。所以我们把 Fdestination 设置为1减去源颜色向量的alpha值。方程将变成:
最终方块结合部分包含了60%的绿色和40%的红色,得到一种脏兮兮的颜色:
最后的颜色被储存到颜色缓冲中,取代先前的颜色。
这个方案不错,但我们怎样告诉OpenGL来使用这样的因子呢?恰好有一个叫做glBlendFunc
的函数。
void glBlendFunc(GLenum sfactor, GLenum dfactor)
接收两个参数,来设置源(source)和目标(destination)因子。OpenGL为我们定义了很多选项,我们把最常用的列在下面。
选项 | 值 |
---|---|
GL_ZERO | 0 |
GL_ONE | 1 |
GL_SRC_COLOR | 源颜色向量 C¯source |
GL_ONE_MINUS_SRC_COLOR | 1−C¯source |
GL_DST_COLOR | 目标颜色向量 C¯destination |
GL_ONE_MINUS_DST_COLOR | 1−C¯destination |
GL_SRC_ALPHA | C¯source 的 alpha 值 |
GL_ONE_MINUS_SRC_ALPHA | 1− C¯source 的 alpha 值 |
GL_DST_ALPHA | C¯destination 的 alpha 值 |
GL_ONE_MINUS_DST_ALPHA | 1− C¯destination 的 alpha 值 |
GL_CONSTANT_COLOR | 常颜色向量 C¯constant |
GL_ONE_MINUS_CONSTANT_COLOR | 1−C¯constant |
GL_CONSTANT_ALPHA | C¯constant 的 alpha 值 |
GL_ONE_MINUS_CONSTANT_ALPHA | 1− C¯constant 的 alpha 值 |
glBlendFunc
之后就像这样:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
OpenGL给了我们更多的自由,我们可以改变方程源和目标部分的操作符。现在,源和目标元素已经相加了。如果我们愿意的话,我们还可以把它们相减。
void glBlendEquation(GLenum mode)
允许我们设置这个操作,有3种可行的选项:
- GL_FUNC_ADD:默认的,彼此元素相加: C¯result=Src+Dst
- GL_FUNC_SUBTRACT:彼此元素相减: C¯result=Src−Dst
- GL_FUNC_REVERSE_SUBTRACT:彼此元素相减,但顺序相反: C¯result=Dst−Src .
通常我们可以简单地省略glBlendEquation
因为GL_FUNC_ADD在大多数时候就是我们想要的,但是如果你如果你真想尝试努力打破主流常规,其他的方程或许符合你的要求。