QT window 中的 DirectX11 渲染不会丢失其他小部件

DirectX11 rendering in QT window without losing other widgets

我正在使用 DirectX 渲染到我的 QT window,在我开始添加控件之前效果很好。然后,当 directx 覆盖它们时,它们会闪烁。 winforms 中的解决方案是在表单的 OnPaintBackground 中进行渲染,但我还没有在 QT 中找到等效项。有没有类似的东西或者可以用更好的方式完成?

我正在考虑渲染为纹理,然后以某种方式将其转换为像素图,然后在 paintEvent() 中绘制。

能够将按钮、面板和其他控件放置在正在呈现的内容之上(实时)对我来说很重要。

编辑。

Sergio Monteleone 的回答几乎有效,控件上的闪烁消失了。我在代码中更改了控件的父级并将其设置为主要 window 而不是 QFrame。但是现在如果我在控件之间快速移动鼠标,我会在控件之间得到一个奇怪的灰色框。

PushButton 后面和 GroupBox 上面的灰色矩形只在几分之一秒内可见。知道这是为什么吗?

编辑 2.

我改变了问题的主题来描述实际问题而不是一个解决方案。

我假设您正在使用 QWidget 的本机 hWnd 使用 DirectX 绘图。如果是这种情况,其他 Qt 控件会闪烁,因为当小部件重新绘制自身时,它也会导致完整的背景更新。然后,您使用 DirectX 在该表面上绘制,丢弃 Qt 控件到目前为止绘制的任何内容。

那么为什么它们会闪烁而不是完全消失?

QWidget 在内部使用 双缓冲 (查看文档 here)。 所以这真的取决于 Qt 后台缓冲区何时失效。

你可以使用一个简单的技巧:添加一个 QFrame 到 window,将 Qt 控件放在它上面,然后使用框架的 hWnd 作为DirectX 目标。此外,您可能需要将该 QFrame 的 autoFillBackground 属性 设置为 false。 应该 允许您渲染到背景。

感谢 Sergio Monteleone 的帮助,我提出了两个我认为可以接受的解决方案。 我已将这两种方法上传到 github: https://github.com/Zephyrox/QT5DX11

方法 1 - 工作但速度慢

  • 从 QFRAME 而不是主要的 window 获取 HWND。
  • 将 DX 渲染转换为纹理
  • 将其转换为QBitmap并在qframe paintEvent中绘制
  • qframe 必须每帧更新

方法 2 - 几乎可行,速度快但会产生闪烁(Sergio Monteleone 的解决方案)

  • 在 qframe 上渲染 DX,将控件放在 qframe 的顶部(不在)

    如果你疯狂地在按钮之间移动鼠标,当 vsync 打开时,它们之间会出现一个闪烁的框。 当 VSync 开启时,这种方法在我的机器上实际上更慢。这当然是因为没有渲染。我没有尝试在这里做任何繁重的渲染,但我怀疑如果 fps 下降到 60 左右,即使没有垂直同步也会出现闪烁。

编辑。在渲染到的 qframe 上将 UpdatesEnabled 设置为 false,即使 fps 或 vsync 较慢也不会出现闪烁。

如果您有兴趣查看实现,请查看存储库。将 DX 纹理转换为 QImage 结果非常简单:

    HRESULT hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast< void** >(&pSurface));

    if(hr != S_OK)
        return;

    context->CopyResource(renderTargetTex, pSurface);

    D3D11_MAP eMapType = D3D11_MAP_READ;
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    context->Map(renderTargetTex, 0, eMapType, NULL, &mappedResource);

    BYTE* pYourBytes = (BYTE*)mappedResource.pData;

    bitmap = QImage(pYourBytes, windowWidth, windowHeight, QImage::Format_RGBA8888);

        context->Unmap(renderTargetTex, 0);

此代码仅用于测试方法,它缺少大多数错误检查,可能会泄漏大量内存。