OpenGL学习笔记(三)-变换-坐标系统-摄像机

本文详细介绍了OpenGL中的向量和矩阵运算,如缩放、位移、旋转,以及如何通过GLM库构建变换矩阵。重点讲解了投影矩阵的正射和透视,以及如何用观察矩阵和摄像机坐标系实现3D场景的动态变换。此外,文章涵盖了鼠标和键盘输入控制摄像机移动的方法。

参考网址:LearnOpenGL 中文版
哔哩哔哩教程

1.5 变换

为了使物体变成动态的,需要使用多个矩阵对象变换一个物体。

1.5.1 向量

向量包含方向和模。由于向量是一个方向,很难用位置表示,因此可指定原点,然后指向一个方向,对应一个点,使其变为位置向量。

1、向量与标量运算:数学中是没有这个运算的,但是在许多线性代数的库中支持这样的运算。该运算就是将向量的每个元素,与标量进行运算。其中的+可以是+,-,·或÷。注意-和÷运算时不能颠倒(标量-/÷向量),因为颠倒的运算是没有定义的。
在这里插入图片描述
2、向量取反:向量前面加上负号,使得方向逆转。
3、向量加减:对应分量相加减,其几何意义为:
在这里插入图片描述在这里插入图片描述
4、向量点乘,两个向量点乘是对应分量相乘再相加,结果是一个标量,同时也等于两个两个向量的模相乘再乘以余弦值,通过下面两个式子,可以通过点乘计算两个向量的夹角,这可用于光照的计算:


5、向量叉乘:两个不平行向量的叉乘结果,为一个正交于两个输入向量的向量


6、在GLSL中,还定义了两个向量的逐元素乘法(componet wise),vec4 c=a*b,结果仍为一个向量。

1.5.2 矩阵

1、矩阵与标量的加减,就是每个分量与标量做运算,同样在数学中是不存在的。
2、矩阵与标量数乘,每个分量相乘。标量用它的值缩放(Scale)矩阵的所有元素。
3、矩阵与向量相乘:向量变为齐次坐标,增加w分量,w分量一般为1,主要用于向量位移。

  • 缩放,对向量长度进行更改
    在这里插入图片描述
  • 位移在这里插入图片描述
  • 使用齐次坐标可以允许我们在3D向量上进行位移。如果一个向量w的齐次坐标是0,这个坐标就是方向向量(Direction Vector),这个向量就不能位移(不能位移一个方向)。
  • 旋转,沿x轴旋转
    在这里插入图片描述
    1.5.3 实践

1、下载GLM库进行矩阵运算,链接,该库只有头文件,需在vs包含目录里添加对应的头文件文件夹,在项目里包含头文件:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

2、定义矩阵

  • 0.9.9版本以前的GLM,默认会将矩阵类型初始化为单位矩阵。
  • 按顺序定义位移、旋转和缩放矩阵,GLM会自动将矩阵相乘,返回的结果是一个包括了多个变换的变换矩阵,即trans=TranslateMat*RotateMat*ScaleMat
  • 对上述矩阵的理解顺序,如果绕着固定坐标系变换,则上述变换为左乘,先缩放,再绕正坐标系Z轴旋转,再平移。
  • 即实际的变换顺序应该与阅读顺序相反:尽管在代码中我们先位移再旋转,实际的变换却是先应用旋转再是位移的。
  • 平移矩阵中,定义三维方向向量 glm::vec3(1.0f, 1.0f, 0.0f)表示平移,注意这里不是齐次矩阵,只有定义顶点数据时,才利用齐次矩阵。
  • 在旋转矩阵中,利用glm::radians(0.1f)将度数转为弧度。
glm::mat4 trans;//单位矩阵
trans = glm::translate(trans, glm::vec3(0, 0, 1.0));
trans = glm::rotate(trans, glm::radians(45.0f), glm::vec3(0, 0, 1.0f));
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));

3、如何把矩阵传递给着色器?在GLSL里也有一个mat4类型,所以修改顶点着色器让其接收一个mat4的uniform变量,然后再用矩阵uniform乘以位置向量:

