使用 OpenGL 渲染会旋转 会变色的三角形(LearnOpenGL P3)

news2024/12/22 16:53:18

文章目录

    • 前言
    • 代码

前言

本文参考文献,侵删!LearnOpenGL - 你好,三角形

本文将假设您完成了 OpenGL 的配置,并且使用 VAO、VBO 渲染图形

由于时间问题,代码的详细讲解将在几日内给出~
在这里插入图片描述

代码

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

// 窗口大小
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;

// 顶点着色器源码
const char* vertexShaderSource = R"(
    #version 330 core
    layout (location = 0) in vec3 aPos;
    uniform float rotation;

    mat3 getRotationMatrix(float angle) {
        float s = sin(angle);
        float c = cos(angle);
        return mat3(
            c, -s, 0.0,
            s, c, 0.0,
            0.0, 0.0, 1.0
        );
    }

    void main()
    {
        mat3 rotationMatrix = getRotationMatrix(rotation);
        gl_Position = vec4(rotationMatrix * aPos, 1.0);
    }
)";

// 片段着色器源码
const char* fragmentShaderSource = R"(
    #version 330 core
    out vec4 FragColor;
    uniform float time; 
    void main()
    {
        float red = sin(time);
        float green = cos(time);
        float blue = 0.5 + 0.5 * sin(2.0 * time);

        FragColor = vec4(red, green, blue, 1.0);
    }
)";

int main() {
    // 初始化GLFW
    if (!glfwInit()) {
        std::cout << "GLFW initialization failed" << std::endl;
        return -1;
    }

    // 配置GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建窗口对象
    GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Triangle", nullptr, nullptr);
    if (window == nullptr) {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    // 将窗口的上下文设置为当前线程的主上下文
    glfwMakeContextCurrent(window);

    // 初始化GLAD
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 创建顶点着色器对象
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    // 检查顶点着色器是否编译成功
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        std::cout << "Failed to compile vertex shader:\n" << infoLog << std::endl;
        return -1;
    }

    // 创建片段着色器对象
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    // 检查片段着色器是否编译成功
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        std::cout << "Failed to compile fragment shader:\n" << infoLog << std::endl;
        return -1;
    }

    // 创建着色器程序对象
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // 检查着色器程序是否链接成功
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        std::cout << "Failed to link shader program:\n" << infoLog << std::endl;
        return -1;
    }

    // 删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 设置顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f, 0.5f, 0.0f,
        0.0f,  0.0f, 0.0f  // 原点坐标
    };

    // 创建顶点缓冲对象(VBO)和顶点数组对象(VAO)
    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    // 绑定VAO和VBO
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 设置顶点属性指针
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // 解绑VAO和VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // 渲染循环
    while (!glfwWindowShouldClose(window)) {
        // 处理输入事件
        glfwPollEvents();

        // 清空颜色缓冲
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 使用着色器程序
        glUseProgram(shaderProgram);

        // 获取当前时间
        float time = glfwGetTime();
        float rotation = time;
        int rotationLocation = glGetUniformLocation(shaderProgram, "rotation");
        glUniform1f(rotationLocation, rotation);
        
        int timeLoadtion = glGetUniformLocation(shaderProgram, "time");
        glUniform1f(timeLoadtion, time);

        // 绑定VAO
        glBindVertexArray(VAO);
        glDrawArrays(GL_POINTS, 3, 1);  // 从索引3开始绘制一个点

        // 绘制三角形
        glDrawArrays(GL_TRIANGLES, 0, 3);

        // 解绑VAO
        glBindVertexArray(0);

        // 交换缓冲区
        glfwSwapBuffers(window);
    }

    // 删除VAO和VBO
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    // 终止GLFW
    glfwTerminate();

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1121214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UML类图中各箭头表示总结

UML类图中各箭头表示总结 1、泛化2、实现3、依赖4、关联5、聚合6、组合 在UML类图中&#xff0c;箭头关系是用来表示类之间的关系的。箭头关系的种类有以下几种&#xff1a; 1、泛化 泛化&#xff1a;表示类之间的继承关系。箭头从子类指向父类。箭头&#xff1a;实线空心三角…

【计算机网络】UDP/TCP协议

文章目录 :peach:1 UDP协议:peach:1.1 :apple:UDP协议端格式:apple:1.2 :apple:UDP的特点:apple:1.3 :apple:UDP的缓冲区:apple:1.4 :apple:UDP使用注意事项:apple:1.5 :apple:基于UDP的应用层协议:apple: 2 :peach:TCP协议:peach:2.1 :apple:TCP协议端格式:apple:2.2 :apple:确…

《windows核心编程》第3章 内核对象

一、内核对象简介 1.1 内核对象有哪些 令牌对象 token、事件对象 Event、文件对象 File、文件映射对象 Mapping_File、线程对象 Thread、时钟对象 Timer、线程池对象 ThreadPool、I/O完成端口对象 Completion port、工作对象 job、邮槽对象 mailslot、互斥对象 Mutex、管道对…

Hook原理--逆向开发

今天我们将继续讲解逆向开发工程另一个重要内容--Hook原理讲解。Hook&#xff0c;可以中文译为“挂钩”或者“钩子”&#xff0c;逆向开发中改变程序运行的一种技术。按照如下过程进行讲解 Hook概述Hook技术方式fishhook原理及实例符号表查看函数名称总结 一、Hook概述 在逆…

LeetCode刷题---有效的括号

这里用到了栈的思想 栈(stack)是限定仅在表尾进行插入或者删除的线性表。对于栈来说&#xff0c;表尾端称为栈顶&#xff08;top&#xff09;&#xff0c;表头端称为栈低&#xff08;bottom&#xff09;。不含元素的空表称为空栈。因为栈限定在表尾进行插入或者删除&#xff0c…

