Hazel 引擎学习笔记 (十五):ImGui 集成
游戏引擎 54

在本集视频中,Cherno 讲解了如何在 Hazel 引擎中集成 ImGui(Immediate Mode GUI),从而在游戏引擎中快速创建调试界面和工具窗口。本文将完整梳理这一集内容,并对核心点做详细解析。

1. 什么是 ImGui

ImGui 是一款即刻模式图形界面库(Immediate Mode GUI):

  • 即时模式:每一帧都会重新绘制 GUI 元素,而不是保存在某个状态树里。

  • 用途:主要用于调试界面、开发工具、可视化调试器。

  • 优势:简单、快速、可扩展。

在游戏引擎开发中,ImGui 是调试工具和编辑器开发的首选库,因为它的渲染和布局逻辑都非常轻量。


2. 项目结构与文件改动

在视频中,Cherno 对 ImGui 的集成主要做了两个改动:

  1. 引入新的后端文件

    • 原版 ImGui 提供 backends/imgui_impl_opengl3.cppimgui_impl_opengl3.h

    • Cherno 将 imgui_impl_opengl3.cpp 重命名为 ImGuiOpenGLRenderer.cpp,放到 Hazel/src/Platform/OpenGL/ 文件夹下,以便和引擎的 OpenGL 渲染模块对应。

  2. 修改 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 改造版本,确保:

    1. 后端文件在 Platform/OpenGL

    2. Premake 已正确包含。

    3. 子模块使用对应 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. 总结

  1. Hazel 通过封装 ImGuiLayer 实现 ImGui 的初始化、帧更新和渲染。

  2. Cherno 改造了 ImGui 后端文件,使其更贴合 Hazel 的 OpenGL 渲染模块。

  3. Premake 配置要正确包含 ImGui 源文件,而不再单独生成 ImGui 静态库。

  4. 运行时可能需要修改 imgui.cpp 内部对 DC 的访问,否则会出现编译错误。

第十五集的目标是让 Hazel 拥有一个可以实时绘制调试界面的基础设施,这为后续编辑器和调试工具开发奠定了基础。

Hazel 引擎学习笔记 (十五):ImGui 集成
http://localhost:8090/archives/hazel-yin-qing-xue-xi-bi-ji-shi-wu-imgui-ji-cheng
作者
Zxy
发布于
更新于
许可