游戏引擎场景编辑器实现:Direct3D只绘制一次

发表于2023-08-29
评论0 1.08w浏览

在阅读《DirectX 12 3D游戏开发实战》,也就是DirectX的龙书。 
看到第4章:Direct3D的初始化的代码。 
Direct3D的初始化的代码的Draw函数,我添加了flag,让Draw函数只绘制场景一次,绘制后,交换前后台缓冲区。 
这样窗口使用的一直是仅一次绘制的前台缓冲区的图像数据。

void InitDirect3DApp::Draw(const GameTimer& gt) 
{  
   //flag的作用:只绘制一次 
   static bool flag = false; 
   if (flag == true) {  
       return; 
    } 

   // Reuse the memory associated with command recording. 
   // We can only reset when the associated command lists have finished execution on the GPU. 
   ThrowIfFailed(mDirectCmdListAlloc->Reset()); 

   // A command list can be reset after it has been added to the command queue via ExecuteCommandList. 
   // Reusing the command list reuses memory. 
   ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr)); 

   // Indicate a state transition on the resource usage. 
   mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), 
 D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); 

   // Set the viewport and scissor rect.  This needs to be reset whenever the command list is reset. 
   mCommandList->RSSetViewports(1, &mScreenViewport); 
   mCommandList->RSSetScissorRects(1, &mScissorRect); 

   // Clear the back buffer and depth buffer. 
   mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr); 
   mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr); 
 
   // Specify the buffers we are going to render to. 
   mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView()); 
 
   // Indicate a state transition on the resource usage. 
   mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), 
 D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); 

   // Done recording commands. 
   ThrowIfFailed(mCommandList->Close()); 
 
   // Add the command list to the queue for execution. 
   ID3D12CommandList* cmdsLists[] = { mCommandList.Get() }; 
   mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists); 

   // swap the back and front buffers 
   ThrowIfFailed(mSwapChain->Present(0, 0)); 
   mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount; 

   flag = true; 

   // Wait until frame commands are complete.  This waiting is inefficient and is 
   // done for simplicity.  Later we will show how to organize our rendering code 
   // so we do not have to wait per frame. 
   FlushCommandQueue(); 

 

 

用UE、Unity的时候,游戏引擎的场景编辑器里界面呈现游戏场景,在我们不碰场景编辑器的时候,场景编辑器始终是一个画面。 
如果游戏引擎为场景编辑器里的画面一直不断地渲染场景,交换前后台缓冲,会非常消耗性能。 
在用户没有碰场景编辑器时,即场景编辑器里的场景没有摄像机移动、角度变换,选定物体,平移、缩放、旋转物体,添加物体时,场景编辑器里的画面是不变的。 
所以,在用户没有碰场景编辑器时,游戏引擎只需要为场景编辑器里的场景绘制一次,交换一次前后台缓冲即可。 
这样,窗口的图像数据始终是一个画面。 
在用户使用场景编辑器时,才需要进行用户交互时长的渲染、呈现(交换前后台缓冲区指针)。 
如此,可以节省性能。

 

  • 允许他人重新传播作品,但他人重新传播时必须在所使用作品的正文开头的显著位置,注明用户的姓名、来源及其采用的知识共享协议,并与该作品在磨坊上的原发地址建立链接
  • 可对作品重新编排、修改、节选或者以作品为基础进行创作和发布
  • 可将作品进行商业性使用

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引