注意,当矩阵相乘时我们先写位移再写缩放变换的。建议您在组合矩阵时,先进行缩放操作,然后是旋转,最后才是位移,否则它们会(消极地)互相影响。比如,如果你先位移再缩放,位移的向量也会同样被缩放(译注:比如向某方向移动2米,2米也许会被缩放成1米)!

(一)矩阵变换

1、添加头文件

我们需要的GLM的大多数功能都可以从下面这3个头文件中找到:

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

2、矩阵初始化

GLM库从0.9.9版本起,默认会将矩阵类型初始化为一个零矩阵(所有元素均为0),而不是单位矩阵(对角元素为1,其它元素为0)。如果你使用的是0.9.9或0.9.9以上的版本,你需要将所有的矩阵初始化改为 glm::mat4 mat = glm::mat4(1.0f)。如果你想与本教程的代码保持一致,请使用低于0.9.9版本的GLM,或者改用上述代码初始化所有的矩阵。

我们来看看是否可以利用我们刚学的变换知识把一个向量(1, 0, 0)位移(1, 1, 0)个单位(注意,我们把它定义为一个glm::vec4类型的值,齐次坐标设定为1.0):

glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
// 译注:下面就是矩阵初始化的一个例子,如果使用的是0.9.9及以上版本
// 下面这行代码就需要改为:
// glm::mat4 trans = glm::mat4(1.0f)
// 之后将不再进行提示
glm::mat4 trans;

我们先用GLM内建的向量类定义一个叫做vec的向量。接下来定义一个mat4类型的trans,默认是一个4×4单位矩阵。

3、变换

我们来做些更有意思的事情,让我们来旋转和缩放之前教程中的那个箱子。首先我们把箱子逆时针旋转90度。然后缩放0.5倍,使它变成原来的一半大。随时间变化,使用GLFW的时间函数来获取不同时间的角度

glm::mat4 trans;
trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));

首先,我们把箱子在每个轴都缩放到0.5倍,然后沿z轴旋转90度。GLM希望它的角度是弧度制的(Radian),所以我们使用glm::radians将角度转化为弧度。注意有纹理的那面矩形是在XY平面上的,所以我们需要把它绕着z轴旋转。因为我们把这个矩阵传递给了GLM的每个函数,GLM会自动将矩阵相乘,返回的结果是一个包括了多个变换的变换矩阵。

矩阵传递给着色器

我们在前面简单提到过GLSL里也有一个mat4类型。所以我们将修改顶点着色器让其接收一个mat4的uniform变量,然后再用矩阵uniform乘以位置向量:

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

GLSL也有mat2mat3类型从而允许了像向量一样的混合运算。前面提到的所有数学运算(像是标量-矩阵相乘,矩阵-向量相乘和矩阵-矩阵相乘)在矩阵类型里都可以使用。当出现特殊的矩阵运算的时候我们会特别说明。

变换矩阵传递给着色器:

unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

我们首先查询uniform变量的地址,然后用有Matrix4fv后缀的glUniform函数把矩阵数据发送给着色器。第一个参数你现在应该很熟悉了,它是uniform的位置值。第二个参数告诉OpenGL我们将要发送多少个矩阵,这里是1。第三个参数询问我们我们是否希望对我们的矩阵进行置换(Transpose),也就是说交换我们矩阵的行和列。OpenGL开发者通常使用一种内部矩阵布局,叫做列主序(Column-major Ordering)布局。GLM的默认布局就是列主序,所以并不需要置换矩阵,我们填GL_FALSE。最后一个参数是真正的矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据。

(二)画出立方体

顶点坐标

float vertices[] = {-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f};

2、绘制图元

 glDrawArrays(GL_TRIANGLES, 0, 36);  //画三角形,从第 0 个数据开始画,到最后一个数据(第 3 个)结束//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

3、增加深度测试

//glEnable(GL_DEPTH_TEST);  //深度测试//glDepthFunc(GL_LESS);  //深度信息小于当期信息,就把进行测试

4、在清除屏幕的时候,也需要把深度缓存的数据清除掉!

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

附加内容:画出多个立方体

现在我们想在屏幕上显示10个立方体。每个立方体看起来都是一样的,区别在于它们在世界的位置及旋转角度不同。立方体的图形布局已经定义好了,所以当渲染更多物体的时候我们不需要改变我们的缓冲数组和属性数组,我们唯一需要做的只是改变每个对象的模型矩阵来将立方体变换到世界坐标系中。

首先,让我们为每个立方体定义一个位移向量来指定它在世界空间的位置。我们将在一个glm::vec3数组中定义10个立方体位置:

glm::vec3 cubePositions[] = {glm::vec3( 0.0f,  0.0f,  0.0f), glm::vec3( 2.0f,  5.0f, -15.0f), glm::vec3(-1.5f, -2.2f, -2.5f),  glm::vec3(-3.8f, -2.0f, -12.3f),  glm::vec3( 2.4f, -0.4f, -3.5f),  glm::vec3(-1.7f,  3.0f, -7.5f),  glm::vec3( 1.3f, -2.0f, -2.5f),  glm::vec3( 1.5f,  2.0f, -2.5f), glm::vec3( 1.5f,  0.2f, -1.5f), glm::vec3(-1.3f,  1.0f, -1.5f)
};

现在,在游戏循环中,我们调用glDrawArrays 10次,但这次在我们渲染之前每次传入一个不同的模型矩阵到顶点着色器中。我们将会在游戏循环中创建一个小的循环用不同的模型矩阵渲染我们的物体10次。注意我们也对每个箱子加了一点旋转:

