OpenGL 浅析隐藏面消除

1,241 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情


  1. Swift Optional
  2. Swift Enum
  3. iOS开发 做一个三角形
  4. Swfit 指针类型
  5. Swift 属性(下)
  6. Swift 属性
  7. Swift 小结
  8. Swift 类与结构体(下)
  9. Swift 类的生命周期
  10. Swift 类的初始化器
  11. Swift 类与结构体
  12. OpenGL 压缩纹理
  13. OpenGL 隧道坐标计算
  14. 0penGL 像素格式及数据类型
  15. OpenGL 纹理对象
  16. OpenGL 纹理
  17. OpenGL 模型变化
  18. OpenGL 视图
  19. OpenGL 矩阵
  20. OpenGL 向量
  21. OpenGL 颜色混合
  22. OpenGL 深度测试的潜在风险
  23. OpenGL 浅析深度测试
  24. OpenGL 浅析隐藏面消除
  25. OpenGL 图元连接方式
  26. 记WKWebView与HTML完成交互两三事
  27. OpenGL 渲染流程图解析
  28. OpenGL 控制你的正方形
  29. OpenGL 专业名词解释
  30. OpenGL 环境搭建 - MacOS


今天我们,简单聊一聊关于在绘制3D场景的时候,可能会产生的渲染问题,以及在解决渲染问题时所使用的隐藏面消失的内容。

问题如下图所示:

在绘制好的3D图形中,我们做旋转操作后,会有部分黑色的情况:

未命名.png

因为我们在使用OpenGL渲染时,都是通过三角形拼接显示出来的, 默认会将观察者能看到的和不能看到的角度,全部绘制出来;然而,观察者不能看到的部分应该及早的丢弃掉,而实际上,那些不应该被我们看到的背面,也渲染并被我们看到,就会导致部分内容存在渲染问题。所以,我们应该将不可见的部分丢弃掉,不做渲染,这中情况叫做 “隐藏面消除”(Hidden surface elimination)


油画算法:

  • 先绘制场景中的离观察者较远的物体,再绘制较近的物体.
  • 例例如下⾯面的图例例: 先绘制红⾊色部分,再绘制⻩黄⾊色部分,最后再绘制灰⾊色部分,即可解决隐藏⾯面消除的问题

未命名.png

就是对这些三角形进行排序,并且首先渲染那些比较远的三角形,再在它们上分渲染那么较近的三角形.

油画算法 存在的问题

未命名3.png

这种方法在计算机图形处理中是非常低效的;
1、 我们必须对任何发生几何图形重叠的地方每个像素进行2次写操作,而在存储其中进行写操作会使速度变慢;
2、对独立三角形进行排序的开销过高。
3、油画算法有瓶颈期,比如绘制图像交叠时,没有明确的先后顺序就无从下手绘制了。

正背面剔除(Face Culling)

  • 尝试想想一个3D图形,你从任何一个方向去观察,最多可以看到几个面?
  • 答案是,最多3面.从一个立方体的任意位置和方向上看,你用过不可能看到多于3个面.
  • 那么思考?我们为何要多余的去绘制那根本看不到的3个面?
  • 如果我们能以某种方式去丟弃这部分数据,OpenGL 在渲染的性能即可提高超过50%。
  • 如何知道某个面在观察者的视野中不会出现?
  • 任何平面都有连个面: 正面/背面, 意味着一个时刻,我们只能看到一个面;
  • OpenGL 可以做到检查所有正面朝向观察者的面,并渲染它们-从而丢弃背面朝向的面.这样可以节约片元着色器的性能;
  • 通过分析顶点数据的顺序 我们可以知道绘制的图形中,哪个面时正面,哪个面时反面。

分析顶点顺序.001.png

OpenGL语法

//1.开启正背面剔除
glEnable(GL_CULL_FACE);
//2.关闭正背面剔除
glDisable(GL_CULL_FACE);
//3. 指定剔除面:mode GL_FRONT  GL_BACK GL_FRONT_AND_BACK 
void glCullFace(GLenum mode);