第五课,OpenGL图像变换

glm 下载&环境配置

OpenGL GLM 环境配置

GLM常用函数及使用

引自 OpenGL矩阵运算——GLM库的使用

头文件

GLM对于矩阵数据类型的定义位于glm/glm.hpp头文件中。
生成变换矩阵的函数位于glm/gtc/matrix_transform.hpp头文件中。
生成投影矩阵的函数位于glm/ext/matrix_clip_space.hpp头文件中。
将数组转换成矩阵的函数位于头文件glm/gtc/type_ptr.hpp中。
glm::value_ptr函数位于头文件glm/gtc/type_ptr.hpp中

GLM常用函数

glm::radians()
角度制转弧度制,可应用于glm::rotate()中。
glm::translate()
返回一个平移矩阵,第一个参数是目标矩阵,第二个参数是平移的方向向量。
glm::rotate()
返回一个将点绕某个轴逆时针旋转一定弧度的旋转矩阵,第一个参数是弧度,第二个参数是旋转轴。
glm::scale()
返回一个缩放矩阵,第一个参数是目标矩阵,第二个参数是在各坐标轴上的缩放系数。
glm::ortho(float left, float right, float bottom, float top, float zNear, float zFar);
正交投影矩阵。前四个参数分别是视口的左、右、上、下坐标。第五和第六个参数则定义了近平面和远平面的距离。
glm::perspective(float fovy, float aspect, float zNear, float zFar);
透视投影矩阵。第一个参数为视锥上下面之间的夹角,第二个参数为视口宽高比,第三、四个参数分别为近平面和远平面的深度。
glm::value_ptr()
传入一个矩阵,返回一个数组。

版权声明:本文为CSDN博主「Iwakura Rein」的原创文章,遵循CC 4.0
BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42537915/article/details/104146135
————————————————

glm的使用详解

1.设置变化矩阵

平移
transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));

glm::translate() 返回一个平移矩阵,第一个参数是目标矩阵,第二个参数是平移的方向向量。

顶点的范围为[-1.0,1.0]。
glm::vec3(0.5f, -0.5f, 0.0f)表示:将所有x轴顶点+0.5f , 所有y轴顶点-0.5f,z轴不变。

旋转
transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));

glm::rotate() 返回一个将点绕某个轴逆时针旋转一定弧度的旋转矩阵,第二个参数是弧度(glm::radians() 角度制转弧度制),第三个参数是旋转轴(起点为(0.0.0)的向量)。

缩放

glm::scale 这个函数一般用于将物体进行缩放

transform = glm::scale(transform, glm::vec3(0.5, 0.5, 0.5));

第二个参数三维向量表示对xyz轴的缩小倍数。大于1为缩小,小于1为扩大。

2.传入变化矩阵

PVPCShader.setMat4("transform", transform);

自定义shader函数,原函数为:

void Shader::setMat4(const std::string& name, const glm::mat4& mat) const{
    glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}

第三个参数询问我们我们是否希望对我们的矩阵进行置换(Transpose),也就是说交换我们矩阵的行和列。

该步将transfrom变化矩阵传入顶点着色器中名为transform的四阶矩阵。

3.在顶点着色器中使用变化矩阵

gl_Position =  transform * vec4(aPos, 1.0);

将变化矩阵与各顶点相乘。即可。

避免影响其他管道的运行

可将tranform初始化为单位矩阵
.vs

uniform mat4 transform = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};

否则将必须在使用该顶点着色器的所有管线前添加uniform初值。

transform = glm::mat4(1.0f);
ChangingColorShader.setMat4("transform", transform);

全部代码

main.cpp

#include <iostream>
//包含命名空间std

#include <glad/glad.h>
#include <GLFW/glfw3.h>
//glad需要在glfw之前,因为GLAD的头文件包含了正确的OpenGL头文件,glfw依赖于OpenGL

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

//stb_image
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

//自定义
#include "Shader.h"//着色器设置
#include "call_back.h"//回调函数设置

