接上一个案例,案例5中,我们使用了深度测试,解决OpenGL绘制立体图形时,由于无法判断该显示两个点A(x,y,z1)和点B(x,y,z2)两个点中的哪个点,而造成图形凹陷的效果,那么深度测试解决的办法时,A、B两点谁距离观察者近,显示谁。那么深度测试有没有什么隐患呢?这个隐患又该怎么解决,看一下图
1 多边形偏移的使用和模式选择
//启⽤Polygon Offset ⽅式
glEnable(GL_POLYGON_OFFSET_FILL)
对应案例5中,使用的表面剔除的不同模式,多边形偏移设置也有三种方式
GL_POLYGON_OFFSET_POINT 对应模式: GL_POINT
GL_POLYGON_OFFSET_LINE 对应模式: GL_LINE
GL_POLYGON_OFFSET_FILL 对应模式: GL_FILL
2 多边形偏移量的设置
2.1多边形偏移量OpenGL中通过glPolygonOffset方法来设置,需要两个参数factor , units
2.2 每个Fragement增加一个偏移量:
Offset = ( m * factor ) + ( r * units); m : 多边形的深度的斜率的最⼤值,理解⼀个多边形越是与近裁剪⾯平⾏,m 就越接近于0。 r : 能产⽣于窗⼝坐标系的深度值中可分辨的差异最⼩值,r是由具体是由具体OpenGL 平台指定的一个常量。
2.3⼀个⼤于0的Offset会把模型推到离你(摄像机)更远的位置,相应的⼀个⼩于0的Offset 会把模型拉近
2.4 ⼀般⽽⾔,只需要将-1 和 -1 这样简单赋值给glPolygonOffset 基本可以满⾜需求。
// 多边形偏移量的设置
glPolygonOffset(-1.0f, -1.0f);
// 偏移深度,在同一位置要绘制填充和边线,会产生z冲突,所以要偏移
glEnable(GL_POLYGON_OFFSET_LINE);
同样,为了不影响整个工程的其他地方,使用结束后,依然需要关闭多边形偏移模式,打开和关闭的模式要对应。
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2.5 如何预防Z-fighting闪烁的问题
a.不要将两个物体靠的太近,避免渲染时三⻆形叠在⼀起。这种⽅式要求对场景中物体插⼊⼀个少量的偏移,那么就可能避免ZFighting现象。例如上⾯的⽴⽅体和平⾯问题中,将平⾯下移0.001f就可以解决这个问题。当然⼿动去插⼊这个⼩的偏移是要付出代价的。
b.尽可能将近裁剪⾯设置得离观察者远⼀些。上⾯我们看到,在近裁剪平⾯附近,深度的精确度是很⾼的,因此尽可能让近裁剪⾯远⼀些的话,会使整个裁剪范围内的精确度变⾼⼀些。但是这种⽅式会使离观察者较近的物体被裁减掉,因此需要调试好裁剪⾯参数。
c.使⽤更⾼位数的深度缓冲区,通常使⽤的深度缓冲区是24位的,现在有⼀些硬件使⽤使⽤32/64位的缓冲区,使精确度得到提⾼。
3颜色混合
OpenGL中会把对应像素的颜色存储在颜色缓存区中,每个⽚段的深度值也是放在深度缓冲区。当深度缓冲区被关闭时,新的颜⾊将简单的覆盖原来颜⾊缓存区存在的颜⾊值,当深度缓冲区再次打开时,新的颜⾊⽚段只是当它们⽐原来的值更接近邻近的裁剪平⾯才会替换原来的颜⾊⽚段。 那么如果开启深度测试后.但是2个重叠的图层中,有⼀个图层是半透明的,有⼀个图层是⾮半透明的。那么此时就不能进⾏单纯的⽐较深度值,然后进⾏覆盖, ⽽是需要将2个图层的颜⾊进⾏混合。
glEnable(GL_BlEND);
目标颜色:已经存储在颜色缓存区的颜色,也就是之前已经完成颜色运算的结果;
源颜色:作为当前渲染命令结果进⼊颜⾊缓存区的颜⾊值; 而颜色的混合,在OpenGL 中是有相应的混合方程式的,在默认的情况下,方程式为:
Cf = (Cs * S) + (Cd * D)
Cf :最终计算参数的颜⾊
Cs : 源颜⾊
Cd :⽬标颜⾊
S:源混合因⼦
D:⽬标混合因⼦
我们可以通过调用方法,设置源混合因子和目标混合因子:
//设置混合因⼦,需要⽤到glBlendFun函数
glBlendFunc(GLenum S,GLenum D);
//S:源混合因⼦ D:⽬标混合因⼦
我们常用的情况:
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
OpenGL中可设置的混合因子,见下图:
//选择混合⽅程式的函数:
glbBlendEquation(GLenum mode);
可选的混合方程式
void glBlendColor(GLclampf red ,GLclampf green ,GLclampf blue ,GLclam pf alpha );
4 抗锯齿
抗锯齿,实际上在案例4中已经使用了,在画金字塔、六边形扇、三角形圆柱带时,我们画出的黑边框,不采用抗锯齿时,黑边线会出现锯齿状效果
glEnable(GL_LINE_SMOOTH);
开启后得到的效果
glDisable(GL_LINE_SMOOTH);