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

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

文章目录

  • 【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(); // 初始化 GLFWglfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);  // 要 OpenGL 3.xglfwWindowHint(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.lryc.cn/news/2380212.html

相关文章:

  • AI大语言模型评测体系演进与未来展望
  • 微服务项目->在线oj系统(Java版 - 5)
  • disryptor和rabbitmq
  • HTTP与HTTPS协议的核心区别
  • Flink 并行度的设置
  • 【微服务】SpringBoot + Docker 实现微服务容器多节点负载均衡详解
  • get请求使用数组进行传参
  • 20. 自动化测试框架开发之Excel配置文件的IO开发
  • 【MySQL成神之路】MySQL常用语法总结
  • Linux动静态库制作与原理
  • 确保高质量的音视频通话,如何最大化利用视频带宽
  • ffmpeg 把一个视频复制3次
  • GPT/Claude3国内免费镜像站更新 亲测可用
  • AI自动化工作流:开启当下智能生产力的价值
  • stm32——EXTI外部中断
  • Python:操作Excel按行写入
  • Redis进阶知识
  • Python机器学习笔记(二十三 模型评估与改进-网格搜索)
  • 12.vue整合springboot首页显示数据库表-实现按钮:【添加修改删除查询】
  • bisheng系列(一)- 本地部署(Docker)
  • 如何用Python批量解压ZIP文件?快速解决方案
  • DriveGenVLM:基于视觉-语言模型的自动驾驶真实世界视频生成
  • JavaScript 中的五种继承方式进行深入对比
  • 企业标准信息公共服务平台已开放标准通编辑器访问入口
  • [Linux]安装吧!我的软件包管理器!
  • Spring Boot 与 RabbitMQ 的深度集成实践(三)
  • 进阶-数据结构部分:1、数据结构入门
  • React 19中useContext不需要Provider了。
  • Json schema校验json字符串(networknt/json-schema-validator库)
  • 交易所开发:构建功能完备的金融基础设施全流程指南