当我们以某一视角观察一个多面立体图形的时候,我们的肉眼只能看到一部分面积,也就是我们的视线正前方的面,例如观察一个圆柱体根据我们观察角度的不同我们只能看到一个曲面或者一个曲面加一个圆,观察一个立方体最多也只能看到三个面,所以为了提高渲染性能,我们完全没有必要去绘制我们看不到的面,在OpenGL中面剔除就可以实现这一需求。
面剔除(Face Culling)
在OpenGL中开启面剔除使用
glEnable(GL_CULL_FACE);
使用glFrontFace (GLenum mode);
可以指定剔除模式参数为GL_CCW
或GL_CW
,GL_CCW
为默认的模式,即以顶点逆时针连接方向为正面,以顶点顺时针连接方向连接为反面。图例如下:(图片来自www.learnopengl.com)。
如上图立方体距离我们眼睛最近的一个面以顶点1>2>3连接顺序为正面,那么后面的那个面为反面。
使用glCullFace (GLenum mode);
可执行剔除,参数可以是GL_BACK
或 GL_FRONT
或GL_BACK_AND_FRONT
,分别是背面剔除、正面剔除、正面反面都剔除。
面剔除除了可以提升渲染性能,还可以解决图元在光栅化渲染的时候由于三角形绘制顺序出错而导致图形的反面覆盖在图形的正面上的显示错误。图例如下:
如上图所示,绘制一个像游泳圈一样的立体图形,通过键盘来控制图形旋转,但是旋转后我们会发现图形出现了一些黑色的条,这种情况就是因为图形旋转重新渲染时在光栅化渲染时会把图元分解为一个个三角形,如果先渲染正面的三角形后渲染反面的三角形,那么三角形重叠的部分就会是反面的三角形覆盖在了正面的三角形上,从而出现了我们在上图看到的那种情况。
通过上图可以很直观的看到图形的反面是黑色的,并且在上方出现了黑色覆盖了红色的情况。
所以我们可以通过反面剔除来解决这个问题。
在使用背面剔除的时候可能会出现重叠部分剔除多了的情况(如下图所示),这种情况我们可以使用开启深度测试来解决。
深度测试(GL_DEPTH_TEST)
在OpenGL中深度指的就是在坐标系中像素Z的值,距离观察者的距离,观察者可以在任何位置,OpenGL中会有专门一块缓存区来存放Z值--深度缓存区,来存放每个像素上的Z值。
深度缓存区的作用
一般情况下,我们绘制图形时,后面绘制的会覆盖前面的图形,绘制的顺序为先后面后前面,这样就会产生一个性能问题,先绘制的会被后绘制的覆盖掉,显然这是没有任何意义的,上面介绍过通过剔除法可以剔除背面的图形,从而提高性能,深度测试也可以解决这个问题,在有了深度缓存区后,绘制的时候会检查Z值,靠近观察者的覆盖,而不是靠绘制顺序来决定的。-
如何使用深度缓存区测试
使用glEnable(GL_DEPTH_TEST);
来开启深度测试。默认情况下,Z值小的面会被覆盖。
如果观察者在Z轴的正方向,Z值大的靠近观察者
如果观察者在Z轴的负方向,Z值小的靠近观察者 深度测试的弊端
在绘制多边形并且开启深度测试时,可能会产生z-stitching和z-fighting。当使用glPolygonMode (GLenum face, GLenum mode)
为多边形绘制边界时,由于线和面的光栅化的方式不同,导致位于同一位置的多边形和直线的深度值并不相同,进而导致直线有时在多边形的里面,有时在多边形的外面,这种现象就是"Stiching。
而Z-fighting主要是指当两个面共面时,二者的深度值一样,深度缓冲就不能清楚的将它们两者分离开来,位于后面的图元上的一些像素就会被渲染到前面的图元上。
使用glPolygonOffset (GLfloat factor, GLfloat units)
可以解决这两个问题。