int main(){
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    // glfw window creation
    //---------------------
    GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
    if (window == nullptr) {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, key_callback);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    
    //glad初始化(GLAD是用来管理OpenGL的函数指针的)
    //load all OpenGL function pointers
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    设置视口
    //int width, height;
    //glfwGetFramebufferSize(window, &width, &height);
    //glViewport(0, 0, width, height);

    //生成着色器
    Shader PVPCShader("./Normal.vs","./setcolor.fs");
    Shader ChangingColorShader("./Normal.vs", "./Changing.fs");


    /*
    第一组数据处理----两个填充三角形************************
    */

    //添加顶点数据
    GLfloat vertices[] = {
        //location(顶点坐标)     color         texture coords(纹理坐标)
        -1.0f,  0.0f, 0.0f,    1.0f, 0.0f, 0.0f,  0.0f, 2.0f,  //左中--左上
        -1.0f, -1.0f, 0.0f,    0.0f, 0.0f, 1.0f,  0.0f, 0.0f,  //左下--左下
         0.0f, -1.0f, 0.0f,    0.0f, 1.0f, 0.0f,  1.0f, 0.0f,  //中下--右下
         0.0f,  0.0f, 0.0f,    0.3f, 0.3f, 0.3f,  1.0f, 2.0f,  //居中--右上
        -1.0f,  0.0f, 0.0f,    1.0f, 0.0f, 0.0f,  0.0f, 2.0f,  //左中--左上
         0.0f, -1.0f, 0.0f,    0.0f, 1.0f, 0.0f,  1.0f, 0.0f,  //中下--右下
    };

    //set up buffers and configure vertex attributes
    //设置缓存区配置顶点属性
    GLuint VBO, VAO;
    glGenBuffers(1, &VBO);//获取一个buffer名为VBO
    glGenVertexArrays(1, &VAO); // 获取一个VertexArrays名为VAO
    
    glBindVertexArray(VAO);//绑定VAO为当前使用顶点数组
    
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(0));
    glEnableVertexAttribArray(0);//启用顶点属性,0号位
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    //加载创建纹理
    //------------
    GLuint texture1;
    //texture 1
    //-----------
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    // set the texture wrapping parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    // set texture filtering parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // load image, create texture and generate mipmaps(纹理映射)
    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true); // y轴翻转纹理
    unsigned char* data = stbi_load("./container.jpg", &width, &height, &nrChannels, 0);//获取图片宽高和颜色通道的个数
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        //glTexImage2D(纹理目标,多级渐远纹理的级别,储存为何种格式,宽,高,0,源图的格式,数据类型,真正的图像数据)
        //当前绑定的纹理对象就会被附加上纹理图像。
        glGenerateMipmap(GL_TEXTURE_2D);//为当前绑定的纹理自动生成所有需要的多级渐远纹理。
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);//释放图像的内存

    //纹理2
    GLuint texture2;
    glGenTextures(1, &texture2);//传入引用,初始化texture2
    glBindTexture(GL_TEXTURE_2D, texture2);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //glTexParameteri(纹理维度,改变类型,改变值);
    unsigned char* data2 = stbi_load("./awesomeface.png", &width, &height, &nrChannels, 0);
    if (data2)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);//png格式加载为GL_RGBA格式
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data2);
//    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  //  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 //   glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    //给纹理采样器分配一个位置值(默认纹理单元是0,所以多个纹理单元需要分配)
    //OpenGL至少保证有16个纹理单元供你使用
    PVPCShader.use(); //激活要绑定的着色器后才可分配
    PVPCShader.setInt("sampler1", 0);//将着色器中texture1采样器分配到GL_TEXTURE0
    PVPCShader.setInt("sampler2", 1);//将着色器中texture2采样器分配到GL_TEXTURE1



    /*
    第二组数据处理----两个线框三角形************************************
    */

    //使用索引数据存储点的顺序,用IBO索引缓冲对象管理
    GLfloat vertices1[] = {
    0.5f, 0.5f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
    };
    unsigned int indices1[] = { // 注意索引从0开始! 
        0, 1, 3, // 第一个三角形
        1, 2, 3  // 第二个三角形
    };
    
    
    //设置缓存区配置顶点属性
    GLuint VBO1,EBO1,VAO1;
    //生成三类对象,不分先后顺序
    glGenBuffers(1, &EBO1);
    glGenBuffers(1, &VBO1);
    glGenVertexArrays(1, &VAO1);
    //绑定三类对象
    glBindVertexArray(VAO1);//VAO必须为第一
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO1);
    glBindBuffer(GL_ARRAY_BUFFER, VBO1);
    //绑定缓冲数据
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices1), indices1, GL_STATIC_DRAW);
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);


    //Loop
    while (!glfwWindowShouldClose(window)){//检查glfw是否被要求退出//
        glfwPollEvents();
        //检查有没有触发什么事件,然后调用对应的回调函数.
        
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        PVPCShader.use();
        glActiveTexture(GL_TEXTURE0);// 在绑定纹理之前先激活纹理单元
        glBindTexture(GL_TEXTURE_2D, texture1);//绑定这个纹理到当前激活的纹理单元
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);

        // create transformations
        glm::mat4 transform = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
        //transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));
        //glm::translate()    返回一个平移矩阵,第一个参数是目标矩阵,第二个参数是平移的方向向量。
        transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
        //glm::rotate()       返回一个将点绕某个轴逆时针旋转一定弧度的旋转矩阵,第一个参数是弧度,第二个参数是旋转轴。
        transform = glm::scale(transform, glm::vec3(0.5, 0.5, 0.5));

        // get matrix's uniform location and set matrix
        PVPCShader.setMat4("transform", transform);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        //glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        //glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//设置为填充模式(默认)
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 2*3);//数量必须为3的倍数
        glDisable(GL_BLEND);

        float timeValue = glfwGetTime();
        float greenValue = (sin(timeValue) / 2.0f) + 0.5f;

        ChangingColorShader.use();//设置uniform值前必须先使用程序。
        ChangingColorShader.setVec3("Color", 0.0f, greenValue, 0.0f);//Color赋值RGB
        //transform = glm::mat4(1.0f);
        //ChangingColorShader.setMat4("transform", transform);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//设置为线框模式
        glBindVertexArray(VAO1);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        //交换颜色缓冲
    }
    //Game Loop

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteVertexArrays(1, &VAO1);
    glDeleteBuffers(1, &VBO1);
    glDeleteBuffers(1, &EBO1);
    glDeleteProgram(PVPCShader.ID);

    glfwTerminate();
    //释放GLFW分配的内存。

    return 0;
}

.vs

#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 outColor;
out vec2 TexCoord;
uniform mat4 transform = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};

void main()
{
    gl_Position =  transform * vec4(aPos, 1.0);
    outColor = aColor;
    TexCoord = aTexCoord;
}

.fs

#version 330 core
out vec4 FragColor;

in vec3 outColor;
in vec2 TexCoord;

uniform sampler2D sampler1;//保证在分配采样器时的名称与该名称一致
uniform sampler2D sampler2;//否则会出现一些无提示的错误,不容易发现

void main()
{
	FragColor = mix(texture(sampler1, TexCoord), texture(sampler2, TexCoord),0.2);
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片