当前位置: 首页 > article >正文

OpengGL教程(六)---坐标的变换和坐标系的变换

本章参考官方教程:坐标系统

本系列历史文
OpengGL教程(一)—OpenGL环境的配置(GLFW3,GLAD)
OpengGL教程(二)—渲染一个简单的窗体
OpengGL教程(三)—使用VAO和VBO方式绘制三角形
OpengGL教程(四)—使用EBO方式绘制矩形
OpengGL教程(五)—纹理的应用

经历前五章的学习我们最终实现了下述效果
在这里插入图片描述
本章节主要讲述了,坐标的变换和坐标系的变换问题,涉及到一些线性代数知识,这部分知识本章不做重点。笔者也是初学OpenGL,其中的一些数学相关的空间变化问题是需要自己独立思考才能理解的,希望读者可以根据文章中的“需求 -> 实现”的代码实现,去掌握其中的数学知识。

注意 : 笔者也是边学边记录,也会存在理解有误的地方,下文若有错误欢迎大家指正。谢谢!

坐标的变换

坐标的变化是比较简单的,通过对顶点坐标的变化从而实现不同的显示效果。此部分主要实现一张图片围绕Z轴旋转。

片元着色器的代码不需要修改和第五章的相同。
VertexShader.glsl

#version 330 core
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec2 aTexture;
uniform mat4 projection;
uniform mat4 trans;
out vec2 ourTexture;

void main()
{
    vec4 ndcPos = projection * vec4(aPosition,1.0f);
    gl_Position = trans * ndcPos;
    ourTexture  = aTexture;
}

main.cpp

#include <iostream>
#include <string>
#include "glew.h"
#include "glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"


#include "log.h"
#include "GlslDealConfig.h"

// 顶点数据
GLfloat vertices_1[] = {
    0.0f, 600.0f, 0.0f,
    0.0f, 0.0f, 0.0f,
    600.0f, 0.0f, 0.0f,
    600.0f, 600.0f, 0.0f
};

GLfloat vertices_2[] = {
    0.0f, 1.0f,
    0.0f, 0.0f,
    1.0f, 0.0f,
    1.0f, 1.0f
};

GLint indices[] = {
    0, 1, 2,
    0, 2, 3
};