#version 330 core									
layout(location = 0) in vec3 aPos;					
layout(location = 1) in vec3 aColor;	
layout(location = 2) in vec2 aTexCoord;		
	
out vec3 vertexColor;
out vec2 TexCoord;
	
uniform mat4 tansform;
					
void main()											
{
   
   													
	gl_Position =tansform*vec4(aPos.x, aPos.y, aPos.z, 1.0);
	vertexColor=aColor;		
	TexCoord=aTexCoord;						
}

4、将矩阵传递给着色器。

  • 用有Matrix4fv后缀的glUniform函数把矩阵数据发送给着色器。第一个参数是uniform的位置值。第二个参数为矩阵数量。第三个参数为是否需要转置。最后一个参数是真正的矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据。
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

在这里插入图片描述

1.6 坐标系统

1.6.1 概述

OpenGL在顶点着色器中会将范围内的坐标变换为标准化设备坐标(-1.0到1.0之间),然后传入光栅器(Rasterizer),变换为屏幕上的二维坐标或像素。
在上述过程中,顶点会经过几个变换矩阵被变换到多个坐标系统。顶点坐标起始于局部坐标,经模型矩阵后变为世界坐标,经观察矩阵后变成观察坐标,经投影矩阵后变成裁剪坐标,并最后以屏幕坐标的形式结束。
在这里插入图片描述
1、局部坐标:某个物体相对于自身局部坐标系原点的坐标。

2、世界坐标:全部物体摆放于世界空间中,某个物体相对于世界坐标系原点的坐标。利用模型矩阵,可以将物体模型放置到场景中的某个位置。

3、观察坐标:某个物体相对于摄像机坐标系原点的坐标。

4、裁剪坐标:为了将顶点坐标从观察变换到裁剪空间,我们需要定义一个投影矩阵(Projection Matrix),它指定了一个范围的坐标,比如在每个维度上的-1000到1000。投影矩阵会将范围内的坐标变换为标准化设备坐标。投影矩阵分为正射投影矩阵(Orthographic Projection Matrix)和透视投影矩阵(Perspective Projection Matrix),由投影矩阵创建的观察箱(Viewing Box)被称为平截头体(Frustum)。

5、屏幕坐标: 所有顶点被变换到裁剪空间后,会自动执行透视除法(Perspective Division),将位置向量的x,y,z分量分别除以向量的齐次w分量;透视除法是将4D裁剪空间坐标变换为3D标准化设备坐标的过程。这一步会在顶点着色器运行的最后自动执行。然后OpenGL会通过glViewport函数将坐标映射到屏幕坐标。

1.6.2 投影矩阵

1、 正射投影矩阵定义了一个类似立方体的平截头箱,创建一个正射投影矩阵需要指定宽、高、近(Near)平面和远(Far)平面。正射平截头体直接将坐标映射为标准化设备坐标,因为每个向量的w分量都没有进行改变,这也导致正射投影矩阵在屏幕上产生的物体没有远近之分,效果不真实。

//创建正射投影矩阵,分别对应左右坐标,底部顶部坐标,近平面和远平面
glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);

在这里插入图片描述
2、透视投影矩阵:在真实世界中,离得越远的物体看起来更小,两条线在很远的地方会相交。为模仿这样的效果,使用透视投影矩阵。
在这里插入图片描述

  • 透视投影矩阵将给定的平截头体范围映射到裁剪空间,并且修改顶点坐标的w值,使得离观察者越远的顶点坐标w分量越大。被变换到裁剪空间的坐标都会在-w到w的范围之间。这也就使得在透视除法时,顶点坐标的每个分量都除以它的w分量,距离观察者越远顶点坐标就会越小。

  • 透视平截头体可以被看作一个不均匀形状的箱子。

    //定义透视投影矩阵,第一个参数为视角大小,通常为45;
    //第二个参数为宽高比,由视口的宽除以高
    //第三四参数为近远平面,一般为0.1与100
    glm::mat4 proj = glm::perspective(glm::radians(45.0f)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值