菜单

渲染器后端

相关源文件

渲染器后端是 Dear ImGui 中用于将抽象绘图命令转换为特定图形 API 调用的组件。它们负责 ImGui 的即时模式 GUI 系统与 DirectX、OpenGL、Vulkan、Metal 和 WebGPU 等各种图形 API 之间的通信。本页将介绍 ImGui 渲染器后端的架构、实现和用法。

有关平台后端(处理窗口创建、输入等)的信息,请参阅 平台后端

1. 架构和目的

渲染器后端充当 Dear ImGui 的通用绘图命令与特定图形 API 之间的桥梁。它们负责以下任务:

  • 将 ImGui 的顶点/索引数据转换为 GPU 可兼容的格式
  • 着色器管理和管线设置
  • 纹理处理和资源绑定
  • 渲染状态管理
  • 绘图命令处理

来源:backends/imgui_impl_vulkan.cpp92-111 backends/imgui_impl_opengl3.cpp224-255 backends/imgui_impl_dx11.cpp53-72

2. 可用的渲染器后端

Dear ImGui 为不同的图形 API 提供了多个渲染器后端

后端文件图形 API主要功能
DirectX 9imgui_impl_dx9.cppDirectX 9.0旧版支持,BGRA 颜色
DirectX 10imgui_impl_dx10.cppDirectX 10现代 DirectX 功能
DirectX 11imgui_impl_dx11.cppDirectX 11现代管线,着色器资源
DirectX 12imgui_impl_dx12.cppDirectX 12现代,基于描述符的方法
OpenGL 2imgui_impl_opengl2.cppOpenGL 2.x旧版固定功能管线
OpenGL 3imgui_impl_opengl3.cppOpenGL 3+/ES2/ES3基于着色器的现代 OpenGL
Vulkanimgui_impl_vulkan.cppVulkan显式 GPU 控制,现代
Metalimgui_impl_metal.mmMetal (Apple)iOS/macOS 原生渲染器
WebGPUimgui_impl_wgpu.cppWebGPUWeb/原生跨平台

大多数后端都支持带有 ImGuiBackendFlags_RendererHasVtxOffset 标志和用户纹理绑定的超大网格(64k+ 顶点)。

来源:backends/imgui_impl_vulkan.cpp1-8 backends/imgui_impl_opengl3.cpp1-9 backends/imgui_impl_dx11.cpp1-7 backends/imgui_impl_dx12.cpp1-8 backends/imgui_impl_metal.mm1-6 backends/imgui_impl_wgpu.cpp1-8

3. 通用后端接口

所有渲染器后端都遵循类似的 API 模式

3.1 初始化和清理

初始化通常涉及存储设备引用、设置后端功能以及创建初始资源。例如,在 Vulkan 后端中,初始化会设置描述符布局和管线状态。

来源:backends/imgui_impl_vulkan.cpp111-131 backends/imgui_impl_opengl3.cpp297-400 backends/imgui_impl_dx11.cpp142-206

3.2 帧处理

NewFrame() 为新帧准备后端,通常会检查设备对象是否需要创建。RenderDrawData() 将 ImGui 命令列表转换为 API 特定的绘图命令。

来源:backends/imgui_impl_vulkan.cpp491-623 backends/imgui_impl_opengl3.cpp503-637 backends/imgui_impl_dx11.cpp146-315

3.3 资源管理

这些函数管理着色器、缓冲区和纹理等 GPU 资源。字体纹理是单独处理的,因为在运行时重新创建它是一个常见的用例。

来源:backends/imgui_impl_vulkan.cpp537-579 backends/imgui_impl_opengl3.cpp640-731 backends/imgui_impl_dx12.cpp317-427

4. 渲染管线

核心渲染流程在所有后端中遵循类似的流程

此流程将 ImGui 的抽象绘图命令转换为特定图形后端的具体 API 调用。

来源:backends/imgui_impl_vulkan.cpp491-623 backends/imgui_impl_opengl3.cpp503-637 backends/imgui_impl_dx11.cpp146-315

5. 顶点和索引缓冲区

所有后端都管理顶点和索引缓冲区,以将几何数据传输到 GPU

缓冲区管理的关键方面

  1. 缓冲区创建:如果缓冲区不存在或太小,将分配新的 GPU 缓冲区
  2. 数据上传:将顶点和索引数据从 ImGui 的结构复制到 GPU 内存
  3. 绑定:将缓冲区设置为活动状态以进行渲染
  4. 动态调整大小:缓冲区会根据需要增长以容纳更大的 UI

来源:backends/imgui_impl_vulkan.cpp519-537 backends/imgui_impl_opengl3.cpp503-541 backends/imgui_impl_dx11.cpp155-243

6. 着色器和管线状态

每个后端都定义了适合其图形 API 的着色器

6.1 着色器程序

大多数后端使用简单的着色器对,它们

  • 使用正交投影矩阵变换顶点
  • 采样纹理并应用顶点颜色

