OpenGL - 文集 - 简书 (jianshu.com)
OpenGLES学习之路-坐标系统 - 简书 (jianshu.com)
上面文章讲解了坐标系的问题。
模型视图矩阵和投影矩阵
讲解坐标系变换问题
OpenGLES是针对嵌入式设备而设计的,其实际是OpenGL的裁剪版本。
变换流程包括:物体坐标系->世界坐标系->摄像机坐标系->裁剪空间->标准设备空间->实际窗口空间
这里面有时会用坐标系,有时会用空间,这主要是侧重点不一样。当使用坐标系时,是因为我们关注点的坐标和它的变换,当使用空间时,是为了强调这是一个有限的空间,超出空间的点会被裁剪。
物体坐标系是指绘制物体的坐标系。
世界坐标系是指摆放物体的坐标系。其实这和物体坐标系是同一个坐标系,因为我们在世界坐标系里添加物体时,会做两件事:1、(习惯)在原点附近绘制物体。2、旋转、平台物体到某个位置,做第一步时叫物体坐标系,做第二步时叫世界坐标系。物体坐标系到世界坐标系的变换就是"摆放"。为什么要分两步?因为当我们要再放一个同样的物体到世界坐标系时,可以重用第一步的代码。
摄像机坐标系是摄像机位置为原点,Z轴负方向和视线方向一致,Y轴正方向和摄像机上方向一致的坐标系。摄像机位置、摄像机上方向和视线方向都是通过调用setLookAtM设置的,调用这个方法时,这些坐标和方向还是相对于世界坐标系的,毕竟摄像坐标系还没出来呢。世界坐标系到摄像坐标系的变换在设置完摄像机坐标系后就确定了,不需要手动去设置。
裁剪空间是摄像机坐标系中的一个六面体空间。通过设置正交投影或透视投影来确定裁剪空间,只有裁剪空间里面的物体才可能被用户看到。当然物体现在还是在摄像机坐标系中,可以理解成没有对物体做变换。
标准设备空间是一个3轴的坐标范围都是-1~1的3维空间。标准设备空间是由裁剪空间变换得来的,不管是透视投影设置的四棱台,还是正交投影设置得长方体,都会变成一个正方体。这里不单包含一个形变,还包括一个坐标系的变换,不过这个变换也不需要手动去设置,在设置投影时这个变换就确定了。
实际窗口空间是在实际窗口坐标系中设置得视口区域。窗口坐标系是由使用的控件(SurfaceView或TextureView……)决定的,并不是手机屏幕,因为控件可以小于屏幕、等于屏幕甚至大于屏幕。窗口坐标系是以控件的左下角为原点的坐标系。实际窗口空间是这个坐标系里的一块区域。
在使用固定管线时,坐标系和坐标系之间变换,就像设置环境变量一样,设置好这些变量,绘制物体,然后物体就会出现在我们期望的地方。
在使用可编程管线时,这些变换会变成一个MVP矩阵,绘制物体的顶点和这个矩阵相乘,然后它们就会变换到相应的位置。
PS:整理这个,是因为在看项目代码时,没理解:有将MVP矩阵直接设置成单位矩阵的代码,而且跑出正常的效果。将MVP矩阵设置成单位矩阵,其实就是直接在标准设备空间里绘制物体。
- 局部空间(Local Space,或者称为物体空间(Object Space)) 对应 物体坐标系
- 世界空间(World Space) 对应 世界坐标系
- 观察空间(View Space,或者称为视觉空间(Eye Space)) 对应 摄像机坐标系
- 裁剪空间(Clip Space)
- 屏幕空间(Screen Space)
这里的空间也即是使用各自的坐标系。
今天主要粗略的讲解以下几个坐标系统:
- 局部空间(Local Space,或者称为物体空间(Object Space))
- 世界空间(World Space)
- 观察空间(View Space,或者称为视觉空间(Eye Space))
- 裁剪空间(Clip Space)
- 屏幕空间(Screen Space)
概述
为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。我们的顶点坐标起始于局部空间(Local Space),在这里它称为局部坐标(Local Coordinate),它在之后会变为世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)的形式结束。下面的这张图展示了整个流程以及各个变换过程做了什么:
![]()
- 局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标。
- 下一步是将局部坐标变换为世界空间坐标(局部坐标系经过model matrix矩阵转化为世界坐标系,世界空间使用世界坐标系),世界空间坐标是处于一个更大的空间范围的。这些坐标相对于世界的全局原点,它们会和其它物体一起相对于世界的原点进行摆放。
- 接下来我们将世界坐标变换为观察空间坐标(世界坐标系经过view matrix矩阵转化为观察者坐标系,即相机坐标系,相机空间使用相机坐标系),使得每个坐标都是从摄像机或者说观察者的角度进行观察的。
- 坐标到达观察空间之后,我们需要将其投影到裁剪坐标(相机坐标系经过投影矩阵转化为裁剪空间,裁剪空间使用裁剪坐标系)。裁剪坐标会被处理至-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上。
- 最后,我们将裁剪坐标变换为屏幕坐标,我们将使用一个叫做视口变换(Viewport Transform)的过程。视口变换将位于-1.0到1.0范围的坐标变换到由glViewport函数所定义的坐标范围内。最后变换出来的坐标将会送到光栅器,将其转化为片段。