菜单

自定义后端开发

相关源文件

本页面提供了创建 Dear ImGui 自定义后端的全面指南。尽管 ImGui 已经为流行的平台和渲染器提供了许多预构建的后端,但在将 ImGui 集成到不支持的图形 API 或平台时,您可能需要创建自定义后端。有关使用现有后端的信息,请参阅后端系统概述

概述

Dear ImGui 需要两种类型的后端才能正常运行

  1. 平台后端:负责窗口创建、输入事件(鼠标、键盘等)、剪贴板操作以及其他平台特定功能。
  2. 渲染器后端:负责使用特定的图形 API 渲染 ImGui 的绘制数据。

自定义后端实现必须遵循特定的模式和接口,才能与 Dear ImGui 核心正确集成。

来源

后端架构

每个后端都必须维护自己的状态,并提供一套标准的函数用于初始化、帧管理和清理。平台后端和渲染器后端都遵循类似的模式

  1. 用于存储后端状态的数据结构
  2. 用于初始化和关闭后端的函数
  3. 用于为每一帧做准备和渲染的函数
  4. 后端特定的实用函数

来源

每帧执行流程

使用自定义后端的 ImGui 的典型执行流程遵循此模式

来源

创建自定义平台后端

平台后端负责向 ImGui 提供输入数据(鼠标、键盘等)并处理平台特定操作,如剪贴板和光标管理。

所需组件

  1. 后端状态结构
  1. 核心功能
功能目的
初始化使用窗口和其他必要句柄初始化平台后端
关机清理资源并恢复原始状态
新帧更新时间差并为主帧准备平台输入
处理事件处理平台特定事件,并将其转换为 ImGui 事件
  1. 输入管理

自定义平台后端需要将平台特定的输入事件转换为 ImGui 的输入模型

  • io.AddKeyEvent() - 用于键盘输入
  • io.AddKeyAnalogEvent() - 用于游戏手柄触发器等模拟输入
  • io.AddMousePosEvent() - 用于鼠标位置
  • io.AddMouseButtonEvent() - 用于鼠标按钮状态
  • io.AddMouseWheelEvent() - 用于鼠标滚轮/滚动输入
  • io.AddFocusEvent() - 用于窗口焦点更改
  • io.AddInputCharacter() - 用于文本输入
  1. 平台能力

在 ImGuiIO 中设置适当的后端能力标志

来源

平台后端实现步骤

  1. 创建后端状态结构以存储平台特定数据

  2. 实现初始化函数,该函数:

    • 设置后端数据结构
    • 存储平台句柄(窗口等)
    • 设置后端标志
    • 设置后端名称
  3. 实现事件处理函数,该函数:

    • 处理平台特定事件
    • 将输入事件转换为 ImGui 输入
    • 更新 ImGui IO 状态
  4. 实现 NewFrame 函数,该函数:

    • 更新时间差
    • 更新显示尺寸
    • 更新鼠标位置和按钮状态
    • 更新键盘修饰键
  5. 实现平台特定实用函数用于

    • 剪贴板操作
    • 鼠标光标管理
    • 窗口管理(如果需要)

来源

创建自定义渲染器后端

渲染器后端将 ImGui 的绘制命令转换为图形 API 特定的渲染命令。

所需组件

  1. 后端状态结构
  1. 核心功能
功能目的
初始化使用设备/上下文句柄初始化渲染器
关机释放所有渲染资源
新帧在必要时准备渲染器以处理新帧
RenderDrawData使用图形 API 渲染 ImGui 绘制数据
CreateFontsTexture将字体图集纹理上传到 GPU
CreateDeviceObjects创建 GPU 资源(着色器、缓冲区等)
DestroyDeviceObjects释放 GPU 资源
  1. 渲染能力

在 ImGuiIO 中设置适当的后端能力标志

  1. 纹理处理

提供一种方法,通过将某个图形 API 纹理句柄视为 ImTextureID 来向 ImGui 注册用户纹理。

