之前我们做的都是2D的图像,现在开始我们就进入3D了。
概述
- 将坐标变换为标准化设备坐标,接着再转化为屏幕坐标的过程通常是分步进行的 (过程类似一个个的shader)
- 物体的顶点在最终转化为屏幕坐标之前还会被变换到多个坐标系统 。
- 局部空间(Local Space)、世界空间(World Space)、观察空间(View Soordiname)(视觉空间)、裁剪空间(Clip Coordiante)、屏幕空间(Screen Coordinate)
- 将一个坐标从一个坐标系变换到另一个坐标系,需要几个变换矩阵。最重要的是三个矩阵是:
- 模型( Model )
- 观察( View )
- 投影( Projection )
- 我们的顶点坐标起始于局部空间,在这里它称为局部坐标,它在之后会变为世界坐标,观察坐标,裁剪坐标,并最后以屏幕坐标的形式结束。
- 局部坐标的对象是相对于局部原点的坐标,也是物体起始的坐标
- 空间坐标是出于一个更大的空间范围内的。这些坐标相对于世界的全局原点,回合其他物体一起相对于世界的原点进行摆放。
- 接下俩将世界坐标转换为空间观察坐标,是的每个坐标都是从摄像机的角度进行观察的。
- 坐标到达观察空间之后,我们需要将其投影到裁剪坐标(-1.0~1.0)。并判断哪些顶点会出现在屏幕上。
- 最后使用视口变换( Viewport Transform )的过程。 视口变换将位于-1.0到1.0范围的坐标变换到由glViewport函数所定义的坐标范围内。最后变换出来的坐标将会送到光栅器,将其转化为片段。
局部空间
- 指的是物体所在的坐标空间,即对象最开始的地方。
世界空间
- 如果我们将我们所有的物体导入到程序当中,它们有可能会全挤在世界的原点(0, 0, 0)上,这并不是我们想要的结果。我们想为每一个物体定义一个位置,从而能在更大的世界当中放置它们。也就是一堆对象在窗口中的摆放方式。坐标从局部变换到世界,通过模型矩阵实现。
- 模型矩阵能通过对物体经行位移、缩放、旋转来将它置于它本身应该在的位置或朝向。
观察空间
- 将世界空间坐标转化为用户视野前方的坐标儿产生的结果。( 涉及到了有关摄像机的内容 )
裁剪空间
- 将顶点坐标从观察变换到裁剪空间,我们需要定义一个投影矩阵,它指定了一个范围坐标。 投影矩阵接着会将在这个指定的范围内的坐标变换为标准化设备坐标的范围(-1.0, 1.0)。所有在范围外的坐标不会被映射到在-1.0到1.0的范围之间,所以会被裁剪掉。
- 由投影矩阵创建的观察箱(Viewing Box)被称为平截头体(Frustum),每个出现在平截头体范围内的坐标都会最终出现在用户的屏幕上。将特定范围内的坐标转化到标准化设备坐标系的过程被称之为投影(Projection)
一旦所有顶点被变换到裁剪空间,最终的操作——透视除法(Perspective Division)将会执行,在这个过程中我们将位置向量的x,y,z分量分别除以向量的齐次w分量;透视除法是将4D裁剪空间坐标变换为3D标准化设备坐标的过程。这一步会在每一个顶点着色器运行的最后被自动执行。
将观察坐标变换为裁剪坐标的投影矩阵可以为两种不同的形式,每种形式都定义了不同的平截头体。我们可以选择创建一个正射投影矩阵(Orthographic Projection Matrix)或一个透视投影矩阵(Perspective Projection Matrix)。
正射投影
- 正射投影矩阵定义了一个类似立方体的平截头箱,它定义了一个裁剪空间,在这空间之外的顶点都会被裁剪掉。
使用GLM内置函数glm::ortho函数创建正射投影矩阵
glm::ortho(0.0f,800.0f,0.0f,600.0f,0.1f,100.0f); /* 参数1 & 参数2:指定了平截头体的左右坐标 参数3 & 参数4:指定了平截头体的底部和顶部 参数5 & 参数6:定义了近平面和远平面的距离 */
透视投影
- 由于透视,两条线在很远的地方会相交,这个效果是通过透视投影矩阵完成的。 这个投影矩阵将给定的平截头体范围映射到裁剪空间 , 除此之外还修改了每个顶点坐标的w值,从而使得离观察者越远的顶点坐标w分量越大。
- 顶点的每一个分量都会除以他的w分量, 距离观察者越远顶点坐标就会越小 。
使用GLM内置函数创建透视投影矩阵
glm::mat4 proj = glm::perspective(glm::radians(45.0f),(float)width/(float)height,0.1f,100.f); /* 参数1:定义了fov并且设置了观察空间大小 参数2:设置了宽高比 参数3 & 参数4:设置了近平面和远平面。我们通常设置近距离为0.1f,而远距离设为100.0f。所有在近平面和远平面内且处于平截头体内的顶点都会被渲染。 */
组合到一起
以上我们一次创建了:模型矩阵、观察矩阵、投影矩阵。一个顶点坐标会根据以下过程被变换到裁剪坐标。
Vclip=Mprojection⋅Mview⋅Mmodel⋅Vlocal
最后使用顶点着色器中的gl_Position。