android openGL ES详解——面剔除

打印 上一主题 下一主题

主题 645|帖子 645|积分 1935

一、什么是面剔除?

1.面剔除

尝试在头脑中想象一下有一个3D立方体,你从任何一个方向去看它,最多可以同时看到多少个面。如果你的想象力不是过于丰富,你终极最多能数出来的面是3个。你可以从一个立方体的恣意位置和方向上去看它,但是你永久不能看到多于3个面。所以我们为何还要去绘制那三个不会显示出来的3个面呢。如果我们可以以某种方式丢弃它们,我们会进步片段着色器超过50%的性能!
   正反面剔除方案,是OpenGL中针对图形绘制的一种本领,紧张用于处理立体图形绘制时,只绘制观察者能看到的部分,看不到的部分就丢弃不绘制,这种做法可以将渲染性能进步50%左右。我们所说的是超过50%而不是50%,因为从一个角度只有2个或1个面可以或许被看到。这种情况下我们就可以或许进步50%以上性能了。
  这简直是个好主意,但是有个问题必要解决:我们怎样知道某个面在观察者的视野中不会出现呢?如果我们去想象任何封闭的多少平面,它们都有两面,一面面向用户,另一面背对用户。如果我们只渲染面向观察者的面会怎样?
这正是面剔除(Face culling)所要做的。OpenGL答应检查所有正面朝向(Front facing)观察者的面,并渲染它们,而丢弃所有反面朝向(Back facing)的面,如许就节约了我们很多片段着色器的命令(它们很昂贵!)。我们必须告诉OpenGL我们使用的哪个面是正面,哪个面是反面。OpenGL使用一种智慧的手段解决这个问题——分析顶点数据的连接顺序(Winding order)。
2.隐藏面消除

任何一个3D的物体,比如立方体,球,多边形多面立方体,等等,就像地球有昼夜一样,太阳光永久只能照射在地球的一个面上,在任何情况下我们都只能看到其中的一个面,那么对于看不到的反面在计算机里图形学内里如果不被渲染,那么性能会进步50%,即使渲染了也不看不到,而且性能降落,所以,完全没有必要。在绘制3D场景的时间,我们必要决定哪些部分是对观察者 可见的,或者哪些部分是对观察者不可⻅的.对于不可见的部分,应该及早丢弃.比方在⼀个不透明的墙壁后,就不应该渲染.这种对于看不到的面不去渲染的情况叫做“隐藏面消除”
二、立方体中的正反面

任何物体都有两面性,正面和反面,而观察者只能看到一个面.OpenGL可以通过分析顶点数据的顺序检测到面向观察者的面从而渲染他们,丢弃反面的渲染.如许可与节约片元着色器的性能.
1.正反面的定义



  • 正面:按照逆时针顶点连接顺序的三角形面
  • 反面:按照顺时针顶点连接顺序的三角形面


2.顶点连接顺序分析



  • 左侧三角形顶点顺序为: 1—> 2—> 3 ; 右侧三角形的顶点顺序为: 1—> 2—> 3 - 当观察者在右侧时,则右侧的三角形方向为逆时针方向则为正面,左侧的三角形为顺时针为反面
  • 当观察者在左侧时,则左侧的三角形方向为逆时针方向为正面,右侧的三角形为顺时针为反面
  1. GLfloat vertices[] = {
  2.     //顺时针
  3.     vertices[0], // vertex 1
  4.     vertices[1], // vertex 2
  5.     vertices[2], // vertex 3
  6.     // 逆时针
  7.     vertices[0], // vertex 1
  8.     vertices[2], // vertex 3
  9.     vertices[1] // vertex 2
  10. };
复制代码

正面和反面是由三角形的顶点定义顺序和观察者的方向共同决定的,随着观察者的角度方向改变,正面反面也会跟着改变。观察者的角度很好理解,站在不同的角度方位看一个物体,能看到的一面是正面,看不到的是反面。现实的顶点连接顺序是在光栅化阶段(Rasterization stage)计算的,所以当顶点着色器已经运行后。顶点就可以或许在观察者的观察点被看到。把所有三角的顶点都定义为逆时针是一个很好的习惯。
三、面剔除常用API



  • 开启正反面剔除(默认是反面剔除)
  1. void glEnable(GL_CULL_FACE)
