- 作者:老汪软件技巧
- 发表时间:2024-09-06 15:01
- 浏览量:
最新大型开源项目-云游戏,云桌面系统,欢迎关注
GammaRay源码地址
本项目代码仓库
点击这里
1.前言
当前,我们已经成功的绘制了矩形,但它是静态不动的。无论游戏还是3D展示模拟,都是动态的,那么如何让它运动起来呢?我们需要用矩阵(Matrix)来处理每个顶点,达到平移,旋转,缩放,切变等操作目的。本篇文章只展示操作,不过分注重推理,详细过程以及图解请看这本书:Fundamentals of Computer Graphics, Fourth Edition的第6章,以下是内容示例,不要找错书:
我们以2D为例进行说明,3D简单推广即可。矩阵虽然麻烦,也有的比较复杂,但是实际使用中都会使用特定的函数来实现,无需自己实现操作。
首先看下OpenGL的坐标系,X轴向右,Y轴向上,Z轴向外:
2. 变换操作
OpenGL中,我们更喜欢使用列向量来表示一个点,因为矩阵可与它直接相乘,操作简单。
图形学中,要将 平移与旋转,缩放相结合,我们引入了其次坐标,比如原本(x,y)变为(x,y,z),在2D场景下,z=0表示向量,z=1表示一个点。三维可直接推广。
3. 组合变换
首先声明一点,默认情况下缩放,旋转都是以原点为参考,比如当我们的物体旋转时,如果不是我们要的效果,那么就要考虑是不是要移动回原点,再进行旋转,完成旋转再移动回原来的位置。
从数学上看,矩阵是没有交换律的,那么从图形的结果上,也很容易得出结论:
注意:两步操作,不同的顺序,得出的结果完全不同。这在实际的开发中,要注意出现错误的表现时,是否是顺序反了。一般情况下,我们是先执行缩放,然后旋转,最后平移。
又因为矩阵是左乘的,比如:T * R * S * 点,执行顺序是这样的:
(T * (R * (S * 点))),最内层的括号先执行,所以在写矩阵操作顺序时,是反着写的,先写平移,再写旋转,最后缩放。
4.实际操作,让我们的正方形转起来
glm库给我们提供了方便的矩阵与向量的操作
现在看一下代码:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
uniform mat4 model;
out vec3 outColor;
void main()
{
gl_Position = model * vec4(aPos, 1.0);
outColor = aColor;
}
从代码可以看出,声明了一个model的mat4矩阵,model这个mat4矩阵,左乘在了顶点上,那么所有点的坐标都会被他改变。
在以下位置添加如下代码, 看下注释:
...
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2, 0.5, 0.5, 1.0);
//通过运行时间获得一个角度,可以自己随意输入
auto rotate = (float)glm::radians(glfwGetTime()) * 10;
//声明一个mat4的单位矩阵
glm::mat4 model(1.0);
//沿着X轴的正方向平移0.5
model = glm::translate(model, glm::vec3(0.5, 0, 0));
//沿着Z轴旋转一个角度,第二个参数的意义:glm::vec(x,y,z),表示哪一个轴。
model = glm::rotate(model, rotate, glm::vec3(0, 0, 1));
glBindVertexArray(VAO);
...
通过执行代码,我们看到矩形会以(0.5, 0)这个点,绕着Z轴进行旋转:
到此,我们实现了一个图形的旋转,任何物体都可以如此操作。