一、坐标空间
上篇文章讲述了如何使用矩阵来表示基本的变换,如平移、旋转和缩放,在本节我们将关注如何使用这些变换来对坐标空间进行变换。
渲染游戏的过程可以理解成是把一个个顶点经过层层处理最终转换为屏幕上的过程,本节我们就将学习这个转换过程是如何实现的。更具体的来说,顶点经过了哪些坐标空间后,最后被画在了我们的屏幕上。
1.1为什么要使用这么多不同的坐标空间
我们需要在不同的情况下使用不同的坐标空间,因为一些概念只有在特定的坐标空间下才有意义,才更容易理解。这也是为什么在渲染中我们要使用这么多坐标空间。现在我们就来看一下游戏渲染流水线中,一个顶点到底经过了怎样的空间变换。
1.2坐标空间的变换
在渲染流水线中,我们往往需要把一个点或方向矢量从一个坐标空间转换到另一个坐标空间。这个过程是怎么实现的呢?
我们可以定义一个坐标空间,指明其原点位置和3个坐标轴的方向,而这些数值实际上相对于另一个坐标空间的。坐标空间会形成一个层次结构——每个坐标空间都是另一个坐标空间的子空间。通过数学公式可以退出从这个空间到子空间或其父空间的变换矩阵的。
一般从模型空间对方向矢量的坐标空间转换到世界空间是通过一个4X4的变换矩阵的,一个有趣的情况是,对方向矢量的坐标空间变换,矢量是没有位置的,因此坐标空间的原点变换是可以忽略的。也就是说我们仅仅平移坐标系的原点是不会对矢量造成任何影响的。那么对矢量的坐标空间就可以使用3X3的矩阵来表示,因为我们不需要表示平移变换。在shader中,我们常常会看到截取变换矩阵的前三行前三列来对法线方向、光照方向来进行空间变换,这正是原因所在。
1.3顶点的坐标空间的变换过程
在渲染流水线中,一个顶点要经过多个坐标空间的变换才能最终被画在屏幕上。一个顶点最开始是在模型空间中定义的,最后他将会变换到屏幕空间中,得到真正的屏幕像素坐标。接下来的内容将解释顶点要进行的各种空间变换的过程。现在模拟一个场景,一群牛在草原吃草,前边有一个摄像机一直在观察它们,小牛想知道自己的鼻子是怎么被画到屏幕上的,下面将一步步进行了解。
1.4模型空间
模型空间是和某个模型或者说是对象有关的。有时模型空间也被称为对象空间或局部空间。每个模型都有自己独立的坐标空间,当它移动或旋转的时候,模型空间也会跟着它移动和旋转。比如自己是游戏模型,我们移动的时候我们的模型空间也在跟着移动,我们转身时本身的前后左右方向也跟着改变。
在模型空间中经常使用一些方向概念,比如前后左右上下等,我们把这些方向称为自然方向,模型空间的坐标轴通常会使用这些自然方向。unity在模型空间中使用左手坐标系,因此在模型空间中,+x,+y,+z轴分别对应的是模型的右、上和前向。我们在Hierarchy视图中单击任意对象就可以看见他们对应的模型空间的3个坐标轴:
模型空间的原点和坐标轴通常由美术人员在建模软件里确定好的。当导入到unity中,我们可以在顶点着色器中访问到模型的顶点信息,其中包含了每个顶点的坐标,这些坐标都是相对于模型空间中的原点(通常位于模型的重心)定义的。若现在小牛的鼻子可以通过访问顶点属性来得到的,假设位置是(0,2,4),由于顶点变换中往往包含了平移变换,因此需要把其扩展到齐次坐标系下,得到顶点坐标是(0,2,4,1)。
1.5世界空间
世界空间是一个特殊的坐标系,因为它建立了我们所关心的最大的空间。世界空间可以被用于描述绝对位置(这里指的是世界坐标系中的位置),通常我们把世界空间的原点放置在游戏空间的中心。
在unity中,世界空间同样使用了左手坐标系。但他的x轴,y轴,z轴是固定不变的。在unity中我们可以通过调整Transfrom组件中的Position属性来改变模型的位置,这里的位置指的是相对于这个Transform的父节点的模型坐标空间中的原点定义的。如果一个transform没有任何父节点,那么这个位置就是在世界坐标系的位置。同样transform的rotation和scale也是同样道理。如果B模型有父节点A,那么这里的position就是在其父节点A的模型空间中的位置。</