|
|
@@ -52,10 +52,73 @@ void ShapeApp::OnResize()
|
|
|
|
|
|
void ShapeApp::Update(const GameTimer& gt)
|
|
|
{
|
|
|
+ UpdateCamera(); // 更 View 矩阵
|
|
|
+
|
|
|
+ // 确定当前使用的帧资源索引序号和帧资源
|
|
|
+ mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
|
|
|
+ mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
|
|
|
+
|
|
|
+ // 如果当前帧资源并没有被 GPU 使用,则强制等待
|
|
|
+ if (mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
|
|
|
+ {
|
|
|
+ HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
|
|
|
+ ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
|
|
|
+ WaitForSingleObject(eventHandle, INFINITE);
|
|
|
+ CloseHandle(eventHandle);
|
|
|
+ }
|
|
|
+
|
|
|
+ UpdateObjectCBs();
|
|
|
+ UpdateMainPassCB(gt);
|
|
|
}
|
|
|
|
|
|
void ShapeApp::Draw(const GameTimer& gt)
|
|
|
{
|
|
|
+ auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
|
|
|
+ cmdListAlloc->Reset();
|
|
|
+
|
|
|
+ if (mIsWireframe)
|
|
|
+ {
|
|
|
+ ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque_wireframe"].Get()));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
|
|
|
+ }
|
|
|
+
|
|
|
+ mCommandList->RSSetViewports(1, &mScreenViewport);
|
|
|
+ mCommandList->RSSetScissorRects(1, &mScissorRect);
|
|
|
+
|
|
|
+ mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
|
|
|
+ mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
|
|
|
+ mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
|
|
|
+
|
|
|
+ mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
|
|
|
+
|
|
|
+ ID3D12DescriptorHeap* descHeaps[] = { mCbvHeap.Get() };
|
|
|
+ mCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps);
|
|
|
+
|
|
|
+ mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
|
|
|
+
|
|
|
+ int passCbvIndex = mPassCbvOffset + mCurrFrameResourceIndex;
|
|
|
+ auto passCbvHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE(mCbvHeap->GetGPUDescriptorHandleForHeapStart());
|
|
|
+ passCbvHandle.Offset(passCbvIndex, mCbvSrvUavDescriptorSize);
|
|
|
+ mCommandList->SetGraphicsRootDescriptorTable(1, passCbvHandle);
|
|
|
+
|
|
|
+ DrawRenderItems(mCommandList.Get(), mOpaqueRitems);
|
|
|
+
|
|
|
+ mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
|
|
|
+
|
|
|
+ mCommandList->Close();
|
|
|
+
|
|
|
+ ID3D12CommandList* cmdList[] = { mCommandList.Get() };
|
|
|
+ mCommandQueue->ExecuteCommandLists(_countof(cmdList), cmdList);
|
|
|
+
|
|
|
+ ThrowIfFailed(mSwapChain->Present(0, 0));
|
|
|
+
|
|
|
+ mCurrentBackBuffer = (mCurrentBackBuffer + 1) % SwapChainBufferCount;
|
|
|
+
|
|
|
+ mCurrFrameResource->Fence = ++mCurrentFence;
|
|
|
+ mCommandQueue->Signal(mFence.Get(), mCurrentFence);
|
|
|
}
|
|
|
|
|
|
void ShapeApp::OnMouseDown(WPARAM btnState, int x, int y)
|
|
|
@@ -415,3 +478,87 @@ void ShapeApp::BuildFrameResource()
|
|
|
mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(), 1, (UINT)mAllRitems.size()));
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+void ShapeApp::UpdateCamera()
|
|
|
+{
|
|
|
+ mEyePos.x = mRadius * sinf(mPhi) * cosf(mTheta);
|
|
|
+ mEyePos.z = mRadius * sinf(mPhi) * sinf(mTheta);
|
|
|
+ mEyePos.y = mRadius * cosf(mPhi);
|
|
|
+
|
|
|
+ // Build the view matrix.
|
|
|
+ XMVECTOR pos = XMVectorSet(mEyePos.x, mEyePos.y, mEyePos.z, 1.0f);
|
|
|
+ XMVECTOR target = XMVectorZero();
|
|
|
+ XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
|
|
|
+
|
|
|
+ XMMATRIX view = XMMatrixLookAtLH(pos, target, up);
|
|
|
+ XMStoreFloat4x4(&mView, view);
|
|
|
+}
|
|
|
+
|
|
|
+void ShapeApp::UpdateObjectCBs()
|
|
|
+{
|
|
|
+ auto currObjectCB = mCurrFrameResource->ObjectCB.get();
|
|
|
+ for (auto& e : mAllRitems)
|
|
|
+ {
|
|
|
+ if (e->NumFramesDirty > 0)
|
|
|
+ {
|
|
|
+ XMMATRIX world = XMLoadFloat4x4(&e->World);
|
|
|
+
|
|
|
+ ObjectConstants objConstants;
|
|
|
+ XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
|
|
|
+
|
|
|
+ currObjectCB->CopyData(e->ObjCBIndex, objConstants);
|
|
|
+
|
|
|
+ e->NumFramesDirty--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void ShapeApp::UpdateMainPassCB(const GameTimer& gt)
|
|
|
+{
|
|
|
+ XMMATRIX view = XMLoadFloat4x4(&mView);
|
|
|
+ XMMATRIX proj = XMLoadFloat4x4(&mProj);
|
|
|
+
|
|
|
+ XMMATRIX viewProj = XMMatrixMultiply(view, proj);
|
|
|
+ XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
|
|
|
+ XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
|
|
|
+ XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
|
|
|
+
|
|
|
+ XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
|
|
|
+ XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
|
|
|
+ XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
|
|
|
+ XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
|
|
|
+ XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
|
|
|
+ XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
|
|
|
+ mMainPassCB.EyePosW = mEyePos;
|
|
|
+ mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
|
|
|
+ mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
|
|
|
+ mMainPassCB.NearZ = 1.0f;
|
|
|
+ mMainPassCB.FarZ = 1000.0f;
|
|
|
+ mMainPassCB.TotalTime = gt.TotalTime();
|
|
|
+ mMainPassCB.DeltaTime = gt.DeltaTime();
|
|
|
+
|
|
|
+ auto currPassCB = mCurrFrameResource->PassCB.get();
|
|
|
+ currPassCB->CopyData(0, mMainPassCB);
|
|
|
+}
|
|
|
+
|
|
|
+void ShapeApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
|
|
|
+{
|
|
|
+ UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
|
|
|
+
|
|
|
+ auto objectCB = mCurrFrameResource->ObjectCB->Resource();
|
|
|
+
|
|
|
+ for (size_t index = 0; index < ritems.size(); ++index) {
|
|
|
+ const auto& ri = ritems[index];
|
|
|
+
|
|
|
+ cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
|
|
|
+ cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
|
|
|
+ cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
|
|
|
+
|
|
|
+ UINT cbvIndex = mCurrFrameResourceIndex * (UINT)mOpaqueRitems.size() + ri->ObjCBIndex;
|
|
|
+ auto cbvHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE(mCbvHeap->GetGPUDescriptorHandleForHeapStart());
|
|
|
+ cbvHandle.Offset(cbvIndex, mCbvSrvUavDescriptorSize);
|
|
|
+
|
|
|
+ cmdList->SetGraphicsRootDescriptorTable(0, cbvHandle);
|
|
|
+ cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
|
|
|
+ }
|
|
|
+}
|