glBindVertexArray(VAO);
for(unsigned int i = 0; i < 10; i++)
{glm::mat4 model;model = glm::translate(model, cubePositions[i]);float angle = 20.0f * i; model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));ourShader.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);
}

这段代码将会在每次新立方体绘制出来的时候更新模型矩阵,如此总共重复10次。然后我们应该就能看到一个拥有10个正在奇葩地旋转着的立方体的世界。

参考链接:

https://blog.csdn.net/Wonz5130/article/details/83155293

https://learnopengl-cn.github.io/01%20Getting%20started/07%20Transformations/

https://www.jianshu.com/p/6dd3e78d4b51

南邮——计算机图像学——会动的立方体(变换)相关推荐

  1. 南邮——计算机图像学——光照、冯氏光照模型

    颜色可以数字化的由红色(Red).绿色(Green)和蓝色(Blue)三个分量组成,它们通常被缩写为RGB.这三个不同的分量组合在一起几乎可以表示存在的任何一种颜色. (一)观察物体 (1)物体的片段 ...

  2. matlab数学实验 南邮,matlab实验练习题(计算机)-南邮-matlab-数学实验大作业答案

    matlab实验练习题(计算机)-南邮-matlab-数学实验大作业答案 1"MATLAB"练习题练习题要求:抄题.写出操作命令.运行结果,并根据要求,贴上运行图.1.求的所有根. ...

  3. 南邮/南邮计算机考研经验贴2022

    南邮/南京邮电大学计算机考研经验贴2022 写在前面,22考研总分400+,数据结构140+,数据结构算是取得了比较好的成绩,下面介绍一下我这一年数据结构如何学习的. 有疑问可以进群一起交流. 一.书 ...

  4. 2018南邮全国计算机大赛,关于举办2018年南京邮电大学第十届数学建模竞赛通知...

    为了提高学生的综合素质,增强创新意识,培养学生应用数学知识解决实际工程问题的能力,激发学生学习数学的积极性,同时选拔参加2018年全国大学生数学建模竞赛和2019年美国大学生数学建模竞赛的队员,经学校 ...

  5. 杭电和南邮计算机考研哪个好考,南京邮电大学研究生,二本考南邮研究生!

    南邮的研究生好考么 你好!当然可以的啊 其实考博士主要还是要导师推荐 仅代表个人观点,不喜勿喷,谢谢. [15届考研生]教南邮和杭电的选择 想问一下了解情况的同学,学长,老师,研究生考试,南京邮电大学 ...

  6. 南邮计算机学院张晓霞,南京邮电大学第四届海内外青年学者云论坛通信与信息工程学院分论坛成功举办...

    11月27日.28日,南京邮电大学第四届海内外青年学者云论坛之通信与信息工程学院分论坛成功举办.分论坛采用线上和线下相结合的方式召开,来自东京大学.南洋理工大学.新南威尔士大学.谢菲尔德大学.悉尼科技 ...

  7. 学计算机去南邮还是南信,南信大和南邮相比怎么样 南信大怎么样

    南信大和南邮相比怎么样,南京邮电大学简称南邮,南京信息工程大学简称南信大,都是南京的高校,那么南信大和南邮相比怎么样呢?南信大怎么样呢? 南信大和南邮相比怎么样 南信大,坐落于南京江北新区,全称为南京 ...

  8. 南邮计算机专业考什么,南京邮电大学计算机考情分析与经验分享

    原标题:南京邮电大学计算机考情分析与经验分享 一.南邮及南邮计算机 南京邮电大学,简称"南邮",是教育部.工业和信息化部.国家邮政局与江苏省共建高校.是双一流学校,虽然不是211/ ...

  9. 南邮计算机考研太难,南京邮电大学的学生要考研到清华的话,有多困难?(南理工、南邮计算机考研近五年分数线复试录取比例各多少?)...

    南京邮电大学考研计算机专业分数线 南邮网站上都有 复试线:信息安全300 计算机系统结构300 计算机软件与理论300 计算机应用技术295 软件工程300 计算机技术(专硕)310 软件工程(专硕) ...

最新文章

  1. Linux系统管理必备知识之利用ssh传输文件
  2. Python 实战多元线性回归模型,附带原理+代码
  3. FPGA基于双端口RAM的乒乓操作
  4. python详细安装教程3.7.4-Linux下Python3.7.4 安装教程
  5. java springmvc mybatis mysql
  6. 在Android工程中,添加ICON资源
  7. 95-150-544-源码-Sink-Flink BucketingSink 源码分析
  8. 17. 合并两个排序的链表(C++版本)
  9. ubuntu安装Arial.ttf字体
  10. linux下安装java
  11. HS系列USB数据采集卡,及高速多通道数据分析软件详解
  12. 股票交易接口的开发工具?
  13. 手风琴效果案例(jQuery)
  14. 3D刷脸支付推动新零售行业发展
  15. 电脑卡住点什么都没反应怎么解决
  16. itext7学习笔记杂谈系列2——在itext7中添加中文(其他字体)和字体相关事
  17. finalshell链接不上虚拟机提示一直登录或链接不上怎么办
  18. 你要的项目复盘都在这里,赶紧学习
  19. CSDN上传资源提示:资源上传中断
  20. 队列实现杨辉三角(附详细图解)

热门文章

  1. 差旅安全,你了解多少?
  2. 三件套都有什么_床上用品三件套,四件套,五件套,七件套分别包括的是哪些...
  3. Oracle-log file sync等待事件分析
  4. 如何发送工资条通知短信
  5. 回首过去 展望未来
  6. 印象笔记终于支持 Markdown 了
  7. Oracle如何保持一致读?
  8. 智慧城市同城V4 v1.7.1
  9. AD20常用快捷键汇总
  10. uni-app 跳转至手机浏览器