【OpenGL学习】(一)创建窗口

news2025/5/20 19:57:49

文章目录

  • 【OpenGL学习】(一)创建窗口

【OpenGL学习】(一)创建窗口

GLFW

OpenGL 本身只是一套图形渲染 API,不提供窗口创建、上下文管理或输入处理的功能。
GLFW 是一个支持创建窗口、处理键盘鼠标输入和管理 OpenGL 上下文的跨平台库。因此,可以将OpenGL 和GLFW结合使用。

注:除了 GLFW,OpenGL 也可以与其他 GUI 框架如 Qt、MFC、SDL 等结合使用,实现更复杂或平台特定的图形界面程序。

GLAD

OpenGL 是一个跨平台的图形 API,其函数并非直接由操作系统或编译器提供,而是通过显卡驱动动态加载。这些函数的地址需要你在程序运行时手动获取,例如:

// 定义一个函数指针类型 GLGENBUFFERSPROC,用于指向 glGenBuffers 函数。
typedef void (*GLGENBUFFERSPROC)(GLsizei, GLuint*);
// 使用 wglGetProcAddress 函数动态加载 OpenGL 的 glGenBuffers 函数。
GLGENBUFFERSPROC glGenBuffers = (GLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");

每一个函数你都得这么写,非常繁琐。

GLAD是一个OpenGL函数加载库,可以自动加载与指定OpenGL版本相关的所有函数指针,避免了繁琐的手动获取,让我们可以像普通函数一样直接调用它们。

示例:创建窗口

#include <glad/glad.h>  // 用于加载 OpenGL 函数指针
#include <GLFW/glfw3.h> // 用于创建窗口和处理用户输入
#include <iostream>

// 函数声明:窗口大小变化回调函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
// 函数声明:处理输入
void processInput(GLFWwindow* window);

// 设置窗口宽高
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
    // 初始化 GLFW 库,并配置 OpenGL 版本
    glfwInit(); // 初始化 GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);  // 要 OpenGL 3.x
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);  // 精确到 3.3 版本
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用现代核心功能,不兼容旧版

#ifdef __APPLE__
    // 兼容 Mac OS 系统
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // 创建 GLFW 窗口对象
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL) // 创建失败则输出错误信息并终止程序
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window); // 将当前上下文设置为刚创建的窗口
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // 注册窗口尺寸改变的回调函数,告诉GLFW当窗口调整大小的时调用这个函数

    // 初始化 GLAD,加载所有 OpenGL 函数指针
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 渲染循环
    while (!glfwWindowShouldClose(window)) // 如果窗口没有被关闭
    {
        // 处理输入
        processInput(window);

        // 设置清屏颜色(RGBA格式,红、绿、蓝、透明度),用于清除颜色缓冲区
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        // 清除颜色缓冲区,使用上面设置的清屏颜色
        glClear(GL_COLOR_BUFFER_BIT);

        glfwSwapBuffers(window); // 交换颜色缓冲区:把画好的图像展示到屏幕上
        glfwPollEvents();  // 从操作系统获取事件(键盘、鼠标、窗口变化等),并更新 GLFW 内部状态,或者触发用户注册的回调函数。
    }

    // 释放资源并退出
    glfwTerminate();
    return 0;
}

// 处理输入
void processInput(GLFWwindow* window)
{
    // 当按下 ESC 键时关闭窗口
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true); // 设置窗口应关闭标志
}

// 窗口尺寸改变时调用的回调函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // 设置视口大小,使其匹配新窗口尺寸
    // 注意:在高 DPI 显示屏上,实际像素尺寸可能比指定尺寸更大
    glViewport(0, 0, width, height);
}


颜色缓冲区

颜色缓冲区是帧缓冲区(Frame Buffer) 的一部分,它保存了当前窗口中每一个像素的颜色值。

当你在屏幕上绘制图形时,你的所有绘制操作(画三角形、贴纹理、光照等)其实都是先写入颜色缓冲区,最后才一次性展示在屏幕上。

OpenGL 中的默认帧缓冲区包括:

缓冲区作用
颜色缓冲区(Color Buffer)存储每个像素的颜色值(RGB 或 RGBA)。
深度缓冲区(Depth Buffer)存储每个像素的深度值(Z 值),用于深度测试。
模板缓冲区(Stencil Buffer)用于进行复杂的遮罩、裁剪操作。

OpenGL 默认使用双缓冲机制(Double Buffering),也就是有两个颜色缓冲区:

