我正在使用DirectX渲染到我的QT窗口,在我开始添加控件之前效果很好。然后当directx超越它们时它们闪烁。 winforms中的解决方案是在表单的OnPaintBackground中进行渲染,但我没有在QT中找到等价物。是否有类似的东西或能以更好的方式完成?
我正在考虑渲染到纹理,然后以某种方式将其转换为像素图,然后我在paintEvent()中绘制。
对我来说,能够将按钮,面板和其他控件置于正在渲染的内容(实时)上非常重要。
EDIT。
Sergio Monteleone的回答几乎可以解决,控件上的闪烁消失了。我在代码中更改控件的父级并将其设置为主窗口而不是QFrame。但是现在,如果我在它们之间快速移动鼠标,我会在控件之间出现一个奇怪的灰色框。
PushButton后面和GroupBox上方的灰色矩形只能在几分之一秒内看到。知道为什么会这样吗?
编辑2。
我改变了问题的主题来描述实际问题,而不是一个解决方案。
答案 0 :(得分:1)
我认为你使用QWidget的原生hWnd绘制DirectX。如果是这种情况,则另一个Qt控制闪烁,因为当窗口小部件重新绘制自身时,它也会导致完整的后台更新。然后,使用DirectX在该表面上绘制,丢弃到目前为止Qt控件绘制的内容。
那么为什么他们闪烁而不是完全消失?
QWidget 在内部使用双缓冲(查看文档here)。 所以它实际上取决于Qt后台缓冲区何时失效。
你可以使用一个简单的技巧:在窗口中添加 QFrame ,将Qt控件置于其上,然后使用框架的hWnd作为DirectX目标。此外,您可能需要将该QFrame的 autoFillBackground 属性设置为false。这个应该允许你渲染到后台。
答案 1 :(得分:0)
感谢Sergio Monteleone,我提出了两个我认为可以接受的解决方案。 我已将这两种方法上传到github: https://github.com/Zephyrox/QT5DX11
方法1 - 工作但很慢
方法2 - 几乎可以工作,速度快但可以产生闪烁(Sergio Monteleone的解决方案)
在qframe上渲染DX,将控件放在qframe(不在其中)
之上如果你像疯了一样在按钮之间移动鼠标,当vsync为ON时,它们之间会出现一个闪烁的框。 当VSync为ON时,此方法实际上在我的机器上较慢。这当然是因为没有渲染。我没有试过在这里做任何重渲染,但我怀疑如果fps下降到60左右,即使没有vsync也会看到闪烁。
修改。在渲染的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);
此代码仅用于测试方法,它缺少大多数错误检查,可能会泄漏大量内存。