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