LearnOpenGL(九)自定义转换类

先提供头文件下载地址:OpenGL Mathematics

我用的是0.9.9的版本,要注意声明mat4时,默认是初始化为0矩阵,而不再是单位矩阵,需要设置

类代码:

复制代码
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

class Translate
{
public:
    glm::mat4 transform_matrix;
    Translate()
    {
        transform_matrix = glm::mat4(1.0f);
    }

    /// @brief 位移
    /// @param x 沿x轴
    /// @param y 沿y轴
    /// @param z 沿z轴
    void Move(float x, float y, float z)
    {
        transform_matrix = glm::translate(transform_matrix, glm::vec3(x, y, z));
    }
    /// @brief 旋转
    /// @param angle 旋转角度
    /// @param rotatingShaft 旋转轴
    void Rotate(float angle, glm::vec3 rotatingShaft)
    {
        transform_matrix = glm::rotate(transform_matrix, angle, rotatingShaft);
    }

    /// @brief 缩放
    /// @param x 沿x轴缩放
    /// @param y 沿y轴缩放
    /// @param z 沿z轴缩放
    void Scale(float x, float y, float z)
    {
        transform_matrix = glm::scale(transform_matrix, glm::vec3(x, y, z));
    }
};

shadertool全代码,注意增加了一个传递uniform的mat4的函数

复制代码
#ifndef SHADERTOOL_H
#define SHADERTOOL_H

#include <glad/glad.h>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

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

class Translate
{
public:
    glm::mat4 transform_matrix;
    Translate()
    {
        transform_matrix = glm::mat4(1.0f);
    }

    /// @brief 位移
    /// @param x 沿x轴
    /// @param y 沿y轴
    /// @param z 沿z轴
    void Move(float x, float y, float z)
    {
        transform_matrix = glm::translate(transform_matrix, glm::vec3(x, y, z));
    }
    /// @brief 旋转
    /// @param angle 旋转角度
    /// @param rotatingShaft 旋转轴
    void Rotate(float angle, glm::vec3 rotatingShaft)
    {
        transform_matrix = glm::rotate(transform_matrix, angle, rotatingShaft);
    }

    /// @brief 缩放
    /// @param x 沿x轴缩放
    /// @param y 沿y轴缩放
    /// @param z 沿z轴缩放
    void Scale(float x, float y, float z)
    {
        transform_matrix = glm::scale(transform_matrix, glm::vec3(x, y, z));
    }
};

class Shader
{
public:
    unsigned int ID;
    Shader(const char *vertexPath, const char *fragmentPath)
    {
        // 声明临时变量
        std::string vertexCode;
        std::string fragmentCode;
        std::ifstream vShaderFile;
        std::ifstream fShaderFile;
        // 确保文件流可以输出错误信息
        vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        try
        {
            // 打开文件
            vShaderFile.open(vertexPath);
            fShaderFile.open(fragmentPath);
            std::stringstream vShaderStream, fShaderStream;
            // 读取文件buffer到流
            vShaderStream << vShaderFile.rdbuf();
            fShaderStream << fShaderFile.rdbuf();
            // 关闭文件
            vShaderFile.close();
            fShaderFile.close();
            // 将流转换为string
            vertexCode = vShaderStream.str();
            fragmentCode = fShaderStream.str();
        }
        catch (std::ifstream::failure &e)
        {
            std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ: " << e.what() << std::endl;
        }
        const char *vShaderCode = vertexCode.c_str();
        const char *fShaderCode = fragmentCode.c_str();
        // 组合shader
        unsigned int vertex, fragment;
        // vertex shader
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);
        checkCompileErrors(vertex, "VERTEX");
        // fragment Shader
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, "FRAGMENT");
        // shader Program
        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        glLinkProgram(ID);
        checkCompileErrors(ID, "PROGRAM");

        glDeleteShader(vertex);
        glDeleteShader(fragment);
    }
    /// @brief 调用Shader
    void use()
    {
        glUseProgram(ID);
    }

    /// @brief Shader全局bool参数设置
    /// @param name Shader参数名
    /// @param value 参数值
    void setBool(const std::string &name, bool value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
    }

    /// @brief Shader全局int参数设置
    /// @param name Shader属性名
    /// @param value 属性值
    void setInt(const std::string &name, int value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
    }

    /// @brief Shader全局float参数设置
    /// @param name Shader属性名
    /// @param value 属性值
    void setFloat(const std::string &name, float value) const
    {
        glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
    }

    void setMat4(const std::string &name, glm::mat4 value)
    {
        glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));
    }
    /// @brief 销毁进程
    void release()
    {
        glDeleteProgram(ID);
    }

