菜单

多视口支持

相关源文件

本页面解释了 Dear ImGui 的多视口支持功能,该功能允许创建和管理多个平台窗口(视口)。多视口支持实现了诸如分离式窗口和浮动工具窗口等功能,这些窗口可以移动到主应用程序窗口之外,类似于许多专业应用程序。

有关基本窗口管理(在单个视口内)的信息,请参阅窗口和布局系统

概述与目的

多视口支持将 Dear ImGui 的功能扩展到其传统的单窗口渲染范式之外,允许窗口从主视口中分离。此功能实现了

  • 创建可移动到不同显示器上的浮动/分离式窗口
  • 存在于主应用程序窗口之外的真实弹出窗口
  • 对用户界面(UI)的多显示器支持
  • 类似于专业应用程序的更复杂布局

来源:imgui.cpp7-100 imgui_internal.h1-50

架构

多视口支持建立在两部分架构上

  1. 核心 ImGui:提供视口管理、跟踪和高级逻辑
  2. 后端实现:平台和渲染器后端实现实际的视口创建和处理

来源:imgui.h180-201 imgui_internal.h170-205

核心结构

多视口系统依赖于几个关键结构

ImGuiViewport

表示单个平台窗口并包含

  • 位置和大小信息
  • DPI 缩放
  • 平台特定句柄
  • 各种状态标志

ImGuiPlatformIO

包含平台后端必须实现以支持多视口功能的函数指针,包括

  • 窗口创建和销毁
  • 窗口定位和大小调整
  • 窗口焦点和可见性管理
  • 渲染功能

来源:imgui.h150-250 imgui_internal.h179-185

启用多视口支持

要启用多视口支持,您需要

  1. ImGuiIO 中设置 ImGuiConfigFlags_ViewportsEnable 标志
  2. 使用支持视口的平台后端
  3. 使用支持视口的渲染器后端

此外,您可以控制其他视口行为

  • ImGuiConfigFlags_ViewportsNoTaskBarIcons: 防止为辅助视口创建任务栏图标
  • ImGuiConfigFlags_ViewportsNoMerge: 防止视口自动合并
  • ImGuiConfigFlags_ViewportsNoAutoMerge: 禁用靠近时视口的自动合并

来源:imgui.cpp275-285 imgui.h232-233

后端支持

并非所有平台和渲染器后端都完全支持多视口功能。下图显示了当前的支持状态

来源:backends/imgui_impl_vulkan.cpp94-110 backends/imgui_impl_opengl3.cpp9-21 backends/imgui_impl_dx12.cpp6-8

使用流程

当启用多视口支持时,每帧的操作流程为

来源:imgui.cpp5000-5200 backends/imgui_impl_vulkan.cpp300-350

窗口分离行为

启用多视口后,Dear ImGui 窗口可以从主视口中分离

  1. 默认情况下,带有 ImGuiWindowFlags_ViewportWindow 标志的窗口可以被分离
  2. 将窗口拖到主视口边缘可以将其分离
  3. 通过将窗口拖回主视口可以重新附加它们

此过程由 ImGui 自动处理,包括

  • 为分离的视口创建新的平台窗口
  • 管理视口之间的输入焦点
  • 确保视口之间渲染一致

来源:imgui.cpp5300-5400

实现细节

视口创建

当窗口被分离时,ImGui

  1. 创建一个新的 ImGuiViewport 实例
  2. 调用平台后端的 Platform_CreateWindow 函数
  3. 配置新视口(大小、位置等)
  4. 将其添加到 ImGuiContext 中的视口列表

输入处理

输入事件需要路由到正确的视口

  • 平台后端必须实现视口特定的输入处理
  • ImGui 的内部输入路由系统将事件定向到相应的窗口
  • 鼠标位置相对于包含视口进行标准化

渲染过程

使用多视口渲染遵循以下步骤

  1. 主视口照常渲染
  2. 辅助视口在循环中渲染
  3. 对于每个视口
    • 获取视口特定的绘制数据
    • 设置视口特定的渲染状态
    • 绘制视口内容
    • 呈现/交换视口的缓冲区

平台和渲染器后端协同工作以完成此过程

  • 平台后端管理窗口/表面
  • 渲染器后端处理实际绘图

来源:imgui_internal.h190-200 backends/imgui_impl_dx11.cpp250-300 backends/imgui_impl_vulkan.cpp350-400

平台注意事项

Windows

在 Windows 平台上,多视口通过原生 Win32 窗口实现。

主要注意事项

  • 每个视口都必须实现 Windows 消息处理
  • 每个视口维护自己的设备/交换链

macOS/iOS

在 Apple 平台上,多视口通过 NSWindow/UIWindow 实现。

主要注意事项

  • Metal 是首选的渲染后端
  • 需要对 Retina 显示器和 DPI 缩放进行特殊处理

Linux/SDL/GLFW

在 Linux 上或使用 SDL/GLFW 时

  • 每个视口对应一个新的 SDL_Window 或 GLFWwindow
  • 平台后端必须处理窗口创建和管理
  • X11/Wayland 特性需要额外的协调

来源:backends/imgui_impl_win32.cpp backends/imgui_impl_metal.mm backends/imgui_impl_sdl2.cpp

性能考量

多视口支持会带来一些性能开销

领域影响缓解
内存每个视口都需要自己的渲染资源限制分离窗口的数量
CPU额外的绘制调用和状态管理考虑批处理操作
显卡多个帧缓冲区和渲染目标尽可能使用共享资源
输入跨视口的输入事件路由后端高效事件处理

来源:imgui.cpp5500-5550

使用示例

以下是启用和使用多视口的基本示例

来源:imgui.cpp290-310

调试和故障排除

多视口支持的常见问题包括

  1. 缺少后端支持:确保平台和渲染器后端都支持多视口
  2. 渲染伪影:检查正确的视口设置和渲染状态管理
  3. 输入处理问题:验证输入事件是否正确路由到正确的视口

ImGui 提供了一些调试工具

  • 演示窗口有一个多视口部分,用于测试功能
  • 指标窗口显示所有活动视口及其属性
  • 可以为视口操作启用调试日志

来源:imgui_demo.cpp95-120

局限性

多视口系统的当前限制

  1. 并非所有后端都完全支持
  2. 渲染代码中的额外复杂性
  3. 可能需要操作系统特定的适配
  4. 移动和网络平台支持有限或不兼容
  5. 管理多个窗口的性能开销

来源:docs/TODO.txt30-40

结论

Dear ImGui 中的多视口支持提供了一种强大的方式,通过可分离的窗口创建更复杂的 UI 布局。启用此功能后,用户可以创建浮动工具窗口、多显示器界面以及类似专业应用程序的布局。

虽然实现需要一些额外的配置和考量,但该系统旨在支持的平台和图形 API 之间无缝工作,同时保持 Dear ImGui 以其简洁和即时性而闻名的特点。