OpenGL学习笔记8——变换

1 概念

基本上都是线性代数的知识,矩阵的运算、向量的运算。就不多写了,挑几个关键点的记一下。

  • 点乘,向量和向量之间做点乘,结果是一个标量。点乘是通过将对应分量逐个相乘,然后再把所得积相加。相当于求投影。用来计算角度很方便,可能用在光照的计算。
  • 叉乘,向量和向量之间做叉乘,结果还是一个向量,并且这个向量会垂直于两个向量所在的平面。
  • OpenGL中的向量相乘在线性代数中并不存在这样的乘法。结果还是一个向量,计算方法是对应位置的标量相乘。可以用来方便平时的开发,但是在数学中并不存在这样的计算方式。
  • 齐次坐标,(x,y,z,w)中w分量就是齐次坐标。表示一个位置的时候为1,表示方向的时候为0。 好处就是用一个位移的变换矩阵对w为0的向量做运算的时候,结果是不会变的,即方向不会被移动。比如一个物体的速度,就是一个方向向量,无论它移动到哪一个位置,他的速度向量不会因为位置而改变。
  • 变换矩阵的顺序。因为矩阵的乘法运算不满足交换律,所以建议在组合矩阵时,先进行缩放操作,然后是旋转,最后才是位移,否则它们会(消极地)互相影响。

2 应用变换

接下来要做的事情其实不多。虽然变换设计的数学知识很多,但是我们不用一个个的取实现那些算法,直接引用一个库就好了。

2.1 GLM

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 <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

然后跟着下面的代码试一下,输出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)这个向量合成一个位移矩阵。

2.2 给四边形应用变换

首先创建一个变换矩阵。

	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)); // 旋转

完整代码
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值