OpenGL 变换

官网学习链接

纹理 - LearnOpenGL CN变换 - LearnOpenGL CN

理论总结:

向量与标量相加减乘除
向量的长度计算
向量取反
向量单位化
向量与向量相加减
向量点乘
向量叉乘
矩阵介绍
线性变换和仿射变换行
主序和列主序
矩阵与标量相加减和数乘

计算虽然复杂,但是我们使用计算机计算,调库传参数足以。

 GLM

GLM是OpenGL Mathematics的缩写,它是一个只有头文件的库,也就是说我们只需包含对应的头文件就行了,不用链接和编译。GLM可以在它们的网站上下载。把头文件的根目录复制到你的includes文件夹,然后你就可以使用这个库了。

建议下载0.99版本起

OpenGL 数学 --- OpenGL Mathematics

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

 代码实践

我们只需要定义一个矩阵,旋转 缩放 位移的操作,通过矩阵来进行。
可以把矩阵当作状态,设置旋转 缩放 位移,最后应用。
举个例子:
//使用案例  把mat当作属性 复制到mat4的uniform变量中
glm::mat4 trans = glm::mat4(1.0f);
//设置旋转 缩放 位移
trans = glm::translate(trans, glm::vec3(-0.3f));
trans = glm::rotate(trans, glm::radians((float)factor *100 ), glm::vec3(0.0f, 0.0f, 1.0f));
trans = glm::scale(trans, glm::vec3(0.5f, 0.5f, 0.5f));
//应用
ourShader.setMat4("transform", trans);


综合实践

/*
坐标转换
https://learnopengl-cn.github.io/01%20Getting%20started/07%20Transformations/#_20

向量+-* × /    矩阵的+- *

*/

#include"Shader.h"

#define STB_IMAGE_IMPLEMENTATION
#include"stb_image.h"

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

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include<cmath>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
// 定义顶点数组
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
};
int main(int argc, char* argv[])
{

    glfwInit();
    // 设置主要和次要版本
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建窗口对象
    GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    // 设置视口
    glViewport(0, 0, 800, 600);
    glEnable(GL_PROGRAM_POINT_SIZE);

    // 注册窗口变化监听
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    Shader ourShader("./vertex.glsl", "./fragment.glsl");



    // 创建缓冲对象
    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    // 绑定VAO缓冲对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    // 填充EBO数据
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    // 绑定VBO缓对象
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // 填充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);
    // 设置顶点颜色属性指针
    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);


    glBindVertexArray(0);

    // 设置线框绘制模式
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    // 图像y轴翻转
    stbi_set_flip_vertically_on_load(true);











    // 创建纹理对象
    unsigned int texture;
    // 绑定纹理
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    // 设置环绕和过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    //加载纹理
    int width, height, nrChannels;
    unsigned char* data = stbi_load("./container.jpg", &width, &height, &nrChannels, 0);
    if (!data)
    {
        std::cout << "Failed to load texture" << std::endl;
        return -1;
    }

    // 加载纹理数据
    glTexImage2D(GL_TEXTURE_2D      //纹理目标
        , 0                 //纹理指定多级渐远纹理的级别,如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0,也就是基本级别
        , GL_RGB            //告诉OpenGL我们希望把纹理储存为何种格式。
        , width             //纹理图像的宽度
        , height            //纹理图像的高度
        , 0                 //历史遗留参数,设置为0
        , GL_RGB            //纹理图像的格式
        , GL_UNSIGNED_BYTE  //纹理图像的数据类型
        , data              //真正的图像数据
    );
    // 生成多级渐远纹理
    glGenerateMipmap(GL_TEXTURE_2D);

    // 释放纹理数据
    stbi_image_free(data);









    // 创建纹理对象2
    unsigned int texture2;

    glGenTextures(1, &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_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 图像y轴翻转
    stbi_set_flip_vertically_on_load(true);
    //加载纹理
    data = stbi_load("./awesomeface.png", &width, &height, &nrChannels, 0);
    if (!data)
    {
        std::cout << "Failed to load texture" << std::endl;
        return -1;
    }

    // 加载纹理数据
    glTexImage2D(GL_TEXTURE_2D      //纹理目标
        , 0                 //纹理指定多级渐远纹理的级别,如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0,也就是基本级别
        , GL_RGBA            //告诉OpenGL我们希望把纹理储存为何种格式。
        , width             //纹理图像的宽度
        , height            //纹理图像的高度
        , 0                 //历史遗留参数,设置为0
        , GL_RGBA            //纹理图像的格式
        , GL_UNSIGNED_BYTE  //纹理图像的数据类型
        , data              //真正的图像数据
    );
    // 生成多级渐远纹理
    glGenerateMipmap(GL_TEXTURE_2D);

    // 释放纹理数据
    stbi_image_free(data);


    //激活和绑定纹理
    ourShader.use();
    ourShader.setInt("ourTexture", 0);
    ourShader.setInt("ourTexture2", 1);


   
    glm::vec4 pos = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
    //把一个向量(1, 0, 0)位移(1, 1, 0)个单位
    glm::mat4 trans = glm::mat4(1.0f);
    std::cout<<"start position:" << pos.x << " " << pos.y << " " << pos.z << std::endl;
    trans = glm::translate(trans, glm::vec3(0.1f, 0.1f, 0.0f));
    pos = trans * pos;
    std::cout << pos.x << " " << pos.y << " " << pos.z << std::endl;

    //旋转90度

    trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    pos = trans * pos;
    std::cout << pos.x << " " << pos.y << " " << pos.z << std::endl;

    //缩放0.5
    trans = glm::scale(trans, glm::vec3(0.5f, 0.5f, 0.5f));
    pos = trans * pos;
    std::cout << pos.x << " " << pos.y << " " << pos.z << std::endl;

    int factor = 0;
    
    

    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        // 渲染指令
        // ...
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        /*ourShader.use();
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);*/
        //激活一个纹理单元
        glActiveTexture(GL_TEXTURE0);
        //将texture绑定到当前激活的纹理单元上
        glBindTexture(GL_TEXTURE_2D, texture);
        //激活另一个纹理单元
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);

        factor = glfwGetTime();
        ourShader.setFloat("factor", factor);
        //使用案例  把mat当作属性 复制到mat4的uniform变量中
        glm::mat4 trans = glm::mat4(1.0f);
        //设置旋转和t
        trans = glm::translate(trans, glm::vec3(-0.3f));
        trans = glm::rotate(trans, glm::radians((float)factor *100 ), glm::vec3(0.0f, 0.0f, 1.0f));
        trans = glm::scale(trans, glm::vec3(0.5f, 0.5f, 0.5f));
        //应用
        ourShader.setMat4("transform", trans);
        // get matrix's uniform location and set matrix 
        ourShader.use();
       
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        ourShader.setMat4("transform", trans);


        // 第二个案例
        // get matrix's uniform location and set matrix
        ourShader.use();
        trans = glm::mat4(1.0f);
        trans = glm::translate(trans, glm::vec3(0.3f));
        trans = glm::scale(trans, glm::vec3(0.5f, 0.5f, 0.5f));
        ourShader.setMat4("transform", trans);


        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    glfwTerminate();
    return 0;
}

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

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

