OpenGL-混合

322 阅读3分钟

开篇

我们已经了解,通常情况下OpenGL渲染时会把颜色值放在颜色缓冲区中。而每个片段的深度值也是放在深度缓冲区的。当深度测试被关闭(禁用)时,新的颜色值简单的覆盖颜色缓冲区中已经存在的其他值。当深度测试被打开(启用)时,新的颜色片段只有当它们比原来的值更接近邻近的裁剪平面时才会替换原来的颜色片段。 在打开混合功能的情况下,新的颜色会与已经存在的颜色值在颜色缓冲区中进行组合。这些颜色的组合方式不同会导致很多不同的特殊效果。

颜色混合

名词解释:

  • 目标颜色:已经存储在颜色缓冲区中的颜色值(和我们通常理解的目标含义有所区别)。这个颜色值包含了单独的红、绿、蓝以及一个可选的alpha值。
  • 源颜色:作为当前渲染命令的结果进入颜色缓冲区的颜色值。它可能与目标颜色进行交互,也可能不与之进行交互。

当混合功能开启时:

glEnable(GL_BLEND);

源颜色和目标颜色的组合方式是由混合方程式控制的。

Cf = (Cs * S) + (Cd * D)
  • Cf:最终计算产生的颜色
  • Cs:源颜色
  • Cd:目标颜色
  • S和D:分别是源和目标混合因子

混合因子是由glBlendFunc(GLenum s, GLenum D)进行设置的。 混合函数可以使用的值如下表:

表中:

  • R、G、B、A 分别代表 红、绿、蓝、alpha
  • 下标S、D 分别代表 源、目标
  • c 代表常量颜色(默认黑色,可以通过函数void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)进行修改)

举个栗子说明一下混合函数的使用: 我们将使用一个常见的混合函数glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);来进行计算。这个函数告诉OpenGL接受源颜色并将这个颜色(RGB值)与alpha值相乘,然后把这个结果加上目标颜色乘以“1减去源颜色的alpha值”的结果

Cd:目标颜色 (1.0f,0.0f,0.0f,0.0f)
Cs:源颜色 (0.0f,0.0f,1.0f,0.6f)
S:源alpha值 = 0.6
D = 1.0 - 源alpha值 = 1.0 - 0.6 = 0.4

Cf = (Cs * S) + (Cd * D)
就等价于
Cf = (blue * 0.6) + (red * 0.4)

这个混合函数经常用于实现在其他一些不透明的物体前面绘制一个透明物体的效果。(如上图:移动矩形的颜色和上面的红色是一样的,但和白色混合后变淡,黑色使红色变深,红色和红色混合还是红色。)

除了上面介绍的默认混合方程式外,还有另外4中方程式,有兴趣的可以自行了解。

OpenGL还提供了更加灵活的计算函数:

void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
  • srcRGB: 源颜色的混合因子
  • dstRGB: 目标颜⾊的混合因子
  • srcAlpha: 源颜色的Alpha因子
  • dstAlpha: ⽬标颜色的Alpha因⼦

glBlendFuncSeparate函数允许为RGB和alpha成分单独指定混合函数!

抗锯齿

OpenGL混合功能的另一个用途是抗锯齿。在绝大多数情况下,一个独立的片段将会映射到计算机屏幕上的一个像素。这些像素是正方形的(或者说近似正方形),通常可以相当清楚的看到两种颜色的分界。

为了消除图元之间的锯齿边缘,OpenGL使用混合功能来混合片段的颜色,也就是把像素的目标颜色与周围像素的颜色进行混合。从本质上说,在任何图元的边缘上,像素颜色会稍微延伸到相邻的像素。

开启抗锯齿:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_MINUS_SRC_ALPHA);

我们还可以调用glEnable函数对点、线和多边形(任何实心图元)进行抗锯齿处理。

glEnable(GL_POINT_SMOOTH);//点
glEnable(GL_LINE_SMOOTH);//线
glEnable(GL_POLYGON _SMOOTH);//多边形