复制代码
从这儿以后,所有的不是正面朝向的面都会被丢弃(尝试飞入立方体看看,内里什么面都看不见了)。目前,在渲染片段上我们节约了超过50%的性能,但记住这只对像立方体如许的封闭外形有用。当我们绘制上个教程中那个草的时间,我们必须关闭面剔除,这是因为它的前、背面都必须是可见的。


  • 关闭正反面剔除(默认是反面剔除)
  1. void glDisable(GL_CULL_FACE)
复制代码


  • 用户选择剔除哪个面(正面/反面)
OpenGL答应我们改变剔除面的类型。要是我们剔除正面而不是反面会怎样?我们可以调用glCullFace来做这件事:
  1. void glCullFace(<#GLenum mode#>)
  2. glCullFace函数有三个可用的选项:
  3. GL_BACK:只剔除背面(默认值)。
  4. GL_FRONT:只剔除正面。
  5. GL_FRONT_AND_BACK:剔除背面和正面。
复制代码


  • 用户指定顺时针或者逆时针为正面
另外,我们还可以告诉OpenGL使用顺时针而不是逆时针来表示正面,这通过glFrontFace来设置:
  1. glFrontFace(GLenum mode)
  2. glFrontFace(GL_CCW); // 逆时针为正面(默认值)
  3. glFrontFace(GL_CW); // 顺时针为正面
复制代码


  • 我们可以做个小实行,告诉OpenGL如今顺时针代表正面:
  1. glEnable(GL_CULL_FACE);
  2. glCullFace(GL_BACK);
  3. glFrontFace(GL_CW);
  4. 或者
  5. glEnable(GL_CULL_FACE);
  6. glCullFace(GL_FRONT);
  7. 上述两段代码功能相同
复制代码

具体实现代码如下
  1.   //例如,剔除背⾯实现(1)
  2.     glCullFace(GL_BACK);
  3.     glFrontFace(GL_CW);
  4.     //例如,剔除正⾯实现(2)
  5.     glCullFace(GL_FRONT);
  6.     //以下两行是默认的,可以不写
  7.     glFrontFace(GL_CCW);
  8.     glCullFace(GL_BACK);
复制代码
剔除正、反面举比方下:
  1. // 剔除背面方式1 - 正常情况下使用默认的情况即可
  2. glEnable(GL_CULL_FACE);
  3. glCullFace(GL_BACK);
  4. //剔除背面方式2
  5. glEnable(GL_CULL_FACE);
  6. glFrontFace(GL_CW);
  7. glCullFace(GL_FRONT);
  8. //剔除正面方式1
  9. glEnable(GL_CULL_FACE);
  10. glCullFace(GL_FRONT);
  11. //剔除正面方式2
  12. glEnable(GL_CULL_FACE);
  13. glFrontFace(GL_CW);
  14. glCullFace(GL_BACK);
复制代码
四、正反面剔除功能举例



  • 未开启反面剔除功能
绘制甜甜圈模子,旋转甜甜圈,会出现如下情况:



  • 开启正反面剔除功能
旋转甜甜圈又出现如下问题:




  • 上面这种情况出现的原因是什么呢?
在甜甜圈旋转的过程中,当前后两部分重叠时,对于我们而言,必要展示的是前面的部分,背面部分是隐藏面,但是OpenGL并不能清楚的区分哪个面在前哪个面在后,因此出现了缺口。


  • 那么怎样解决这种问题呢?
利用深度测试解决。深度测试参考文章:android openGL ES详解——深度缓冲区_opengl 深度信息-CSDN博客
五、总结

隐藏面消除总结:


  • 正反面消除:必要根据顶点数据顺序判断用户可见部分与隐藏面,隐藏面直接丢弃,不绘制,只绘制可见部分
  • 深度测试:可以一次性解决隐藏面消除问题,原理是不管有多少图层,只显示可见图层,剩余不可见的都丢弃
正如你所看到的那样,面剔除是OpenGL进步服从的一个强大工具,它使应用节流运算。你必须跟踪下来哪个物体可以使用面剔除,哪些不能。


 



参考文章
OpenGL_正面剔除,深度测试和Z辩论 - 简书
OpenGL--- (四)OpenGL渲染本领:正反面剔除 - 简书
Open GL 渲染本领-正反面剔除、深度测试、颜色混合 - 简书
OpenGL--- (四)OpenGL渲染本领:正反面剔除 - 简书
OpenGL---(五)OpenGL渲染本领:深度测试、多边形偏移、混合 - 简书
面剔除 - LearnOpenGL-CN

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

钜形不锈钢水箱

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表