最近要做个游戏场景编辑器,需要directx11配合gui框架使用,所以简单地弄了一个directx11嵌入到Qt窗体中的程序。
1 建立工程
建一个Qt的工程,配置好directx的包含目录和库目录(以及附加依赖项),Qt vs2013 add-in的话很方便,直接在vs2013里面加,Qt creator的话写到pro文件里,可以选择生成对应的ui文件,或者不生成。
2 代码结构
工程的结构
- D3d11RenderWidget类继承自QWidegt,用于directx11渲染
- MainWidget继承自QMainWindow,是包含dx11渲染窗体的父窗体
- Effects.fx是shader文件,VS和PS写到一起,注意要在工程中设置排除编译
- main函数是程序入口
3 关键代码
(1)dx11嵌入到Qt中就需要获得某个widgt的句柄hwnd,所以在D3D初始化时要改一个参数,swapChainDesc.OutputWindow=(HWND)winId()
swapChainDesc.BufferDesc=bufferDesc; swapChainDesc.SampleDesc.Count=1; swapChainDesc.SampleDesc.Quality=0; swapChainDesc.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.BufferCount=1; swapChainDesc.OutputWindow=(HWND)winId(); swapChainDesc.Windowed=TRUE; swapChainDesc.SwapEffect=DXGI_SWAP_EFFECT_DISCARD;
(2)用于渲染的子widget必须设置属性为
setAttribute(Qt::WA_PaintOnScreen,true); setAttribute(Qt::WA_NativeWindow,true);
否则渲染是乱的
(3)渲染更新借助的就是Qt的paintEvent函数,在里面再调用update()就可以实现渲染循环。(也可以设置定时器隔一定时间强制刷新,不过这样效果不好)
void D3d11RenderWidget::paintEvent(QPaintEvent *event) { //计算fps frameCount++; if(getTime() > 1.0f) { fps=frameCount; frameCount=0; startFPStimer(); //设置父窗口标题显示fps值 parentWidget()->setWindowTitle("FPS: "+QString::number(fps)); } frameTime=getFrameTime(); //更新场景和渲染场景 UpdateScene(frameTime); RenderScene(); //保证此函数体每一帧都调用 update(); }
(4)必须重写resizeEvent函数,重新设置帧缓存、深度和模板缓存以及视口,防止窗口缩放时场景被拉伸或者视口不对应
void D3d11RenderWidget::resizeEvent(QResizeEvent *event)
4 截图
源代码:
csdn:demo
github:demo
版权声明:转载请注明地址,谢谢
时间: 2024-10-25 06:30:28