ToB企服应用市场:ToB评测及商务社交产业平台
标题:
android openGL ES详解——面剔除
[打印本页]
作者:
钜形不锈钢水箱
时间:
2024-8-31 01:24
标题:
android openGL ES详解——面剔除
一、什么是面剔除?
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 - 当观察者在右侧时,则右侧的三角形方向为逆时针方向则为正面,左侧的三角形为顺时针为反面
当观察者在左侧时,则左侧的三角形方向为逆时针方向为正面,右侧的三角形为顺时针为反面
GLfloat vertices[] = {
//顺时针
vertices[0], // vertex 1
vertices[1], // vertex 2
vertices[2], // vertex 3
// 逆时针
vertices[0], // vertex 1
vertices[2], // vertex 3
vertices[1] // vertex 2
};
复制代码
正面和反面是由三角形的顶点定义顺序和观察者的方向共同决定的,随着观察者的角度方向改变,正面反面也会跟着改变。观察者的角度很好理解,站在不同的角度方位看一个物体,能看到的一面是正面,看不到的是反面。现实的顶点连接顺序是在
光栅化
阶段(Rasterization stage)计算的,所以当顶点着色器已经运行后。顶点就可以或许在观察者的观察点被看到。把所有三角的顶点都定义为逆时针是一个很好的习惯。
三、面剔除常用API
开启正反面剔除(默认是反面剔除)
void glEnable(GL_CULL_FACE)
复制代码
从这儿以后,所有的不是正面朝向的面都会被丢弃(尝试飞入立方体看看,内里什么面都看不见了)。目前,在渲染片段上我们节约了超过50%的性能,但记住这只对像立方体如许的封闭外形有用。当我们绘制上个教程中那个草的时间,我们必须关闭面剔除,这是因为它的前、背面都必须是可见的。
关闭正反面剔除(默认是反面剔除)
void glDisable(GL_CULL_FACE)
复制代码
用户选择剔除哪个面(正面/反面)
OpenGL答应我们改变剔除面的类型。要是我们剔除正面而不是反面会怎样?我们可以调用glCullFace来做这件事:
void glCullFace(<#GLenum mode#>)
glCullFace函数有三个可用的选项:
GL_BACK:只剔除背面(默认值)。
GL_FRONT:只剔除正面。
GL_FRONT_AND_BACK:剔除背面和正面。
复制代码
用户指定顺时针或者逆时针为正面
另外,我们还可以告诉OpenGL使用顺时针而不是逆时针来表示正面,这通过glFrontFace来设置:
glFrontFace(GLenum mode)
glFrontFace(GL_CCW); // 逆时针为正面(默认值)
glFrontFace(GL_CW); // 顺时针为正面
复制代码
我们可以做个小实行,告诉OpenGL如今顺时针代表正面:
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
或者
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
上述两段代码功能相同
复制代码
具体实现代码如下
//例如,剔除背⾯实现(1)
glCullFace(GL_BACK);
glFrontFace(GL_CW);
//例如,剔除正⾯实现(2)
glCullFace(GL_FRONT);
//以下两行是默认的,可以不写
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
复制代码
剔除正、反面举比方下:
// 剔除背面方式1 - 正常情况下使用默认的情况即可
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
//剔除背面方式2
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
glCullFace(GL_FRONT);
//剔除正面方式1
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
//剔除正面方式2
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
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企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4