必须掌握的前置技能:https://blog.csdn.net/Jaihk662/article/details/103811465(向量与矩阵)

其实也不难,也就是一些线性代数的基本知识,暂时只需要理解到这种程度就好,后面可以再说

一、GLM库

和SOIL一样,GLM也是一个openGL的库,里面存着各种数学公式和算法

OpenGL环境配置(超全整合版)GLM库也可以从这篇文章中的链接中下载到,有个叫做glm-0.9.9.8的文件夹就是了,打开后将其中整个glm文件夹丢到VS的includes文件夹中(C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include)就OK了,不需要额外进行其它操作

一样,我们测试一下:

#include<iostream>
#include<opengl/glew.h>
#define GLEW_STATIC
#include<GLFW/glfw3.h>
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
#include"Shader.h"
#include<opengl/freeglut.h>
#include<SOIL.h>
int main()
{glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);glm::mat4 trans = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f, 1.0f, 0.0f));vec = trans * vec;printf("向量平移后结果:(%.0f, %.0f, %.0f)\n", vec.x, vec.y, vec.z);trans = glm::scale(glm::mat4(1.0f), glm::vec3(3, 3, 2));vec = trans * vec;printf("在此之后,向量缩放后结果:(%.0f, %.0f, %.0f)\n", vec.x, vec.y, vec.z);trans = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));vec = trans * vec;printf("在此之后,向量围绕z轴旋转90度后结果:(%.0f, %.0f, %.0f)\n", vec.x, vec.y, vec.z);vec = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);trans = glm::mat4(1.0f);trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));trans = glm::scale(trans, glm::vec3(3, 3, 2));trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));vec = trans * vec;printf("(%.0f, %.0f, %.0f)\n", vec.x, vec.y, vec.z);
}

可以从上面看出,我们暂时只用到了以下3个库

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

结合文章开头的那篇文章(线代基础公式XX),我们看一下其中的一些函数/用法

基础变量/方法:

  • glm::vec4:定义一个长度为4的向量
  • glm::mat4:定义一个4x4的矩阵
  • glm::mat4(1.0f):获得一个单位矩阵E
  • glm::radians(90.0f):将角度转化为弧度

几个基础矩阵运算:

  • glm::translate(, ):获得向量对应的位移矩阵,用矩阵乘以位移矩阵并得到最后的结果
  • glm::scale(, ):获得向量对应的缩放矩阵,用矩阵乘以位移矩阵并得到最后的结果
  • glm::rotate(, ):获得向量对应的旋转矩阵,用矩阵乘以位移矩阵并得到最后的结果

可以看出上面的代码中看出3点:这里也作为提醒

  1. 所有矩阵都是左乘,我们也可以先同时将位移矩阵、缩放矩阵和旋转矩阵先相乘得到一个新的矩阵,并拿这个新的矩阵乘与我们的向量以同时实现平移、旋转和缩放
  2. 矩阵乘法不遵循交换律
  3. 我们必须需要齐次坐标

二、会旋转的长方形

我们来实际运用一下,我们以这一章(SOIL库)的代码为基础扩展

效果如下:

非常简单,我们只需要将时间作为旋转和缩放的参数就好了,如下:

GLint transformLoc = glGetUniformLocation(shaderYellow.Program, "transform");
glm::mat4 trans = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f, -0.5f, 0.0f));
trans = glm::rotate(trans, (GLfloat)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);GLfloat val = sin(glfwGetTime());
trans = glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, 0.5f, 0.0f));
trans = glm::scale(trans, glm::vec3(val, val, val));
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

可以看出,我们绘制了两次,一次的位移向量为右下,并进行旋转,一次的位移向量为左上,并进行缩放(当然我们肯定是先进行的旋转,再进行的位移),其中trans即最终的变换矩阵,我们在计算完毕后用有Matrix4fv后缀的glUniform函数将其发送给着色器

  • glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans)):第1个参数是uniform的位置值,第2个参数表示我们需要传送的矩阵个数,这里肯定是1,第三个参数表示是否对矩阵进行置换(Transpose),也就是说交换矩阵的行和列,最后一个参数才是真正的矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据

