005-OpenGL-深度测试,多边形偏移,混合

2020-07-14  本文已影响0人  沉默Coder

上一章节我们了解了什么是正背面剔除,但是引入了一个新的问题,就是当圆环旋转到一定角度的时候,会出现缺口,如下图:

圆环缺口

要解决这个问题,就涉及到我们这一章节的内容深度测试

什么是深度?

深度就是在OpenGL坐标系中,像素点的z坐标距离观察者的距离
观察者和像素点z坐标有如下关系:
如果观察者在Z轴正方向,Z值越大则越靠近观察者
如果观察者在Z轴负方向,Z值越小则越靠近观察者

深度缓冲区(DepthBuffer)

深度缓冲区存储在显存中,深度缓冲区就是把观察者平面(近裁剪面)的深度值与窗口中每个像素点1对1进行关联以及存储;120 * 120 就需要存储 120 * 120个深度值。

当绘制一个物体表面时,首先将对应像素的深度值和当前深度缓冲区中的深度值进行比较,如果大于深度缓冲区中的值,则需要丢弃这部分。否则利用这个像素对应的深度值和颜色值分别更新深度缓冲区和颜色缓冲区。这个过程称为深度测试

开启深度测试:

glEnable(GL_DEPTH_TEST)

关闭深度测试:

glDisable(GL_DEPTH_TEST)

清除深度缓冲区和颜色缓冲区:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

我们可以通过glDepthFunc(GLenum func)来修改深度测试的规则。测试的规则主要在于该函数中的枚举值:

参数 说明
GL_ALWAYS 总是通过测试
GL_NEVER 总是不通过测试
GL_LESS 当前深度值<存储的深度值时通过
GL_EQUAL 当前深度值=存储的深度值时通过
GL_LEQUAL 当前深度值<=存储的深度值时通过
GL_GREATER 当前深度值>存储的深度值时通过
GL_NOTEQUAL 当前深度值!=存储的深度值时通过
GL_GEQUAL 当前深度值>=存储的深度值时通过

我们修改上一章节的代码(主要是在RenderScene函数中添加如下代码):

//根据设置iDepth标记来判断是否开启深度测试
    if(iDepth)
        glEnable(GL_DEPTH_TEST);
    else
        glDisable(GL_DEPTH_TEST);

修改后,我们再次旋转视图:


开启深度测试

我们发现缺口消失了,得到了一个完整的甜甜圈

但是开启深度测试以后还是有一些潜在问题

深度测试的潜在风险 Z-finghting(z冲突,z闪烁)问题

什么是Z-finghting

开启深度测试之后,OpenGL就不会再去绘制模型被遮挡的部分,
这样可以节约性能,免去了不必要的绘制。
但是由于深度缓冲区精度的限制,对于深度相差非常小的
情况下,(例如在同一平面上进行两次绘制)
OpenGL就可能不能正确判断两者的深度值,
会导致深度测试的结果不可预测。
显示出来的图像交错闪烁,如下图:
Z-fighting

ZFighting的解决方案 --- 多边形偏移(Polygon Offset)

既然导致ZFighting的原因是距离太近,无法区分图层的先后。那么我们可以在两个图层中间添加一个深度间隔。这个解决方案也叫多边形偏移
启用多边形偏移:

glEnable(GLPOLYGON_OFFSET_FILL)

关闭多边形偏移:

glDisable(GLPOLYGON_OFFSET_FILL)

开启多边形偏移的可选参数:

参数 对应模式
GL_POLYGON_OFFSET_POINT GL_POINT
GL_POLYGON_OFFSET_LINE GL_LINE
GL_POLYGON_OFFSET_FILL GL_FILL

除了这种默认的方式之外,我们还可以指定偏移量

预防ZFighting问题

颜色混合

OpenGL在渲染时会把颜色值存储在颜色缓冲区中,每个像素的深度值存放在深度缓冲区中。当深度缓冲区关闭时,新的颜色将简单覆盖原来颜色缓冲区的值,当深度缓冲区打开时,比原来的值更接近的颜色值才会被替换
当开启深度测试之后,两个互相叠加的图层一个是半透明的,另外一个是非半透明的,那么我们就不能简单的进行颜色值的覆盖,而是将两个图层的颜色进行混合;
开启颜色混合

glEnable(GL_BLEND)

关闭颜色混合

glDisable(GL_BLEND)

当混合功能被启用时,源颜色和目标颜色的组合方式是混合方程式控制的。在默认情况下,混合方程式如下:
Cf = (Cs * S) + (Cd * D)

设置混合因子

glBlendFunc(GLenum S,GLenum D)

在混合方程中,源颜色的alpha值越高,添加的源颜色成分就越高,目标颜色值就保留的越少

上一篇下一篇

猜你喜欢

热点阅读