在D3D12中绘制多个对象

问题描述:

我正在修补DirectX 12,并在试图绘制“棋盘”时碰壁。我有相当多的搜索网络,所以任何帮助/指针将不胜感激。在D3D12中绘制多个对象

在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

你只是写你的平移矩阵为模型的每个副本的同一块内存。由于在你写完最后一个翻译矩阵的时候,GPU还没有开始绘制第一个模型,所以这些模型中任何一个将要绘制的唯一地方就是写入最后一个翻译矩阵的地方。

您需要将每个矩阵写入内存中独立的不同位置,并确保它们不会被其他任何东西覆盖,直到GPU完成绘制模型。

调用DrawIndexedInstanced的行为不会立即指示GPU绘制任何东西,它只是向命令列表添加一个命令,以便将来在某个时间绘制该对象。如果你不熟悉图形API和GPU执行的异步特性,你应该多读一点它的工作原理。