ShapeApp.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. #include "ShapeApp.h"
  2. #include "GeometryGenerator.h"
  3. const std::string PSKey = "PS";
  4. const std::string VSKey = "VS";
  5. ShapeApp::ShapeApp(HINSTANCE hInstance) : D3DApp(hInstance)
  6. {
  7. }
  8. ShapeApp::~ShapeApp()
  9. {
  10. }
  11. bool ShapeApp::Initialize()
  12. {
  13. if (!D3DApp::Initialize()) {
  14. return false;
  15. }
  16. // 重置命令列表
  17. ThrowIfFailed(mCommandList->Reset(mCommandAllocator.Get(), nullptr));
  18. BuildRootSignature();
  19. BuildShaderAndInputLayout();
  20. BuildShapeGeometry();
  21. BuildRenderItems();
  22. BuildFrameResource();
  23. BuildDescriptorHeaps();
  24. BuildConstantBuffers();
  25. BuildPSO();
  26. // 执行初始化时的命令
  27. ThrowIfFailed(mCommandList->Close());
  28. ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  29. mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  30. // 等待初始化命令完成
  31. FlushCommandQueue();
  32. return true;
  33. }
  34. void ShapeApp::OnResize()
  35. {
  36. D3DApp::OnResize();
  37. // 窗口大小更新时 更新视图矩阵
  38. XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f * MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  39. XMStoreFloat4x4(&mProj, P);
  40. }
  41. void ShapeApp::Update(const GameTimer& gt)
  42. {
  43. UpdateCamera(); // 更 View 矩阵
  44. // 确定当前使用的帧资源索引序号和帧资源
  45. mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  46. mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  47. // 如果当前帧资源并没有被 GPU 使用,则强制等待
  48. if (mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  49. {
  50. HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  51. ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  52. WaitForSingleObject(eventHandle, INFINITE);
  53. CloseHandle(eventHandle);
  54. }
  55. UpdateObjectCBs();
  56. UpdateMainPassCB(gt);
  57. }
  58. void ShapeApp::Draw(const GameTimer& gt)
  59. {
  60. auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  61. cmdListAlloc->Reset();
  62. if (mIsWireframe)
  63. {
  64. ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque_wireframe"].Get()));
  65. }
  66. else
  67. {
  68. ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  69. }
  70. mCommandList->RSSetViewports(1, &mScreenViewport);
  71. mCommandList->RSSetScissorRects(1, &mScissorRect);
  72. mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  73. mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  74. mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  75. mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  76. ID3D12DescriptorHeap* descHeaps[] = { mCbvHeap.Get() };
  77. mCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps);
  78. mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  79. int passCbvIndex = mPassCbvOffset + mCurrFrameResourceIndex;
  80. auto passCbvHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE(mCbvHeap->GetGPUDescriptorHandleForHeapStart());
  81. passCbvHandle.Offset(passCbvIndex, mCbvSrvUavDescriptorSize);
  82. mCommandList->SetGraphicsRootDescriptorTable(1, passCbvHandle);
  83. DrawRenderItems(mCommandList.Get(), mOpaqueRitems);
  84. mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  85. mCommandList->Close();
  86. ID3D12CommandList* cmdList[] = { mCommandList.Get() };
  87. mCommandQueue->ExecuteCommandLists(_countof(cmdList), cmdList);
  88. ThrowIfFailed(mSwapChain->Present(0, 0));
  89. mCurrentBackBuffer = (mCurrentBackBuffer + 1) % SwapChainBufferCount;
  90. mCurrFrameResource->Fence = ++mCurrentFence;
  91. mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  92. }
  93. void ShapeApp::OnMouseDown(WPARAM btnState, int x, int y)
  94. {
  95. mLastMousePos.x = x;
  96. mLastMousePos.y = y;
  97. SetCapture(mhMainWnd);
  98. }
  99. void ShapeApp::OnMouseUp(WPARAM btnState, int x, int y)
  100. {
  101. ReleaseCapture();
  102. }
  103. void ShapeApp::OnMouseMove(WPARAM btnState, int x, int y)
  104. {
  105. if ((btnState & MK_LBUTTON) != 0)
  106. {
  107. float dx = XMConvertToRadians(0.25f * static_cast<float>(x - mLastMousePos.x));
  108. float dy = XMConvertToRadians(0.25f * static_cast<float>(y - mLastMousePos.y));
  109. mTheta += dx;
  110. mPhi += dy;
  111. mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f);
  112. }
  113. else if ((btnState & MK_RBUTTON) != 0)
  114. {
  115. float dx = 0.005f * static_cast<float>(x - mLastMousePos.x);
  116. float dy = 0.005f * static_cast<float>(y - mLastMousePos.y);
  117. mRadius += dx - dy;
  118. mRadius = MathHelper::Clamp(mRadius, 3.0f, 15.0f);
  119. }
  120. mLastMousePos.x = x;
  121. mLastMousePos.y = y;
  122. }
  123. void ShapeApp::BuildDescriptorHeaps()
  124. {
  125. UINT renderNum = mOpaqueRitems.size();
  126. // 每个渲染项一个 CBV,再加一个 PrePass CBV 用于给每个渲染项共享的 CBV
  127. // 由于有 gNumFrameResources 帧资源,所以是 (renderNum + 1) * gNumFrameResources
  128. UINT descNum = (renderNum + 1) * gNumFrameResources;
  129. // 计算 PrePass CBV 在堆描述符中的偏移
  130. // 以 gNumFrameResources 为 3,renderNum 为 4 为例
  131. // 前面 4 * 3 表示 3 个帧资源 每个帧资源的 4 个渲染项的 CBV,最后 3 个 表示每个帧资源的 PrePass CBV
  132. // 所以 PrePass CBV 的偏移地址就是 renderNum * gNumFrameResources
  133. mPassCbvOffset = renderNum * gNumFrameResources;
  134. D3D12_DESCRIPTOR_HEAP_DESC desc;
  135. desc.NumDescriptors = descNum;
  136. desc.NodeMask = 0;
  137. desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  138. desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  139. md3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&mCbvHeap));
  140. }
  141. void ShapeApp::BuildConstantBuffers()
  142. {
  143. UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  144. UINT objCount = (UINT)mOpaqueRitems.size();
  145. // 创建 Render Item 的 CBV
  146. for (int frameIndex = 0; frameIndex < gNumFrameResources; ++frameIndex) {
  147. auto objectCB = mFrameResources[frameIndex]->ObjectCB->Resource();
  148. for (int itemIndex = 0; itemIndex < objCount; ++itemIndex) {
  149. D3D12_GPU_VIRTUAL_ADDRESS cbAddress = objectCB->GetGPUVirtualAddress();
  150. cbAddress += itemIndex * objCBByteSize;
  151. int heapIndex = frameIndex * objCount + itemIndex;
  152. auto handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(mCbvHeap->GetCPUDescriptorHandleForHeapStart());
  153. handle.Offset(heapIndex, mCbvSrvUavDescriptorSize);
  154. D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc;
  155. cbvDesc.BufferLocation = cbAddress;
  156. cbvDesc.SizeInBytes = objCBByteSize;
  157. md3dDevice->CreateConstantBufferView(&cbvDesc, handle);
  158. }
  159. }
  160. // 创建 pre pass CBV
  161. for (int frameIndex = 0; frameIndex < gNumFrameResources; ++frameIndex) {
  162. auto passCB = mFrameResources[frameIndex]->PassCB->Resource();
  163. D3D12_GPU_VIRTUAL_ADDRESS cbAddress = passCB->GetGPUVirtualAddress();
  164. int heapIndex = mPassCbvOffset + frameIndex;
  165. auto handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(mCbvHeap->GetCPUDescriptorHandleForHeapStart());
  166. handle.Offset(heapIndex, mCbvSrvUavDescriptorSize);
  167. D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc;
  168. cbvDesc.BufferLocation = cbAddress;
  169. cbvDesc.SizeInBytes = objCBByteSize;
  170. md3dDevice->CreateConstantBufferView(&cbvDesc, handle);
  171. }
  172. }
  173. void ShapeApp::BuildRootSignature()
  174. {
  175. CD3DX12_DESCRIPTOR_RANGE cbvTable0;
  176. cbvTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
  177. CD3DX12_DESCRIPTOR_RANGE cbvTable1;
  178. cbvTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 1);
  179. CD3DX12_ROOT_PARAMETER rootParameters[2];
  180. rootParameters[0].InitAsDescriptorTable(1, &cbvTable0);
  181. rootParameters[1].InitAsDescriptorTable(1, &cbvTable1);
  182. CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(2, rootParameters, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  183. ComPtr<ID3DBlob> serializedRootSig = nullptr;
  184. ComPtr<ID3DBlob> errorBlob = nullptr;
  185. HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  186. if (errorBlob != nullptr)
  187. {
  188. ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  189. }
  190. ThrowIfFailed(hr);
  191. ThrowIfFailed(md3dDevice->CreateRootSignature(0, serializedRootSig->GetBufferPointer(), serializedRootSig->GetBufferSize(), IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  192. }
  193. void ShapeApp::BuildShaderAndInputLayout()
  194. {
  195. mShaders[VSKey] = d3dUtil::CompileShader(L"res/shape.hlsl", nullptr, VSKey, "vs_5_1");
  196. mShaders[PSKey] = d3dUtil::CompileShader(L"res/shape.hlsl", nullptr, PSKey, "ps_5_1");
  197. mInputLayout = {
  198. {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  199. {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
  200. };
  201. }
  202. void ShapeApp::BuildPSO()
  203. {
  204. D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
  205. ZeroMemory(&psoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  206. psoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  207. psoDesc.pRootSignature = mRootSignature.Get();
  208. psoDesc.VS = { reinterpret_cast<BYTE*>(mShaders[VSKey]->GetBufferPointer()), mShaders[VSKey]->GetBufferSize() };
  209. psoDesc.PS = { reinterpret_cast<BYTE*>(mShaders[PSKey]->GetBufferPointer()), mShaders[PSKey]->GetBufferSize() };
  210. psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  211. psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  212. psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  213. psoDesc.SampleMask = UINT_MAX;
  214. psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  215. psoDesc.NumRenderTargets = 1;
  216. psoDesc.RTVFormats[0] = mBackBufferFormat;
  217. psoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  218. psoDesc.SampleDesc.Quality = m4xMsaaState ? m4xMsaaQuality - 1 : 0;
  219. psoDesc.DSVFormat = mDepthStencilFormat;
  220. psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
  221. md3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&mPSOs["opaque"]));
  222. D3D12_GRAPHICS_PIPELINE_STATE_DESC opaqueWireframePsoDesc = psoDesc;
  223. opaqueWireframePsoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_WIREFRAME; // 使用 WIREFRAME 线框模式
  224. md3dDevice->CreateGraphicsPipelineState(&opaqueWireframePsoDesc, IID_PPV_ARGS(&mPSOs["opaque_wireframe"]));
  225. }
  226. void ShapeApp::BuildRenderItems()
  227. {
  228. auto boxRitem = std::make_unique<RenderItem>();
  229. XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 2.0f, 2.0f) * XMMatrixTranslation(0.0f, 0.5f, 0.0f));
  230. boxRitem->ObjCBIndex = 0;
  231. boxRitem->Geo = mGeometries["shapeGeo"].get();
  232. boxRitem->PrimitiveType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  233. boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  234. boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  235. boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  236. mAllRitems.push_back(std::move(boxRitem));
  237. auto gridRitem = std::make_unique<RenderItem>();
  238. gridRitem->World = MathHelper::Identity4x4();
  239. gridRitem->ObjCBIndex = 1;
  240. gridRitem->Geo = mGeometries["shapeGeo"].get();
  241. gridRitem->PrimitiveType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  242. gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  243. gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  244. gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  245. mAllRitems.push_back(std::move(gridRitem));
  246. UINT objCBIndex = 2;
  247. for (int i = 0; i < 5; ++i)
  248. {
  249. auto leftCylRitem = std::make_unique<RenderItem>();
  250. auto rightCylRitem = std::make_unique<RenderItem>();
  251. auto leftSphereRitem = std::make_unique<RenderItem>();
  252. auto rightSphereRitem = std::make_unique<RenderItem>();
  253. XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i * 5.0f);
  254. XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i * 5.0f);
  255. XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i * 5.0f);
  256. XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i * 5.0f);
  257. XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
  258. leftCylRitem->ObjCBIndex = objCBIndex++;
  259. leftCylRitem->Geo = mGeometries["shapeGeo"].get();
  260. leftCylRitem->PrimitiveType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  261. leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  262. leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  263. leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  264. XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
  265. rightCylRitem->ObjCBIndex = objCBIndex++;
  266. rightCylRitem->Geo = mGeometries["shapeGeo"].get();
  267. rightCylRitem->PrimitiveType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  268. rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  269. rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  270. rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  271. XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
  272. leftSphereRitem->ObjCBIndex = objCBIndex++;
  273. leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
  274. leftSphereRitem->PrimitiveType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  275. leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  276. leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  277. leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  278. XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
  279. rightSphereRitem->ObjCBIndex = objCBIndex++;
  280. rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
  281. rightSphereRitem->PrimitiveType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  282. rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  283. rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  284. rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  285. mAllRitems.push_back(std::move(leftCylRitem));
  286. mAllRitems.push_back(std::move(rightCylRitem));
  287. mAllRitems.push_back(std::move(leftSphereRitem));
  288. mAllRitems.push_back(std::move(rightSphereRitem));
  289. }
  290. // All the render items are opaque.
  291. for (auto& e : mAllRitems)
  292. mOpaqueRitems.push_back(e.get());
  293. }
  294. void ShapeApp::BuildShapeGeometry()
  295. {
  296. GeometryGenerator geoGen;
  297. GeometryGenerator::MeshData box = geoGen.CreateBox(1.5f, 0.5f, 1.5f, 3);
  298. GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
  299. GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
  300. GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
  301. // 定义各个模型顶点缓冲区的偏移
  302. UINT boxVertexOffset = 0;
  303. UINT gridVertexOffset = (UINT)box.Vertices.size();
  304. UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
  305. UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
  306. // 定义各个模型顶点索引缓冲区的偏移
  307. UINT boxIndexOffset = 0;
  308. UINT gridIndexOffset = (UINT)box.Indices32.size();
  309. UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
  310. UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
  311. // 构建子模型
  312. SubmeshGeometry boxSubmesh;
  313. boxSubmesh.IndexCount = (UINT)box.Indices32.size();
  314. boxSubmesh.StartIndexLocation = boxIndexOffset;
  315. boxSubmesh.BaseVertexLocation = boxVertexOffset;
  316. SubmeshGeometry gridSubmesh;
  317. gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
  318. gridSubmesh.StartIndexLocation = gridIndexOffset;
  319. gridSubmesh.BaseVertexLocation = gridVertexOffset;
  320. SubmeshGeometry sphereSubmesh;
  321. sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
  322. sphereSubmesh.StartIndexLocation = sphereIndexOffset;
  323. sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
  324. SubmeshGeometry cylinderSubmesh;
  325. cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
  326. cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
  327. cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
  328. auto totalVertexCount = box.Vertices.size() + grid.Vertices.size() + sphere.Vertices.size() + cylinder.Vertices.size();
  329. std::vector<Vertex> vertices(totalVertexCount);
  330. UINT k = 0;
  331. for (size_t i = 0; i < box.Vertices.size(); ++i, ++k)
  332. {
  333. vertices[k].Pos = box.Vertices[i].Position;
  334. vertices[k].Color = XMFLOAT4(DirectX::Colors::DarkGreen);
  335. }
  336. for (size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
  337. {
  338. vertices[k].Pos = grid.Vertices[i].Position;
  339. vertices[k].Color = XMFLOAT4(DirectX::Colors::ForestGreen);
  340. }
  341. for (size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
  342. {
  343. vertices[k].Pos = sphere.Vertices[i].Position;
  344. vertices[k].Color = XMFLOAT4(DirectX::Colors::Crimson);
  345. }
  346. for (size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
  347. {
  348. vertices[k].Pos = cylinder.Vertices[i].Position;
  349. vertices[k].Color = XMFLOAT4(DirectX::Colors::SteelBlue);
  350. }
  351. std::vector<std::uint16_t> indices;
  352. indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
  353. indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
  354. indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
  355. indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
  356. const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  357. const UINT ibByteSize = (UINT)indices.size() * sizeof(std::uint16_t);
  358. auto geo = std::make_unique<MeshGeometry>();
  359. geo->Name = "shapeGeo";
  360. ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  361. CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  362. ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  363. CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  364. geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(), mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  365. geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(), mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  366. geo->VertexByteStride = sizeof(Vertex);
  367. geo->VertexBufferByteSize = vbByteSize;
  368. geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  369. geo->IndexBufferByteSize = ibByteSize;
  370. geo->DrawArgs["box"] = boxSubmesh;
  371. geo->DrawArgs["grid"] = gridSubmesh;
  372. geo->DrawArgs["sphere"] = sphereSubmesh;
  373. geo->DrawArgs["cylinder"] = cylinderSubmesh;
  374. mGeometries[geo->Name] = std::move(geo);
  375. }
  376. void ShapeApp::BuildFrameResource()
  377. {
  378. for (int i = 0; i < gNumFrameResources; ++i) {
  379. mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(), 1, (UINT)mAllRitems.size()));
  380. }
  381. }
  382. void ShapeApp::UpdateCamera()
  383. {
  384. mEyePos.x = mRadius * sinf(mPhi) * cosf(mTheta);
  385. mEyePos.z = mRadius * sinf(mPhi) * sinf(mTheta);
  386. mEyePos.y = mRadius * cosf(mPhi);
  387. // Build the view matrix.
  388. XMVECTOR pos = XMVectorSet(mEyePos.x, mEyePos.y, mEyePos.z, 1.0f);
  389. XMVECTOR target = XMVectorZero();
  390. XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  391. XMMATRIX view = XMMatrixLookAtLH(pos, target, up);
  392. XMStoreFloat4x4(&mView, view);
  393. }
  394. void ShapeApp::UpdateObjectCBs()
  395. {
  396. auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  397. for (auto& e : mAllRitems)
  398. {
  399. if (e->NumFramesDirty > 0)
  400. {
  401. XMMATRIX world = XMLoadFloat4x4(&e->World);
  402. ObjectConstants objConstants;
  403. XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  404. currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  405. e->NumFramesDirty--;
  406. }
  407. }
  408. }
  409. void ShapeApp::UpdateMainPassCB(const GameTimer& gt)
  410. {
  411. XMMATRIX view = XMLoadFloat4x4(&mView);
  412. XMMATRIX proj = XMLoadFloat4x4(&mProj);
  413. XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  414. XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  415. XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  416. XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  417. XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  418. XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  419. XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  420. XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  421. XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  422. XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  423. mMainPassCB.EyePosW = mEyePos;
  424. mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  425. mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  426. mMainPassCB.NearZ = 1.0f;
  427. mMainPassCB.FarZ = 1000.0f;
  428. mMainPassCB.TotalTime = gt.TotalTime();
  429. mMainPassCB.DeltaTime = gt.DeltaTime();
  430. auto currPassCB = mCurrFrameResource->PassCB.get();
  431. currPassCB->CopyData(0, mMainPassCB);
  432. }
  433. void ShapeApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  434. {
  435. UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  436. auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  437. for (size_t index = 0; index < ritems.size(); ++index) {
  438. const auto& ri = ritems[index];
  439. cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  440. cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  441. cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  442. UINT cbvIndex = mCurrFrameResourceIndex * (UINT)mOpaqueRitems.size() + ri->ObjCBIndex;
  443. auto cbvHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE(mCbvHeap->GetGPUDescriptorHandleForHeapStart());
  444. cbvHandle.Offset(cbvIndex, mCbvSrvUavDescriptorSize);
  445. cmdList->SetGraphicsRootDescriptorTable(0, cbvHandle);
  446. cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  447. }
  448. }