首页 > 其他分享 >opengl日记12-opengl坐标系统

opengl日记12-opengl坐标系统

时间:2024-03-21 16:59:05浏览次数:28  
标签:mat4 12 glm opengl 变换 矩阵 坐标 include 日记

文章目录


在这里插入图片描述

环境

  • 系统:ubuntu20.04
  • opengl版本:4.6
  • glfw版本:3.3
  • glad版本:4.6
  • cmake版本:3.16.3
  • gcc版本:10.3.0

在<opengl学习日记11-opengl的transformtions变换示例>的基础上,进行修改,实现坐标系统变换效果。

代码

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(CoordinateSystems )

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)


find_package(glfw3 REQUIRED)
message("PROJECT_NAME:${PROJECT_NAME}")
file(GLOB project_file glad.c main.cpp  stb_image.h stbimage.h)

add_executable(${PROJECT_NAME} ${project_file})

target_link_libraries(${PROJECT_NAME}
    -lglfw
    -lGL
    -lm
    -lXrandr
    -lX11
    -lpthread
    -ldl
    )

vertexShaderSource.vs

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;


out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
        gl_Position = projection * view * model * vec4(aPos, 1.0f);
//        gl_Position = vec4(aPos, 1.0);

        TexCoord = vec2(aTexCoord.x,1.0 - aTexCoord.y);
}

main.cpp

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


#include "stbimage.h"

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

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

//定义窗口大小
int SCR_WIDTH = 800;
int SCR_HEIGHT = 600;

std::string readFile(const std::string filename)
{
    std::string data;
    data = readFile(filename.c_str());
    return data;
}

std::string readFile(const char* filename)
{
    std::string data;
    std::ifstream infile;
    infile.open(filename);
    std::stringstream neirong;
    neirong << infile.rdbuf();
    infile.close();
    data = neirong.str();
    return data;
}

int main()
{
    std::cout << "Hello World!" << std::endl;

    std::cout << "初始化" << std::endl;
    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, "transformtions", NULL, NULL);
    if (window == NULL) {
        std::cout << "创建窗口失败" << std::endl;
        return -1;
    }

    glfwMakeContextCurrent(window);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "初始化glad失败" << std::endl;
        return -1;
    }

    std::cout << "顶点定义,VAO,VBO,EBO" << std::endl;
    float vertices[] = {
        0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
        0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
        -0.5f, 0.5f, 0.0f, 0.0f, 1.0f
    };

    //索引缓冲区
    unsigned int indices[] = { 0, 1, 3,
        1, 2, 3 };

    unsigned int VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

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

    //定位点关系
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    std::cout << "着色器定义" << std::endl;
    std::cout << "着色器定义:顶点着色器" << std::endl;
    std::string vertexShaderSource = readFile("vertexShaderSource.vs");
    const char* vertexShaderSourceCtr = vertexShaderSource.c_str();
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSourceCtr, NULL);
    glCompileShader(vertexShader);

    int success;
    char infolog[512] = { 0 };
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"
                  << infolog << std::endl;
    }

    std::cout << "着色器定义:片段着色器" << std::endl;
    std::string fragmentShaderSource = readFile("fragmentShaderSource.fs");
    const char* fragmentShaderSourceCtr = fragmentShaderSource.c_str();
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSourceCtr, NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"
                  << infolog << std::endl;
    }

    std::cout << "着色器定义:启用着色器程序" << std::endl;
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"
                  << infolog << std::endl;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    std::cout << "纹理定义" << std::endl;
    unsigned int texture1;
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);

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

    stbi_set_flip_vertically_on_load(true);
    std::cout << "读取纹理图片" << std::endl;
    int width, height, nrChannels;
    unsigned char* texturesData = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
    if (texturesData) {
        //绑定和纹理图片数据结合
        glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGB,
            width,
            height,
            0,
            GL_RGB,
            GL_UNSIGNED_BYTE,
            texturesData);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "读取图片数据错误" << std::endl;
    }
    stbi_image_free(texturesData);

    std::cout << "纹理定义2" << std::endl;
    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);

    std::cout << "读取纹理图片" << std::endl;
    //        int width, height, nrChannels;
    texturesData = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
    if (texturesData) {
        //绑定和纹理图片数据结合
        glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGB,
            width,
            height,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            texturesData);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "读取图片数据错误" << std::endl;
    }
    stbi_image_free(texturesData);

    glUseProgram(shaderProgram);
    glUniform1i(glGetUniformLocation((GLuint)shaderProgram, "texture1"), 0);
    glUniform1i(glGetUniformLocation((GLuint)shaderProgram, "texture2"), 1);

    std::cout << "绘制" << std::endl;
    while (!glfwWindowShouldClose(window)) {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);

        glUseProgram(shaderProgram);


        glm::mat4 model = glm::mat4(1.0f);
        model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));

        glm::mat4 view = glm::mat4(1.0f);
        view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.f));

        glm::mat4 projection = glm::mat4(1.0f);
        projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH /(float) SCR_HEIGHT, 0.1f, 100.0f);

        unsigned int transformLoc = glGetUniformLocation(shaderProgram, "model");
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(model));

        unsigned int viewLoc = glGetUniformLocation(shaderProgram, "view");
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

        unsigned int projectionLoc = glGetUniformLocation(shaderProgram, "projection");
        glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));


        glBindVertexArray(VAO);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid*)0);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    std::cout << "内存释放" << std::endl;
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);
    glfwTerminate();

    return 0;
}

