在本集视频中,Cherno 讲解了如何在 Hazel 引擎中集成 ImGui(Immediate Mode GUI),从而在游戏引擎中快速创建调试界面和工具窗口。本文将完整梳理这一集内容,并对核心点做详细解析。
1. 什么是 ImGui
ImGui 是一款即刻模式图形界面库(Immediate Mode GUI):
即时模式:每一帧都会重新绘制 GUI 元素,而不是保存在某个状态树里。
用途:主要用于调试界面、开发工具、可视化调试器。
优势:简单、快速、可扩展。
在游戏引擎开发中,ImGui 是调试工具和编辑器开发的首选库,因为它的渲染和布局逻辑都非常轻量。
2. 项目结构与文件改动
在视频中,Cherno 对 ImGui 的集成主要做了两个改动:
引入新的后端文件
原版 ImGui 提供
backends/imgui_impl_opengl3.cpp和imgui_impl_opengl3.h。Cherno 将
imgui_impl_opengl3.cpp重命名为ImGuiOpenGLRenderer.cpp,放到Hazel/src/Platform/OpenGL/文件夹下,以便和引擎的 OpenGL 渲染模块对应。
修改
ImGuiLayer创建
Hazel::ImGuiLayer类,统一管理 ImGui 的初始化、帧更新和渲染。OnAttach():创建 ImGui 上下文,配置样式和 IO。OnDetach():清理 ImGui 相关资源。OnUpdate():每帧开始新帧,渲染 GUI。
3. premake5.lua 配置
在 Hazel 的 Premake 配置中,需要调整:
包含目录:
Hazel/vendor/imgui。
示例:
IncludeDir["ImGui"] = "Hazel/vendor/imgui"
include "Hazel/vendor/imgui"
files
{
"%{prj.name}/src/**.h",
"%{prj.name}/src/**.cpp"
}
includedirs
{
"%{prj.name}/src",
"%{prj.name}/vendor/spdlog/include",
"%{IncludeDir.GLFW}",
"%{IncludeDir.Glad}",
"%{IncludeDir.ImGui}"
}
links
{
"GLFW",
"Glad",
"ImGui",
"opengl32.lib"
}4. 注意事项与常见问题
4.1 DC 未定义
原版 ImGui 在
imgui.cpp内部使用DC变量访问ImGuiWindow的布局数据。Cherno 的版本改为通过
window->DC。解决方法:
修改
修改 'imgui.cpp' 文件,找到第 3839 行和 3841 行,分别修改为“for (int i = 0; i < window->DC.Layouts.Data.Size; i++)”和“ImGuiLayout* layout = (ImGuiLayout*)window->DC.Layouts.Data[i].val_p;”
// 修改前
for (int i = 0; i < DC.Layouts.Data.Size; i++)
{
ImGuiLayout* layout = (ImGuiLayout*)DC.Layouts.Data[i].val_p;
IM_DELETE(layout);
}
// 修改后
for (int i = 0; i < window->DC.Layouts.Data.Size; i++)
{
ImGuiLayout* layout = (ImGuiLayout*)window->DC.Layouts.Data[i].val_p;
IM_DELETE(layout);
}
4.2 GUI 显示异常
如果 GUI 显示不对,通常是 ImGui 后端文件路径或者版本问题。
视频中使用的是 Cherno 自己的 ImGui 改造版本,确保:
后端文件在
Platform/OpenGL。Premake 已正确包含。
子模块使用对应 commit。
5. ImGuiLayer 使用流程
5.1 初始化
void ImGuiLayer::OnAttach()
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(windowHandle, true);
ImGui_ImplOpenGL3_Init("#version 410");
}
5.2 每帧更新
void ImGuiLayer::OnUpdate()
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// 在这里绘制 GUI
ImGui::Begin("Debug Window");
ImGui::Text("Hello Hazel!");
ImGui::End();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
5.3 销毁
void ImGuiLayer::OnDetach()
{
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
6. 总结
Hazel 通过封装
ImGuiLayer实现 ImGui 的初始化、帧更新和渲染。Cherno 改造了 ImGui 后端文件,使其更贴合 Hazel 的 OpenGL 渲染模块。
Premake 配置要正确包含 ImGui 源文件,而不再单独生成 ImGui 静态库。
运行时可能需要修改
imgui.cpp内部对DC的访问,否则会出现编译错误。
第十五集的目标是让 Hazel 拥有一个可以实时绘制调试界面的基础设施,这为后续编辑器和调试工具开发奠定了基础。