☰
Piccolo 引擎集成 Dear ImGui Backends:Platform 与 Renderer 双后端架构解析与实践指南
2026/10/15 15:38:30 网站建设 项目流程
  • 游戏开发
  • 图形学

【免费下载链接】Piccolo

Piccolo (formerly Pilot) – mini game engine for games104

项目地址:https://gitcode.com/gh_mirrors/pi/Piccolo
点击查看免费下载

本篇技术指南以 Dear ImGui 官方文档docs/BACKENDS.md(仓库中位于 engine/3rdparty/imgui/docs/BACKENDS.md)为主体,系统讲解 ImGui 后端(Backends)的职责划分、平台后端与渲染后端的选择、自定义引擎的集成策略,并结合 Piccolo 迷你游戏引擎的真实接入代码(GLFW 平台后端 + Vulkan 渲染后端),说明从初始化到逐帧渲染的完整调用链。读完本文,你将掌握 ImGui 后端机制的核心原理,并能够对照 Piccolo 的源码把 ImGui 移植进自己的引擎。

什么是 Backends:Platform 与 Renderer 的分类

Dear ImGui 的backends/目录存放着面向主流平台与图形 API 的后端实现,其用途是让你在自己的应用或引擎中轻松集成 Dear ImGui。每个后端通常自包含在一对文件中:imgui_impl_XXXX.cpp+imgui_impl_XXXX.h。以 Piccolo 仓库中的 backends/ 目录为例,其中完整保留了 Dear ImGui 官方提供的全部后端源码。

后端按职责分为三大类:

  • 平台后端(Platform Backends):负责鼠标 / 键盘 / 手柄输入、光标形状、时间(timing)与窗口管理。典型代表如 Windows 的 imgui_impl_win32.cpp、GLFW 的 imgui_impl_glfw.cpp、SDL2 的 imgui_impl_sdl.cpp 等。
  • 渲染后端(Renderer Backends):负责创建字体图集纹理(atlas texture)并渲染 ImGui 的绘制数据(draw data)。典型代表如 DirectX11 的 imgui_impl_dx11.cpp、OpenGL/WebGL 的 imgui_impl_opengl3.cpp、Vulkan 的 imgui_impl_vulkan.cpp 等。
  • 高层框架后端(High-level Frameworks Backends):对于某些高层框架,单个后端即可同时承担 Platform 与 Renderer 两部分职责,例如 Allegro 5 的 imgui_impl_allegro5.cpp。如果你最终要为自己的引擎编写自定义后端,官方建议参考这种"一文件双职责"的做法。

一个典型的应用组合方式是:1 个平台后端 + 1 个渲染后端 + Dear ImGui 主源码。例如example_win32_directx11示例应用就组合了 imgui_impl_win32.cpp 与 imgui_impl_dx11.cpp。在 examples/ 目录下共有 20+ 个官方示例应用(如example_glfw_vulkan、example_sdl_opengl3、example_emscripten_opengl3等),对应着各种平台与图形 API 的组合。

一旦 Dear ImGui 成功运行起来,请调用并参考ImGui::ShowDemoWindow()——它定义在 imgui_demo.cpp 中,是学习端侧 API 用法的最佳入口。官方在 imgui.cpp 的注释中也反复强调"调用并阅读 ShowDemoWindow 以了解大部分特性的用法"。

Backends 究竟做了什么:必需功能与可选功能

Dear ImGui 本身高度可移植,运行时只依赖少数几项能力,这些正是每个后端必须提供的:

  • 必需:提供鼠标 / 键盘输入(馈入ImGuiIO结构体);
  • 必需:将字体图集纹理上传到显存;
  • 必需:渲染带裁剪矩形(clipping rectangle)的索引化纹理三角形。

在这三项必需功能之外,可选功能按需启用,官方后端会尽可能多地支持:

  • 可选:自定义纹理绑定(custom texture binding);
  • 可选:剪贴板(clipboard)支持;
  • 可选:手柄(gamepad)支持;
  • 可选:鼠标光标形状(mouse cursor shape)支持;
  • 可选:IME 输入法支持;
  • 可选:多视口(multi-viewports)支持;
  • 等等。

简而言之,每个后端做的就是上述工作外加必要的可移植性胶水代码(portability cruft)。使用官方默认后端的好处在于:你能直接获得全部这些特性,包括那些自己实现起来很困难的部分(例如多视口支持)。这一点在 Piccolo 的接入中得到了印证——引擎只写了极少的桥接代码,就完整拿到了 GLFW 的输入/窗口能力与 Vulkan 的渲染能力,详见下文"Piccolo 实战案例"一节。

