2015-12-27 87 views
1

我正在修補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

回答

2

你只是寫你的平移矩陣爲模型的每個副本的同一塊內存。由於在你寫完最後一個翻譯矩陣的時候,GPU還沒有開始繪製第一個模型,所以這些模型中任何一個將要繪製的唯一地方就是寫入最後一個翻譯矩陣的地方。

您需要將每個矩陣寫入內存中獨立的不同位置,並確保它們不會被其他任何東西覆蓋,直到GPU完成繪製模型。

調用DrawIndexedInstanced的行爲不會立即指示GPU繪製任何東西,它只是向命令列表添加一個命令,以便將來在某個時間繪製該對象。如果你不熟悉圖形API和GPU執行的異步特性,你應該多讀一點它的工作原理。