什么是隐藏面消除
-
在绘制一个3D物体的时候,我们只能够看到物体的一部分(正面),对于不可见的背面和里面,应该不予绘制,这样既可保证图像显示正确还可以提高程序性能,这种情况叫做“隐藏面消除”。
隐藏面消除前
隐藏面消除后
实现隐藏面消除的解决方案
1.油画算法
-
原理:
先绘制场景中的离观察者较远的物体,在绘制较近的物体。例如下图中:先绘制红色部分,在绘制黄色部分,最后在绘制灰色部分,即可解决隐藏面消除的问题。
油画算法 -
弊端
1.把不该显示的图像也绘制了一遍,影响性能。
2.如果是几个图像互相叠加的情况下(如下图),油画算法将无法处理。
图像互相叠加
2.正背面剔除(Face Cuilling)
-
原理:
任何平面都有2个面,正面/背面。意味着你一个时刻只能看到一面。OPenGL 可以做到检查所有正面朝向观察者的面,并渲染它们。从而丢弃背面朝向的面。这样可以节约片元着色器的性能。
问题:如何告诉OpenGL 你绘制的图形,哪个面是正面,哪个面是背面?
答:通过分析图形的顶点数据绘制顺序。
正面:按照逆时针顺序连接顶点数据。
背面:按照顺时针顺序连接顶点数据。
正背面剔除
-
存在问题1
当绘制一个复杂图形时,图形有两个正面重叠,OPenGL 无法判断该绘制哪一个。如下图的圆环:A面跟B面都是面向观察者的正面,当他们互相叠加时会出现问题。
-
解决方法:开启深度测试
简单来讲,深度测试就是在绘制图形的时候判断该像素点的Z值(深度值),深度值越大说明离观察者越远,如果两个正面互相叠加那么只绘制离观察者近的那个面。
//开启深度测试
glEnable(GL_DEPTH_TEST);
开启深度测试后的圆环:
开启深度测试后
-
存在问题2
当2个正面的深度值完全一样时,OpenGL 无法正确判断该绘制哪一个面,深度测试结果不可预测。显示出来的图像会出现闪烁的情况,这个就是ZFighting闪烁。
ZFighting闪烁问题 -
解决方法:使用多边形偏移(Polygon Offset)
使用多边形偏移后,如果两个正面的深度值一样,OpenGL 会让它们的深度值产生细微的偏移,这样就能让2个面之间有所区分。
//开启多边形偏移:
glEnable(GL_POLYGON_OFFSET_FILL);
//指定偏移量
glPolygonOffset(-1,-1);
ZFighting闪烁问题预防:
1.不要将两个物体靠得太近,避免渲染时叠在一起。
2.尽可能将近裁剪面设置的离观察者远一点,因为近裁剪面深度的精确度是很高的。
3.使用更高位数的深度缓冲区,通常使用的深度缓冲区是24位,现在有一些硬件使用32位的缓冲区,使精确度得到提高。
网友评论