例如,Vulkan 后端定义了 GLSL 着色器,它们

  1. 在顶点着色器中应用顶点变换 backends/imgui_impl_vulkan.cpp268-286
  2. 在片段着色器中采样纹理并应用颜色 backends/imgui_impl_vulkan.cpp334-343

OpenGL 3 同样提供了 GLSL 着色器,适用于桌面和移动端。

6.2 管线配置

后端配置通用渲染状态

状态管理典型配置
混合Alpha 混合(SrcAlpha, OneMinusSrcAlpha)
深度测试禁用(UI 是 2D 的)
剔除禁用(显示所有三角形)
裁剪启用(用于裁剪)
基本类型三角形列表
视口设置为帧缓冲大小
采样器线性过滤,夹取寻址

来源:backends/imgui_impl_vulkan.cpp447-489 backends/imgui_impl_opengl3.cpp429-501 backends/imgui_impl_dx11.cpp88-142

7. 纹理处理

ImGui 至少需要一个纹理用于其字体图集,并且应用程序通常希望绑定自己的纹理。

7.1 字体纹理

字体纹理的工作流程对于所有后端都是通用的

  1. 从 ImGui 获取原始字体图集纹理数据
  2. 在图形 API 中创建纹理
  3. 将像素数据上传到 GPU 内存
  4. 创建必要的视图/资源以供绑定

来源: backends/imgui_impl_vulkan.cpp537-579 backends/imgui_impl_opengl3.cpp640-687 backends/imgui_impl_dx11.cpp322-377

7.2 用户纹理

后端支持使用正确的 API 对象作为 ImTextureID 来绑定用户纹理

后端ImTextureID 类型
DirectX 9LPDIRECT3DTEXTURE9
DirectX 11ID3D11ShaderResourceView*
DirectX 12D3D12_GPU_DESCRIPTOR_HANDLE
OpenGL 2/3GLuint (纹理 ID)
VulkanVkDescriptorSet
MetalMTLTexture
WebGPUWGPUTextureView

来源: backends/imgui_impl_vulkan.h119-123 backends/imgui_impl_dx12.h4-7 backends/imgui_impl_opengl3.h7-8

8. 集成步骤

要在您的应用程序中使用渲染器后端

  1. 选择合适的后端以支持您的图形 API
  2. 在 ImGui 上下文创建后初始化后端
  3. 在每一帧开始时调用 NewFrame 函数
  4. 在 ImGui::Render() 之后调用 RenderDrawData 以将绘制数据发送到 GPU
  5. 在关闭应用程序时关闭后端

来源: backends/imgui_impl_vulkan.h111-117 backends/imgui_impl_opengl3.h33-37 backends/imgui_impl_dx11.h27-34

9. 高级功能

9.1 绘制回调

所有渲染器后端都支持通过 ImDrawList::AddCallback() 注册特殊的绘制回调。特殊值 ImDrawCallback_ResetRenderState 告知渲染器重置其状态。

来源: backends/imgui_impl_vulkan.cpp581-590 backends/imgui_impl_dx11.cpp287-290

9.2 渲染状态访问

许多后端通过 ImGuiPlatformIO.Renderer_RenderState 结构在绘制回调期间公开其渲染状态,以实现高级集成。

来源: backends/imgui_impl_vulkan.h129-137 backends/imgui_impl_dx12.h69-73 backends/imgui_impl_wgpu.h58-65

9.3 资源处理

后端在资源管理上有不同的方法

  • Vulkan 提供显式描述符管理,使用 ImGui_ImplVulkan_AddTexture()
  • DirectX 12 使用描述符句柄来处理纹理
  • OpenGL 使用简单的纹理 ID

来源: backends/imgui_impl_vulkan.h119-123 backends/imgui_impl_dx12.h37-44

10. 常见模式和最佳实践

  1. 后端数据模式:所有后端都将其数据存储在特定于上下文的结构中,可通过 ImGui_ImplXXX_GetBackendData() 访问
  2. 延迟初始化:许多资源在首次使用时创建
  3. 资源增长:缓冲区会根据需要自动增长,无需手动调整大小
  4. 后端标志:后端在 io.BackendFlags 中设置适当的标志以指示其功能
  5. API 抽象:每个后端将 ImGui 的绘制模型转换为其 API 的匹配模式

来源: backends/imgui_impl_vulkan.cpp380-383 backends/imgui_impl_opengl3.cpp252-255 backends/imgui_impl_dx11.cpp97-100

11. 结论

Dear ImGui 中的渲染器后端为将即时模式 GUI 渲染与各种图形 API 集成提供了一种灵活的方式。通过抽象化这些 API 之间的差异,ImGui 允许开发者编写一次 UI 代码即可在任何地方进行渲染。

在实现您自己的渲染器后端或扩展现有后端时,请遵循既定的模式,并专注于在 ImGui 的绘制抽象与目标 API 的特定要求之间进行转换。