核心库与 Backends 的区别:必须理解的分层

理解 Dear ImGui 时,区分核心库(仓库根目录下的文件,如 imgui.cpp、imgui.h、imgui_draw.cpp 等)与本文描述的 backends/目录十分重要:

  • 某些问题可能只与后端或平台相关,与核心库无关;
  • 你几乎可以为任何平台和任何 3D 图形 API 编写后端——甚至可以发挥创意使用软件渲染,或在不同机器上远程渲染。

这个分层设计也解释了为什么 Piccolo 的编辑器 UI 代码(editor_ui.cpp)只包含#include <imgui.h>与#include <imgui_internal.h>,而平台相关的 GLFW/Vulkan 集成则全部收敛在渲染后端的桥接层中(见 ui_pass.cpp)。

如何集成一个后端

集成的起点是"Getting Started",详见同目录下的 EXAMPLES.md。整体流程可归纳为:

  1. 在构建系统中加入核心库源文件(imgui.cpp、imgui_draw.cpp、imgui_tables.cpp、imgui_widgets.cpp)以及所需后端的 .cpp/.h 文件;
  2. 在应用初始化时依次调用平台后端的 Init 函数(如ImGui_ImplGlfw_InitForVulkan)与渲染后端的 Init 函数(如ImGui_ImplVulkan_Init),并填充渲染后端所需的初始化信息结构体;
  3. 在每一帧中依次调用两个后端的NewFrame(),再调用ImGui::NewFrame()开始构建 UI;
  4. 调用ImGui::Render()之后,用渲染后端把绘制数据提交到图形队列(如ImGui_ImplVulkan_RenderDrawData);
  5. 退出时调用各后端的Shutdown()释放资源。

