默认的OpenGL ES映射到屏幕的坐标为左下角(-1.0,-1.0)右上角(1.0,1.0)。如果没有坐标变换的话,那么我们绘制出的物体坐标以及大小并不能按我们所想。
在OpenGL ES2.0及以后的版本中,都采取可渲染管线编程。好处是可以编程控制GPU处理顶点数据,得到各种牛逼炫酷帅的效果,麻烦的地方就是坐标转换等等都要自己去编程处理。其实想想也对,目前CPU和GPU的处理速度完全不在一个档次上,GPU的瓶颈在于每次等待CPU数据传输的时间。那么,把大量的数据一次性送入GPU,然后在GPU中实现快速运算就成为理所当然的考虑了。这就是采用GPU编程的好处。
OpenGL采用列向量以及列矩阵表示数据。例如:
因此,OpenGL中都是采取左乘。例如将一个物体先旋转再移动(这里假设旋转矩阵为R,移动矩阵为T,物体坐标向量为v),正确的操作顺序就应该是
从3D模型到屏幕的成像所经历的变化是 模型坐标 -> 观察变换 -> 视图变换 -> 剪裁 -> 视口变换。其中,需要我们编程处理的是观察变换以及视图变换这两步。
那么,既然x,y,z就可以表示三维坐标,为什么还要有w分量。w分量是用于处理平行的两条线交于一点的问题。既然平行为什么会相交?因为在透视观察中,会发现一个有趣的现象就是当两条平行的直线延伸到很远的点的时候,看起来就是汇聚于一点的。为了解决这个问题,引入w分量。
另外采用矩阵相乘的形式会引发万向节锁的问题。这个问题我没研究过,就不班门弄斧了。等研究了之后再谈这个问题。
一个模型要转换为屏幕坐标的编程处理过程为:
好了,经过上面的铺垫,开始进入正题——开启iOS的深度测试(这部分很短)。
原本以为iOS中深度测试就是一句glEnable(GL_DEPTH_TEST)就可以搞定的。
结果绘制出来的图像,前后面上下面顺序什么的乱七八糟。总之就是前后面上下面顺序完全错了,完全不像有深度测试的感觉。最后意识到是深度测试没搞定,于是搜了一些资料。处理完成后整理如下:
和颜色缓冲不同的就是使用glRenderbufferStorage()函数进行分配的时候,需要指定缓冲区的宽高。其中第二个参数表示计算精度,值越高越平滑,当然内存也消耗的更大。
接下来关联深度缓冲到帧缓冲区
完了?
我也以为完了,结果渲染出来不是黑屏就是粉红色!!!然后找了一份源码看了一下,发现后面还有一句
加上,正确渲染了。
不明白为什么,希望高手赐教。
最后渲染结果如下(我加了光照):
可以在Github上下载到代码,运行环境为MacOS 10.12.4 Xcode 8.3.1