【OpenGL学习】transform

视图变换

进行视图变换的学习之前,首先需要明白为什么需要视图变换,一个模型在某种第三方软件(blender,maya,3Dmax…)被创建出的的时候,其顶点都是对应于自身所在的空间的,也就是模型空间(物体空间),但是最终显示在屏幕上对应的是屏幕空间,如果直接吧物体空间对应的坐标绘制到屏幕空间上,显然是不正确的,因此要通过变换将物体空间的坐标一步步变换到屏幕空间,才能得到正确的绘制结果。

一、坐标空间与空间转化

一个顶点从物体空间转化到屏幕空间,一般会经历下面几个空间坐标系:

  • 模型(物体)空间(Object Space)

    局部空间是指物体所在的坐标空间,即对象最开始所在的地方。想象在一个建模软件(比如说Blender)中创建了一个立方体。创建的立方体的原点有可能位于(0, 0, 0),即便它有可能最后在程序中处于完全不同的位置。甚至有可能创建的所有模型都以(0, 0, 0)为初始位置(译注:然而它们会最终出现在世界的不同位置)。所以,你的模型的所有顶点都是在局部空间中:它们相对于你的物体来说都是局部的。

  • 世界空间(World Space)

    如果我们将我们所有的物体导入到程序当中,它们有可能会全挤在世界的原点(0, 0, 0)上,因为其顶点都是模型空间所对应的顶点。世界空间(world space)是一个宏观的特殊坐标系,其代表了我们关心的最大坐标系,每一个模型在世界空间中都对应着自己的位置,所以需要通过模型变换将模型的顶点转化到世界空间当中。一般包括:缩放,旋转,平移。

  • 观察空间(View Space)

    观察空间是将世界空间坐标转化为用户视野前方的坐标而产生的结果。因此观察空间就是从摄像机的视角所观察到的空间。一般的操作是将摄像机移动到世界坐标的坐标原点,然后将摄像机的坐标和世界空间的坐标重合,注意要对所有的物体均做和相机相同的变化,这样才能保证物体和相机的相对位置不变。

  • 裁剪空间(Clip Space)

    在一个顶点着色器运行的最后,OpenGL期望所有的坐标都能落在一个特定的范围内,且任何在这个范围之外的点都应该被裁剪掉(Clipped)。被裁剪掉的坐标就会被忽略,所以剩下的坐标就将变为屏幕上可见的片段。这也就是裁剪空间(Clip Space)名字的由来。通过投影变换,可以将观察空间对应的的坐标转化到裁剪空间当中,需要定义一个投影矩阵(Projection Matrix),它指定了一个范围的坐标,比如在每个维度上的-1000到1000。投影矩阵接着会将在这个指定的范围内的坐标变换为标准化设备坐标的范围(-1.0, 1.0)。所有在范围外的坐标不会被映射到在-1.0到1.0的范围之间,所以会被裁剪掉。

    一旦所有顶点被变换到裁剪空间,最终的操作——透视除法(Perspective Division)将会执行,在这个过程中我们将位置向量的x,y,z分量分别除以向量的齐次w分量;透视除法是将4D裁剪空间坐标变换为3D标准化设备坐标的过程。这一步会在每一个顶点着色器运行的最后被自动执行。

  • 屏幕空间(Screen Space)

    屏幕空间(屏幕坐标Screnn Space):就是屏幕的2d空间,大小就是屏幕的大小,以像素作为单位,可以设定屏幕大小,如常见的1024*768等等,0点在左上角,向右为x正向,向下为y正向

下面这幅图展示了顶点变化的整个过程:

在这里插入图片描述

其中从模型空间转化到世界空间对应的变换矩阵为 模型矩阵(Model Matrix) ,从世界空间转化到观察空间对应 视图矩阵(View Matrix) ,从观察空间转化到裁剪空间对应 投影矩阵(Projection Matrix),三个矩阵共同组成了我们熟悉的 MVP 矩阵。一个位于模型空间的顶点坐标,乘上这个矩阵之后,将会转化到裁剪空间。有关投影和变换,可以看这篇文章:图形学基础 - 变换 - 投影,大佬讲解的非常详细。

二、创建MVP矩阵

首先创建一个模型矩阵。这个模型矩阵包含了位移、缩放与旋转操作,它们会被应用到所有物体的顶点上,以变换它们到全局的世界空间。让我们变换一下我们的平面,将其绕着x轴旋转,使它看起来像放在地上一样。这个模型矩阵看起来是这样的:

//model
	glm::mat4 model = glm::mat4(1.0f);
	model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));

接着需要创建一个观察矩阵。我们想要在场景里面稍微往后移动,以使得物体变成可见的(当在世界空间时,我们位于原点(0,0,0))。

我们自然不可能在场景中真的去移动摄像机,因为摄像机在场景中一般是没有实体的,但是将摄像机向后移动,和将整个场景向前移动是一样的,所以,观察矩阵所做的,以相反于摄像机移动的方向移动整个场景,因为最终的矩阵是作用在场景中的所有顶点上的。

OpenGL是一个右手坐标系(Right-handed System),要沿着z轴的正方向移动是通过将场景沿着z轴负方向平移来实现。它会给我们一种我们在往后移动的感觉。

观察矩阵定义如下:

//view
	glm::mat4 view = glm::mat4(1.0f);
	view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));

然后定义一个透视投影矩阵:

//projection
	glm::mat4 projection = glm::mat4(1.0f);
	projection = glm::perspective(glm::radians(45.0f), (float)screen_width / (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值