学习OpenGL ES for Android(二十一)— 面剔除

首先我们绘制一个立方体,想象一下能看到几个面。一般情况下我们最多能看到三个面,极端的情况我们甚至只能看到一个面,这时候如果不绘制看不到的面,是不是非常节省资源,忽略掉看不到的面就叫面剔除。那么怎么判断一个面是否面向观察点呢,在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时,不会绘制任何多边形,只会绘制其他例如点和线。

你可以参考文档https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/04%20Face%20culling/来了解对于面剔除更详细的介绍。本章源码https://github.com/jklwan/OpenGLProject/blob/master/sample/src/main/java/com/chends/opengl/renderer/advanced/opengl/FaceCullingRenderer.java,可以修改参数来观察显示效果。

发布了53 篇原创文章 · 获赞 17 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/jklwan/article/details/103913152