private:
    /// @brief 检测Shader组合与编译的工具方法
    /// @param shader shaderID
    /// @param type 检测的类型
    void checkCompileErrors(unsigned int shader, std::string type)
    {
        int success;
        char infoLog[1024];
        if (type != "PROGRAM")
        {
            glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
            if (!success)
            {
                glGetShaderInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
                          << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
        else
        {
            glGetProgramiv(shader, GL_LINK_STATUS, &success);
            if (!success)
            {
                glGetProgramInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
                          << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
    }
};
#endif

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

class Texture2D
{
public:
    unsigned int ID;
    int width, height, colorChannels;
    /// @brief 2D贴图
    /// @param filename 贴图路径
    /// @param ST_WARP_MINMAX_FILTER ST的Warp模式,缩小和放大的纹理过滤模式
    /// @param internalformat 保存的颜色格式
    /// @param format 源文件的颜色格式
    /// @param type 源文件的数据类型
    /// @param mipmap_level 手动设置mimap级别,默认为0
    Texture2D(const char *filename, GLint ST_WARP_MINMAX_FILTER[4], GLint internalformat, GLenum format, GLenum type, int mipmap_level = 0)
    {
        glGenTextures(1, &ID);
        glBindTexture(GL_TEXTURE_2D, ID);
        // 为当前绑定的纹理对象设置环绕、过滤方式
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ST_WARP_MINMAX_FILTER[0]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ST_WARP_MINMAX_FILTER[1]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ST_WARP_MINMAX_FILTER[2]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ST_WARP_MINMAX_FILTER[3]);
        // 加载并生成纹理
        unsigned char *data = stbi_load(filename, &width, &height, &colorChannels, 0);
        if (data)
        {
            glTexImage2D(GL_TEXTURE_2D, mipmap_level, internalformat, width, height, 0, format, type, data);
            glGenerateMipmap(GL_TEXTURE_2D);
        }
        else
        {
            std::cout << "Failed to load texture" << std::endl;
        }
        stbi_image_free(data);
    };

    /// @brief 2D贴图,图像翻转
    /// @param filename 贴图路径
    /// @param ST_WARP_MINMAX_FILTER ST的Warp模式,缩小和放大的纹理过滤模式
    /// @param internalformat 保存的颜色格式
    /// @param format 源文件的颜色格式
    /// @param type 源文件的数据类型
    /// @param flipY 加载前是否反转图像
    /// @param mipmap_level 手动设置mimap级别,默认为0
    Texture2D(const char *filename, GLint ST_WARP_MINMAX_FILTER[4], GLint internalformat, GLenum format, GLenum type, bool flipY, int mipmap_level = 0)
    {
        glGenTextures(1, &ID);
        glBindTexture(GL_TEXTURE_2D, ID);
        // 为当前绑定的纹理对象设置环绕、过滤方式
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ST_WARP_MINMAX_FILTER[0]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ST_WARP_MINMAX_FILTER[1]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ST_WARP_MINMAX_FILTER[2]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ST_WARP_MINMAX_FILTER[3]);
        // 加载并生成纹理
        stbi_set_flip_vertically_on_load(flipY);
        unsigned char *data = stbi_load(filename, &width, &height, &colorChannels, 0);
        if (data)
        {
            glTexImage2D(GL_TEXTURE_2D, mipmap_level, internalformat, width, height, 0, format, type, data);
            glGenerateMipmap(GL_TEXTURE_2D);
        }
        else
        {
            std::cout << "Failed to load texture" << std::endl;
        }
        stbi_image_free(data);
    };
};

#endif

调用函数:

顶点Shader:

复制代码
#version 330 core
layout (location=0) in vec3 aPos;
layout (location=1) in vec3 color;
layout (location=2) in vec2 texcoord;

out vec3 vertexColor;
out vec2 uv;
uniform mat4 transform;
void main()
{
    gl_Position = transform*vec4(aPos.x,aPos.y,aPos.z,1.0);
    vertexColor = color;
    uv=texcoord;
}

片元Shader:

复制代码
#version 330 core
out vec4 fragColor;
in vec3 vertexColor;
in vec2 uv;

uniform sampler2D mainTexture;
uniform sampler2D secondTexture;

void main()
{
    vec4 baseColor=texture(mainTexture,uv);
    vec4 addColor = texture(secondTexture,vec2(-uv.x*2.,uv.y*2.));
    fragColor=mix(baseColor,addColor,addColor.a);
}

主函数:

复制代码
#include <shadertool.h>
#include <GLFW/glfw3.h>

unsigned int Screen_Width = 600;
unsigned int Screen_Height = 600;

void player_input(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

void frame_sizebuffer_callback(GLFWwindow *window, int width, int height)
{
    glViewport(0, 0, width, height);
}

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_COMPAT_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#endif

    GLFWwindow *window = glfwCreateWindow(Screen_Width, Screen_Height, "DrawTriangle", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Fail to create window !" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, frame_sizebuffer_callback);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Fail to initialize glad !" << std::endl;
        return -1;
    }

    Shader triangle_shader("shaders/vertex.vs", "shaders/fragment.fs");

    float vertices[] = {
        //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
        0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,   // 右上
        0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,  // 右下
        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
        -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f   // 左上
    };
    unsigned int indices[] = {
        0, 1, 3, // first triangle
        1, 2, 3  // second triangle
    };

    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    // 先绑定VAO,再绑定和设置VBO,然后配置顶点属性
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);
    // color attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    // texture coord attribute
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    GLint wrapFilterParams[4] = {GL_REPEAT, GL_REPEAT, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR};
    Texture2D texture("textures/container.jpg", wrapFilterParams, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
    Texture2D texture2("textures/awesomeface.png", wrapFilterParams, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true);

    triangle_shader.use();                                                   // 设置uniform变量之前激活着色器程序!
    glUniform1i(glGetUniformLocation(triangle_shader.ID, "mainTexture"), 0); // 手动设置贴图采样器绑定
    triangle_shader.setInt("secondTexture", 1);                              // 或者使用着色器类设置贴图采样器绑定

    while (!glfwWindowShouldClose(window))
    {
        /* code */
        player_input(window);

        glClear(GL_COLOR_BUFFER_BIT);

        // render container
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture.ID);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2.ID);

        Translate transform;
        transform.Move(0.0f, 0.1f, 0.0f);
        transform.Rotate((float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
        // unsigned int transformLoc = glGetUniformLocation(triangle_shader.ID, "transform");
        // glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform.transform_matrix));
        triangle_shader.setMat4("transform", transform.transform_matrix);

        triangle_shader.use();
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    triangle_shader.release();
    glfwTerminate();
    return 0;
}

效果:

相关推荐
qystca14 分钟前
蓝桥云客 岛屿个数
算法·dfs·bfs
什码情况1 小时前
回文时间 - 携程机试真题题解
数据结构·python·算法·华为od·机试
Alfadi联盟 萧瑶1 小时前
Python-Django入手
开发语言·python·django
lwewan2 小时前
26考研——栈、队列和数组_数组和特殊矩阵(3)
数据结构·笔记·考研·算法
晚雾也有归处2 小时前
链表(C++)
数据结构·c++·链表
-代号95272 小时前
【JavaScript】十二、定时器
开发语言·javascript·ecmascript
拾零吖2 小时前
枚举算法-day2
数据结构·算法·leetcode
已经成为了代码的形状2 小时前
关于交换并查集内元素的一些题的做法
数据结构·算法
勘察加熊人2 小时前
c++实现录音系统
开发语言·c++
self-discipline6342 小时前
【Java】Java核心知识点与相应面试技巧(七)——类与对象(二)
java·开发语言·面试