// 主函数
int main() {
    GlslDealConfig glslConfig;

    // 初始化 GLFW
    if (!glfwInit()) {
        LOGE("Failed to initialize GLFW");
        return -1;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(600, 600, "Texture", nullptr, nullptr);
    if (!window) {
        LOGE("Failed to create GLFW window");
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    GLenum err = glewInit();
    if (err != GLEW_OK) {
        LOGE("Failed to initialize GLEW: %s", reinterpret_cast<const char*>(glewGetErrorString(err)));
        return -1;
    }

    glfwSwapInterval(1);

    // 加载着色器
    std::string vertexShaderCode   = glslConfig.ReadGlslFile("/home/ryan/zxp/Rendering/demo/glsl/Trans/VertexShader.glsl");
    std::string fragmentShaderCode = glslConfig.ReadGlslFile("/home/ryan/zxp/Rendering/demo/glsl/Trans/FragmentShader.glsl");

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    const GLchar* vShaderSource = vertexShaderCode.c_str();
    const GLchar* fShaderSource = fragmentShaderCode.c_str();

    glShaderSource(vertexShader, 1, &vShaderSource, nullptr);
    glShaderSource(fragmentShader, 1, &fShaderSource, nullptr);

    glCompileShader(vertexShader);
    glCompileShader(fragmentShader);
    glslConfig.CheckShaderCompileV(vertexShader);
    glslConfig.CheckShaderCompileF(fragmentShader);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glslConfig.CheckProgmaLinkStatus(shaderProgram);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 配置 VAO, VBO, EBO
    GLuint VAO, VBO[2], EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(2, VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_1), vertices_1, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_2), vertices_2, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (void*)0);
    glEnableVertexAttribArray(1);

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

    // 加载纹理
    GLuint texture[2];
    texture[0] = glslConfig.loadTexture("/home/ryan/zxp/Rendering/demo/resource/brickwall.jpg",   GL_RGB);
    texture[1] = glslConfig.loadTexture("/home/ryan/zxp/Rendering/demo/resource/awesomeface.png", GL_RGBA);

    // 设置投影矩阵
    glm::mat4 projection = glm::ortho(0.0f, 600.0f, 0.0f, 600.0f, -1.0f, 1.0f);
    glUseProgram(shaderProgram);
    GLuint projLoc = glGetUniformLocation(shaderProgram, "projection");
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    // 激活纹理单元
    glActiveTexture(GL_TEXTURE3);
    GLuint textureLocation = glGetUniformLocation(shaderProgram, "textureClass");
    glUniform1i(textureLocation, 3);

    glActiveTexture(GL_TEXTURE6);
    GLuint textureLocation2 = glGetUniformLocation(shaderProgram, "textureClass2");
    glUniform1i(textureLocation2, 6);

    // 渲染循环
    while (!glfwWindowShouldClose(window)) {
        glViewport(0, 0, 600, 600);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

        glActiveTexture(GL_TEXTURE3);
        glBindTexture(GL_TEXTURE_2D, texture[0]);

        glActiveTexture(GL_TEXTURE6);
        glBindTexture(GL_TEXTURE_2D, texture[1]);

        glm::mat4 transform = glm::mat4(1.0f);
        transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
        // transform = glm::translate(transform, glm::vec3(0.1f, -0.1f, 0.0f)); // switched the order 
        GLuint Trans = glGetUniformLocation(shaderProgram, "trans");
        glUniformMatrix4fv(Trans, 1, GL_FALSE, glm::value_ptr(transform));

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glBindVertexArray(0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glBindTexture(GL_TEXTURE_2D, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // 清理资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(2, VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);

    glfwTerminate();
    return 0;
}

相对于第五章的代码主要是在while循环中增加了下列代码

        glm::mat4 transform = glm::mat4(1.0f);
        //构建绕Z轴旋转矩阵
        transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
        //平移矩阵
        // transform = glm::translate(transform, glm::vec3(0.1f, -0.1f, 0.0f)); // switched the order 
        GLuint Trans = glGetUniformLocation(shaderProgram, "trans");
        glUniformMatrix4fv(Trans, 1, GL_FALSE, glm::value_ptr(transform));

运行效果

(实际效果就是逆时针旋转,动画上传太麻烦…)

坐标系的变换

为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。我们的顶点坐标起始于局部空间(Local Space),在这里它称为局部坐标(Local Coordinate),它在之后会变为世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)的形式结束。下面的这张图展示了整个流程以及各个变换过程做了什么:

在这里插入图片描述

1、局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标。
2、下一步是将局部坐标变换为世界空间坐标,世界空间坐标是处于一个更大的空间范围的。这些坐标相对于世界的全局原点,它们会和其它物体一起相对于世界的原点进行摆放。
3、接下来我们将世界坐标变换为观察空间坐标,使得每个坐标都是从摄像机或者说观察者的角度进行观察的。
4、坐标到达观察空间之后,我们需要将其投影到裁剪坐标。裁剪坐标会被处理至-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上。
5、最后,我们将裁剪坐标变换为屏幕坐标,我们将使用一个叫做视口变换(Viewport Transform)的过程。视口变换将位于-1.0到1.0范围的坐标变换到由glViewport函数所定义的坐标范围内。最后变换出来的坐标将会送到光栅器,将其转化为片段。

简单来说主要就是:局部空间->世界空间( M )->观察空间( V )->裁剪空间( P )的变换。

具体含义请详细阅读:坐标系统

在“坐标的变换”中我们实现了一个图片的Z轴旋转,下面根据上述MVP的讲解,我们实现一个图片绕X轴旋转的动画。

VertexShader.glsl

#version 330 core
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec2 aTexture;
uniform mat4 projection;
uniform mat4 Mtrans;
uniform mat4 Vtrans;
uniform mat4 Ptrans;
out vec2 ourTexture;

void main()
{
    vec4 ndcPos = projection * vec4(aPosition,1.0f);
    gl_Position = Ptrans * Vtrans * Mtrans * ndcPos;
    ourTexture  = aTexture;
}

main.cpp

#include <iostream>
#include <string>
#include "glew.h"
#include "glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"


#include "log.h"
#include "GlslDealConfig.h"

// 顶点数据
GLfloat vertices_1[] = {
    0.0f, 1000.0f, 0.0f,
    0.0f, 0.0f, 0.0f,
    1000.0f, 0.0f, 0.0f,
    1000.0f, 1000.0f, 0.0f
};

GLfloat vertices_2[] = {
    0.0f, 1.0f,
    0.0f, 0.0f,
    1.0f, 0.0f,
    1.0f, 1.0f
};

GLint indices[] = {
    0, 1, 2,
    0, 2, 3
};

// 主函数
int main() {
    GlslDealConfig glslConfig;

    // 初始化 GLFW
    if (!glfwInit()) {
        LOGE("Failed to initialize GLFW");
        return -1;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(1000, 1000, "Texture", nullptr, nullptr);
    if (!window) {
        LOGE("Failed to create GLFW window");
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    GLenum err = glewInit();
    if (err != GLEW_OK) {
        LOGE("Failed to initialize GLEW: %s", reinterpret_cast<const char*>(glewGetErrorString(err)));
        return -1;
    }

    glfwSwapInterval(1);

    // 加载着色器
    std::string vertexShaderCode   = glslConfig.ReadGlslFile("/home/ryan/Rendering/demo/glsl/Trans/VertexShader.glsl");
    std::string fragmentShaderCode = glslConfig.ReadGlslFile("/home/ryan/Rendering/demo/glsl/Trans/FragmentShader.glsl");

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    const GLchar* vShaderSource = vertexShaderCode.c_str();
    const GLchar* fShaderSource = fragmentShaderCode.c_str();

    glShaderSource(vertexShader, 1, &vShaderSource, nullptr);
    glShaderSource(fragmentShader, 1, &fShaderSource, nullptr);

    glCompileShader(vertexShader);
    glCompileShader(fragmentShader);
    glslConfig.CheckShaderCompileV(vertexShader);
    glslConfig.CheckShaderCompileF(fragmentShader);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glslConfig.CheckProgmaLinkStatus(shaderProgram);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 配置 VAO, VBO, EBO
    GLuint VAO, VBO[2], EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(2, VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_1), vertices_1, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_2), vertices_2, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (void*)0);
    glEnableVertexAttribArray(1);

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

    // 加载纹理
    GLuint texture[2];
    texture[0] = glslConfig.loadTexture("/home/ryan/Rendering/demo/resource/brickwall.jpg",   GL_RGB);
    texture[1] = glslConfig.loadTexture("/home/ryan/Rendering/demo/resource/awesomeface.png", GL_RGBA);

    // 设置投影矩阵
    glm::mat4 projection = glm::mat4(1.0f);
    projection = glm::ortho(0.0f, 1000.0f, 0.0f, 1000.0f, -1.0f, 1.0f);
    glUseProgram(shaderProgram);
    GLuint projLoc = glGetUniformLocation(shaderProgram, "projection");
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    // 激活纹理单元
    glActiveTexture(GL_TEXTURE3);
    GLuint textureLocation = glGetUniformLocation(shaderProgram, "textureClass");
    glUniform1i(textureLocation, 3);

    glActiveTexture(GL_TEXTURE6);
    GLuint textureLocation2 = glGetUniformLocation(shaderProgram, "textureClass2");
    glUniform1i(textureLocation2, 6);

    // 渲染循环
    while (!glfwWindowShouldClose(window)) {
        glViewport(0, 0, 1000, 1000);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

        glActiveTexture(GL_TEXTURE3);
        glBindTexture(GL_TEXTURE_2D, texture[0]);

        glActiveTexture(GL_TEXTURE6);
        glBindTexture(GL_TEXTURE_2D, texture[1]);

        //此例子视点只在Z轴移动


        glm::mat4 Mmatrix    = glm::mat4(1.0f);
        glm::mat4 Vmatrix    = glm::mat4(1.0f);
        glm::mat4 Pmatrix    = glm::mat4(1.0f);

        Mmatrix = glm::rotate(Mmatrix,(float)glfwGetTime(), glm::vec3(1.0f, 0.0f, 0.0f));
        Vmatrix = glm::translate(Vmatrix, glm::vec3(0.0f, 0.0f, -3.0f));
        Pmatrix = glm::perspective(glm::radians(90.0f), 1000.0f/1000.0f, 0.1f, 100.0f);

        GLuint TransM = glGetUniformLocation(shaderProgram, "Mtrans");
        GLuint TransV = glGetUniformLocation(shaderProgram, "Vtrans");
        GLuint TransP = glGetUniformLocation(shaderProgram, "Ptrans");
        glUniformMatrix4fv(TransM, 1, GL_FALSE, glm::value_ptr(Mmatrix));
        glUniformMatrix4fv(TransV, 1, GL_FALSE, glm::value_ptr(Vmatrix));
        glUniformMatrix4fv(TransP, 1, GL_FALSE, glm::value_ptr(Pmatrix));


        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glBindVertexArray(0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glBindTexture(GL_TEXTURE_2D, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // 清理资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(2, VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);

    glfwTerminate();
    return 0;
}

主要部分代码
在这里插入图片描述

实现效果
在这里插入图片描述3D效果
下面看一3D表示的效果,不需要修改着色器。
main.cpp

#include <iostream>
#include <string>
#include "glew.h"
#include "glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"


#include "log.h"
#include "GlslDealConfig.h"


GLfloat 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.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,  0.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,  1.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,  0.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,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
};

// 主函数
int main() {
    GlslDealConfig glslConfig;

    // 初始化 GLFW
    if (!glfwInit()) {
        LOGE("Failed to initialize GLFW");
        return -1;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(1000, 1000, "3D Demo", nullptr, nullptr);
    if (!window) {
        LOGE("Failed to create GLFW window");
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    GLenum err = glewInit();
    if (err != GLEW_OK) {
        LOGE("Failed to initialize GLEW: %s", reinterpret_cast<const char*>(glewGetErrorString(err)));
        return -1;
    }

    glfwSwapInterval(1);

    // 加载着色器
    std::string vertexShaderCode   = glslConfig.ReadGlslFile("/home/ryan/Rendering/demo/glsl/Trans/VertexShader.glsl");
    std::string fragmentShaderCode = glslConfig.ReadGlslFile("/home/ryan/Rendering/demo/glsl/Trans/FragmentShader.glsl");

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    const GLchar* vShaderSource = vertexShaderCode.c_str();
    const GLchar* fShaderSource = fragmentShaderCode.c_str();

    glShaderSource(vertexShader, 1, &vShaderSource, nullptr);
    glShaderSource(fragmentShader, 1, &fShaderSource, nullptr);

    glCompileShader(vertexShader);
    glCompileShader(fragmentShader);
    glslConfig.CheckShaderCompileV(vertexShader);
    glslConfig.CheckShaderCompileF(fragmentShader);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glslConfig.CheckProgmaLinkStatus(shaderProgram);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 配置 VAO, VBO, EBO
    GLuint VAO, VBO[2];
    glGenVertexArrays(1, &VAO);
    glGenBuffers(2, VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    // 加载纹理
    GLuint texture[2];
    texture[0] = glslConfig.loadTexture("/home/ryan/Rendering/demo/resource/brickwall.jpg",   GL_RGB);
    texture[1] = glslConfig.loadTexture("/home/ryan/Rendering/demo/resource/awesomeface.png", GL_RGBA);

    // 设置投影矩阵
    glm::mat4 projection = glm::mat4(1.0f);
    // projection = glm::ortho(0.0f, 1000.0f, 0.0f, 1000.0f, -1.0f, 1.0f);
    glUseProgram(shaderProgram);
    GLuint projLoc = glGetUniformLocation(shaderProgram, "projection");
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    // 激活纹理单元
    glActiveTexture(GL_TEXTURE3);
    GLuint textureLocation = glGetUniformLocation(shaderProgram, "textureClass");
    glUniform1i(textureLocation, 3);

    glActiveTexture(GL_TEXTURE6);
    GLuint textureLocation2 = glGetUniformLocation(shaderProgram, "textureClass2");
    glUniform1i(textureLocation2, 6);

    glEnable(GL_DEPTH_TEST);

    // 渲染循环
    while (!glfwWindowShouldClose(window))
    {
        glViewport(0, 0, 1000, 1000);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);


        glActiveTexture(GL_TEXTURE3);
        glBindTexture(GL_TEXTURE_2D, texture[0]);

        glActiveTexture(GL_TEXTURE6);
        glBindTexture(GL_TEXTURE_2D, texture[1]);

        //此例子视点只在Z轴移动


        glm::mat4 Mmatrix    = glm::mat4(1.0f);
        glm::mat4 Vmatrix    = glm::mat4(1.0f);
        glm::mat4 Pmatrix    = glm::mat4(1.0f);

        Mmatrix = glm::rotate(Mmatrix,(float)glfwGetTime(), glm::vec3(1.0f, 1.0f, 0.0f));
        Vmatrix = glm::translate(Vmatrix, glm::vec3(0.0f, 0.0f, -3.0f));
        Pmatrix = glm::perspective(glm::radians(45.0f), 1000.0f/1000.0f, 0.1f, 100.0f);

        GLuint TransM = glGetUniformLocation(shaderProgram, "Mtrans");
        GLuint TransV = glGetUniformLocation(shaderProgram, "Vtrans");
        GLuint TransP = glGetUniformLocation(shaderProgram, "Ptrans");
        glUniformMatrix4fv(TransM, 1, GL_FALSE, glm::value_ptr(Mmatrix));
        glUniformMatrix4fv(TransV, 1, GL_FALSE, glm::value_ptr(Vmatrix));
        glUniformMatrix4fv(TransP, 1, GL_FALSE, glm::value_ptr(Pmatrix));


        glDrawArrays(GL_TRIANGLES, 0, 36);

        glBindVertexArray(0);
        glBindTexture(GL_TEXTURE_2D, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // 清理资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(2, VBO);
    glDeleteProgram(shaderProgram);

    glfwTerminate();
    return 0;
}

运行效果
在这里插入图片描述感谢阅读^ _ ^
如有问题欢迎评论区交流指正,如需要对应源码资源可私聊我。


http://www.kler.cn/news/308240.html

相关文章:

  • 文献多\bibliographystyle和文献少\begin{thebibliography}
  • 【JAVA】数据脱敏技术(对称加密算法、非对称加密算法、哈希算法、消息认证码(MAC)算法、密钥交换算法)使用方法
  • JUC学习笔记(二)
  • sed编辑器与awk的用法
  • 0917np.power()
  • 径向基函数神经网络RBFNN案例实操
  • 人工智能GPT____豆包使用的一些初步探索步骤 体验不一样的工作
  • 3GPP祝大家中秋快乐!!!
  • 数据结构,栈,队列(线性表实现)
  • 云服务与虚拟主机:数字时代的网络托管选择
  • 光华里社区“电亮生活”行动:智能科技携手志愿温情,老旧小区焕发新生机
  • 在docker环境下启动php的注意事项-docker完整挂载php目录、在Docker查看容器完整启动命令以及mysql ERROR 2059问题
  • win+linux平台C语言获取进程的线程数量
  • LeetCode 815.公交路线(BFS广搜 + 建图)(中秋快乐啊)
  • 从零到一:构建你的第一个AI项目(实战教程)
  • Python 数学建模——Pearson/Spearman 相关系数
  • easy-es动态索引支持
  • 数据库的约束
  • Java4----String
  • 【新片场-注册安全分析报告-无验证方式导致安全隐患】
  • c++元编程tookit类
  • 前端 + 接口请求实现 vue 动态路由
  • 惬意享受阅读,优雅的微信公众号订阅方式,极空间部署『WeWe RSS』
  • Golang | Leetcode Golang题解之第402题移掉K位数字
  • 无人机之防风性能篇
  • deepinlinux-v23用deepinunioncode初始c例子
  • 小程序开发设计-第一个小程序:注册小程序开发账号②
  • godot——tween_method插值,如何处理多参数?参数位置怎么调?
  • oracle 使用 PL/SQL Developer创建表并插入单条、多条数据
  • 【程序人生】《把时间当做朋友》李笑来思维导图