生成包含10个随机字母或数字的字符串,然后统计每个字符的出现次数

from random import choices from string import ascii_letters, digitsx .join(choices(ascii_lettersdigits, k10)) d dict() # 创建空字典 for ch in x:d[ch] d.get(ch, 0) 1 # x中有ch字符,个数1,并作为字典的值 print(x) print(d)也可以使用collections模块的defaul…

从车窗升降一探 Android 车机的重要 API:车辆属性 CarProperty

前言 前面我们介绍过 Android 车机 Automotive OS 的几块重要内容&#xff1a; 一文了解 Android 车机如何处理中控的旋钮输入从实体按键看 Android 车机的自定义事件机制深度入门 Android 车机核心 CarService 的构成和链路 本篇文章我们聚焦 Android 车机上最重要、最常用…

LeetCode--180 连续出现的数字

文章目录 1 题目描述2 结果示例3 解题思路3.1 MySQL 代码 4 知识拓展 1 题目描述 Logs表: ---------------------- | Column Name | Type | ---------------------- | id | int | | num | varchar | ----------------------在 SQL 中&#xff0c;id …

Mybatis的SqlRunner执行流程

Mybatis的SqlRunner执行流程 SqlRunner exec new SqlRunner(connection); Map<String, Object> row exec.selectOne("SELECT * FROM PRODUCT WHERE PRODUCTID ?", "FI-SW-01");connection.close();assertEquals("FI-SW-01", row.ge…

YOLOv5算法改进(19)— 手把手教你去更换NMS(DIoU-NMS/CIoU-NMS/EIoU-NMS/GIoU-NMS/SIoU-NMS)

前言:Hello大家好,我是小哥谈。YOLOv5中的NMS指非极大值抑制(Non-Maximum Suppression),它是一种用于目标检测算法中的后处理技术。在检测到多个重叠的边界框时,NMS可以帮助选择最佳的边界框。NMS的工作原理是首先根据预测边界框的置信度对它们进行排序,然后从置信度最高…

iOS逆向工程之Theos

如果你对iOS逆向工程有所了解&#xff0c;那么你对Tweak并不陌生。那么由Tweak我们又会引出Theos, 那么什么是Theos呢&#xff0c;简单一句话&#xff0c;Theos是一个越狱开发工具包&#xff0c;Theos是越狱开发工具的首先&#xff0c;因为其最大的特点就是简单。大道至简&…

python中多行注释与取消注释

在小白学习python编程的过程中&#xff0c;我们经常会发现很多同学们喜欢问的一个问题&#xff1a; 怎么多行注释呢&#xff1f; 怎么取消多行注释呢&#xff1f; 以上种种问题我相信来到这里都会得到相应答案 那我们接下来开始吧&#xff01; 文章目录 单行注释多行注释取消多…

c初阶检测题

选择题 1.局部变量的作用域是&#xff1a;&#xff08;D&#xff09; A.main函数内部 B.整个程序 C.main函数之前 D.局部变量所在的局部范围 2.字符串的结束标志是&#xff1a;&#xff08;A&#xff09; 作业内容 A.是’0’ B.是EOF C. 是’\0’ D.是空格 3.下面那个不是…

精选六个大学生可以做的兼职副业,学习赚钱两不误

在当今的社会中&#xff0c;大学生们面临着学业压力和生活开销。为了减轻家庭的负担&#xff0c;同时也为了更好地拓宽自己的视野和实践能力&#xff0c;许多大学生开始寻找一种既可以学习又能赚钱的副业。这样的选择&#xff0c;不仅可以弥补金钱上的不足&#xff0c;还可以提…

【java计算机毕设】博客管理系统 javaweb springboot vue mysql

目录 1.项目功能截图​ 2.项目简介 3.源码下载地址 1.项目功能截图 2.项目简介 博客管理系统 idea mysql5.7/8 vue html jdk1.8 系统功能&#xff1a; 前台功能&#xff1a;文章信息&#xff0c;相册信息&#xff0c;留言板&#xff0c;个人中心&#xff0c;后台管理 后…

闭包(函数)

把内部函数通过return扔出去 必要条件

靶机 DC-2

DC_2 信息搜集 存活检测 详细扫描 添加 host 后台网页扫描 网页信息搜集 主页面 找到 flag1&#xff0c;提示使用 cewl 密码生成工具 wp 登陆界面 使用 wpscan 扫描用户 wpscan --url http://dc-2/ --enumerate u 扫描出用户 tom、jerry、admin 将三个用户名写入文件中…

一文解密网络背后的秘密

一文解密网络背后的秘密 网络的发展史从键入网址到网页进行显示期间法上了什么&#xff1f;首先我们需要了解一下URLDNS解析建立连接什么是三次握手&#xff0c;可不可以两次呢&#xff1f; 本地发送请求&#xff0c;服务器处理请求断开连接 实践一下 相信大家对网络都不陌生了…

《认知觉醒:开启自我改变的原动力》

目录 第一章 大脑 — 一切问题的起源 第二章 潜意识 — 生命留给我们的彩蛋 第三章 元认知 — 人类的终极能能力 第四章 专注力——情绪和智慧的交叉地带 第五章 学习力——学习不是一味地努力 第六章 行动力 — 没有行动世界只是个概念 第七章 情绪力 — 情绪是多角度看…

【JavaScript】深入讲解浏览器渲染原理

一. 浏览器是如何渲染页面的&#xff1f; 当浏览器的网络线程收到 HTML 文档后&#xff0c;会产生一个渲染任务&#xff0c;并将其传递给渲染主线程的消息队列。 在事件循环机制的作用下&#xff0c;渲染主线程取出消息队列中的渲染任务&#xff0c;开启渲染流程。 渲染&…