VulkanSceneGraph学习教程(二十二)
2026/8/22 18:01:12 网站建设 项目流程

第 22 章 与 ImGui 集成

本章定位:调试面板、实时调参离不开 UI。vsgImGui是独立组件库,将 Dear ImGui 叠加到 VSG 渲染之上。本章讲集成模式(具体类名随版本可能微调,模式稳定)。

摘要:本章介绍如何在 VulkanSceneGraph (VSG) 中集成 Dear ImGui 调试界面。通过vsgImGui外部组件库,创建 ImGui 叠加渲染节点,实现每帧更新 UI 控件。关键步骤包括:1) 安装并链接vsgImGui库;2) 继承RenderImGui类重写update方法绘制控件;3) 使用CollectEvents转发鼠标键盘事件;4) 将 UI 控件绑定到 uniform 值实现实时调参。最终构建带调试面板的查看器,支持曝光等参数动态调整。


22.1 本章目标

  • 了解vsgImGui组件库的作用;
  • 掌握「ImGui 叠加节点 + 每帧update绘制控件」的集成模式;
  • 将 UI 控件绑定到场景参数(呼应第 10 章 uniform)。

22.2 前置准备

  • 第 8 章(状态命令)与第 10 章(uniform/描述符)已读;
  • 已安装vsgImGui组件库(独立仓库,非核心)。

22.3 组件库与链接

vsgImGui外部组件库(与vsgXchange同级),需单独安装并链接:

find_package(vsgImGui REQUIRED) target_link_libraries(my_app PRIVATE vsg::vsg vsgImGui::vsgImGui)

若你的版本把 ImGui 整合进核心,则无需find_package;但按当前仓库现状,vsgImGui是独立组件库,请以你安装的版本为准。


22.4 集成模式:ImGui 叠加节点

标准做法:创建一个渲染 ImGui 的节点(通常是vsgImGui::RenderImGui的子类),把它加入场景图。它在自己的渲染通道里把 Dear ImGui 的绘制指令输出到屏幕,叠加在主场景之上。

// 1) 自定义一个 ImGui 节点,重写每帧更新classMyGui:publicvsgImGui::RenderImGui{public:MyGui(ref_ptr<vsg::Camera>cam,ref_ptr<vsg::floatValue>exposure):camera(cam),exposure(exposure){}voiddoUpdate(bool&updated)override// 每帧调用,绘制控件{ImGui::Begin("调试面板");floate=exposure->value;if(ImGui::SliderFloat("曝光",&e,0.0f,3.0f))exposure->value=e;// 修改 uniform(见第 10 章)ImGui::Text("FPS: %.1f",ImGui::GetIO().Framerate);ImGui::End();updated=true;}ref_ptr<vsg::Camera>camera;ref_ptr<vsg::floatValue>exposure;};

方法名(doUpdate/update)与基类依据vsgImGui版本而定;核心是「每帧回调里调用 ImGui 控件 API」。请对照你所用版本的RenderImGui头文件确认重写点。


22.5 事件转发

要让鼠标/键盘驱动 ImGui,需要把 VSG 的PointerEvent/KeyEvent转发给 ImGui。组件库通常提供事件收集器(如vsgImGui::CollectEvents),将其添加到Viewer的事件处理器:

viewer->addEventHandlers({vsgImGui::CollectEvents::create(guiNode)});

这样 ImGui 能正确响应悬停、点击、输入。


22.6 绑定到场景参数(实时调参)

UI 控件直接修改第 10 章的Value类型即可实时生效:

autoexposure=vsg::floatValue::create(1.0f);// 作为 DescriptorBuffer 绑到管线(第 10 章)autoubo=vsg::DescriptorBuffer::create(exposure,0);// GUI 里改 exposure->value,帧循环里:exposure->value=e;ubo->copyDataListToBuffers();// CPU → GPU

于是拖动滑块,画面曝光立即变化——典型的「调试面板实时参数调整」。


22.7 完整示例:带调试面板的查看器

autoexposure=vsg::floatValue::create(1.0f);autogui=MyGui::create(camera,exposure);// 你的 RenderImGui 子类autoroot=vsg::Group::create();root->addChild(model);root->addChild(gui);// 将 ImGui 叠加到场景图autocommandGraph=vsg::createCommandGraphForView(window,camera,root);viewer->assignRecordAndSubmitTaskAndPresentation({commandGraph});viewer->addEventHandlers({vsgImGui::CollectEvents::create(gui)});

22.8 常见问题

现象原因解决代码/配置示例
编译找不到vsgImGui没安装/链接组件库find_package(vsgImGui REQUIRED)+ 链接错误 CMakeLists.txt
cmake<br>find_package(vsg REQUIRED)<br>target_link_libraries(my_app PRIVATE vsg::vsg)<br>
正确 CMakeLists.txt
cmake<br>find_package(vsg REQUIRED)<br>find_package(vsgImGui REQUIRED) # ← 必须添加<br>target_link_libraries(my_app PRIVATE vsg::vsg vsgImGui::vsgImGui)<br>
ImGui 不响应输入没转发事件CollectEvents(或等价事件收集器)添加到 Viewer错误写法(缺少事件收集器)
cpp<br>auto gui = MyGui::create(camera, exposure);<br>root->addChild(gui);<br>// 忘记添加事件收集器,ImGui 无法接收鼠标/键盘事件<br>
正确写法
cpp<br>auto gui = MyGui::create(camera, exposure);<br>root->addChild(gui);<br>viewer->addEventHandlers({ vsgImGui::CollectEvents::create(gui) }); // ← 关键<br>
控件改了无效果没把值同步到 uniform修改value后调用copyDataListToBuffers()错误写法(只改值不同步)
cpp<br>void doUpdate(bool& updated) override {<br> ImGui::SliderFloat("曝光", &exposure->value, 0.0f, 3.0f);<br> // 缺少 copyDataListToBuffers(),GPU 未更新<br> updated = true;<br>}<br>
正确写法
cpp<br>void doUpdate(bool& updated) override {<br> float e = exposure->value;<br> if (ImGui::SliderFloat("曝光", &e, 0.0f, 3.0f)) {<br> exposure->value = e;<br> ubo->copyDataListToBuffers(); // ← 同步到 GPU<br> }<br> updated = true;<br>}<br>
面板挡住主场景叠加顺序/通道问题确保 ImGui 在最后渲染(叠加通道)错误场景图结构
cpp<br>auto root = vsg::Group::create();<br>root->addChild(gui); // ImGui 节点在前<br>root->addChild(model); // 模型节点在后,会被 ImGui 遮挡<br>
正确场景图结构
cpp<br>auto root = vsg::Group::create();<br>root->addChild(model); // 先渲染模型<br>root->addChild(gui); // 最后渲染 ImGui(叠加在最上层)<br>// 或者使用专门的叠加通道:<br>// auto overlay = vsg::OverlayNode::create(gui);<br>// root->addChild(overlay);<br>

22.9 小结

  • vsgImGui是外部组件库,提供 ImGui 叠加渲染节点;
  • 模式:子类RenderImGui→ 每帧update绘制控件 → 加入场景图;事件通过收集器转发给 ImGui;
  • UI 控件直接修改Value/uniform,配合copyDataListToBuffers()实时生效。

22.10 延伸阅读与下一章预告

  • 第 10 章《描述符与资源绑定》:UI 修改的就是这些 uniform;
  • 第 24 章《模型查看器》:把 ImGui 面板做成完整的查看器控制;
  • 第 26 章《调试技巧》:验证层 + RenderDoc 配合参数调整。

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

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

立即咨询