来源

渲染器后端实现步骤

  1. 创建后端状态结构以存储渲染资源

  2. 实现初始化函数,该函数:

    • 设置后端数据结构
    • 存储图形设备/上下文句柄
    • 设置后端标志
    • 设置后端名称
  3. 实现设备对象创建,该操作:

    • 创建着色器
    • 创建顶点/索引缓冲区
    • 创建管线状态
    • 创建采样器状态
  4. 实现 RenderDrawData 函数,该函数:

    • 设置渲染状态(混合模式等)
    • 使用 ImGui 数据更新顶点/索引缓冲区
    • 将 ImGui 绘制命令转换为 API 特定的绘制调用
    • 处理剪裁矩形
    • 按需绑定纹理
  5. 实现字体纹理创建以渲染文本

来源

后端状态管理

两种类型的后端都需要进行适当的状态管理。通用模式如下:

  1. 将后端数据存储在 ImGui 上下文中
  2. 提供一个 getter 函数来访问后端数据

这种模式有利于支持多个 ImGui 上下文,尽管这不是推荐的使用模式。

来源

顶点和绘制数据处理

渲染器后端的一个关键部分是处理顶点和索引数据

  1. 准备缓冲区,其大小适合当前帧
  2. 将数据从 ImGui 的顶点和索引缓冲区复制到渲染器缓冲区
  3. 设置着色器 uniform 以用于投影矩阵和其他参数
  4. 处理绘制命令,以便使用正确的纹理、剪刀等渲染每个命令

来源

处理多上下文支持

虽然不推荐(优先使用多视口而不是多个上下文),但后端应支持多个 ImGui 上下文

  1. 将后端数据存储在当前上下文的 IO 结构中
  2. 使用后端数据获取函数访问当前上下文数据
  3. 添加适当的清理以防止上下文销毁时发生内存泄漏

来源

最佳实践

  1. 错误处理

    • 检查空指针和失败的 API 调用
    • 为调试提供有意义的错误消息
    • 在错误路径上清理资源
  2. 资源管理

    • 正确初始化和释放所有资源
    • 最小化每帧的资源创建/销毁
    • 尽可能重用缓冲区
  3. 性能考量

    • 最小化渲染过程中的状态更改
    • 使用适当的缓冲区大小以减少重新分配
    • 尽可能将相似的绘制命令进行批处理
  4. 兼容性

    • 优雅地处理不同的 API 版本
    • 为缺失的功能提供回退
    • 记录最低 API 要求
  5. 集成

    • 允许使用不同的渲染上下文/设备
    • 尽可能避免全局状态
    • 使后端可重用且依赖项最少

来源

测试自定义后端

  1. 功能测试

    • 测试所有输入类型(鼠标、键盘、游戏手柄)
    • 测试剪贴板功能
    • 测试光标类型和可见性
    • 测试窗口大小调整处理
  2. 渲染测试

    • 使用标准小部件进行测试
    • 使用自定义渲染和用户纹理进行测试
    • 使用不同字体大小和样式进行测试
    • 使用高 DPI 显示器进行测试
  3. 边界情况

    • 使用非常大的 UI 元素进行测试
    • 使用大量 UI 元素进行测试(压力测试)
    • 使用快速窗口大小调整进行测试
    • 使用多个显示器进行测试

来源

结论

为 Dear ImGui 创建自定义后端需要理解 ImGui API 和目标平台或渲染 API。通过遵循现有后端中建立的模式并实现所需接口,您可以将 ImGui 与几乎任何平台或图形系统集成。

请记住,后端应

  1. 正确地将平台输入转换为 ImGui 事件
  2. 高效地渲染 ImGui 绘制命令
  3. 妥善管理资源
  4. 进行干净的初始化和关闭

遵循这些指南并研究现有的后端实现,您可以创建健壮的自定义后端,无缝地将 Dear ImGui 与您的应用程序集成。