首先直观的感受下,在不消除隐藏面的情况下,图形旋转中会出现的场景: 正背面不消除问题图片
针对上述问题,提供两种解决方法:
1、正背面消除:根据顶点数据顺序判断用户可见部分(阳面)与隐藏面(阴面),隐藏面直接丢弃,不绘制,只绘制可见部分
2、深度测试:不管图层数量,只显示绘制可见图层,剩余不可见的直接丢弃
正背面消除:该方法不能从根本上解决上述场景的问题,会出现缺口,如下图; 缺口问题
上述场景出现的原因:甜甜圈旋转过程中,当前后两部分重叠时,OpenGL中并不能清楚地区分,两个图层谁显示在前,谁显示在后,导致甜甜圈产生了缺口。
关于正背面消除方法具体实现原理,这里不详细阐述(主要需了解下阳面,阴面的判定)
针对正背面消除方法存在的缺陷,深度测试应运而生,首先理解下以下几个概念
深度:指OpenGL坐标系中,像素点的Z坐标距观察者的距离,存在如下关系:
1、如果观察者在Z轴的正方向,Z值越大则越靠近观察者
2、如果观察者在Z轴的负方向,Z值越小则越靠近观察者
深度缓存区(Depth Buffer):
指一块专门内存区域,存储在显存中,用于存储屏幕上所绘制图形的每个像素点的深度值,对应关系如下:
1、深度值越大,离观察者越远
2、深度值越小,里观察者越近
注意事项:
1、深度缓存区中,每个像素点和深度值一一对应
2、深度缓冲区的范围是[0, 1]之间,默认值是1.0,表示深度值的最大值
3、每次绘制前需清空深度缓存区,否则会存在上次绘制缓存的深度值,影响当前图形的绘制
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
深度测试:
一个物体在绘制时,像素点新的深度值与深度缓存中已经存在的深度值作比较,若新值 > 旧值,则丢弃,反之,将新的深度值更新至深度缓存区,由于深度缓存区与颜色缓存区是一一对应的,同时也需要更新该像素点的颜色值到颜色缓存区,该过程就是深度测试
开启深度测试
glEnable(GL_DEPTH_TEST);
关闭深度测试
glDisable(GL_DEPTH_TEST);
开启深度测试后,效果图如下:
开启深度测试后效果图
多边形偏移(Polygon Offset)
深度测试虽然解决了上述出现的缺口问题,但同时引出了Z-Fighting(Z冲突,闪烁)问题,发生z冲突的原因如下:开启深度测试后,由于深度缓冲区精度限制,导致深度值在误差极小时,OpenGL出现无法判断的情况,出现画面交错闪现的现象,举例如下: Z冲突剧烈开启深度测试
glEnable(GL_POLYGON_OFFSET_FILL)
关闭深度测试
glDisable(GL_POLYGON_OFFSET_FILL)
预防解决Z冲突方法:
1、避免两个物体靠的太近:在绘制时,插入一个小偏移
指定偏移量glPolygonOffset (GLfloat factor, GLfloat units),参数一般填 -1 和 -1
2、将近裁剪面(设置透视投影时设置)设置的离观察者远一些:提高裁剪范围内的精确度
2、使用更高位数的深度缓冲区:提高深度缓冲区的精确度
网友评论