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

199 阅读2分钟

在阅读《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的时候,游戏引擎的场景编辑器里界面呈现游戏场景,在我们不碰场景编辑器的时候,场景编辑器始终是一个画面。

如果游戏引擎为场景编辑器里的画面一直不断地渲染场景,交换前后台缓冲,会非常消耗性能。

在用户没有碰场景编辑器时,即场景编辑器里的场景没有摄像机移动、角度变换,选定物体,平移、缩放、旋转物体,添加物体时,场景编辑器里的画面是不变的。

所以,在用户没有碰场景编辑器时,游戏引擎只需要为场景编辑器里的场景绘制一次,交换一次前后台缓冲即可。

这样,窗口的图像数据始终是一个画面。

在用户使用场景编辑器时,才需要进行用户交互时长的渲染、呈现(交换前后台缓冲区指针)。

如此,可以节省性能。