其中对于第3个参数,OpenGL开发者通常使用一种内部矩阵布局,叫做列主序(Column-major Ordering)布局,GLM的默认布局就是列主序,所以我们并不需要置换矩阵,填GL_FALSE,所谓的列主序布局,即是将长度为n的向量表示成的形式,并且与矩阵进行乘法运算时只能使用左乘(left or pre-multiplication)

其实顶点着色器我们当然也要修改,多一个uniform的变量,应该很容易理解:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
layout (location = 2) in vec2 texture;
out vec4 colorIn;
out vec2 texIn;
uniform mat4 transform;
void main()
{gl_Position = transform * vec4(position, 1.0);colorIn = color;texIn = vec2(texture.x, 1.0f - texture.y);
}

好了到这就大功告成了,完整代码如下,其中片段着色器和Shader.h的代码可以在SOIL库这一章找到,没有修改

#include<iostream>
#include<opengl/glew.h>
#define GLEW_STATIC
#include<GLFW/glfw3.h>
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
#include"Shader.h"
#include<opengl/freeglut.h>
#include<SOIL.h>void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
const GLuint WIDTH = 800, HEIGHT = 600;int main()
{glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);glfwMakeContextCurrent(window);glfwSetKeyCallback(window, key_callback);glewExperimental = GL_TRUE;glewInit();int width, height;glfwGetFramebufferSize(window, &width, &height);glViewport(0, 0, width, height);Shader shaderYellow("VShader.txt", "FShaderY.txt");GLfloat vertices[] ={-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};GLuint indices[] ={0, 1, 2,        //用前3个顶点绘制第一个三角形1, 2, 3         //用后3个顶点绘制第二个三角形};GLuint VBO, EBO, VAO, texture;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glGenTextures(1, &texture);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBindTexture(GL_TEXTURE_2D, texture);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));glEnableVertexAttribArray(1);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));glEnableVertexAttribArray(2);int picWidth, picHeight;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);unsigned char* image = SOIL_load_image("timg.jpg", &picWidth, &picHeight, 0, SOIL_LOAD_RGB);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);SOIL_free_image_data(image);glBindTexture(GL_TEXTURE_2D, 0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);GLint transformLoc = glGetUniformLocation(shaderYellow.Program, "transform");while (!glfwWindowShouldClose(window)){glfwPollEvents();glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glBindTexture(GL_TEXTURE_2D, texture);shaderYellow.Use();GLint transformLoc = glGetUniformLocation(shaderYellow.Program, "transform");glm::mat4 trans = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f, -0.5f, 0.0f));trans = glm::rotate(trans, (GLfloat)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);GLfloat val = sin(glfwGetTime());trans = glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, 0.5f, 0.0f));trans = glm::scale(trans, glm::vec3(val, val, val));glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glBindVertexArray(0);glfwSwapBuffers(window);}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);glfwTerminate();return 0;
}void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)glfwSetWindowShouldClose(window, GL_TRUE);
}

