在D3D12中绘制多个对象

时间:2015-12-27 19:02:38

标签: c++ directx-12

我正在修补DirectX 12,并在试图绘制“棋盘格”时撞墙。我已经搜索了很多网,所以任何帮助/指针都会受到赞赏。

在D3D11中,工作代码如下。

auto context = m_deviceResources->GetD3DDeviceContext();

for (int i = -10; i < 10; i++)
{
    for (int j = -10; j < 10; j++)
    {
        // perform translation
        XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixTranslation(i, j, 0.0f)));
        context->UpdateSubresource(
            m_constantBuffer.Get(),
            0,
            NULL,
            &m_constantBufferData,
            0,
            0
            );

        // shaders, etc...

        // draw the square
        context->DrawIndexed(
            m_indexCount,
            0,
            0
            );
    }
}

在D3D12中,我尝试过做同样的事情,但似乎全局执行翻译,因为所有广场都在同一个位置。

bool Sample3DSceneRenderer::Render()
{
    if (!m_loadingComplete)
    {
        return false;
    }

    DX::ThrowIfFailed(m_deviceResources->GetCommandAllocator()->Reset());

    DX::ThrowIfFailed(m_commandList->Reset(m_deviceResources->GetCommandAllocator(), m_pipelineState.Get()));


    PIXBeginEvent(m_commandList.Get(), 0, L"Draw the objects");
    {
        m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
        ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
        m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

        CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandle(m_cbvHeap->GetGPUDescriptorHandleForHeapStart(), m_deviceResources->GetCurrentFrameIndex(), m_cbvDescriptorSize);
        m_commandList->SetGraphicsRootDescriptorTable(0, gpuHandle);

        D3D12_VIEWPORT viewport = m_deviceResources->GetScreenViewport();
        m_commandList->RSSetViewports(1, &viewport);
        m_commandList->RSSetScissorRects(1, &m_scissorRect);

        CD3DX12_RESOURCE_BARRIER renderTargetResourceBarrier =
            CD3DX12_RESOURCE_BARRIER::Transition(m_deviceResources->GetRenderTarget(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
        m_commandList->ResourceBarrier(1, &renderTargetResourceBarrier);

        D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = m_deviceResources->GetRenderTargetView();
        D3D12_CPU_DESCRIPTOR_HANDLE depthStencilView = m_deviceResources->GetDepthStencilView();
        m_commandList->ClearRenderTargetView(renderTargetView, m_colors.Get_background(), 0, nullptr);
        m_commandList->ClearDepthStencilView(depthStencilView, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);


        m_commandList->OMSetRenderTargets(1, &renderTargetView, false, &depthStencilView);

        m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
        m_commandList->IASetIndexBuffer(&m_indexBufferView);


        for (float i = -10.0f; i < 10.0f; i++)
        {
            for (float j = -10.0f; j < 10.0f; j++)
            {
                // as far as I know, this is how I should perform the translation
                XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixTranslation(i, j, 0.0f)));

                UINT8* destination = m_mappedConstantBuffer + (m_deviceResources->GetCurrentFrameIndex() * c_alignedConstantBufferSize);
                memcpy(destination, &m_constantBufferData, sizeof(m_constantBufferData));

                m_commandList->DrawIndexedInstanced(6, 1, 0, 0, 0);
            }
        }

        CD3DX12_RESOURCE_BARRIER presentResourceBarrier =
            CD3DX12_RESOURCE_BARRIER::Transition(m_deviceResources->GetRenderTarget(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
        m_commandList->ResourceBarrier(1, &presentResourceBarrier);
    }
    PIXEndEvent(m_commandList.Get());

    DX::ThrowIfFailed(m_commandList->Close());

    ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
    m_deviceResources->GetCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);

    return true;
}

谢谢你,  Chelsey

1 个答案:

答案 0 :(得分:3)

您只需将翻译矩阵写入模型的每个副本的同一块内存中。由于GPU在完成最后一个模型的翻译矩阵编写之后甚至还没有开始绘制第一个模型,因此这些模型中唯一要绘制的位置是写入最后一个翻译矩阵的位置。

您需要将每个矩阵写入内存中的一个单独的不同位置,并确保在GPU完成绘制模型之前不会被其他任何内容覆盖。

调用DrawIndexedInstanced的行为不会立即指示GPU绘制任何内容,它只是在命令列表中添加命令以在将来的某个时间绘制对象。如果您不熟悉Graphics API和GPU执行的异步性质,您应该阅读更多有关它如何工作的内容。