OpenGL ES for Android(面剔除)

397 阅读2分钟

简介

首先我们绘制一个立方体,想象一下能看到几个面。一般情况下我们最多能看到三个面,极端的情况我们甚至只能看到一个面,这时候如果不绘制看不到的面,是不是非常节省资源,忽略掉看不到的面就叫面剔除。那么怎么判断一个面是否面向观察点呢,在OpenGL中用了这样一个技巧:分析顶点数据的环绕顺序(Winding Order)。

环绕顺序

绘制三角形时用到了三个顶点,这三个顶点的顺序就是我们提到的环绕顺序。三个点的顺序要么是顺时针,要么是逆时针的,而且当一个面在面向观察点时是顺时针时,那么它在背向观察点时肯定是逆时针的,看下下图:

我们绘制三角形时顺序是123时,面向我们是逆时针的;旋转180度后,还是123的顺序,此时面向我们就是逆时针的。这样我们就可以用这个逻辑来处理面剔除:当一个图形是逆时针绘制时就显示出来,如果是顺时针的就忽略掉。

面剔除

我们复制一下前面绘制立方体的代码,先显示出来,然后开启面剔除,使用下面的代码开启剔除:

  GLES20.glEnable(GLES20.GL_CULL_FACE);

我们先看下效果:

只留下了两面,其他面都被剔除了,但是显示的效果不对,我们应该保留前面,上面和右面,根本原因是我们绘制三角的顺序有错误。默认情况下,只会保留逆时针绘制的面,我们需要重新定义绘制三角形的顶点顺序,按照逆时针绘制就可以了,修改之后我们再看效果就正常了:

开启面剔除后可以使用的两个方法glFrontFace和glCullFace。

glFrontFace(int mode):设置哪种环绕顺序是面向观察点的。默认值是GLES20.GL_CCW(逆时针),当我们设置为GLES20.GL_CW(顺时针)效果如下:

glCullFace(int mode):设置剔除哪些面。参数可以有三个:1、GL_BACK:只剔除背向面;2、GL_FRONT:只剔除正向面;3、GL_FRONT_AND_BACK:剔除正向面和背向面。GL_BACK是默认值。

当使用GLES20.glFrontFace(GLES20.GL_CCW)和GLES20.glCullFace(GLES20.GL_FRONT)时,只会显示左下后三面,它等同于使用GLES20.glFrontFace(GLES20.GL_CW)和GLES20.glCullFace(GLES20.GL_BACK)。

当使用GL_FRONT_AND_BACK时,不会绘制任何多边形,只会绘制其他例如点和线。

你可以参考文档learnopengl-cn.github.io/04%20Advanc…来了解对于面剔除更详细的介绍。

如有不足敬请谅解,路过的看官帮忙点赞关注下。