本文讲解的是OpenGL中实现抗锯齿的两种方式,一种是颜色混合,一种是多重采样,这两种方式各有优劣。
为什么会产生锯齿?
OpenGL中,像素点是正方形的,在两个正方形之间,会有颜色的分界。会给人一种不逼真的感觉。为了抗锯齿,OpenGL给了两种方案来实现
颜色混合
组合颜色的概念:
目标颜色:已经存储在颜色缓冲区的颜色值
远颜色:作为当前渲染命令结果进入颜色缓冲区的颜色值
当混合功能被启动时,源颜色和目标颜色的组合方式时混合方程式控制的,在默认情况下,混合方程式如下:
Cf = (CsS)+(CdD);
Cf:最终计算参数的颜色
Cs:源颜色
Cd:目标颜色
S :源颜色混合因子
D :目标颜色混合因子
设置混合因子
设置混合因子,需要用到glBlendFunc函数,两个参数根据项目产品的需求来定,并且已经有了一张混合因子枚举列表,如下图所示,混合因子不光有颜色的混合,还有透明度因子的混合
image.png我们通过一个常见的混合函数组合来说明问题:
glBlendFunc(GL_SRC_ALPHA,GLONE_MINUS_ALPHA);
S = GL_SRC_ALPHA:RGB混合因子(As,As,As),Alpha混合因子As
D = G_LONE_MINUS_ALPHA混合因子 1-(As,As,As),Alpha = 1-As;
Cf = (CsS)+(CdD)
那么我们如何去计算呢?
如果颜色缓冲区,已经有一种红色 (1.0f,0.0f,0.0f,0.0f),如果在上面用一种蓝色(0.0f,0.0f,1.0f,0.6f)
Color = (R,G,B,A);
Cd(目标颜色) = (1.0f,0.0f,0.0f,0.0f);
Cs(源颜色) = (0.0f,0.0f,1.0f,0.6f);
S(RGB) = (As,As,As),S(Alpha) = As
D(RGB) = 1- (As,As,As),D(Alpha) = 1-As
S(r) = 0.6f,S(g) = 0.6f, S(b) = 0.6f,S(a) = 0.6f;
D(r) = 1-As = 0.4f,同理D(g) = 0.4f,D(b) =0.4f,D(a) = 0.4f;
因此可得:Cf = (Cs*S)+(Cd*D)
Cf(Red) = (0.0f*0.6)+(1.0*0.4) = 0.4f
Cf(Green) = (0.0*0.6f)+(0.0*0.4) = 0.0f
Cf(Blue) = (1.0*0.6)+(0.0*0.4) = 0.6f
Cf(Alpha) = (0.6*0.6)+(0.0*0.4) = 0.36f;
Cf = (0.4f,0.0f,0.6f,0.36f);
最终颜色是以原先的红色(目标颜色)与后来的蓝色(源颜色)进行组合,源颜色的alpha值越高,添加蓝色的成分越高,目标颜色所保留的成分越少
混合函数通常用于实现在其他一些不透明的物体前面绘制一个透明物体的效果
颜色混合抗锯齿
OpenGL将两个颜色的交界处进行混合来实现平滑过渡
glEnable(Gl_BLEND);//开启混合处理
glBlendFunc(GL_SRC_ALPHA,GLONE_MINUS_ALPHA);//指定混合因子(只能是)
glBlendEquation(GL_FUNC_ADD);//指定混合方程式(只能是)
glEnable(GL_POINT_SMOOTH)//对点进行抗锯齿处理
glEnable(GL_LINE_SMOOTH)//对线进行抗锯齿处理
glEnable(GL_POLYGON_SMOOTH);//对多边形进行抗锯齿处理
多重采样抗锯齿
有些平台是没有办法帮助你完成混合抗锯齿的,因为混合的底层非常的复杂,那么这时候我们就要用到多重采样了
OpenGL中有个缓冲区叫多重采样缓冲区,会对我们的图元的每一个像素进行多次采样然后存储到我们的缓冲区中,幸运的是这个过程是自动的,不需要我们开发者去关心,属于幕后发生的事情,所以我们也没办法去解释这个实现的过程。
虽然多重采样会造成额外的资源开销,但是以目前的设备性能,我们几乎可以忽略不计。
如何使用多重采样呢?
//1.调用glutInitDisplayMode 添加采样缓冲区
glutInitDisplayMode(GLUT_MULTSAMPLE);
//2.打开|关闭
glEnable(GLUT_MULTSAMPLE);
glDisable(GLUT_MULTSAMPLE);
需要注意的是当你开启多重采样来进行抗锯齿时,颜色混合会失效
因此我们需要在合适的地方开启多重采样,那么如果你只是对点、线进行抗锯齿,那么颜色混合效果更佳(前提是平台支持),多边形采用多重采样
在使用颜色混合前,为了避免之前用过多重采样,最好先关闭,然后在使用颜色混合之后再在需要的时候开启
拓展
多重采样缓冲区在默认情况下使用片段RGB值,并不包含颜色的Alpha成分,我们可以通过glEnable来修改这个行为:
*GL_SAMPLE_ALPHA_TO_COVERAGE使用alpha值
*GL_SAMPLE_ALPHA_TO_ON使用alpha值并设置为1
*GL_SAMPLE_COVERAGE 使用glSampleCoverage所设置的值
当启用GL_SAMPLE_COVERAGE时,可以使用glSampleCoverage函数指定一个特定的值,它是与片段覆盖值进行按位与操作的结果。
网友评论