前言
本章将介绍vsg与Qt的窗口集成方案vsgQt。本章将从窗口初始化、消息映射、定时器运行帧循环三方方面进行介绍,以深入分析vsg与Qt的窗口集成的具体技术实现细节。
目录
- 1 vsgQt下载与编译
- 2 vsg与Qt的窗口集成技术方案
- 3 效果演示
1vsgQt下载与编译
下载地址,最新的版本为v0.4.0。
https://github.com/vsg-dev/vsgQt.git使用CMake-gui对vsgQt进行编译,需要依赖vulkanscenegraph(v1.1.15)、qt(qt5或者qt6)。点击CMake Configuration选择本地的vs studio作为生成器(generator)。设置好依赖库vulkanscenegraph(v1.1.15)、qt。接着点击生成("Generate")按钮生成解决方案。最后点击打开("Open")按钮打开解决方案。如下图所示:
其中vulkanscenegraph(v1.1.15)windows下的编译结果可从如下地址下载:通过网盘分享的文件:https://pan.baidu.com/s/1cSA5TPWubEB-r-00kMuryA?pwd=izir 提取码: izir,其中包含了glslang和vsg二进制文件,下载后可将其中的cmake路径设置到vsg_DIR、glslang_DIR、SPIRV-Tools_DIR、SPRIV-Tools-opt_DIR中即可。当然VulkanSDK的安装是比不可少的,需前往VulKan官网下载安装。
其中qt执行qt5和qt6两个版本,通过QT_PACKAGE_NAME名即可。qt5(5.12.10)可通过如下网盘地址下载:https://pan.baidu.com/s/1UAsLsbO_DZgCEpqJieSbvA?pwd=khrs 提取码: khrs。qt6的安装可参考:Qt6安装教程——国内源-CSDN博客。以visual studio 2022为例,安装过程需勾选msvc2022_64开发包进行安装。安装完成后Visual studio需安装Qt Visual studio Tools,并通过【扩展】->【Options】设置开发包路径:
其中Name可任意,Location指定为安装的Qt对应的Visual studio的开发包路径。
最后点击【Open Project】按钮,打开解决方案,进行编译,编译结果可从如下地址下载:https://pan.baidu.com/s/1oor41Tcjwu1dVQKWSSb_5A?pwd=vm9z 提取码: vm9z
2 vsg与Qt的窗口集成技术方案
vsg与Qt的结合主要通过窗口初始化、消息映射、定时器运行帧循环三个方面实现。整体的类图集成关系如下所示:
其中窗口初始化过程中将QWindow中的窗口句柄传递给vsg::WindowTraits,具体代码实现如下:
void Window::initializeWindow() { if (windowAdapter) return; if (!traits) traits = vsg::WindowTraits::create(); #if defined(VK_USE_PLATFORM_WIN32_KHR) traits->nativeWindow = reinterpret_cast<HWND>(winId()); #elif defined(VK_USE_PLATFORM_XLIB_KHR) traits->nativeWindow = static_cast<::Window>(winId()); #elif defined(VK_USE_PLATFORM_XCB_KHR) traits->nativeWindow = static_cast<xcb_window_t>(winId()); #elif defined(VK_USE_PLATFORM_MACOS_MVK) traits->nativeWindow = winId(); #endif traits->x = convert_coord(x()); traits->y = convert_coord(y()); traits->width = convert_coord(width()); traits->height = convert_coord(height()); windowAdapter = vsg::Window::create(traits); _initialized = true; }其中消息映射,是将Qt窗口捕获到的消息映射为vsg的消息的过程,其中vsgQt::KeyboardMap记录了两者的消息映射表,通过重写QWindow的各种消息响应函数,将Qt窗口捕获到的消息转换为vsg的消息,通过重写vsg::Viewer的pollEvent函数,将转换后的vsg消息队列接入到vsg的帧循环过程中。vsgQt::Viewer代码具体实现如下,其中windows->bufferedEvents为转换后得到的vsg消息队列。
bool Viewer::pollEvents(bool discardPreviousEvents) { if (discardPreviousEvents) _events.clear(); for (auto& window : _windows) { _events.splice(_events.end(), window->bufferedEvents); window->bufferedEvents.clear(); } return !_events.empty(); }定时器运行帧循环部分,通过vsgQt::Viewer提供Render接口,定时执行Render方法实现,定时默认时间为8ms,其中Render方法的具体实现如下:
void Viewer::render(double simulationTime) { if (!continuousUpdate && requests.load() == 0) { //vsg::info("render() no render : requests = ", requests.load()); return; } if (advanceToNextFrame(simulationTime)) { handleEvents(); update(); recordAndSubmit(); present(); } else { if (status->cancel()) { QCoreApplication::quit(); } } requests = 0; }3 效果演示
最后展示下运行效果:
| vsgqtviewer |
| vsgqtwindows |
| vsgqtmdi |