注:本文旨在记录笔者的学习过程,仅代表笔者个人的理解,如果有表述不准确的地方,欢迎各位指正!因为涉及到的概念来源自网络,所以如有侵权,也望告知!
前言
本文通过案例的形式来逐步拆解3D图形绘制流程,从而了解3D图形中正背面剔除及深度测试的概念。
正文
知识点回顾
首先我们来回顾一下,OpenGL绘制一个图形需要我们给顶点着色器传递顶点数据,同时也需要指定图元装配的规则。比如通过下面这段代码,我们就可以得到一个金字塔的图形,图形是通过4个三角形共12个顶点拼接成的,其中vPyramid是图形的顶点数据,GL_TRIANGLES则是图元的装配规则。
当然,绘制图形需要的顶点数据的数量也受图元装配方式的影响,不同的装配方式会不同程度的复用顶点数据,选择合适的图元装配方式可以达到高效的绘制效率。OpenGL为我们提供了以下这些图元装配方式:
绘制甜甜圈
闲话不多说,来看一下我们本次案例绘制的3D图形是什么?对!你没看错,是一个甜甜圈!那我们需要哪些过程才能得到我们的甜甜圈呢?
同样我们需要初始化OpenGL环境并设置图形的顶点数据图元装配方式,但是这里可以看到我们并没有自己去创建顶点数据,因为OpenGL提供了API为一些常用的图形获取顶点数据,gltMakeTorus函数就帮我们生成了甜甜圈的顶点数据。
其中viewFrame对象大家可以理解为观察者,我们可以通过调整观察者的视角来查看整个3D图形。
同时3D图形的绘制,需要通过模型视图矩阵、投影矩阵等矩阵变换后才能将图形绘制到2D视图上。其中modelViewMatix就我们需要的模型视图矩阵;projectionMatrix是我们需要的投影矩阵;而transformPipeline则是我们的渲染管线,它可以为我们生成最终我们想要的变换矩阵。最后通过默认光源着色器将我们美味的甜甜圈渲染到了视图上。
正背面剔除
这时当我们调整观察者视角去查看我们的甜甜圈,你发现了什么?wtf!这是什么鬼?我们发现甜甜圈出现bug了,竟然出现了一些黑色块。
这又是为什么呢?大家可以结合我们的实际场景联想一下,从⼀个⽴⽅体的任意位置和⽅向上看,你能看到几个面?答案毫无疑问,你永远不可能看到多于3个⾯。在OpenGL中也是一样的道理,甜甜圈的背光面其实是看不到的部分,OpenGL将它绘制成了黑色,所以当我们调整观察者的时候就出现了上述的问题。
既然知道了问题的所在,那我们要怎么解决呢?其实很简单,只需要通过OpenGL的API将我们的背面剔除就可以啦,是不是So Easy!
这时我们再看一下,发现原先的黑块已经消失的无影无踪了,perfect!
这个时候你可能又会有疑问,虽然OpenGL提供了API可以直接调用,但是它是怎么知道哪一部分是正面哪一部分又是背面呢?
深度测试
如果你以为这一切已经大功告成了,那你会发现意外总是会不合时宜的出现,wait!我又发现了什么!我的甜甜圈是被谁咬了一口吗?
想要解决这个问题,我们得先了解3D图形深度相关的概念:
通过概念不难发现,这个问题其实是由于像素点的深度导致的,在不开启深度测试的情况下,就会出现像素点被覆盖的问题,也就出现了上面甜甜圈出现缺口的现象,那么我们只需要将OpenGL深度测试功能打开就可以解决问题啦。
打开深度测试后,我们再重新看一下我们的甜甜圈,果然不出所料,甜甜圈完整了。