缓冲区用途
前缓冲区(Front Buffer)当前正在显示在屏幕上的图像
后缓冲区(Back Buffer)当前正在绘制的图像内容(你所有的渲染操作都写在这里)

渲染流程大致如下:

  1. 你通过 OpenGL API 画东西 → 写入后缓冲区
  2. 绘制完成后,调用 glfwSwapBuffers(window); → 前后缓冲区交换
  3. 后缓冲区的图像变成可见,前缓冲区变成新的绘制目标。

这样就可以避免画面撕裂或闪烁,保证画面平滑流畅。

processInput()和glfwPollEvents()的关系

glfwPollEvents()processInput()
谁写的GLFW 提供的函数你自己写的函数
属于哪一层系统层(事件驱动层)应用层(行为控制层)
作用从操作系统获取输入事件(键盘、鼠标、窗口)并更新内部状态基于 GLFW 状态判断执行逻辑,比如关闭窗口、移动物体
必须调用吗是的,否则无法接收到新输入可选,但你不写就不会响应用户行为
通常调用顺序一般在主循环每帧末尾调用一般在主循环每帧开始调用
是否处理输入行为不处理输入逻辑,只更新状态你写的行为处理代码(比如 ESC 退出)就在这里

参考:
https://learnopengl-cn.github.io/01%20Getting%20started/03%20Hello%20Window/

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

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

相关文章

AI大语言模型评测体系演进与未来展望

随着人工智能技术的飞速发展,大语言模型(LLMs)已成为自然语言处理领域的核心研究方向。2025年最新行业报告显示,当前主流模型的评测体系已从单一任务评估转向多维度、全链路的能力剖析。例如,《全球首个大语言模型意识水平”识商”白盒DIKWP测评报告》通过数据、信息、知识…

微服务项目->在线oj系统(Java版 - 5)

相信自己,终会成功 微服务代码: lyyy-oj: 微服务 目录 C端代码 用户题目接口 修改后用户提交代码(应用版) 用户提交题目判题结果 代码沙箱 1. 代码沙箱的核心功能 2. 常见的代码沙箱实现方式 3. 代码沙箱的关键问题与解决方案 4. 你的代码如何与沙箱交互&#xff1f; …

get请求使用数组进行传参

get请求使用数组进行传参,无需添加中括号 mvc接口要添加参数名&#xff0c;使用array承接。不能用list, 否则会报错 这里是用apifox模拟前端调用。 前端调用代码 // 根据项目ID和角色ID查询相关审批人 export function findRelativeApproverByProjectIdAndRoleId(roleIds, p…

【MySQL成神之路】MySQL常用语法总结

目录 MySQL 语法总结 数据库操作 表操作 数据操作 查询语句 索引操作 约束 事务控制 视图操作 存储过程和函数 触发器 用户和权限管理 数据库操作 创建数据库&#xff1a; CREATE DATABASE database_name; 选择数据库&#xff1a; USE database_name; 删除数…

Linux动静态库制作与原理

什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人的代码都从零开始&#xff0c;因此库的存在意义非同寻常。 本质上来说库是一种可执行代码的二进制形式&#xff0c;可以被操作系统…

ffmpeg 把一个视频复制3次

1. 起因&#xff0c; 目的: 前面我写过&#xff0c;使用 python 把一个视频复制3次但是速度太慢了&#xff0c;我想试试看能否改进。而且我想换一种新的视频处理思路&#xff0c;并试试看速度如何。 2. 先看效果 效果就是能行&#xff0c;而且速度也快。 3. 过程: 代码 1…

GPT/Claude3国内免费镜像站更新 亲测可用

无限次使用&#xff1a;无限制的提问次数&#xff0c;不设上限&#xff0c;随心所欲。 无需魔法、稳定流畅&#xff1a;操作简便&#xff0c;无需复杂设置&#xff0c;即可享受稳定流畅的服务。 手机和电脑均能用&#xff1a;轻松适配手机和电脑&#xff0c;使用体验更佳。 …

Python:操作Excel按行写入

Python按行写入Excel数据,5种实用方法大揭秘! 在日常的数据处理和分析工作中,我们经常需要将数据写入到Excel文件中。Python作为一门强大的编程语言,提供了多种库和方法来实现将数据按行写入Excel文件的功能。本文将详细介绍5种常见的Python按行写入Excel数据的方法,并附上…

Redis进阶知识

