- 局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标。
- 下一步是将局部坐标变换为世界空间坐标,世界空间坐标是处于一个更大的空间范围的。这些坐标相对于世界的全局原点,它们会和其它物体一起相对于世界的原点进行摆放。
- 接下来我们将世界坐标变换为观察空间坐标,使得每个坐标都是从摄像机或者说观察者的角度进行观察的。
- 坐标到达观察空间之后,我们需要将其投影到裁剪坐标。裁剪坐标会被处理至-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上。
- 最后,我们将裁剪坐标变换为屏幕坐标,我们将使用一个叫做视口变换(Viewport Transform)的过程。视口变换将位于-1.0到1.0范围的坐标变换到由glViewport函数所定义的坐标范围内。最后变换出来的坐标将会送到光栅器,将其转化为片段。
我们之所以将顶点变换到各个不同的空间的原因是有些操作在特定的坐标系统中才有意义且更方便。例如,当需要对物体进行修改的时候,在局部空间中来操作会更说得通;如果要对一个物体做出一个相对于其它物体位置的操作时,在世界坐标系中来做这个才更说得通,等等。如果我们愿意,我们也可以定义一个直接从局部空间变换到裁剪空间的变换矩阵,但那样会失去很多灵活性。
接下来我们将要更仔细地讨论各个坐标系统:
- 物体坐标系
这是物体在被应用任何变换之前的初始位置和方向所在的坐标系,也就是当前绘图坐标系。该坐标系不是固定的,每个物体都有他们独立的坐标系,且仅对该对象适用。在默认情况下,该坐标系与世界坐标系重合。当物体移动或者改变方向时(通过glTranslatef(),glScalef(), glRotatef()这几个函数进行变换),改物体相关联的坐标系将随之移动或改变方向。 -
世界坐标系
世界坐标系是系统的绝对坐标系,在没有建立用户坐标系之前画面上所有的点的坐标都可以在该坐标系的原点来确定各自的位置,世界坐标系始终是固定不变的。世界坐标系是右手坐标系:使用右手定则X是你的拇指方向,Y是你的食指方向,Z是你的中指方向。如图:
- 摄像机坐标系(照相机坐标系)
在坐标系的范畴里,摄像机坐标系和照相机坐标系都是一样的意义。照相机坐标系是和观察者密切相关的坐标系。照相机坐标系和屏幕坐标系相似,差别在于照相机坐标系处理3D空间中,而屏幕坐标系在2D平面里。默认情况下,眼坐标系与世界坐标系也是重合的。 - 裁剪坐标系
眼坐标到裁剪坐标是通过投影完成的。眼坐标通过乘以GL_PROJECTION矩阵(投影矩阵)变成了裁剪坐标。 - 归一化设备坐标系(NDC)
既然要规范化,那么就得先有一个规范。每种投影,都有一个剪裁空间,称之为观察体,对正交投影来说是一个立方体,对透视投影来说是一个棱台。如果一个观察体是一个x、y、z坐标范围都是 [-1, 1] 的立方体,则称之为规范化立方体,这个就是所谓的规范。那么,将原来的观察体,映射到规范化立方体的过程,就是规范化。 - 屏幕坐标系
通常将屏幕上的设备坐标称为屏幕坐标。设备坐标又称为物理坐标,是指输出设备上的坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置,是以像素为单位来表示的,设备坐标的 X 轴向右为正,Y 轴向下为正,坐标原点位于窗口的左上角。
从NDC坐标到屏幕坐标基本上是一个线性映射关系。通过对NDC坐标进行视口变换得到。这时候就要用到函数glViewport(),该函数用来定义渲染区域的矩形,也就是最终图像映射到的区域。
OpenGL最终的渲染设备是2D的,我们需要将3D表示的场景转换为最终的2D形式,这个过程如下图所示!