1.
深度渲染缓存(Depth Render Buffer)
三角形、线段和点是按它们被GPU处理的顺序被渲染的。如果没有一个深度缓存,为最后一个对象的绘制而产生的片元总是会覆盖以前渲染的层叠的片元。
视点决定了场景中的哪一个对象会被渲染在其他对象前面。
变换(transformation)使从任意视点渲染场景成为可能。
一个变化的视点必然需要重新计算所绘制对象的正确顺序。
深度渲染缓存是一个可选的输出缓存,与像素颜色渲染缓存相似。
几乎所有的OpenGLES应用都使用深度缓存,因为几乎所有的OpenGLES应用都使用深度缓存,因为几乎所有的应用都使用坐标系转换来改变渲染的视点。
在大部分情况下,一个深度缓存会消除对于三角形、线段和点进行排序的需求。
深度缓存也常常叫做Z缓存,因为如果坐标系的X轴和Y轴对应于屏幕的宽和高,那么Z轴只是的就是屏幕的内外。一个片元和视点之间的距离大体相当于这个片元沿着Z轴深入屏幕的位置。
GPU把对于每个片元的深度的计算作为渲染的一个固定部分。深度缓存的使用为GPU提供了一个用来保存计算出深度的地方,之后这个深度又被GPU利用来控制在像素颜色渲染缓存中的片元的位置的置换。
2.
利用GLKit添加深度缓存
GLKit支持使用16位或24位来保存深度值的深度渲染缓存。
以上代码使用了一个变换来矫正拉伸的渲染效果。
GLKMatrix4GLKMatrix4MakeScale(float sx,float sy,float sz)函数,上面代码中表示会沿着X轴,Z轴保持不变,沿着Y轴的单位长度aspectRatio为(GLfloat)view.drawableWidth/(GLfloat)view.drawableHeight的值,drawableWidth属性以像素为单位提供了视图的像素颜色渲染缓存的宽度,与视图全屏Core Animation相适配。drawableHeight属性以像素为单位提供了高度。屏幕纵横比为宽度除以高度。
3.
深入探讨不用GLKit添加深度缓存
管理一个深度缓存需要的步骤:
(1)Generate (生成) ——— 告诉OpenGLES为深度缓存生成一个独一无二的标识符。
(2)Bind (绑定) ——— 告诉OpenGLES在接下来的操作中使用哪一个缓存。
(3)Configure Storage(配置存储) ——— 指定深度缓存的大小
(4)Attach (附加)——— 附加深度缓存到一个帧缓存。
与一个Core Animation层分享内存的像素颜色渲染缓存在层调整大小时会自动调整大小。其他的缓存,例如深度缓存,并不会自动调整大小。每当一个AGLKView实例被重新调整大小时,与他相关联的层也会调整大小并且视图的-(void)layoutSubviews方法会被调用。
4.
变换
从数学上说,变换就是在两个坐标系之间转换顶点坐标。
每个坐标系都是相对于其他的参照坐标系的。
对于OpenGLES来说,最终的参照坐标系实在一个像素颜色渲染缓存中的像素位置的2D数组。
在渲染过程中,GPU会转换点、线和三角形的顶点坐标为着色片元。当前(实际上是在GPU处理顶点数据时)坐标系决定了片元在像素颜色渲染缓存和深度缓存中的位置。
线性代数可以为坐标系间转换提供解决方案。任意数量任意顺序的基本变换都可以能够被捕获并保存在一个简单的4*4的浮点值矩阵中。一个矩阵定义一个坐标系。
矩阵计算几乎完全使用加法和乘法,并且在现代GPU上执行的非常快。这是好事,因为每次一个场景被渲染时,GPU就会变换所有的顶点,并且在一个场景中常常含有几十万个顶点。
5.
基本变换
平移translation、旋转rotation、缩放scale、透视perspective
以上四个基本变换联合决定了在一个新坐标系中的每一个顶点位置是怎么转换为参考坐标系中的一个位置的。
每个基本变换对应于矩阵的一个简单变化。
(1)平移:
通过相对于参考坐标系的原点移动新坐标系的原点,定义了一个新的坐标系。平移不会影响坐标轴的单位长度,平移不会改变坐标轴相对于参考坐标系的方向。
GLKMatrix4GLKMatrix4MakeTranslation(float tx,float ty,float tz)
函数通过平移一个单位矩阵来返回一个定义了坐标系的新矩阵。x、y、z参数指定了新坐标系的原点沿着当前参考坐标系的每个轴移动的单位数。
(2)旋转:
通过相对于参考坐标系坐标轴的方向旋转新坐标系的坐标轴来定义一个新的坐标系。旋转的坐标系会与参考坐标系使用同一个原点。旋转不会影响坐标轴的单位长度,只有坐标轴的方向会发生变化。
GLKMatrix4GLKMatrix4MakeRotation(float radians,float x,float y,float z);
函数通过旋转一个单位矩阵来返回定义了一个坐标系的新矩阵。radians参数指定了要旋转的弧度数。
(3)缩放:
通过相对于参考坐标系的坐标系的单位长度改变新坐标系的坐标轴的单位长度来定义一个新的坐标系。缩放的坐标系与参考坐标系使用同一个原点,坐标轴的防线通常不会改变。不过,通过一个负值所做的缩放会反转坐标轴的方向。
GLKMatrix4GLKMatrix4MakeScale(floatsx,floatsy,floatsz)
函数会通过扩大或缩小一个单位矩阵的任意坐标轴的单位长度来返回一个定义了坐标系的矩阵。x、y、z参数指定了用来扩大或缩小每个轴的单位长度的因数。
(4)透视:
透视是通过相对于参考坐标轴的单位长度多样化新坐标系的坐标轴的单位长度来定义一个新的坐标系。透视不会改变坐标轴的方向或者原点,但是坐标轴的每个单位离原点越远长度越短。这个效果会让在远处的物体比离原点近的物体显得更小。
GLKMatrix4GLKMatrix4MakeFrustum(float left,float right,float bottom,float top,float nearZ,float farZ);
函数会透视一个单位矩阵来返回一个定义了坐标系的新矩阵。透视坐标系的的形状是一个类似角椎体的平截头体。
以上为5-4例子中处理基本变幻的代码。
结合四大变幻,可以定义新的坐标系,不过重要的是变换的顺序。平移在旋转的前面还是后面会产生不同的坐标系。缩放在旋转的前面还是后面也会产生不同的坐标系。先旋转再平移最后缩放与先平移再旋转最后缩放是不同的。
5.1
projectionMatrix 和 modelviewMatrix
GLKBaseEffect的transform属性是一个GLKEffectPropertyTransform类型的实例并为支持常见的操作保存了三个不同的矩阵。
projectionMatrix用于整个场景的坐标系。
modelviewMatrix用于控制对象(场景内模型)显示位置的坐标系。
GLKBaseEffect会级联modelviewMatrix和projectionMatrix以产生一个modelviewProjectionMatrix矩阵,这个矩阵会把对象顶点完全地变换到OpenGLES默认坐标系中。
默认坐标系直接映射到像素颜色缓存中的片元位置。
5-4例子中在viewDidLoad方法中初始化modelviewMatrix,使用一个明显的右上视角来渲染对象。
5-4中移动滑块时,会更新每个用户用来控制变换的值。首先保存baseEffect的modelviewMatrix的当前值,以便加载。然后通过按特定的顺序连接当前矩阵与用户控制的三个变换矩阵,这个例子构建了一个新的矩阵。
在用户控制的变换结合到modelviewMatrix后,为绘制准备好baseEffect,最后用一个白色的漫反射光绘制场景中的对象。
重新设置modelviewMatrix为保存的值,灯光颜色改为黄色,再次绘制相同的对象。场景中的黄色对象提供了一个参考,以便可以清楚地观察用户控制的变换会怎么影响在最终的像素颜色渲染缓存中的白色对象的哪些片元。
总结:除了使用以上通过临时变量保存并回复modelviewMatrix外。GLKit还提供了一个方便的数据类型GLKMatrixStack,还提供了一个用来向堆栈数据结构保存矩阵的函数集合。堆栈是一个后进先出的数据结构,它可以方便地存储某个程序可能需要回复的矩阵。
5.2
textureMatrix
以上5-5中代码显示了
5-5例子实现了纹理矩阵textureMatrix.
6.
复合变换手册
倾斜
是一个复合变换,这个变换产生了不再相互垂直的坐标轴。立方体会变成带有梯形面的盒子。
围着一个点旋转
旋转和缩放常常围绕着当前坐标系的原点发生。
围着一个点缩放
和围着一个点旋转相似。
7.
透视和平截头体
OpenGLES使用一个叫做视域(viewing volumn)的几何图形来决定一个场景生成的哪些片元将会显示在最终的渲染结果中。处于视域范围之外的几何图形都会被剔除,这意味着它会被丢弃。视域有时候也被称为投影(projection)。
一个立方体或矩形视域叫做一个正摄投影(orthographic)。利用一个正射投影,视点与每个位置之间的距离对于投影毫无影响。
当使用投影(perspective projection)时,视域不再是矩形。而是平截头体。
5-6例子可展现这部分内容。
使用视域的另一个关键要认识到,正射和透视投影都是由站在位置{0,0, 0}并向下俯视的z轴的观察者的视点产生的。本章开头说变换任意视点称为可能,但实际上,视点是恒定的。变换会施加到场景中的所有顶点上,并会投影这些顶点到视域的界面上。从概念上看,当假设的观察者的观察者的视点不变时,OpenGLES会变换所有的几何图形。整个世界移动的错觉只是看起来像是由视点变换产生的。
总结:
本章介绍了深度缓存、变换、GLKit的矩阵堆栈和视域。实际上本章没有例子会改变保存在顶点缓存中的顶点的成分。顶点位置保持不变。作为替代,变换改变了顶点被映射到2D像素颜色渲染缓存的方式。