源代码

jbj62/OpenGL-demo

学习资料分享

0voice · GitHub

OpenGL是一种图形渲染API,可以进行图形变换,让图形在屏幕上进行平移、旋转、缩放等操作。下面以一个简单的OpenGL变换实例来说明。 在OpenGL中,变换是通过矩阵操作来实现的。首先,我们需要定义一个模型视图投影矩阵(Model-View-Projection matrix),它包含了模型坐标到屏幕坐标的转换。可以使用OpenGL提供的函数来创建和设置这个矩阵。 接下来,我们可以使用OpenGL提供的变换函数来进行变换操作。比如,使用glTranslatef函数进行平移、glRotatef函数进行旋转、glScalef函数进行缩放等。这些函数的参数确定了变换的程度和方向。 假设我们有一个矩形需要进行平移和旋转变换。我们可以先用glMatrixMode函数选择投影矩阵堆栈,然后使用glLoadIdentity函数将矩阵重置为单位矩阵。接着,使用glTranslatef函数进行平移,把矩形移动到目标位置。最后,使用glRotatef函数进行旋转,让矩形沿着某个轴旋转。 完成变换后,可以调用OpenGL提供的绘制函数来将变换后的图形绘制到屏幕上。需要注意的是,在绘制时,先执行变换操作,再进行绘制,以确保正确的变换效果。 在整个变换过程中,需要确保正确地设置OpenGL的状态和变换矩阵,并且按照正确的顺序进行变换操作。只有在正确的环境中进行变换操作,才能得到预期的结果。 总结来说,OpenGL变换实例通过矩阵操作和变换函数,可以实现图形的平移、旋转、缩放等效果。在使用时,需要设置正确的变换矩阵和状态,并按照正确的顺序进行变换操作。这样,就可以在屏幕上绘制出变换后的图形。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值