OpenGL基础10:变换相关推荐

  1. OpenGL基础图形编程(八)变换

    八.OpenGL变换 OpenGL变换是本篇的重点内容,它包括计算机图形学中最基本的三维变换,即几何变换.投影变换.裁剪变换.视口变换,以及针对OpenGL的特殊变换概念理解和用法,如相机模拟.矩阵堆 ...

  2. OpenGL基础54:点光源阴影

    前置: OpenGL基础53:阴影映射(下) 一.万象阴影贴图 之前成功实现了平行光阴影,生成阴影贴图时使用的矩阵是正交矩阵,若是想要实现点光源的阴影效果,那么理论上只需要修改投影矩阵为透视矩阵就好了 ...

  3. OpenGL基础图形编程

    一.OpenGL与3D图形世界 1.1.OpenGL使人们进入三维图形世界 我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,我们必须能在三维空间描绘这些物体.我们又生活在一个 ...

  4. OpenGL基础知识介绍和简单使用

    OpenGL基础知识介绍 OpenGL简介 OpenGL 专业词解析 1.OpenGL上下文[context] 2.渲染 3.顶点数组和顶点缓冲区 4.着色器程序Shader 5.顶点着色器(Vert ...

  5. OpenGL基础编程

    一.OpenGL与3D图形世界 1.1.OpenGL使人们进入三维图形世界 我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,我们必须能在三维空间描绘这些物体.我们又生活在一个 ...

  6. 【转】OpenGL基础图形编程(一)

    原文:http://blog.chinaunix.net/uid-20638550-id-1909183.html  分类: 一.OpenGL与3D图形世界 1.1.OpenGL使人们进入三维图形世界 ...

  7. OpenGL基础图形编程(转)

    一.OpenGL与3D图形世界 1.1.OpenGL使人们进入三维图形世界 我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,我们必须能在三维空间描绘这些物体.我们又生活在一个 ...

  8. OpenGL基础图形编程(一)

    一.OpenGL与3D图形世界 1.1.OpenGL使人们进入三维图形世界 我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,我们必须能在三维空间描绘这些物体.我们又生活在一个 ...

  9. opengl基础学习专题 (二) 点直线和多边形

    题外话 随着学习的增长,越来越觉得自己很水.关于上一篇博文中推荐用一个 学习opengl的 基于VS2015的 simplec框架.存在 一些问题. 1.这个框架基于VS 的Debug 模式下,没有考 ...

最新文章

  1. 《Java虚拟机规范》阅读(三):Class文件格式
  2. Win7新手系列教程:从安装到简单使用(新人必读)
  3. luogu P3379 【模板】最近公共祖先(LCA)
  4. 【面试】编译器为我们实现了几个类成员函数?(c++)
  5. 如何关掉Eclipse里对于Maven下载包的校验值检查
  6. win10 平台VS2019最简安装实现C++/C开发
  7. SQLSERVER得到数据库中所有表字段及字段中文描述
  8. lisp如何调用linux头文件,Lisp之 程序的交互执行和非交互执行
  9. Handbook of Constraints Programming——Chapter4 Backtracking Search Algorithms-Preliminaries
  10. DB2添加数据时主键、唯一键冲突的解决方法
  11. php post提交 java接收,asp如何接收php或java提交post过来的json数据
  12. 物理课上该怎样使用计算机,物理课堂教学中怎样使用演示课件.doc
  13. 持久层框架:Mybatis快速入门
  14. python 成语接龙-连接数据库
  15. [附源码]java毕业设计流浪宠物免费领养系统
  16. 动物网页html5设置思想,网站设计思想
  17. mysql 1236错误_mysql报1236错误解决方法
  18. 电影《寒战1》中的管理知识
  19. 基于qt的计算机论文,基于qt的科学计算器的设计与实现本科毕业论文.doc
  20. 无人驾驶数据库汇总(不断更新)

热门文章

  1. python自学看什么书-自学Python要看哪些书?有什么推荐?
  2. python教程推荐-关于推荐系统的详细介绍
  3. 学python可以从事什么工作-学Python能干什么工作?工作前景怎么样?
  4. python能做什么工作-学完python能从事什么工作?
  5. python自动化测试-Python自动化测试入门,看这一篇就足以
  6. 21天学通python-21天学通Python PDF 高清版
  7. 论文笔记:语音情感识别(三)手工特征+CRNN
  8. HTML5语音识别(已被抛弃)
  9. VueRouter(记录)
  10. c语言马拉松试题,C语言马拉松_04.2_函数与指针