Piccolo 的构建脚本 engine/3rdparty/imgui.cmake 展示了第 1 步的落地方式:它通过file(GLOB ...)收集imgui/*.cpp作为静态库源文件,并显式追加imgui_impl_glfw.cpp/h与imgui_impl_vulkan.cpp/h,最终add_library(imgui STATIC ...)并把 glfw 与 Vulkan 链接进来。

官方后端清单

平台后端(Platforms Backends)

仓库 backends/ 目录中提供的平台后端:

文件目标平台 / API
imgui_impl_android.cppAndroid 原生应用 API
imgui_impl_glfw.cppGLFW(Windows、macOS、Linux 等)
imgui_impl_osx.mmmacOS 原生 API(功能完整度不如 glfw/sdl 后端)
imgui_impl_sdl.cppSDL2(Windows、macOS、Linux、iOS、Android)
imgui_impl_win32.cppWin32 原生 API(Windows)
imgui_impl_glut.cppGLUT/FreeGLUT(官方明确标注为"史前软件",当前强烈不推荐使用)

渲染后端(Renderer Backends)

文件图形 API
imgui_impl_dx9.cppDirectX9
imgui_impl_dx10.cppDirectX10
imgui_impl_dx11.cppDirectX11
imgui_impl_dx12.cppDirectX12
imgui_impl_metal.mmMetal(使用 ObjC)
imgui_impl_opengl2.cppOpenGL 2(传统固定管线,不要与现代 OpenGL 上下文混用)
imgui_impl_opengl3.cppOpenGL 3/4、OpenGL ES 2、OpenGL ES 3(现代可编程管线)
imgui_impl_sdlrenderer.cppSDL_Renderer(SDL2 的可选组件,自 SDL 2.0.18+ 起提供)
imgui_impl_vulkan.cppVulkan
imgui_impl_wgpu.cppWebGPU

高层框架后端(组合 Platform + Renderer)

  • imgui_impl_allegro5.cpp

Emscripten 亦受支持:官方example_emscripten_opengl3示例使用 imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp 的组合,其他组合方式也是可行的。

第三方框架 / 图形 API / 语言的后端绑定

除官方后端外,社区还维护着面向大量第三方框架与引擎的绑定(如 Adventure Game Studio、Cinder、Cocos2d-x、Game Maker Studio2、Godot、LÖVE+LUA、Magnum、Monogame、Ogre、openFrameworks、OpenSceneGraph、SFML、Sokol、Unity、Unreal Engine 等),完整列表见官方 Wiki 的 Bindings 页面。这些第三方绑定通常也遵循"平台 + 渲染"的组合约定,选择时同样建议优先采用官方后端以保证特性完整度。

推荐后端组合

如果你不确定该选哪个后端,官方为可移植应用推荐以下平台 / 框架:

库后端备注
GLFWimgui_impl_glfw.cpp通用跨平台窗口与输入库
SDL2imgui_impl_sdl.cpp功能全面的跨平台媒体库
Sokolutil/sokol_imgui.h比 GLFW/SDL 更低层

在 GLFW 后端中,跨平台的可移植性同样体现在头文件注释里:它要求 GLFW 3.1+,推荐 GLFW 3.3+ 以获得完整特性支持,并提供了ImGui_ImplGlfw_InitForOpenGL/ImGui_ImplGlfw_InitForVulkan/ImGui_ImplGlfw_InitForOther三个针对不同图形环境的初始化入口(见 imgui_impl_glfw.h),这正是 Piccolo 采用 GLFW + Vulkan 组合的依据。

使用自定义引擎?请三思而后行

当你为自己的引擎集成 ImGui 时,很可能会想"直接用引擎自有的高层设施重写一个后端"——官方文档明确建议:想清楚再做。

  • 如果你是 Dear ImGui 新手,请先原样使用现有后端。这会为你节省大量集成时间;
  • 你完全可以之后再决定是否重写自定义后端——大多数情况下,自定义后端的特性更少、bug 比官方标准后端更多;
  • 如果你追求可移植性,可以使用多个后端,并在编译期或运行期之间选择其一。

官方给出的三个典型场景建议:

  • 示例 A:你的引擎基于 Windows + DirectX11,但在 DX11 之上又封装了自己的一套高层渲染系统。建议:先用 imgui_impl_win32.cpp + imgui_impl_dx11.cpp 跑通;跑通后若确有必要,再把 imgui_impl_dx11.cpp 替换为使用自有渲染函数的自定义渲染器,同时保留标准 Win32 平台后端。
  • 示例 B:你的引擎横跨 Windows、Mac、Linux,分别使用 DirectX11、Metal、Vulkan。建议:直接使用多个通用后端;跑通后如确有必要,再用自有抽象替换后端的部分代码。
  • 示例 C:你的引擎运行在官方无法提供公共后端的平台(如 PS4/PS5、Switch),且各子系统均有高层封装。建议:先用一个不可移植后端(如 win32 + 底层图形 API)把桌面版本跑起来,快速熟悉 ImGui 的初始化和工作方式,之后再基于自有引擎 API 重写自定义后端。

总体结论是:为项目自研后端通常不会带来额外价值。这一点在 Piccolo 的架构中体现得很直接——引擎选择了"原样使用"官方后端(GLFW + Vulkan),仅在渲染管线中做薄薄一层桥接,把精力集中在游戏引擎本身的功能开发上。

多视口(Multi-Viewports)特性

'Docking' 分支中的多视口特性允许 ImGui 窗口从主应用窗口中无缝脱离(detach)。其实现方式是在 Platform 与 Renderer 后端之上增加一层额外机制,让 ImGui 能向平台发送特定请求,例如:"创建额外的 OS 窗口"、"创建渲染上下文"、"获取该窗口的 OS 位置"等——详见ImGuiPlatformIO结构。

两点关键提示:

  1. 用 100% 自有抽象正确支持多视口特性,比支持单视口(single-viewport)困难得多;
  2. 如果你直接使用未修改的imgui_impl_XXXX.cpp文件,就能自动获得与视口 / 平台窗口相关的改进与修复,无需额外工作。

从 imgui_impl_glfw.h 头文件可以看到,GLFW 后端已标记支持ImGuiConfigFlags_ViewportsEnable多视口;而 imgui_impl_vulkan.h 则注明其多视口 / 平台窗口功能依赖ImGui_ImplVulkanH_XXX系列内部辅助函数(如ImGui_ImplVulkanH_CreateOrResizeWindow、ImGui_ImplVulkanH_SelectSurfaceFormat、ImGui_ImplVulkanH_SelectPresentMode),这些辅助代码主要服务于官方示例与多视口内部实现,你自己的引擎通常不需要直接使用它们。

Piccolo 实战案例:GLFW + Vulkan 后端的完整接入链

Piccolo(mini game engine for games104)在仓库中实测了"平台后端 + 渲染后端"的标准组合,具体为imgui_impl_glfw.cpp(平台)+ imgui_impl_vulkan.cpp(渲染),两者由构建脚本 engine/3rdparty/imgui.cmake 显式纳入静态库imgui。

初始化:填充 ImGui_ImplVulkan_InitInfo

引擎的 UI 渲染通道位于 ui_pass.cpp,其initializeUIRenderBackend展示了 Vulkan 渲染后端的标准初始化姿势:

  1. 调用ImGui_ImplGlfw_InitForVulkan(m_window, true)初始化 GLFW 平台后端(第二个参数install_callbacks=true表示由 ImGui 安装 GLFW 回调,同时会转发用户此前安装的回调);
  2. 构造并零初始化ImGui_ImplVulkan_InitInfo,填入引擎 Vulkan RHI 中的Instance、PhysicalDevice、Device、图形队列族(QueueFamily)、图形队列(Queue)、描述符池(DescriptorPool)与Subpass = _main_camera_subpass_ui;
  3. 特别地,MinImageCount与ImageCount均设为 3,并在注释中说明"可能与真实交换链图像数不同,参见ImGui_ImplVulkanH_GetMinImageCountFromPresentMode"——这与 imgui_impl_vulkan.h 中MinImageCount >= 2、ImageCount >= MinImageCount的约束完全吻合;
  4. 调用ImGui_ImplVulkan_Init(&init_info, render_pass),传入引擎自定义渲染通道的VkRenderPass句柄。

字体图集上传

uploadFonts()展示了"必需功能"之一的实现:引擎分配一次性命令缓冲(RHI_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT),调用ImGui_ImplVulkan_CreateFontsTexture将字体图集纹理上传到显存,提交并queueWaitIdle等待完成后,再调用ImGui_ImplVulkan_DestroyFontUploadObjects释放上传用的临时对象——与 imgui_impl_vulkan.h 导出的ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer)/ImGui_ImplVulkan_DestroyFontUploadObjects()接口一一对应。

逐帧渲染

draw()展示了标准的每帧调用顺序:

ImGui_ImplVulkan_NewFrame(); // 渲染后端新帧 ImGui_ImplGlfw_NewFrame(); // 平台后端新帧(收集输入到 ImGuiIO) ImGui::NewFrame(); // 核心库开始构建 UI m_window_ui->preRender(); // 引擎层回调,构建编辑器窗口内容 ImGui::Render(); // 生成绘制数据 ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), current_command_buffer); // 提交渲染

引擎还通过pushEvent/popEvent在 GPU 调试标签中标记了 "ImGUI" 事件,方便在 RenderDoc 等工具中定位 UI 渲染区间。

编辑器端 UI:ShowDemoWindow 之外的真实业务用法

Piccolo 编辑器(editor_ui.cpp)展示了端侧 API 的实战形态:它使用ImGui::SetNextWindowPos/SetNextWindowSize/SetNextWindowViewport结合主视口(ImGui::GetMainViewport())布局菜单栏,用ImGui::DockBuilderXXX系列(DockBuilderSplitNode、DockBuilderDockWindow、DockBuilderFinish)构建可停靠布局,将 "World Objects"、"Components Details"、"File Content"、"Game Engine" 四个面板停靠到对应区域;通过ImGui::BeginMenuBar/BeginMenu/MenuItem实现 "Reload Current Level"、"Save Current Level"、渲染调试开关(骨骼显示、包围盒、相机运行时信息)等菜单功能,并用ImGui::Selectable实现对象选中交互。这些 API 都属于核心库的端侧接口,与后端完全解耦——这正是"核心库 + 后端"分层设计的收益。

总结

Dear ImGui 的后端体系是一套"核心库保持零平台依赖、后端负责全部平台与渲染细节"的成熟架构。集成时坚持三条原则即可获得最佳体验:优先原样使用官方后端、按"1 平台后端 + 1 渲染后端"组合、仅在确有必要时再自研后端并优先替换渲染端。Piccolo 以 GLFW + Vulkan 的官方后端组合在 ui_pass.cpp 中给出了一个可直接对照的最小集成范本,覆盖了初始化、字体图集上传与逐帧渲染的全流程,值得作为自定义引擎集成 ImGui 的参考起点。

  • 游戏开发
  • 图形学

【免费下载链接】Piccolo

Piccolo (formerly Pilot) – mini game engine for games104

项目地址:https://gitcode.com/gh_mirrors/pi/Piccolo
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询