概述:
一个顶点在最终被转化为片段之前需要经历的所有不同状态——五个坐标系统
局部空间/物体空间
世界空间
观察空间/视觉空间
裁剪空间
屏幕空间
为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型、观察、投影三个矩阵。我们的顶点坐标起始于局部空间(局部坐标)——世界坐标——观察坐标——裁剪坐标——屏幕坐标。流程如下:
1)局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标。
2)下一步是将局部坐标变换为世界空间坐标,世界空间坐标是处于一个更大的空间范围的。这些坐标相对于世界的全局原点,它们会和其它物体一起相对于世界的原点进行摆放。
3)接下来我们将世界坐标变换为观察空间坐标,使得每个坐标都是从摄像机或者说观察者的角度进行观察的。
4)坐标到达观察空间之后,我们需要将其投影到裁剪坐标。裁剪坐标会被处理至-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上。
5)最后,我们将裁剪坐标变换为屏幕坐标,我们将使用一个叫做视口变换(Viewport Transform)的过程。视口变换将位于-1.0到1.0范围的坐标变换到由glViewport函数所定义的坐标范围内。最后变换出来的坐标将会送到光栅器,将其转化为片段。
- 局部空间
物体所在的坐标空间,对象最开始所在的地方。 - 世界空间
为每一个物体定义一个位置,从而能在更大的世界当中放置它们。该变换是由模型矩阵实现的。
模型矩阵是一种变换矩阵,他能通过对物体进行位移、缩放、旋转来将它置于它本应发你在的位置或朝向。 - 观察空间
称为OpenGL的摄像机(称为摄像机空间或视觉空间),观察空间是将世界空间坐标转化为用户视野前方的坐标而产生的结果。由一系列位移和旋转的组合来完成。该变换是由观察矩阵实现的。 - 裁剪空间
OpenGL期望所有的坐标都能落在一个特定的范围内,且任何在这个范围之外的点都应该被裁剪掉(Clipped)。该变换由投影矩阵实现,它指定了一个范围的坐标,它指定了一个范围的坐标,比如在每个维度上的-1000到1000。投影矩阵接着会将在这个指定的范围内的坐标变换为标准化设备坐标的范围(-1.0, 1.0)。所有在范围外的坐标不会被映射到在-1.0到1.0的范围之间,所以会被裁剪掉。
由投影矩阵创建的观察箱被称为平截头体,每个出现在平截头体范围内的坐标都会最终出现在屏幕上。将特定范围内的坐标转化到标准化设备坐标系的过程被称之为投影,因为使用投影矩阵能将3D坐标投影到很容易映射到2D的标准化设备坐标系中。
一旦所有顶点被变换到裁剪空间,最终的操作——透视除法(Perspective Division)将会执行,在这个过程中我们将位置向量的x,y,z分量分别除以向量的齐次w分量;透视除法是将4D裁剪空间坐标变换为3D标准化设备坐标的过程。这一步会在每一个顶点着色器运行的最后被自动执行。
在这一阶段之后,最终的坐标将会被映射到屏幕空间中(使用glViewport中的设定),并被变换成片段。
1)正射投影
glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
前两个参数指定了平截头体的左右坐标,第三和第四参数指定了平截头体的底部和顶部。通过这四个参数我们定义了近平面和远平面的大小,然后第五和第六个参数则定义了近平面和远平面的距离。这个投影矩阵会将处于这些x,y,z值范围内的坐标变换为标准化设备坐标。
2)透视投影
由于透视,这两条线在很远的地方看起来会相交。这正是透视投影想要模仿的效果,它是使用透视投影矩阵来完成的。out=(x/w y/w z/w)
- 把他们都组合到一起
每一步都创建了变换矩阵:模型矩阵、观察矩阵、投影矩阵,组合:
Vclip=Mprojection⋅Mview⋅Mmodel⋅Vlocal
注意矩阵运算的顺序是相反的(记住我们需要从右往左阅读矩阵的乘法)。
最后的顶点应该被赋值到顶点着色器中的gl_Position,OpenGL将会自动进行透视除法和裁剪。
OpenGL会使用glViewPort内部的参数来将标准化设备坐标映射到屏幕坐标,每个坐标都关联了一个屏幕上的点(在我们的例子中是一个800x600的屏幕)。这个过程称为视口变换。 - 进入3D
OpenGL是一个右手坐标系。
Z缓冲深度缓冲,深度测试