Redis 1.事务2. 主从复制2.1 如何启动多个Redis服务器2.2 监控主从节点的状态2.3 断开主从复制关系2.4 额外注意2.5拓扑结构2.6 复制过程2.6.1 数据同步 3.哨兵选举原理注意事项 4.集群4.1 数据分片算法4.2 故障检测 5. 缓存5.1 缓存问题 6. 分布式锁 1.事务 Redis的事务只能保…

12.vue整合springboot首页显示数据库表-实现按钮:【添加修改删除查询】

vue整合springboot首页显示数据库表&#xff1a;【添加修改删除查询】 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是node.js和vue的使用。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性。【帮帮志系…

bisheng系列(一)- 本地部署(Docker)

目录 一、导读 二、说明 1、镜像说明 2、本节内容 三、docker部署 1、克隆代码 2、运行镜像 3、可能的错误信息 四、页面测试 1、注册用户 2、登陆成功 3、添加模型 一、导读 环境&#xff1a;Ubuntu 24.04、Windows 11、WSL 2、Python 3.10 、bisheng 1.1.1 背景…

如何用Python批量解压ZIP文件?快速解决方案

如何用Python批量解压ZIP文件&#xff1f;快速解决方案 文章目录 **如何用Python批量解压ZIP文件&#xff1f;快速解决方案**代码结果详细解释 话不多说&#xff0c;先上干货&#xff01;&#xff01;&#xff01; 代码 import os import zipfiledef unzip_file(dir_path: str…

DriveGenVLM:基于视觉-语言模型的自动驾驶真实世界视频生成

《DriveGenVLM: Real-world Video Generation for Vision Language Model based Autonomous Driving》2024年8月发表&#xff0c;来自哥伦比亚大学的论文。 自动驾驶技术的进步需要越来越复杂的方法来理解和预测现实世界的场景。视觉语言模型&#xff08;VLM&#xff09;正在成…

企业标准信息公共服务平台已开放标准通编辑器访问入口

标准通 数字化标准编辑器 专业、高效、便捷 企业标准信息公共服务平台 近日&#xff0c;企业标准信息公共服务平台已开放标准通编辑器访问入口&#xff0c;可进入官网指定版块使用&#xff01; 核心功能亮点 解决企业痛点 传统标准编制&#xff0c;需反复核对格式、逐条…

进阶-数据结构部分:1、数据结构入门

飞书文档https://x509p6c8to.feishu.cn/wiki/HRLkwznHiiOgZqkqhLrcZNqVnLd 一、存储结构 顺序存储 链式存储 二、常用数据结构 2.1、栈 先进后出 场景&#xff1a; 后退/前进功能&#xff1a;网页浏览器中的后退和前进按钮可以使用栈来实现。在浏览网页时&#xff0c;每次…

React 19中useContext不需要Provider了。

文章目录 前言一、React 19中useContext移除了Provider&#xff1f;二、使用步骤总结 前言 在 React 19 中&#xff0c;useContext 的使用方式有所更新。开发者现在可以直接使用 作为提供者&#xff0c;而不再需要使用 <Context.Provider>。这一变化简化了代码结构&…

Json schema校验json字符串(networknt/json-schema-validator库)

学习链接 json-schema官网 - 英文 jsonschemavalidator 可在线校验网站 networknt的json-schema-validator github地址 networknt的json-schema-validator 个人gitee地址 - 里面有md文档说明和代码示例 JSON Schema 入门指南&#xff1a;如何定义和验证 JSON 数据结构 JS…

交易所开发:构建功能完备的金融基础设施全流程指南

交易所开发&#xff1a;构建功能完备的金融基础设施全流程指南 ——从技术架构到合规安全的系统性解决方案 一、开发流程&#xff1a;从需求分析到运维优化 开发一款功能完备的交易所需要遵循全生命周期管理理念&#xff0c;涵盖市场定位、技术实现、安全防护和持续迭代四大阶…

Axure疑难杂症:统计分析页面引入Echarts示例动态效果

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:统计分析页面引入Echarts示例动态效果 主要内容:echart示例引入、大小调整、数据导入 应用场景:统计分析页面…

展锐Android14及更新版本split_build编译方法

更改split_build.py文件内容后按照下面方法编译&#xff1a; zip -r sys/vendor/sprd/release/split_build.zip sys/vendor/sprd/release/split_build/ rm -r sys/vendor/sprd/release/split_build/ cp -r vnd/vendor/sprd/release/split_build/ sys/vendor/sprd/release/cd s…