OpenGL中隐藏面消除解决方案

什么是隐藏面消除

  • 在绘制一个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位的缓冲区,使精确度得到提高。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容