正背面剔除和深度测试

一、正常渲染会出现的问题

默认情况下,OpenGL 将逆时针⽅向环绕绘制的的三角形定义为正⾯,反之为背面。当我们需要渲染一个图案到屏幕上时,图案中的每个点、线或三角形都会在屏幕上进行光栅化,并按照图元装配时的顺序进行排列。

如上图,当我们绘制一个由多个三角形组成的复杂图形时,由于每个三角形都有自己的绘制顺序(正背面之分),所以移动图案时就会出现部分背面的三角形会显示出来,也就是图中黑色部分。那么如何解决这一问题呢:

二、正背面剔除

油画算法:绘制遵循严格的先后顺序,先远后近,近处的图案会把远处的不应展示的部分进行遮盖以解决这一问题。虽然看似完美但也会有其他问题,当我们绘制一个互相层叠覆盖的图案时,由于没有严格的先后顺序,计算机只能进行多次绘制,但是多次绘制自然也会导致性能的浪费

正背面剔除:通过图元装配阶段的方向进而区分正背面,背面的直接被抛弃不渲染,自然就可以解决上述问题了(省略背面渲染流程还可以起到节省性能消耗的作用)。

开启背面剔除:glEnable(GL_CULL_FACE);

关闭背面剔除:glDisable(GL_CULL_FACE);

虽然剔除了不应显示的背面,修复了黑色的问题,但如果旋转图案我们会发现如上情况(两个正面同时存在,电脑无法区分应使用哪个,最终导致错抛的情况)。继续解决问题,请看下文:

三、深度测试

深度:OpenGL坐标系中像素点的Z坐标距离观察者的距离。观察者可能放在坐标系的任何位置,那么,就不能简单的说Z数值越大或越小,就是越靠近观察者。(如果观察者在Z轴的正方向,Z值大的靠近观察者,如果是在Z轴的反方向,则Z值小的更靠近观察者。)

深度缓冲区(DepthBuffer):深度缓冲区原理就是把一个距离观察平面(近裁剪面)的深度值(或距离)与窗口中的每个像素相关联。

首先使用glClear(GL_DEPTH_BUFFER_BIT),把所有像素的深度值设置为最大值。

启用了深度缓冲区,在绘制每个像素之前OpenGL都会把它的深度值和已经存储在这个像素的深度值进行比较。如果新像素深度值<原先像素深度值,则新像素值会取代原先的像素值;反之新像素的颜色值和深度将被丢弃。这个比较丢弃的过程就叫做深度测试,深度测试是另一种高效消除隐藏面的技术。

申请颜色和深度缓冲区:

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);

启用深度测试:glEnable(GL_DEPTH_TEST);

关闭深度测试:glDisable(GL_DEPTH_TEST);

注意:如果没有深度缓冲区,那么启动深度测试的命令将被忽略。在绘制场景前,清除颜色缓冲区和深度缓冲区:

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

理想结果

四、z-fighting(z冲突、闪烁)问题

当深度值精确度较低,像素点所处深度距离较接近,界面前后图案交替显示的情况。

那么如何解决这一问题呢:

1、插入偏移量(第二个像素点绘制时深度增加偏移量与之前深度形成较大区分)

2、使用 glPolygonOffset 函数调节片段的深度值

3、硬件层面解决,采用更高性能设备以使用更高位的深度缓存区使精确度得到提高(通常使用的深度缓冲区是24位的,现在有一些硬件使用32位的缓冲区)

你可能感兴趣的:(正背面剔除和深度测试)