总结

  1. 之前注意到需要把下面两个头文件引入放在头文件的最前端,否则报错,今天发现,不仅这两个头文件需要放在最前端,而且引入顺序也不能更改,否则同样会报错,有函数找不到
#include <glad/glad.h>
#include <GLFW/glfw3.h>
  1. 世界空间的变换(模型矩阵)
物体的坐标将会从局部变换到世界空间;该变换是由模型矩阵(Model Matrix)实现的。

模型矩阵是一种变换矩阵,它能通过对物体进行位移、缩放、旋转来将它置于它本应该在的位置或朝向。

所以,局部空间到世界空间的变换可以用以下glm::rotate函数实现,只要最后得到一个mat4类型的结构就可以

glm::mat4 model;
model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));

所以,这里我们可以引申一下,就是位移、缩放、旋转这三个功能函数都可以得到mat4结构,即将局部空间转换为世界空间

  1. 观察空间变换(观察矩阵)
观察空间经常被人们称之OpenGL的摄像机(Camera)(所以有时也称为摄像机空间(Camera Space)或视觉空间(Eye Space))。观察空间是将世界空间坐标转化为用户视野前方的坐标而产生的结果。

这通常是由一系列的位移和旋转的组合来完成,平移/旋转场景从而使得特定的对象被变换到摄像机的前方。这些组合在一起的变换通常存储在一个观察矩阵(View Matrix)里,它被用来将世界坐标变换到观察空间。

通过以上解释,我理解的是观察空间的变换也是由位移和旋转,平移/旋转这些变换来的,所以这些个函数也可以用作观察空间的变换

glm::mat4 view;
// 注意,我们将矩阵向我们要进行移动场景的反方向移动。
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
  1. 裁剪空间(投影矩阵)
在一个顶点着色器运行的最后,OpenGL期望所有的坐标都能落在一个特定的范围内,且任何在这个范围之外的点都应该被裁剪掉(Clipped)。被裁剪掉的坐标就会被忽略,所以剩下的坐标就将变为屏幕上可见的片段。这也就是裁剪空间(Clip Space)名字的由来。

投影矩阵(Projection Matrix),它指定了一个范围的坐标

透视投影glm创建函数为

glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
  1. 顶点坐标变换为裁剪坐标的公式
{V}_{clip} = M_{projection} ⋅ M_{view} ⋅ M_{model} ⋅ V_{local}

注意 矩阵运算的顺序是相反的(记住我们需要从右往左阅读矩阵的乘法)。

最后的顶点应该被赋值到顶点着色器中的gl_Position,OpenGL将会自动进行透视除法和裁剪。

标签:mat4,12,glm,opengl,变换,矩阵,坐标,include,日记
From: https://blog.csdn.net/bootleader/article/details/136913837

