头文件区
#include <GLFW/glfw3.h>Code language: HTML, XML (xml)
引入 GLFW 窗口库头文件:负责创建窗口、处理鼠标 / 键盘输入、管理 OpenGL 上下文、窗口消息循环。
GLFW 是一个用来创建和管理窗口的库,是C语言开发的。它是独立的,不属于Imgui,但是IMGUI用到了它。所以需要引用它。读者在上一节中,已经把它下载到项目目录里面了。并且页配置集成到了项目中了。
#include "imgui.h"Code language: CSS (css)
这是imgui的核心头文件,里面有所有 UI 控件、上下文、样式、绘制基础 API等等。
#include "backends/imgui_impl_glfw.h"Code language: PHP (php)
这是imgui和glfw的对接桥梁,负责把glfw中窗口鼠标、键盘、窗口尺寸等等转发给 ImGui
#include "backends/imgui_impl_opengl3.h"Code language: PHP (php)
ImGui OpenGL3 渲染后端适配层:生成 OpenGL 着色器、顶点缓冲,将 ImGui UI 图形提交给 GPU 绘制。
#include <cstdio>Code language: HTML, XML (xml)
C++ 标准 C 输入输出库,用于printf打印错误日志。
int main()
入口函数,相信不用小编多说了。
GLFW 初始化
// Initialize GLFW
if (!glfwInit())
{
printf("GLFW initialization failed\n");
return -1;
}Code language: JavaScript (javascript)
glfwInit():初始化 GLFW 全局资源(例如显卡、窗口驱动、输入设备)
如果不通过,则弹出错误提示,并且返回-1 程序就异常退出,操作系统会捕捉到这个-1
OpenGL 版本配置
// OpenGL 3.3
const char* glsl_version = "#version 330";Code language: JavaScript (javascript)
定义 GLSL 着色器版本字符串,OpenGL3.3 对应 GLSL 330
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
设置 OpenGL 主版本号为 3
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
设置 OpenGL 次版本号为 3
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
使用核心模式 Core Profile
创建窗口
// Create window
GLFWwindow* window = glfwCreateWindow(1000, 600, "ImGui Minimal Demo (VS2022)", nullptr, nullptr);Code language: JavaScript (javascript)
窗口宽高是1000*600,窗口标题是“ImGui Minimal Demo (VS2022)”,第 4 参数,是nullptr空指针,表示窗口模式,第 5 参数,是否共享 OpenGL 上下文的窗口,nullptr = 不共享。
返回窗口句柄指针GLFWwindow*
if (!window)
{
glfwTerminate();
return -1;
}Code language: JavaScript (javascript)
上面的GLFWwindow window 如果窗口创建失败句柄为 nullptr
glfwTerminate() 销毁所有 GLFW 资源
然后返回-1,告诉操作系统,程序错误退出。
glfwMakeContextCurrent(window);Code language: JavaScript (javascript)
将当前窗口绑定为 OpenGL 渲染上下文,后续所有 OpenGL 绘制指令都作用于该窗口
glfwSwapInterval(1);
开启垂直同步,参数 1 = 每帧等待显示器刷新,限制帧率和显示器刷新率同步,防止画面撕裂;0 = 关闭 VSync,无帧率限制。
以上这个配置很重要,如果没有开启,那么显示器刷新的时候和glfw刷新不同步,会导致画面出现错乱。
ImGui 全局初始化
IMGUI_CHECKVERSION(); // 校验头文件与后端版本一致性,版本不符直接断言报错
ImGui::CreateContext(); // 创建ImGui全局上下文,存储UI所有运行状态
ImGuiIO& io = ImGui::GetIO(); // 获取IO配置对象,管控输入、字体、全局开关等设置
ImGui::StyleColorsDark(); // 加载官方深色UI配色样式Code language: PHP (php)
绑定 GLFW+OpenGL 后端
ImGui_ImplGlfw_InitForOpenGL(window, true);Code language: JavaScript (javascript)
第二个参数设置true是,让 ImGui 接管所有输入事件(鼠标、键盘),自动屏蔽输入穿透到游戏底层
ImGui_ImplOpenGL3_Init(glsl_version);
初始化 OpenGL3 渲染后端,传入 GLSL 版本字符串,编译 UI 绘制用的顶点 / 片段着色器、创建 GPU 缓冲
float slider_value = 0.5f; // 滑动条绑定数值
int click_count = 0; // 按钮点击计数
bool show_full_demo = false; // 控制是否显示ImGui官方演示窗口Code language: JavaScript (javascript)
以上几个参数用来存储控件的值。每次刷新UI,都会读取或者修改,跨帧保留数值
主渲染循环
程序核心,每秒循环几十到上百次
while (!glfwWindowShouldClose(window))Code language: JavaScript (javascript)
窗口未收到关闭信号,例如 点击右上角 x关闭按钮或者Alt+F4,就持续渲染。
glfwPollEvents();
轮询窗口系统所有消息,例如鼠标点击 移动 键盘按键按下,窗口缩放 关闭等等。
ImGui_ImplOpenGL3_NewFrame();
OpenGL 后端帧前置更新:重置渲染资源、准备下一帧绘制缓存
ImGui_ImplGlfw_NewFrame();
GLFW 后端帧前置更新:读取当前鼠标坐标、按键状态、窗口尺寸,写入 ImGui IO 输入数据
ImGui::NewFrame();Code language: CSS (css)
开启新一帧 UI 布局计算,必须在所有ImGui::xxx()控件代码前调用;内部清空上一帧绘制指令,准备收集本帧 UI 数据
ui控件数据变更构建部分
// Draw custom UI panel
ImGui::Begin("Control Panel"); // 开启自定义控制面板窗口
ImGui::Text("Hello ImGui + VS2022"); // 输出静态文本
ImGui::SliderFloat("Slider Value", &slider_value, 0.f, 1.f); // 浮点滑动条,绑定数值变量
if (ImGui::Button("Click to Count")) // 创建点击按钮,按下返回true
click_count++; // 按钮点击后计数器+1
ImGui::SameLine(); // 下一个控件与当前同行显示
ImGui::Text("Click Count: %d", click_count); // 打印按钮点击次数
ImGui::Checkbox("Show Full ImGui Demo Window", &show_full_demo); // 复选框控制演示窗口显隐
ImGui::End(); // 结束当前自定义窗口绘制
if (show_full_demo)
ImGui::ShowDemoWindow(&show_full_demo); // 打开ImGui官方全套演示窗口Code language: C++ (cpp)
以上部分,是用来每次循环,就显示内容,检查是否点击了按钮,如果是就计数器增加。打印计数器等等。
真正绘制渲染部分
// Render ImGui draw data
ImGui::Render(); // 生成本帧UI顶点绘制数据
int width, height;
glfwGetFramebufferSize(window, &width, &height); // 获取窗口实际渲染分辨率
glViewport(0, 0, width, height); // 设置OpenGL渲染视口铺满窗口
glClearColor(0.12f, 0.12f, 0.12f, 1.f); // 设置窗口清屏底色(深灰色)
glClear(GL_COLOR_BUFFER_BIT); // 清空画布颜色缓冲
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());// 用OpenGL绘制所有ImGui界面
glfwSwapBuffers(window); // 交换前后缓冲区,显示画面Code language: JavaScript (javascript)
退出后清除资源部分
如下是用户退出后,进行资源清理部分
// Cleanup resources
ImGui_ImplOpenGL3_Shutdown(); // 释放OpenGL渲染后端资源(着色器、缓冲等)
ImGui_ImplGlfw_Shutdown(); // 释放GLFW窗口适配后端资源
ImGui::DestroyContext(); // 销毁ImGui全局上下文,释放UI内存
glfwDestroyWindow(window); // 关闭GLFW窗口,销毁窗口句柄
glfwTerminate(); // 彻底卸载GLFW库,释放全局窗口/输入资源
return 0; // 程序正常退出,返回成功码0Code language: JavaScript (javascript)
销毁顺序和初始化顺序完全相反,防止内存泄漏、资源残留。
ok,本部分解析上一节课的的例子,读者有什么不明白,可以下方留言。
