OpenGL学习(五)变换

OpenGL学习(六)变换

参考官方文档https://learnopengl-cn.github.io/

那么现在有意思的来了。首先关于矩阵运算就不用多做介绍了。直接进入实战部分。先下载GLM。这个直接百度可以找到:https://github.com/g-truc/glm。(官方文档中给出的链接打不开,只能百度)下载解压。刚开始我以为需要用cMake,后面发现不用cMake,只需要在你当前的项目的属性中添加包含目录就行了。需要用到的大多数功能都可以在下面3个头文件中找到。

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

例如:

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

int main() {
	glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);//创建向量
	glm::mat4 trans = glm::mat4(1.0f);//创建一个4*4的单位矩阵
	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;//1+1,0+1,0+0=>2,1,0
}

输出结果为:

210

C:\Users\xhh\Source\Repos\glmTest\x64\Debug\glmTest.exe (进程 58428)已退出,代码为 0。
按任意键关闭此窗口. . .

下面我们将再我们前面的窗口的基础上,运用glm的矩阵来操作窗口的绘图。

顶点着色器shader.vs

#version 330 core
layout(location=0) in vec3 aPos;
layout(location=1) in vec3 aColor;
layout(location=2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 transform;

void main(){
	gl_Position=transform*vec4(aPos.x,aPos.y,aPos.z,1.0);
	ourColor=aColor;
	TexCoord=vec2(aTexCoord.x,1.0-aTexCoord.y);
}

主程序中main.cpp

...;
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
...;
int main(){
    ...;
    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));
    ...;
    while(...){
        ...;
        unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
		glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
        ...;
    }
    ...;
}

这样对我们的图案旋转90度并缩小为原来的二分之一。像这样

或者再渲染循环中将举证创建为:

		glm::mat4 trans = glm::mat4(1.0f);
		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));
		unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
		glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

最终运行时会发现窗口中的图片会不断的旋转:
在这里插入图片描述
练习:

  1. 使用应用在箱子上的最后一个变换,尝试将其改变为先旋转,后位移。看看发生了什么,试着想想为什么会发生这样的事情

改为:

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

这时它会绕窗口的中心旋转而不是箱子的中心旋转,
在这里插入图片描述

为什么这两个操作的顺序反过来结果会差别这么大呢?

这个问题学过量子力学的应该很好理解。其实很简单的一个问题,前面的代码是平移在前而旋转在后,两个操作平移记为T,旋转记为R,作用到向量X上,TRX,所以实际上是先绕窗口中心旋转然后再平移到右下角。而现在就是反过来,先平移到右下角然后再绕中心旋转。旋转角度是随时间增大的,所以实际上就变成这样了。

  1. 尝试再次调用glDrawElements画出第二个箱子,使用变换将其摆放在不同的位置。让这个箱子被摆放在窗口的左上角,并且会不断的缩放(而不是旋转)。(sin函数在这里会很有用,不过注意使用sin函数时应用负值会导致物体被翻转)

第二个箱子,再渲染循环中接着前面的glDrawElements来,代码如下:

//第二个箱子
		trans = glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, 0.5f, 0.0f));
		trans = glm::scale(trans, glm::vec3(abs(sin((float)(glfwGetTime()))),abs(sin((float)glfwGetTime())), 1.0f));
		transformLoc = glGetUniformLocation(ourShader.ID, "transform");
		glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, texture1);
		ourShader.use();
		glBindVertexArray(VAO);
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

很顺利的得到了想要的结果了,它会随时间缩小幅度变化:

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章