ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Dear ImGui 集成与架构指南:核心文件组织、后端体系与即时模式 UI 的完整实践

Dear ImGui 集成与架构指南:核心文件组织、后端体系与即时模式 UI 的完整实践 Dear ImGui 集成与架构指南核心文件组织、后端体系与即时模式 UI 的完整实践【免费下载链接】imguiDear ImGui: Bloat-free Graphical User interface for C with minimal dependencies项目地址: https://gitcode.com/GitHub_Trending/im/imgui本文基于仓库根目录的 项目 README 展开带你完整理解 Dear ImGui当前仓库版本为 imgui.h 中的1.93.0 WIP的核心设计定位、文件组织方式、即时模式Immediate Mode渲染原理以及如何将标准后端或自研后端接入你的 C 应用。读完后你将能够独立完成 Dear ImGui 的集成、配置与渲染循环搭建并理解其“输出顶点缓冲、不触碰 GPU”的底层工作方式。一、项目定位无膨胀的 C 图形用户界面库README 对项目给出的核心定位是Dear ImGui 是一个为 C 提供的无膨胀bloat-free图形用户界面库它输出优化过的顶点缓冲vertex buffers你可以随时在具备 3D 渲染管线能力的应用中渲染它。其特点是快速、可移植、渲染器无关且完全自包含无外部依赖。与设计目标同样重要的是它的取舍。README 明确指出Dear ImGui 的设计目标是支持快速迭代、帮助程序员构建内容创作工具与可视化/调试工具而非面向普通终端用户的成品 UI因此它刻意不提供更高层库中常见的功能完整的国际化支持从右到左文本、双向文本、文本整形等不支持无障碍accessibility特性不支持。它特别适合集成进游戏引擎用于工具链、实时 3D 应用、全屏应用、嵌入式应用以及操作系统特性不标准的任何主机console平台应用。README 将其核心优势归纳为最小化状态同步、最小化用户侧 UI 相关状态存储、最小化搭建与维护成本、便于创建反映动态数据集合的动态 UI、便于创建代码驱动或数据驱动的工具、便于创建从临时短命工具到长期复杂工具的各级工具、易于二次修改、可移植且能在目标机主机、手机等上运行、运行时与内存占用高效、经过工业级实战检验。适用边界的工程含义这段取舍说明对工程选型有直接指导意义如果你的工具需要长期维护、需要被团队反复打开编辑Dear ImGui 完全胜任其 examples/ 中的 20 多个示例应用即为参照但如果需要面向最终用户的多语言产品界面则需要另选方案。README 也提示由于“状态”是即时模式 UI 中错误的主要来源文档开头引用的 ryg 名言即点明这一点把 UI 状态集中管理是使用者需要掌握的第一课。二、库的组织结构核心文件与后端平台无关的核心README 指出Dear ImGui 的核心是少数平台无关文件可以直接编译进你的应用/引擎即仓库根目录下的全部imgui*.cpp与imgui*.h文件不需要专门的构建流程可以直接把这些文件加入现有工程。当前仓库根目录的实际核心文件为文件职责imgui.cpp核心实现上下文、主循环逻辑、布局、交互等文件头部注释还包含完整的集成骨架imgui.h公共 API 与配置结构ImGuiIO定义imgui_internal.h内部实现头文件非公共 APIimgui_widgets.cpp各类控件按钮、输入框、滑块、菜单等实现imgui_draw.cpp绘制列表、纹理管理、字体渲染等绘制层实现imgui_tables.cpp表格系统实现imgui_demo.cpp演示窗口ShowDemoWindow()的完整实现imconfig.h编译期配置模板imstb_textedit.h、imstb_truetype.h、imstb_rectpack.h嵌入的 stb 系列第三方代码公有领域后端与示例各类图形 API 与渲染平台的后端位于 backends/ 目录配套的示例应用位于 examples/ 目录你也可以自己编写后端。README 给出了一句关键判断“任何能渲染带纹理三角形textured triangles的地方就能渲染 Dear ImGui。”当前仓库中官方维护的后端覆盖渲染器后端DirectX 9/10/11/12、Metal 3/4imgui_impl_metal.mm、imgui_impl_metal4.mm、OpenGL/ES/ES2imgui_impl_opengl3.cpp、imgui_impl_opengl2.cpp、SDL_GPUimgui_impl_sdlgpu3.cpp、SDL_Renderer 2/3imgui_impl_sdlrenderer2.cpp、Vulkanimgui_impl_vulkan.cpp、WebGPUimgui_impl_wgpu.cpp等平台后端GLFWimgui_impl_glfw.cpp、SDL2/SDL3imgui_impl_sdl2.cpp、imgui_impl_sdl3.cpp、Win32imgui_impl_win32.cpp、Glut、OSX、Androidimgui_impl_android.cpp框架级后端Allegro5、Emscriptenmisc/ 与示例中的 emscripten 支持。关于版本选择README 的建议是项目偶尔打版本标签带完整的 Release 说明但一般安全且推荐的做法是同步最新的master或docking分支进阶用户可使用docking分支获得多视口Multi-Viewport与停靠Docking功能该分支会与 master 保持定期同步。API 的破坏性变更历史维护在 imgui.cpp 头部的 “API BREAKING CHANGES” 列表中例如 1.92.9 中DragXXX/SliderXXX/InputScalar键入中间值写回行为的改变docs/CHANGELOG.txt 则提供完整的版本变更日志——README 特别建议定期阅读 changelog它是发现新功能的最佳途径。三、工作原理即时模式范式与“不触碰 GPU”README 的 “How it works” 一节是理解整个库的关键它包含三层信息最小化状态。IMGUI 范式在其 API 层面试图最小化多余的状态复制、状态同步与状态保留从使用者角度看比传统的保留模式retained-mode接口更少出错更少代码、更少 bug也更利于构建动态用户界面。输出顶点缓冲与命令列表。Dear ImGui 输出可直接渲染的顶点缓冲与绘制命令列表渲染所需的 draw call 与状态切换数量很少。因为它不知道也不触碰任何图形状态你可以随时在代码的任何位置调用它的函数比如在正在运行的算法中间或在你自己的渲染流程中间。纠正一个常见误解很多人把“即时模式 GUI”误认为“即时模式渲染”——即在 GUI 函数被调用的同时不停向驱动/GPU 发起大量低效的 draw call 和状态切换。这不是 Dear ImGui 的做法它输出的是顶点缓冲和一小批绘制命令从不直接接触 GPU这些批次经过合理优化可以在稍后、在你的应用中甚至远端机器上再渲染。源码印证主循环四步这一描述在 imgui.h 的 API 声明中得到了逐字印证Render()—— 结束当前 Dear ImGui 帧完成绘制数据draw data的最终化之后即可调用GetDrawData()ImDrawData* GetDrawData()—— 在Render()之后、下一次NewFrame()之前有效随后应调用渲染器后端的ImGui_ImplXXXX_RenderDrawData()进行实际渲染ShowDemoWindow()—— 创建演示窗口演示绝大多数特性。对应地imgui.cpp 头部注释的 “HOW A SIMPLE APPLICATION MAY LOOK LIKE” 展示了标准后端的完整主循环其核心四步为// 1) 把输入喂给 Dear ImGui开始新帧 ImGui_ImplDX11_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); // 2) 你的任意应用代码可以在此调用任何 ImGui:: 控件 ImGui::Text(Hello, world!); // 3) 渲染 Dear ImGui 到帧缓冲 ImGui::Render(); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); g_pSwapChain-Present(1, 0);值得注意的是 imgui.cpp 中的两条集成建议NewFrame()应尽量早调用以便在整个主循环中随时使用 ImGuiEndFrame()/Render()应尽量晚调用以便在你自己的游戏渲染代码中使用 ImGui。输入路由方面注释明确要求判断鼠标/键盘事件该派发给 ImGui 还是你的应用时应读取io.WantCaptureMouse、io.WantCaptureKeyboard与io.WantTextInput标志。README 中的两个典型用例README “Usage” 一节给出的两段示例代码体现了库的使用层次最小用例——从程序的任何位置调用控件ImGui::Text(Hello, world %d, 123); if (ImGui::Button(Save)) MySaveFunction(); ImGui::InputText(string, buf, IM_COUNTOF(buf)); ImGui::SliderFloat(float, f, 0.0f, 1.0f);完整工具窗口——带菜单栏、颜色编辑、实时曲线、滚动区域// 创建带菜单栏的窗口 My First Tool ImGui::Begin(My First Tool, my_tool_active, ImGuiWindowFlags_MenuBar); if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu(File)) { if (ImGui::MenuItem(Open.., CtrlO)) { /* Do stuff */ } if (ImGui::MenuItem(Save, CtrlS)) { /* Do stuff */ } if (ImGui::MenuItem(Close, CtrlW)) { my_tool_active false; } ImGui::EndMenu(); } ImGui::EndMenuBar(); } // 编辑一个以 4 个 float 存储的颜色 ImGui::ColorEdit4(Color, my_color); // 生成并绘制采样曲线 float samples[100]; for (int n 0; n 100; n) samples[n] sinf(n * 0.2f ImGui::GetTime() * 1.5f); ImGui::PlotLines(Samples, samples, 100); // 在滚动区域中显示内容 ImGui::TextColored(ImVec4(1,1,0,1), Important Stuff); ImGui::BeginChild(Scrolling); for (int n 0; n 50; n) ImGui::Text(%04d: Some text, n); ImGui::EndChild(); ImGui::End();README 进一步说明了该范式的实际价值边界从“极短命”的工具利用编译器的 EditContinue 热重载功能运行中临时加入几个控件调参、一分钟后删掉到长寿命的复杂编辑器不只是调参还可以追踪正在运行的算法直接输出文本命令、配合自定义反射数据实时浏览数据集、暴露引擎子系统内部、构建 logger、检视工具、profiler、调试器乃至整个游戏编辑器/框架。四、集成实战一标准后端组合README “Getting Started Integration” 一节的核心建议是在大多数平台、使用 C 时你应该可以直接使用一组imgui_impl_xxxx后端而无需修改例如imgui_impl_win32.cppimgui_impl_dx11.cpp。如果你的引擎支持多平台建议优先复用更多imgui_impl_xxxx文件而不是重写它们——工作量更小还能立即跑起来日后再决定是否为自定义引擎重写后端。把 Dear ImGui 集成进自定义引擎本质上就是三件事1接通鼠标/键盘/手柄输入2向 GPU/渲染引擎上传一张纹理3提供一个能够创建/更新纹理并渲染带纹理三角形的渲染函数——这正是各后端所做的全部工作。docs/BACKENDS.md 对此给出了规范表述必需能力提供鼠标/键盘输入喂入ImGuiIO结构创建、更新、销毁纹理渲染带裁剪矩形clipping rectangle的索引化带纹理三角形可选能力各后端尽力支持自定义纹理绑定、剪贴板、手柄、鼠标光标形状、IME、多视口等。使用标准后端可确保获得这些特性尤其是多视口这类自己实现难度较高的功能。后端还分为两类见 docs/BACKENDS.md平台Platform后端负责鼠标/键盘/手柄输入、光标形状、计时与窗口管理。例如 imgui_impl_win32.cpp、imgui_impl_sdl3.cpp、imgui_impl_glfw.cpp渲染器Renderer后端负责创建字体图集纹理、渲染 imgui 绘制数据。例如 imgui_impl_dx11.cpp、imgui_impl_opengl3.cpp、imgui_impl_vulkan.cpp某些高层框架的后端同时承担两部分例如 imgui_impl_allegro5.cpp。一个应用通常是一个平台后端 一个渲染器后端 主 Dear ImGui 源码。例如 example_win32_directx11 示例即组合了imgui_impl_win32.cppimgui_impl_dx11.cpp。examples/ 目录提供了 20 多个覆盖 Win32/Glfw/SDL2/SDL3 × D3D9-12/OpenGL/Metal/Vulkan/WebGPU 等组合的完整可构建应用如 example_glfw_opengl3/、example_sdl3_vulkan/docs/EXAMPLES.md 有详细说明。README 的估计是在支持库已链接的前提下把 Dear ImGui 集成进现有代码库理论上一小时内可完成。完整的初始化/退出序列来自 imgui.cpp// 初始化创建上下文设置选项加载字体 ImGui::CreateContext(); ImGuiIO io ImGui::GetIO(); // 可选设置 io.ConfigFlags例如启用键盘导航 // io.ConfigFlags | ImGuiConfigFlags_NavEnableKeyboard; // 可选io.Fonts-AddFontFromFileTTF(...) 加载 TTF/OTF 字体 ImGui_ImplWin32_Init(hwnd); // 平台后端 ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); // 渲染器后端 // ... 主循环见上一节 ... // 退出 ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext();关于构建方式imgui.cpp 头部注释建议以静态方式把 .cpp 文件编进项目并静态链接而不建议做成共享库DLL编译期行为可通过 imconfig.h 定制。五、集成实战二自定义后端骨架如果你既不想用标准后端、也不想用第三方后端README 与 imgui.cpp 给出了自研后端的完整骨架。与标准后端路径的主要差别在于输入需要你自己逐字段喂入绘制数据渲染由你的RenderDrawData()实现纹理更新需要你自己处理// 初始化 ImGui::CreateContext(); ImGuiIO io ImGui::GetIO(); io.ConfigFlags | ImGuiConfigFlags_NavEnableKeyboard; // 启用键盘导航 io.Fonts-AddFontFromFileTTF(NotoSans.ttf); // 加载字体 while (true) { // 喂入低层输入 io.DeltaTime 1.0f/60.0f; // 帧间隔秒 io.DisplaySize.x 1920.0f; // 显示宽度 io.DisplaySize.y 1280.0f; // 显示高度 io.AddMousePosEvent(mouse_x, mouse_y); // 鼠标位置 io.AddMouseButtonEvent(0, mouse_b[0]); // 鼠标按键 io.AddMouseButtonEvent(1, mouse_b[1]); ImGui::NewFrame(); // 你的应用代码更新与渲染阶段都可以调用 ImGui ImGui::Text(Hello, world!); MyGameUpdate(); MyGameRender(); ImGui::EndFrame(); // 实际上会被 Render() 自动调用但也单独提供 ImGui::Render(); // 更新纹理 ImDrawData* draw_data ImGui::GetDrawData(); for (ImTextureData* tex : *draw_data-Textures) if (tex-Status ! ImTextureStatus_OK) MyImGuiBackend_UpdateTexture(tex); MyImGuiBackend_RenderDrawData(draw_data); // 你的渲染实现 SwapBuffers(); } ImGui::DestroyContext();其中RenderDrawData()的实现指导在 docs/BACKENDS.md 的 “Rendering: Implementing your RenderDrawData function” 一节ImGuiBackendFlags_RendererHasTextures1.92 引入的纹理更新支持则对应各后端中的ImGui_ImplXXXX_UpdateTexture()实现。backends/ 中约 20 个官方后端本身就是最佳的自研参照实现。六、配置体系imconfig.h 与 ImGuiIOREADME 指向 Wiki 的 Getting Started 指南之外仓库内有两个可直接下手的配置入口。编译期imconfig.himconfig.h 是编译期选项模板其头部注释给出的两条使用规则值得逐字遵守方式 A直接编辑imconfig.h更新 Dear ImGui 时注意保留修改方式 B在自己的工程中#define IMGUI_USER_CONFIG my_imgui_config.h然后在自己的文件中写配置指令无需触碰模板。注释同时强调配置必须在所有使用 Dear ImGui 的编译单元中一致定义包括imgui*.cpp和你自己使用 Dear ImGui 的代码因为部分编译期选项会影响数据结构布局并建议在自己的 .cpp 中调用IMGUI_CHECKVERSION()校验布局一致性。模板中值得关注的选项包括IM_ASSERT(_EXPR)断言处理器不建议用 NDEBUG 全部剥离因为断言用于提示编程错误IMGUI_API导出/导入属性。注释明确指出不推荐通过共享库使用 Dear ImGui函数调用开销 不保证 ABI 前后兼容IMGUI_DISABLE_OBSOLETE_FUNCTIONS更新版本后定期开启可清理代码中的废弃 API 用法IMGUI_DISABLE/IMGUI_DISABLE_DEMO_WINDOWS/IMGUI_DISABLE_DEBUG_TOOLS整体禁用或禁用演示窗口、调试工具注释强烈建议开发期间不要禁用演示窗口和调试工具。运行期ImGuiIO 常用字段运行期配置集中在 imgui.h 的ImGuiIO结构体中注释中标注了默认值以下是与主循环直接相关的主要字段字段默认值说明DeltaTime1/60 秒距上一帧的时间每帧更新DisplaySize未设置主显示尺寸像素DisplayFramebufferScale(1, 1)主显示密度Retina 屏上窗口坐标与帧缓冲坐标不同时使用IniFilenameimgui.ini窗口位置/尺寸持久化文件路径设NULL可禁用自动加载/保存IniSavingRate5.0 秒两次保存 .ini 之间的最小间隔ConfigFlags0用户侧配置标志键盘/手柄导航等BackendFlags0由后端设置声明后端支持的特性Fonts/FontDefault自动 / NULL字体图集与默认字体MouseDrawCursorfalse请求 ImGui 绘制鼠标光标无系统光标的平台MouseDragThreshold6.0拖拽判定距离阈值像素KeyRepeatDelay/KeyRepeatRate0.275 / 0.05 秒按键按住后的重复延迟与重复速率MouseDoubleClickTime/MaxDist0.30 秒 / 6.0双击判定时间窗口与距离阈值ConfigMemoryCompactTimer60.0 秒空闲时释放临时窗口/表格内存缓冲的计时器-1 禁用所有选项都可以在运行时的 Demo 窗口 “Configuration” 页中可视化查看与交互调整imgui.h 注释明确指出了这一点这本身就是一个强大的调试手段。七、演示窗口最好的学习入口README 的 “Demo” 一节说明调用ImGui::ShowDemoWindow()会创建一个展示各类特性与示例的演示窗口其代码始终可以在 imgui_demo.cpp 中查阅——文件头部的注释imgui_demo.cpp建议把ShowDemoWindow()接入你游戏/应用一个永远可用的调试菜单且整个文件在不调用时会被链接器剔除零成本。README 同时提供了 Windows 平台的预编译演示二进制包下载1.92.62026-02-25 构建供快速预览并提到社区制作的带源码浏览器的 Web 版 demo。实践中ShowDemoWindow()加上 docs/FAQ.mdREADME “Support, FAQ” 一节明确指向是新手排障的第一站README 反复强调“花时间阅读 FAQ、注释和示例应用”。此外 README 提及项目维护了一套专门的自动化测试体系Dear ImGui Test Engine独立仓库docs/FAQ.md、docs/CONTRIBUTING.md 与 docs/FONTS.md字体加载专题是仓库内其余值得一读的文档。八、许可与署名事实README 末节的署名与许可信息作为引用本项目时应遵守的事实记录如下许可Dear ImGui 采用MIT 许可见 LICENSE.txt嵌入字体ProggyClean 字体Tristan GrimmerMIT 许可、stb_textedit.h / stb_truetype.h / stb_rect_pack.hSean Barrett公有领域——仓库根目录可见对应的 imstb_textedit.h、imstb_truetype.h、imstb_rectpack.h历史项目由 Omar Cornut 开发早期版本在 Media Molecule 支持下开发最早内部用于 PS Vita 平台游戏《Tearaway》社区生态README 列出了大量第三方绑定C、C#、Python、Rust、Lua、Godot、Unity、Unreal 等多数由 cimgui 或 dear_bindings 自动生成与知名第三方扩展如 ImPlot 绘图库、节点编辑器、文本编辑器等实际使用时可按需在社区生态中挑选但注意它们不属于本仓库的官方维护范围。结语回到 README 的核心骨架Dear ImGui 的价值链非常清晰——平台无关的核心文件根目录imgui*.cpp/.h负责布局、交互与绘制数据生成可自由组合的后端backends/ 中约 20 个官方实现 examples/ 中 20 多个完整示例负责输入接入、纹理上传与三角形渲染NewFrame → 任意位置画控件 → Render → GetDrawData/RenderDrawData的四步主循环把两者串起来。由于核心从不触碰 GPU 状态你可以在算法执行中途插入调试面板也可以把渲染延迟到帧末甚至远端执行。对需要在 C 项目中快速构建工具、调试器或检视器的团队而言理解上述结构后从标准后端入手的一小时集成路径见 docs/BACKENDS.md 与 imgui.cpp 骨架注释就是最短的工程路线。【免费下载链接】imguiDear ImGui: Bloat-free Graphical User interface for C with minimal dependencies项目地址: https://gitcode.com/GitHub_Trending/im/imgui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表