相关文章

  • opengl日记7-ubuntu20.04开发环境opengl拓展glfw和glad环境搭建
    文章目录ubuntu中安装opengl核心环境安装glfw安装glad测试验证程序vscode的task.json配置如下note参考ubuntu中安装opengl核心环境可执行如下命令进行整体安装:sudoapt-getinstalllibgl1-mesa-dev*或者单独安装1、提供编译程序必须软件包的列表信息sudoapt......
  • 12 vi编辑器
    介绍vi\vim是visualinterface的简称,是Linux中最经典的文本编辑器命令行下对文本文件进行编辑的绝佳选择vim是vi的加强版本,兼容vi的所有指令,不仅能编辑文本,而且还具有shell程序编辑的功能,可以不同颜色的字体来辨别语法的正确性,极大方便了程序的设计和编辑性。vi\vim......
  • H12-811题库(带解析,亲测高分可以通过)
    大家可以直接点赞+关注后,加作者微信(备注“CSDN”)就可以获取,微信在文章最后!808、[单选题]某公司网管要进行网络规划的时候,能够要让PC1访问PC2的数据包从G0/0/0口走(图上G0/0/2)。PC2访问PC1的数据包从G0/0/4口走(图上G0/0/0)。()A10.0.12.5255.255.255.25511.0.12.610.0......
  • 解决 [FATAL] plugin/loop: Loop (127.0.0.1:49443 -> :53) detected for zone "." 报
    问题背景:这个是安装k8s时报的错,安装使用的是ubuntu系统,当安装到coredns时报如下错 解决方法:查找了一番资料,得出结论这个算是ubuntu和k8scoredns安装的一个兼容性问题,不过很好解决,参照coredns官方文档就可以~首先贴出官网:https://coredns.io/plugins/loop/#troubleshooting......
  • 鸿蒙 HarmonyOS学习日记 Day 1 安装与入门
    提示:学习本课程应该有一定的前端基础文章目录一、学前准备1、了解官网2、进行下载3、初始化4、项目创建二、ArkTS基础入门1、认识和存储数据2、数组3、函数4、箭头函数5、对象6、联合类型7、枚举类型一、学前准备1、了解官网https://www.openharmony.cn/mainP......
  • 鸿蒙 HarmonyOS学习日记 Day 2 界面开发、布局
    文章目录一、界面开发1、代码书写方式2、界面开发-布局思路3、组件的属性方法4、文字溢出省略号、行高5、Image图片组件6、输入框与按钮四、综合实战-华为登录五、svg图标六、布局元素的组成二、单位问题一、界面开发1、代码书写方式1、代码块在build()方法中书......
  • 【数据结构和算法初阶(C语言)】二叉树的顺序结构--堆的实现/堆排序/topk问题详解---二
     目录 ​编辑1.二叉树的顺序结构及实现1.1二叉树的顺序结构2堆的概念及结构3堆的实现3.1堆的代码定义3.2堆插入数据3.3打印堆数据3.4堆的数据的删除3.5获取根部数据3.6判断堆是否为空3.7堆的销毁 4.建堆以及堆排序 4.1堆排序---是一种选择排序4.2升......
  • 中考英语首字母快速突破012-2021上海青浦英语二模-Earth Hour: A Global Call for Env
    PDF格式公众号回复关键字:ZKSZM012原文​WhatisEarthHour?​EarthHourisorganizedbytheWorldWideFundforNature(WWF)andit’sabigeventusuallyattheendofMarcheveryyear.Onthisevening,people‘godark’-thatis,switcho......
  • 【漏洞复现】Progress Kemp LoadMaster 命令注入漏洞(CVE-2024-1212)
    0x01产品简介ProgressKempLoadMaster是一款高性能的应用交付控制器,具有可扩展性,支持实体硬件和虚拟机的负载均衡。它提供了当今应用服务所需的各种功能,包括深度用户验证、资安防护(如WAF/IPS/DDoS防护)以及零信任架构服务。这款控制器旨在为各种规模的企业和单位提供出色的负......
  • 【无标题】计算机图形学OpenGL基础
    一、OpenGL的主要功能模型绘制模型观察颜色模式光照应用图像效果增强位图和图像处理纹理映射实时动画交互技术二、OpenGL的绘制流程----------工作方式**一个完整的窗口系统的OpenGL图形处理系统的结构为:最底层为图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenG......