1.坐标空间的变换
要定义一个坐标空间(三维),需要指明其原点坐标和三个坐标轴的方向,而这些数值实际上是相对于另一个坐标空间的.也就是说,坐标空间会形成一个层次结构,每个空间都有一个父坐标空间(原点和坐标轴定义的空间).坐标空间之间的变换就是对同一个点或矢量在不同父子空间中的表示进行转换.
给定一个具体的例子描述一下这个空间变换:假定在父空间中有一个子空间,子空间的坐标原点是父空间中的(1,1,1)点,父空间的三个坐标轴方向矢量变换到子空间中分别是(2,-1,2),(2,2,-1),(-1,2,2),值得注意的是,这三个坐标轴方向矢量长度都是3,说明父空间中的矢量变换到子空间中三个坐标分量也会都扩大到原来的3倍.现在我们就可以得到父空间中的任意点或者矢量变换到子空间中的矩阵描述:
1)首先使用父空间中的三个坐标轴方向矢量变换到子空间中的矢量作为列向量构成一个三维方阵:
2)子空间的坐标原点是父空间中的(1,1,1)点,说明父空间中的点或矢量变换到子空间中描述也会像原点一样经过*移操作,因此将这个方阵扩充为四维,使用其次坐标描述这个*移操作:
3)这个四阶方阵就是这个父空间中的点变换到子空间中时的计算矩阵.需要注意的是,这是使用其次坐标描述,齐次坐标要求我们首先要在原来坐标的最后增加一个分量,这个分量的值只有0和1,其中0代表这个坐标描述的是一个矢量,1代表这个坐标描述的是一个点.举例说明:父空间中的点(1,0,0)和向量(1,0,0)变换到子空间中得到的点和向量分别这样计算:
2.模型空间
模型空间(model space),是和某个模型或者对象有关的空间,也称为对象空间(object space)或局部空间(local space),一般是以模型自身作为原点建立的坐标系.在生活中我们描述某个物体的上下左右前后即时使用的以该物体作为原点的模型空间.在Unity中也可以查看物体的局部空间,且Unity中物体的局部空间使用的是左手坐标系.
3.世界空间
世界空间(world space),是一个特殊的坐标空间,可以理解为用于描述整个世界中所有物体位置的统一空间,类似于地球上的经纬度的概念.世界空间和模型空间的关系也类似于文件的绝对路径和相对路径的关系,我们使用世界空间就可以描述所有物体的绝对位置.
在Unity中使用Transfrom组件来描述物体的旋转\位置和缩放,其实Transform内部的数据就是一个四维的齐次坐标转换矩阵,其位置\旋转和缩放等信息都可以根据这个矩阵转换出来,而这个矩阵就是该物体模型空间相对于其父物体模型空间的转换矩阵.如果一个物体没有父物体,它的这个转换矩阵就是它的局部坐标相对于世界空间的转换矩阵.
4.观察空间
观察空间(view space),或称为摄像机空间(camera space).观察空间可以认为是一个特殊的模型空间:摄像机的模型空间.在渲染前,所有顶点的空间坐标都会先转换为世界空间中的坐标,然后在转换为摄像机的局部坐标下的坐标,这样我们就可以很方便地计算这个顶点是否需要被裁剪等信息,因此摄像机的局部空间被单独列为了观察空间.
需要注意的是,在Unity中,局部空间和世界空间都是使用的左手坐标系,但是观察空间却是使用的右手坐标系,这是符合OpenGL的传统的.也正是由于这个原因,点转换到摄像机的局部空间坐标下后,继续转换为观察空间的点坐标需要将z轴值取相反数.
5.裁剪空间
顶点转化到观察空间后,接下来就会转化到裁剪空间(clip space),或称为齐次裁剪空间.从观察空间到裁剪空间的转换矩阵称为裁剪矩阵(clip matrix)或投影矩阵(projection matrix).
裁剪空间的目标是能够方便地对渲染图元进行裁剪,所以裁剪空间的变换矩阵是用于判定顶点是否位于摄像机的渲染空间内的.完全位于空间外的图元被舍弃,完全位于空间内的图元被保留,而跨越了空间边界的图元被裁剪.根据摄像机的投影方式(正交投影和透视投影)不同,裁剪空间有两种:
5.1 正交投影
正交投影(orhographic projection)没有*大远小的效果,它的视椎体是一个长方体,其裁剪矩阵如下:
其中Aspect是指屏幕纵横比,如1920*1080屏幕的Aspect值是1920/1080;Size是摄像机渲染高度的一半的单位数,如Size为10,且摄像机所处位置的纵坐标是0,朝向(0,0,-1)方向,代表会被摄像机渲染的点的纵坐标一定在-10~10之间;Far是视椎体远*面到摄像机的距离;Near是视椎体**面到摄像机的距离.我们假设有一个点坐标为(x,y,z),在左乘裁剪矩阵后结果如下:
观察得到的结果坐标会发现,这个坐标的x轴和y轴坐标就是将原来的坐标对应缩放,如果缩放后的值在区间[-1,1]外,则顶点处于视椎体外部;z轴坐标也进行了一定比例的缩放.
详细说说z轴的缩放.这里的z轴坐标使用的是摄像机的局部空间坐标的z轴值,因此在转换时有一个取反的过程.将-z = Far和-z = Near分别代入,可以得到这个缩放后的结果分别是1和-1,因此这个缩放后的计算结果在区间[-1.1]外时说明顶点处于视椎体外部.
5.2 透视投影
透视投影(perspective projection)具有*大远小的效果,它的视椎体是一个四棱台,*裁剪*面和远裁剪*面分别是四棱台的上*面和下*面.它的透视投影矩阵如下:
其中FOV是摄像机的视角.我们假设有一个点坐标为(x,y,z),在左乘裁剪矩阵后结果如下:
同样地,原来的坐标轴分量都被缩放,z轴坐标还进行了*移.这个裁剪矩阵对应的变换是将原来的视椎体缩放为一个棱长为2z长度的正方体,绕z轴旋转了90°,还将顶点*移到了缩放后的正方体中心.因此只需要判断缩放后的点坐标的分量是否在区间[-z,z]内即可.
6.屏幕空间
对于正交投影,裁剪矩阵的变换结果是将原来的视椎体变换为一个棱长为2的立方体,空间原点是立方体中心;对于透视投影,裁剪矩阵的变换结果是将视椎体变换为一个棱长为2z的立方体,空间原点是立方体中心,因此透视投影只需要将所有顶点的坐标分量都除以z,这个视椎体也变换为了棱长为2的矩形(相当于对空间再次缩放),这个除以z的过程称为齐次除法(homogeneous division)或透视除法(perspective division).在OpenGL中,最终得到的顶点坐标也称为归一化的设备坐标(Normalized Device Coordinates, NDC).
接下来我们再将归一化的设备坐标根据屏幕的不同进行不同比例的缩放,就可以得到这个顶点在屏幕上的实际渲染位置.