基本上都是线性代数的知识,矩阵的运算、向量的运算。就不多写了,挑几个关键点的记一下。
接下来要做的事情其实不多。虽然变换设计的数学知识很多,但是我们不用一个个的取实现那些算法,直接引用一个库就好了。
GLM是OpenGL Mathematics的缩写,它是一个只有头文件的库。在这里下载(0.9.9和0.9.8有一个区别就是默认矩阵的类型不同,教材用的是0.9.8)。介绍是这样的,跟OpenGL还是一家的,基于GLSL。
OpenGL Mathematics (GLM) is a header only C++ mathematics library for graphics software based on the OpenGL Shading Language (GLSL) specifications.
GLM provides classes and functions designed and implemented with the same naming conventions and functionalities than GLSL so that anyone who knows GLSL, can use GLM as well in C++.
This project isn’t limited to GLSL features. An extension system, based on the GLSL extension conventions, provides extended capabilities: matrix transformations, quaternions, data packing, random numbers, noise, etc…
This library works perfectly with OpenGL but it also ensures interoperability with other third party libraries and SDK. It is a good candidate for software rendering (raytracing / rasterisation), image processing, physic simulations and any development context that requires a simple and convenient mathematics library.
下载下来之后像以前搭建OpenGL环境一样,把文件解压到特定的地方。在vs的项目中添加引用目录。
然后include一下。
#include
#include
#include
然后跟着下面的代码试一下,输出210说明就已经没问题了。
glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
glm::mat4 trans;
trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));
vec = trans * vec;
std::cout << vec.x << vec.y << vec.z << std::endl;
translate函数把trans单位矩阵和(1,1,0)这个向量合成一个位移矩阵。
首先创建一个变换矩阵。
glm::mat4 trans; // 变换矩阵
trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0)); // 旋转
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5)); // 缩放
顶点着色器的代码要加一个mat4的unifrom,用来传入矩阵。然后在传出定点位置前先用变换矩阵进行变换。
#version 330 core
uniform mat4 transform;
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;
out vec3 Color;
out vec2 TexCoord;
void main() {
gl_Position = transform * vec4(aPos, 1.0); // 用变换矩阵乘上位置的向量,可以看到这里的齐次坐标为1
Color = aColor;
TexCoord = aTexCoord;
}
在渲染循环中,可以像教程一样用以前的方法传入矩阵。如下。
unsigned int transformLoc = glGetUniformLocation(myShader.id, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
但是我们既然都实现我们自己的shader类了,为什么不用呢?因为之前跟着教程做只做了设置int、boolean、float三种参数的函数,没有mat4的。跟着加一个就好。
// shader.h中
void setBool(const std::string &name, bool value)const;
void setInt(const std::string& name, int value) const;
void setFloat(const std::string& name, float value)const;
// 新增
void setMat4(const std::string& name, glm::mat4 value)const;
// shader.cpp中
···
···
void Shader::setFloat(const std::string& name, float value) const {
glUniform1f(glGetUniformLocation(id, name.c_str()), value);
}
// 新增
void Shader::setMat4(const std::string& name, glm::mat4 value) const {
glUniformMatrix4fv(glGetUniformLocation(id, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));
}
然后再渲染循环内这样简单的调用就好啦。
/*Uniform*/
myShader.setFloat("mixValue", mixValue);
myShader.setFloat("uvScale", uvScale);
// 新增
myShader.setMat4("transform", trans);
也没啥特别的,就是转了下缩放了下。
瞎玩了一下,把变换写在渲染循环里面。
/*Uniform*/
myShader.setFloat("mixValue", mixValue);
myShader.setFloat("uvScale", uvScale);
myShader.setMat4("transform", trans);
/*变换*/
trans = glm::scale(trans, glm::vec3(1.0, 1.0, 1.0) * (glm::float32(1) + glm::float32((sin(glfwGetTime()*10)/10)/100))); // 缩放
trans = glm::rotate(trans, glm::radians(0.3f), glm::vec3(0.0, 0.0, 1.0)); // 旋转
完整代码