LearnOpenGL-笔记4

变换这一章都是基础的数学知识,不多记录。
GLM(OpenGL Mathematics)
只有头文件的库,包含对应的头文件就行了,不用链接和编译。

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

int main() {
   
	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;
	return 0;
}

输出结果正确。(100向量移动110,为210)
在这里插入图片描述
对箱子进行操作:

glm::mat4 trans;
trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
//绕z旋转90°
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));

把矩阵传递给着色器:

#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);
}

把变换矩阵传递给着色器:

unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
//第一个参数:program,着色器程序id;
//之前的用法:		
//int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
/* ourshader:
        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        glLinkProgram(ID);
*/
/* initial shader:
	unsigned int shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);
*/
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

参1:uniform的位置值。
参2:将要发送多少个矩阵,这里是1。
参3:是否转置
参4:矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据。

传入参数后顺利得到如下结果。
顺便说一句这里又发生了拼错单词的尴尬,又因为这个找了一小会错误(> - <)
在这里插入图片描述
使用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));
//注意要写在迭代循环里

可以看到,学习opengl的我们的表情正在右下角旋转(好怪!)
在这里插入图片描述
记住,实际的变换顺序应该与阅读顺序相反:尽管在代码中我们先位移再旋转,实际的变换却是先应用旋转再是位移的。

坐标系统

局部空间(Local Space,或者称为物体空间(Object Space))

我们一直使用的那个箱子的顶点是被设定在-0.5到0.5的坐标范围中,(0, 0)是它的原点。这些都是局部坐标。

世界空间(World Space)

将箱子的局部坐标变换到场景/世界中的不同位置。

观察空间(View Space,或者称为视觉空间(Eye Space))
裁剪空间(Clip Space)
屏幕空间(Screen Space)
在这里插入图片描述
MVP变换,games中也有详细的讲解。
由投影矩阵创建的观察箱(Viewing Box)被称为平截头体(Frustum)

相机永远不动且看向-z方向。动我们自己的视角可以通过反着移动物体来实现。
projection是包含ortho和perspective两部分,需要二者相乘,ortho在左perspective在右。
perspective的作用是可以把一个透视的四棱锥压成一个小盒子;就是把透视的东西先挤成长方体,然后再做一次正交投影就可以解决这个问题。
在这里插入图片描述
ortho的作用就是空间的标准化:
在这里插入图片描述
正交投影的效果:
在这里插入图片描述
代码:

projection = glm::ortho(-5.0f, 4.0f, -4.0f, 6.0f, 0.1f, 100.0f);

透视投影的效果:
在这里插入图片描述

v:

因为我们想要往后移动,并且OpenGL是一个右手坐标系(Right-handed System),所以我们需要沿着z轴的正方向移动。我们会通过将场景沿着z轴负方向平移来实现。

P:

ortho
映射标准立方体:
要创建一个正射投影矩阵,我们可以使用GLM的内置函数glm::ortho:

glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);

perspective:

glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);

第一个参数定义了fov的值,如果想要一个真实的观察效果,它的值通常设置为45.0f,但想要一个末日风格的结果你可以将其设置一个更大的值。第二个参数设置了宽高比,由视口的宽除以高所得。第三和第四个参数设置了平截头体的近和远平面。我们通常设置近距离为0.1f,而远距离设为100.0f。 (near 值设置太大时(如10.0f),OpenGL会将靠近摄像机的坐标(在0.0f和10.0f之间)都裁剪掉,这会导致一个你在游戏中很熟悉的视觉效果:在太过靠近一个物体的时候你的视线会直接穿过去。)
所有在近平面和远平面内且处于平截头体内的顶点都会被渲染。

这章由于有games的基础,思路比较清晰,所以就直接上10个立体箱子旋转代码。注释和注意事项在代码中已经体现了。

另外有一点就是不知道自己漏看了还是什么原因,ourShader神不知鬼不觉多了一个成员函数setMat4.记得补一下:

    void setMat4(const std::string& name, glm::mat4 value) const
    {
   
        glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));
    }

主文件代码如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <shader.h>
#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_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);
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);

    //深度测试打开(默认是关闭的)
    glEnable(GL_DEPTH_TEST);
    Shader ourShader("6box.vs", "6box.fs");
    //六个面的参数,而且没有用EBO所以有六行
    float vertices[] = {
   
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值