home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 13 The Compute Shader / Blur / BlurApp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2016-03-02  |  42.2 KB  |  1,200 lines

  1. //***************************************************************************************
  2. // BlurApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "FrameResource.h"
  10. #include "Waves.h"
  11. #include "BlurFilter.h"
  12.  
  13. using Microsoft::WRL::ComPtr;
  14. using namespace DirectX;
  15. using namespace DirectX::PackedVector;
  16.  
  17. #pragma comment(lib, "d3dcompiler.lib")
  18. #pragma comment(lib, "D3D12.lib")
  19.  
  20. const int gNumFrameResources = 3;
  21.  
  22. // Lightweight structure stores parameters to draw a shape.  This will
  23. // vary from app-to-app.
  24. struct RenderItem
  25. {
  26.     RenderItem() = default;
  27.  
  28.     // World matrix of the shape that describes the object's local space
  29.     // relative to the world space, which defines the position, orientation,
  30.     // and scale of the object in the world.
  31.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  32.  
  33.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  34.  
  35.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  36.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  37.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  38.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  39.     int NumFramesDirty = gNumFrameResources;
  40.  
  41.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  42.     UINT ObjCBIndex = -1;
  43.  
  44.     Material* Mat = nullptr;
  45.     MeshGeometry* Geo = nullptr;
  46.  
  47.     // Primitive topology.
  48.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  49.  
  50.     // DrawIndexedInstanced parameters.
  51.     UINT IndexCount = 0;
  52.     UINT StartIndexLocation = 0;
  53.     int BaseVertexLocation = 0;
  54. };
  55.  
  56. enum class RenderLayer : int
  57. {
  58.     Opaque = 0,
  59.     Transparent,
  60.     AlphaTested,
  61.     Count
  62. };
  63.  
  64. class BlurApp : public D3DApp
  65. {
  66. public:
  67.     BlurApp(HINSTANCE hInstance);
  68.     BlurApp(const BlurApp& rhs) = delete;
  69.     BlurApp& operator=(const BlurApp& rhs) = delete;
  70.     ~BlurApp();
  71.  
  72.     virtual bool Initialize()override;
  73.  
  74. private:
  75.     virtual void OnResize()override;
  76.     virtual void Update(const GameTimer& gt)override;
  77.     virtual void Draw(const GameTimer& gt)override;
  78.  
  79.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  80.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  81.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  82.  
  83.     void OnKeyboardInput(const GameTimer& gt);
  84.     void UpdateCamera(const GameTimer& gt);
  85.     void AnimateMaterials(const GameTimer& gt);
  86.     void UpdateObjectCBs(const GameTimer& gt);
  87.     void UpdateMaterialCBs(const GameTimer& gt);
  88.     void UpdateMainPassCB(const GameTimer& gt);
  89.     void UpdateWaves(const GameTimer& gt); 
  90.  
  91.     void LoadTextures();
  92.     void BuildRootSignature();
  93.     void BuildPostProcessRootSignature();
  94.     void BuildDescriptorHeaps();
  95.     void BuildShadersAndInputLayout();
  96.     void BuildLandGeometry();
  97.     void BuildWavesGeometry();
  98.     void BuildBoxGeometry();
  99.     void BuildPSOs();
  100.     void BuildFrameResources();
  101.     void BuildMaterials();
  102.     void BuildRenderItems();
  103.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  104.  
  105.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
  106.  
  107.     float GetHillsHeight(float x, float z)const;
  108.     XMFLOAT3 GetHillsNormal(float x, float z)const;
  109.  
  110. private:
  111.  
  112.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  113.     FrameResource* mCurrFrameResource = nullptr;
  114.     int mCurrFrameResourceIndex = 0;
  115.  
  116.     UINT mCbvSrvUavDescriptorSize = 0;
  117.  
  118.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  119.     ComPtr<ID3D12RootSignature> mPostProcessRootSignature = nullptr;
  120.  
  121.     ComPtr<ID3D12DescriptorHeap> mCbvSrvUavDescriptorHeap = nullptr;
  122.  
  123.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  124.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  125.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  126.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  127.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  128.  
  129.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  130.  
  131.     RenderItem* mWavesRitem = nullptr;
  132.  
  133.     // List of all the render items.
  134.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  135.  
  136.     // Render items divided by PSO.
  137.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  138.  
  139.     std::unique_ptr<Waves> mWaves;
  140.  
  141.     std::unique_ptr<BlurFilter> mBlurFilter;
  142.  
  143.     PassConstants mMainPassCB;
  144.  
  145.     XMFLOAT3 mEyePos = { 0.0f, 0.0f, 0.0f };
  146.     XMFLOAT4X4 mView = MathHelper::Identity4x4();
  147.     XMFLOAT4X4 mProj = MathHelper::Identity4x4();
  148.  
  149.     float mTheta = 1.5f*XM_PI;
  150.     float mPhi = XM_PIDIV2 - 0.1f;
  151.     float mRadius = 50.0f;
  152.  
  153.     POINT mLastMousePos;
  154. };
  155.  
  156. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  157.     PSTR cmdLine, int showCmd)
  158. {
  159.     // Enable run-time memory check for debug builds.
  160. #if defined(DEBUG) | defined(_DEBUG)
  161.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  162. #endif
  163.  
  164.     try
  165.     {
  166.         BlurApp theApp(hInstance);
  167.         if(!theApp.Initialize())
  168.             return 0;
  169.  
  170.         return theApp.Run();
  171.     }
  172.     catch(DxException& e)
  173.     {
  174.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  175.         return 0;
  176.     }
  177. }
  178.  
  179. BlurApp::BlurApp(HINSTANCE hInstance)
  180.     : D3DApp(hInstance)
  181. {
  182. }
  183.  
  184. BlurApp::~BlurApp()
  185. {
  186.     if(md3dDevice != nullptr)
  187.         FlushCommandQueue();
  188. }
  189.  
  190. bool BlurApp::Initialize()
  191. {
  192.     if(!D3DApp::Initialize())
  193.         return false;
  194.  
  195.     // Reset the command list to prep for initialization commands.
  196.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  197.  
  198.     // Get the increment size of a descriptor in this heap type.  This is hardware specific, 
  199.     // so we have to query this information.
  200.     mCbvSrvUavDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  201.  
  202.     mWaves = std::make_unique<Waves>(128, 128, 1.0f, 0.03f, 4.0f, 0.2f);
  203.  
  204.     mBlurFilter = std::make_unique<BlurFilter>(md3dDevice.Get(), 
  205.         mClientWidth, mClientHeight, DXGI_FORMAT_R8G8B8A8_UNORM);
  206.  
  207.     LoadTextures();
  208.     BuildRootSignature();
  209.     BuildPostProcessRootSignature();
  210.     BuildDescriptorHeaps();
  211.     BuildShadersAndInputLayout();
  212.     BuildLandGeometry();
  213.     BuildWavesGeometry();
  214.     BuildBoxGeometry();
  215.     BuildMaterials();
  216.     BuildRenderItems();
  217.     BuildFrameResources();
  218.     BuildPSOs();
  219.  
  220.     // Execute the initialization commands.
  221.     ThrowIfFailed(mCommandList->Close());
  222.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  223.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  224.  
  225.     // Wait until initialization is complete.
  226.     FlushCommandQueue();
  227.  
  228.     return true;
  229. }
  230.  
  231. void BlurApp::OnResize()
  232. {
  233.     D3DApp::OnResize();
  234.  
  235.     // The window resized, so update the aspect ratio and recompute the projection matrix.
  236.     XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  237.     XMStoreFloat4x4(&mProj, P);
  238.  
  239.     if(mBlurFilter != nullptr)
  240.     {
  241.         mBlurFilter->OnResize(mClientWidth, mClientHeight);
  242.     }
  243. }
  244.  
  245. void BlurApp::Update(const GameTimer& gt)
  246. {
  247.     OnKeyboardInput(gt);
  248.     UpdateCamera(gt);
  249.  
  250.     // Cycle through the circular frame resource array.
  251.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  252.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  253.  
  254.     // Has the GPU finished processing the commands of the current frame resource?
  255.     // If not, wait until the GPU has completed commands up to this fence point.
  256.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  257.     {
  258.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  259.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  260.         WaitForSingleObject(eventHandle, INFINITE);
  261.         CloseHandle(eventHandle);
  262.     }
  263.  
  264.     AnimateMaterials(gt);
  265.     UpdateObjectCBs(gt);
  266.     UpdateMaterialCBs(gt);
  267.     UpdateMainPassCB(gt);
  268.     UpdateWaves(gt);
  269. }
  270.  
  271. void BlurApp::Draw(const GameTimer& gt)
  272. {
  273.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  274.  
  275.     // Reuse the memory associated with command recording.
  276.     // We can only reset when the associated command lists have finished execution on the GPU.
  277.     ThrowIfFailed(cmdListAlloc->Reset());
  278.  
  279.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  280.     // Reusing the command list reuses memory.
  281.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  282.  
  283.     mCommandList->RSSetViewports(1, &mScreenViewport);
  284.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  285.  
  286.     // Indicate a state transition on the resource usage.
  287.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  288.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  289.  
  290.     // Clear the back buffer and depth buffer.
  291.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), (float*)&mMainPassCB.FogColor, 0, nullptr);
  292.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  293.  
  294.     // Specify the buffers we are going to render to.
  295.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  296.  
  297.     ID3D12DescriptorHeap* descriptorHeaps[] = { mCbvSrvUavDescriptorHeap.Get() };
  298.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  299.  
  300.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  301.  
  302.     auto passCB = mCurrFrameResource->PassCB->Resource();
  303.     mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
  304.  
  305.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  306.  
  307.     mCommandList->SetPipelineState(mPSOs["alphaTested"].Get());
  308.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::AlphaTested]);
  309.  
  310.     mCommandList->SetPipelineState(mPSOs["transparent"].Get());
  311.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Transparent]);
  312.  
  313.     mBlurFilter->Execute(mCommandList.Get(), mPostProcessRootSignature.Get(), 
  314.         mPSOs["horzBlur"].Get(), mPSOs["vertBlur"].Get(), CurrentBackBuffer(), 4);
  315.  
  316.     // Prepare to copy blurred output to the back buffer.
  317.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  318.         D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST));
  319.  
  320.     mCommandList->CopyResource(CurrentBackBuffer(), mBlurFilter->Output());
  321.  
  322.     // Transition to PRESENT state.
  323.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  324.         D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT));
  325.  
  326.     // Done recording commands.
  327.     ThrowIfFailed(mCommandList->Close());
  328.  
  329.     // Add the command list to the queue for execution.
  330.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  331.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  332.  
  333.     // Swap the back and front buffers
  334.     ThrowIfFailed(mSwapChain->Present(0, 0));
  335.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  336.  
  337.     // Advance the fence value to mark commands up to this fence point.
  338.     mCurrFrameResource->Fence = ++mCurrentFence;
  339.  
  340.     // Add an instruction to the command queue to set a new fence point. 
  341.     // Because we are on the GPU timeline, the new fence point won't be 
  342.     // set until the GPU finishes processing all the commands prior to this Signal().
  343.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  344. }
  345.  
  346. void BlurApp::OnMouseDown(WPARAM btnState, int x, int y)
  347. {
  348.     mLastMousePos.x = x;
  349.     mLastMousePos.y = y;
  350.  
  351.     SetCapture(mhMainWnd);
  352. }
  353.  
  354. void BlurApp::OnMouseUp(WPARAM btnState, int x, int y)
  355. {
  356.     ReleaseCapture();
  357. }
  358.  
  359. void BlurApp::OnMouseMove(WPARAM btnState, int x, int y)
  360. {
  361.     if((btnState & MK_LBUTTON) != 0)
  362.     {
  363.         // Make each pixel correspond to a quarter of a degree.
  364.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  365.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  366.  
  367.         // Update angles based on input to orbit camera around box.
  368.         mTheta += dx;
  369.         mPhi += dy;
  370.  
  371.         // Restrict the angle mPhi.
  372.         mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f);
  373.     }
  374.     else if((btnState & MK_RBUTTON) != 0)
  375.     {
  376.         // Make each pixel correspond to 0.2 unit in the scene.
  377.         float dx = 0.2f*static_cast<float>(x - mLastMousePos.x);
  378.         float dy = 0.2f*static_cast<float>(y - mLastMousePos.y);
  379.  
  380.         // Update the camera radius based on input.
  381.         mRadius += dx - dy;
  382.  
  383.         // Restrict the radius.
  384.         mRadius = MathHelper::Clamp(mRadius, 5.0f, 150.0f);
  385.     }
  386.  
  387.     mLastMousePos.x = x;
  388.     mLastMousePos.y = y;
  389. }
  390.  
  391. void BlurApp::OnKeyboardInput(const GameTimer& gt)
  392. {
  393. }
  394.  
  395. void BlurApp::UpdateCamera(const GameTimer& gt)
  396. {
  397.     // Convert Spherical to Cartesian coordinates.
  398.     mEyePos.x = mRadius*sinf(mPhi)*cosf(mTheta);
  399.     mEyePos.z = mRadius*sinf(mPhi)*sinf(mTheta);
  400.     mEyePos.y = mRadius*cosf(mPhi);
  401.  
  402.     // Build the view matrix.
  403.     XMVECTOR pos = XMVectorSet(mEyePos.x, mEyePos.y, mEyePos.z, 1.0f);
  404.     XMVECTOR target = XMVectorZero();
  405.     XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  406.  
  407.     XMMATRIX view = XMMatrixLookAtLH(pos, target, up);
  408.     XMStoreFloat4x4(&mView, view);
  409. }
  410.  
  411. void BlurApp::AnimateMaterials(const GameTimer& gt)
  412. {
  413.     // Scroll the water material texture coordinates.
  414.     auto waterMat = mMaterials["water"].get();
  415.  
  416.     float& tu = waterMat->MatTransform(3, 0);
  417.     float& tv = waterMat->MatTransform(3, 1);
  418.  
  419.     tu += 0.1f * gt.DeltaTime();
  420.     tv += 0.02f * gt.DeltaTime();
  421.  
  422.     if(tu >= 1.0f)
  423.         tu -= 1.0f;
  424.  
  425.     if(tv >= 1.0f)
  426.         tv -= 1.0f;
  427.  
  428.     waterMat->MatTransform(3, 0) = tu;
  429.     waterMat->MatTransform(3, 1) = tv;
  430.  
  431.     // Material has changed, so need to update cbuffer.
  432.     waterMat->NumFramesDirty = gNumFrameResources;
  433. }
  434.  
  435. void BlurApp::UpdateObjectCBs(const GameTimer& gt)
  436. {
  437.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  438.     for(auto& e : mAllRitems)
  439.     {
  440.         // Only update the cbuffer data if the constants have changed.  
  441.         // This needs to be tracked per frame resource.
  442.         if(e->NumFramesDirty > 0)
  443.         {
  444.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  445.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  446.  
  447.             ObjectConstants objConstants;
  448.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  449.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  450.  
  451.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  452.  
  453.             // Next FrameResource need to be updated too.
  454.             e->NumFramesDirty--;
  455.         }
  456.     }
  457. }
  458.  
  459. void BlurApp::UpdateMaterialCBs(const GameTimer& gt)
  460. {
  461.     auto currMaterialCB = mCurrFrameResource->MaterialCB.get();
  462.     for(auto& e : mMaterials)
  463.     {
  464.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  465.         // data changes, it needs to be updated for each FrameResource.
  466.         Material* mat = e.second.get();
  467.         if(mat->NumFramesDirty > 0)
  468.         {
  469.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  470.  
  471.             MaterialConstants matConstants;
  472.             matConstants.DiffuseAlbedo = mat->DiffuseAlbedo;
  473.             matConstants.FresnelR0 = mat->FresnelR0;
  474.             matConstants.Roughness = mat->Roughness;
  475.             XMStoreFloat4x4(&matConstants.MatTransform, XMMatrixTranspose(matTransform));
  476.  
  477.             currMaterialCB->CopyData(mat->MatCBIndex, matConstants);
  478.  
  479.             // Next FrameResource need to be updated too.
  480.             mat->NumFramesDirty--;
  481.         }
  482.     }
  483. }
  484.  
  485. void BlurApp::UpdateMainPassCB(const GameTimer& gt)
  486. {
  487.     XMMATRIX view = XMLoadFloat4x4(&mView);
  488.     XMMATRIX proj = XMLoadFloat4x4(&mProj);
  489.  
  490.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  491.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  492.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  493.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  494.  
  495.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  496.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  497.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  498.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  499.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  500.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  501.     mMainPassCB.EyePosW = mEyePos;
  502.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  503.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  504.     mMainPassCB.NearZ = 1.0f;
  505.     mMainPassCB.FarZ = 1000.0f;
  506.     mMainPassCB.TotalTime = gt.TotalTime();
  507.     mMainPassCB.DeltaTime = gt.DeltaTime();
  508.     mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
  509.     mMainPassCB.Lights[0].Direction = { 0.57735f, -0.57735f, 0.57735f };
  510.     mMainPassCB.Lights[0].Strength = { 0.6f, 0.6f, 0.6f };
  511.     mMainPassCB.Lights[1].Direction = { -0.57735f, -0.57735f, 0.57735f };
  512.     mMainPassCB.Lights[1].Strength = { 0.3f, 0.3f, 0.3f };
  513.     mMainPassCB.Lights[2].Direction = { 0.0f, -0.707f, -0.707f };
  514.     mMainPassCB.Lights[2].Strength = { 0.15f, 0.15f, 0.15f };
  515.  
  516.     auto currPassCB = mCurrFrameResource->PassCB.get();
  517.     currPassCB->CopyData(0, mMainPassCB);
  518. }
  519.  
  520. void BlurApp::UpdateWaves(const GameTimer& gt)
  521. {
  522.     // Every quarter second, generate a random wave.
  523.     static float t_base = 0.0f;
  524.     if((mTimer.TotalTime() - t_base) >= 0.25f)
  525.     {
  526.         t_base += 0.25f;
  527.  
  528.         int i = MathHelper::Rand(4, mWaves->RowCount() - 5);
  529.         int j = MathHelper::Rand(4, mWaves->ColumnCount() - 5);
  530.  
  531.         float r = MathHelper::RandF(0.2f, 0.5f);
  532.  
  533.         mWaves->Disturb(i, j, r);
  534.     }
  535.  
  536.     // Update the wave simulation.
  537.     mWaves->Update(gt.DeltaTime());
  538.  
  539.     // Update the wave vertex buffer with the new solution.
  540.     auto currWavesVB = mCurrFrameResource->WavesVB.get();
  541.     for(int i = 0; i < mWaves->VertexCount(); ++i)
  542.     {
  543.         Vertex v;
  544.  
  545.         v.Pos = mWaves->Position(i);
  546.         v.Normal = mWaves->Normal(i);
  547.         
  548.         // Derive tex-coords from position by 
  549.         // mapping [-w/2,w/2] --> [0,1]
  550.         v.TexC.x = 0.5f + v.Pos.x / mWaves->Width();
  551.         v.TexC.y = 0.5f - v.Pos.z / mWaves->Depth();
  552.  
  553.         currWavesVB->CopyData(i, v);
  554.     }
  555.  
  556.     // Set the dynamic VB of the wave renderitem to the current frame VB.
  557.     mWavesRitem->Geo->VertexBufferGPU = currWavesVB->Resource();
  558. }
  559.  
  560. void BlurApp::LoadTextures()
  561. {
  562.     auto grassTex = std::make_unique<Texture>();
  563.     grassTex->Name = "grassTex";
  564.     grassTex->Filename = L"../../Textures/grass.dds";
  565.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  566.         mCommandList.Get(), grassTex->Filename.c_str(),
  567.         grassTex->Resource, grassTex->UploadHeap));
  568.  
  569.     auto waterTex = std::make_unique<Texture>();
  570.     waterTex->Name = "waterTex";
  571.     waterTex->Filename = L"../../Textures/water1.dds";
  572.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  573.         mCommandList.Get(), waterTex->Filename.c_str(),
  574.         waterTex->Resource, waterTex->UploadHeap));
  575.  
  576.     auto fenceTex = std::make_unique<Texture>();
  577.     fenceTex->Name = "fenceTex";
  578.     fenceTex->Filename = L"../../Textures/WireFence.dds";
  579.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  580.         mCommandList.Get(), fenceTex->Filename.c_str(),
  581.         fenceTex->Resource, fenceTex->UploadHeap));
  582.  
  583.     mTextures[grassTex->Name] = std::move(grassTex);
  584.     mTextures[waterTex->Name] = std::move(waterTex);
  585.     mTextures[fenceTex->Name] = std::move(fenceTex);
  586. }
  587.  
  588. void BlurApp::BuildRootSignature()
  589. {
  590.     CD3DX12_DESCRIPTOR_RANGE texTable;
  591.     texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
  592.  
  593.     // Root parameter can be a table, root descriptor or root constants.
  594.     CD3DX12_ROOT_PARAMETER slotRootParameter[4];
  595.  
  596.     // Perfomance TIP: Order from most frequent to least frequent.
  597.     slotRootParameter[0].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_PIXEL);
  598.     slotRootParameter[1].InitAsConstantBufferView(0);
  599.     slotRootParameter[2].InitAsConstantBufferView(1);
  600.     slotRootParameter[3].InitAsConstantBufferView(2);
  601.  
  602.     auto staticSamplers = GetStaticSamplers();
  603.  
  604.     // A root signature is an array of root parameters.
  605.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
  606.         (UINT)staticSamplers.size(), staticSamplers.data(),
  607.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  608.  
  609.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  610.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  611.     ComPtr<ID3DBlob> errorBlob = nullptr;
  612.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  613.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  614.  
  615.     if(errorBlob != nullptr)
  616.     {
  617.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  618.     }
  619.     ThrowIfFailed(hr);
  620.  
  621.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  622.         0,
  623.         serializedRootSig->GetBufferPointer(),
  624.         serializedRootSig->GetBufferSize(),
  625.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  626. }
  627.  
  628. void BlurApp::BuildPostProcessRootSignature()
  629. {
  630.     CD3DX12_DESCRIPTOR_RANGE srvTable;
  631.     srvTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
  632.  
  633.     CD3DX12_DESCRIPTOR_RANGE uavTable;
  634.     uavTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0);
  635.  
  636.     // Root parameter can be a table, root descriptor or root constants.
  637.     CD3DX12_ROOT_PARAMETER slotRootParameter[3];
  638.  
  639.     // Perfomance TIP: Order from most frequent to least frequent.
  640.     slotRootParameter[0].InitAsConstants(12, 0);
  641.     slotRootParameter[1].InitAsDescriptorTable(1, &srvTable);
  642.     slotRootParameter[2].InitAsDescriptorTable(1, &uavTable);
  643.  
  644.     // A root signature is an array of root parameters.
  645.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(3, slotRootParameter,
  646.         0, nullptr,
  647.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  648.  
  649.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  650.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  651.     ComPtr<ID3DBlob> errorBlob = nullptr;
  652.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  653.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  654.  
  655.     if(errorBlob != nullptr)
  656.     {
  657.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  658.     }
  659.     ThrowIfFailed(hr);
  660.  
  661.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  662.         0,
  663.         serializedRootSig->GetBufferPointer(),
  664.         serializedRootSig->GetBufferSize(),
  665.         IID_PPV_ARGS(mPostProcessRootSignature.GetAddressOf())));
  666. }
  667.  
  668. void BlurApp::BuildDescriptorHeaps()
  669. {
  670.     const int textureDescriptorCount = 3;
  671.     const int blurDescriptorCount = 4;
  672.  
  673.     //
  674.     // Create the SRV heap.
  675.     //
  676.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  677.     srvHeapDesc.NumDescriptors = textureDescriptorCount + 
  678.         blurDescriptorCount;
  679.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  680.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  681.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mCbvSrvUavDescriptorHeap)));
  682.  
  683.     //
  684.     // Fill out the heap with texture descriptors.
  685.     //
  686.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mCbvSrvUavDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  687.  
  688.     auto grassTex = mTextures["grassTex"]->Resource;
  689.     auto waterTex = mTextures["waterTex"]->Resource;
  690.     auto fenceTex = mTextures["fenceTex"]->Resource;
  691.  
  692.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  693.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  694.     srvDesc.Format = grassTex->GetDesc().Format;
  695.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  696.     srvDesc.Texture2D.MostDetailedMip = 0;
  697.     srvDesc.Texture2D.MipLevels = -1;
  698.     md3dDevice->CreateShaderResourceView(grassTex.Get(), &srvDesc, hDescriptor);
  699.  
  700.     // next descriptor
  701.     hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  702.  
  703.     srvDesc.Format = waterTex->GetDesc().Format;
  704.     md3dDevice->CreateShaderResourceView(waterTex.Get(), &srvDesc, hDescriptor);
  705.  
  706.     // next descriptor
  707.     hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  708.  
  709.     srvDesc.Format = fenceTex->GetDesc().Format;
  710.     md3dDevice->CreateShaderResourceView(fenceTex.Get(), &srvDesc, hDescriptor);
  711.  
  712.     //
  713.     // Fill out the heap with the descriptors to the BlurFilter resources.
  714.     //
  715.  
  716.     mBlurFilter->BuildDescriptors(
  717.         CD3DX12_CPU_DESCRIPTOR_HANDLE(mCbvSrvUavDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), 3, mCbvSrvUavDescriptorSize),
  718.         CD3DX12_GPU_DESCRIPTOR_HANDLE(mCbvSrvUavDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), 3, mCbvSrvUavDescriptorSize),
  719.         mCbvSrvUavDescriptorSize);
  720. }
  721.  
  722. void BlurApp::BuildShadersAndInputLayout()
  723. {
  724.     const D3D_SHADER_MACRO defines[] =
  725.     {
  726.         "FOG", "1",
  727.         NULL, NULL
  728.     };
  729.  
  730.     const D3D_SHADER_MACRO alphaTestDefines[] =
  731.     {
  732.         "FOG", "1",
  733.         "ALPHA_TEST", "1",
  734.         NULL, NULL
  735.     };
  736.  
  737.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_0");
  738.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", defines, "PS", "ps_5_0");
  739.     mShaders["alphaTestedPS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", alphaTestDefines, "PS", "ps_5_0");
  740.     mShaders["horzBlurCS"] = d3dUtil::CompileShader(L"Shaders\\Blur.hlsl", nullptr, "HorzBlurCS", "cs_5_0");
  741.     mShaders["vertBlurCS"] = d3dUtil::CompileShader(L"Shaders\\Blur.hlsl", nullptr, "VertBlurCS", "cs_5_0");
  742.  
  743.     mInputLayout =
  744.     {
  745.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  746.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  747.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  748.     };
  749. }
  750.  
  751. void BlurApp::BuildLandGeometry()
  752. {
  753.     GeometryGenerator geoGen;
  754.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(160.0f, 160.0f, 50, 50);
  755.  
  756.     //
  757.     // Extract the vertex elements we are interested and apply the height function to
  758.     // each vertex.  In addition, color the vertices based on their height so we have
  759.     // sandy looking beaches, grassy low hills, and snow mountain peaks.
  760.     //
  761.  
  762.     std::vector<Vertex> vertices(grid.Vertices.size());
  763.     for(size_t i = 0; i < grid.Vertices.size(); ++i)
  764.     {
  765.         auto& p = grid.Vertices[i].Position;
  766.         vertices[i].Pos = p;
  767.         vertices[i].Pos.y = GetHillsHeight(p.x, p.z);
  768.         vertices[i].Normal = GetHillsNormal(p.x, p.z);
  769.         vertices[i].TexC = grid.Vertices[i].TexC;
  770.     }
  771.  
  772.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  773.  
  774.     std::vector<std::uint16_t> indices = grid.GetIndices16();
  775.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::uint16_t);
  776.  
  777.     auto geo = std::make_unique<MeshGeometry>();
  778.     geo->Name = "landGeo";
  779.  
  780.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  781.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  782.  
  783.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  784.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  785.  
  786.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  787.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  788.  
  789.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  790.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  791.  
  792.     geo->VertexByteStride = sizeof(Vertex);
  793.     geo->VertexBufferByteSize = vbByteSize;
  794.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  795.     geo->IndexBufferByteSize = ibByteSize;
  796.  
  797.     SubmeshGeometry submesh;
  798.     submesh.IndexCount = (UINT)indices.size();
  799.     submesh.StartIndexLocation = 0;
  800.     submesh.BaseVertexLocation = 0;
  801.  
  802.     geo->DrawArgs["grid"] = submesh;
  803.  
  804.     mGeometries["landGeo"] = std::move(geo);
  805. }
  806.  
  807. void BlurApp::BuildWavesGeometry()
  808. {
  809.     std::vector<std::uint16_t> indices(3 * mWaves->TriangleCount()); // 3 indices per face
  810.     assert(mWaves->VertexCount() < 0x0000ffff);
  811.  
  812.     // Iterate over each quad.
  813.     int m = mWaves->RowCount();
  814.     int n = mWaves->ColumnCount();
  815.     int k = 0;
  816.     for(int i = 0; i < m - 1; ++i)
  817.     {
  818.         for(int j = 0; j < n - 1; ++j)
  819.         {
  820.             indices[k] = i*n + j;
  821.             indices[k + 1] = i*n + j + 1;
  822.             indices[k + 2] = (i + 1)*n + j;
  823.  
  824.             indices[k + 3] = (i + 1)*n + j;
  825.             indices[k + 4] = i*n + j + 1;
  826.             indices[k + 5] = (i + 1)*n + j + 1;
  827.  
  828.             k += 6; // next quad
  829.         }
  830.     }
  831.  
  832.     UINT vbByteSize = mWaves->VertexCount()*sizeof(Vertex);
  833.     UINT ibByteSize = (UINT)indices.size()*sizeof(std::uint16_t);
  834.  
  835.     auto geo = std::make_unique<MeshGeometry>();
  836.     geo->Name = "waterGeo";
  837.  
  838.     // Set dynamically.
  839.     geo->VertexBufferCPU = nullptr;
  840.     geo->VertexBufferGPU = nullptr;
  841.  
  842.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  843.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  844.  
  845.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  846.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  847.  
  848.     geo->VertexByteStride = sizeof(Vertex);
  849.     geo->VertexBufferByteSize = vbByteSize;
  850.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  851.     geo->IndexBufferByteSize = ibByteSize;
  852.  
  853.     SubmeshGeometry submesh;
  854.     submesh.IndexCount = (UINT)indices.size();
  855.     submesh.StartIndexLocation = 0;
  856.     submesh.BaseVertexLocation = 0;
  857.  
  858.     geo->DrawArgs["grid"] = submesh;
  859.  
  860.     mGeometries["waterGeo"] = std::move(geo);
  861. }
  862.  
  863. void BlurApp::BuildBoxGeometry()
  864. {
  865.     GeometryGenerator geoGen;
  866.     GeometryGenerator::MeshData box = geoGen.CreateBox(8.0f, 8.0f, 8.0f, 3);
  867.  
  868.     std::vector<Vertex> vertices(box.Vertices.size());
  869.     for (size_t i = 0; i < box.Vertices.size(); ++i)
  870.     {
  871.         auto& p = box.Vertices[i].Position;
  872.         vertices[i].Pos = p;
  873.         vertices[i].Normal = box.Vertices[i].Normal;
  874.         vertices[i].TexC = box.Vertices[i].TexC;
  875.     }
  876.  
  877.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  878.  
  879.     std::vector<std::uint16_t> indices = box.GetIndices16();
  880.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::uint16_t);
  881.  
  882.     auto geo = std::make_unique<MeshGeometry>();
  883.     geo->Name = "boxGeo";
  884.  
  885.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  886.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  887.  
  888.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  889.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  890.  
  891.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  892.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  893.  
  894.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  895.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  896.  
  897.     geo->VertexByteStride = sizeof(Vertex);
  898.     geo->VertexBufferByteSize = vbByteSize;
  899.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  900.     geo->IndexBufferByteSize = ibByteSize;
  901.  
  902.     SubmeshGeometry submesh;
  903.     submesh.IndexCount = (UINT)indices.size();
  904.     submesh.StartIndexLocation = 0;
  905.     submesh.BaseVertexLocation = 0;
  906.  
  907.     geo->DrawArgs["box"] = submesh;
  908.  
  909.     mGeometries["boxGeo"] = std::move(geo);
  910. }
  911.  
  912. void BlurApp::BuildPSOs()
  913. {
  914.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
  915.  
  916.     //
  917.     // PSO for opaque objects.
  918.     //
  919.     ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  920.     opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  921.     opaquePsoDesc.pRootSignature = mRootSignature.Get();
  922.     opaquePsoDesc.VS = 
  923.     { 
  924.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  925.         mShaders["standardVS"]->GetBufferSize()
  926.     };
  927.     opaquePsoDesc.PS = 
  928.     { 
  929.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  930.         mShaders["opaquePS"]->GetBufferSize()
  931.     };
  932.     opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  933.     opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  934.     opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  935.     opaquePsoDesc.SampleMask = UINT_MAX;
  936.     opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  937.     opaquePsoDesc.NumRenderTargets = 1;
  938.     opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
  939.     opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  940.     opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  941.     opaquePsoDesc.DSVFormat = mDepthStencilFormat;
  942.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  943.  
  944.     //
  945.     // PSO for transparent objects
  946.     //
  947.  
  948.     D3D12_GRAPHICS_PIPELINE_STATE_DESC transparentPsoDesc = opaquePsoDesc;
  949.  
  950.     D3D12_RENDER_TARGET_BLEND_DESC transparencyBlendDesc;
  951.     transparencyBlendDesc.BlendEnable = true;
  952.     transparencyBlendDesc.LogicOpEnable = false;
  953.     transparencyBlendDesc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
  954.     transparencyBlendDesc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
  955.     transparencyBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
  956.     transparencyBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
  957.     transparencyBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
  958.     transparencyBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
  959.     transparencyBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
  960.     transparencyBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
  961.  
  962.     transparentPsoDesc.BlendState.RenderTarget[0] = transparencyBlendDesc;
  963.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&transparentPsoDesc, IID_PPV_ARGS(&mPSOs["transparent"])));
  964.  
  965.     //
  966.     // PSO for alpha tested objects
  967.     //
  968.  
  969.     D3D12_GRAPHICS_PIPELINE_STATE_DESC alphaTestedPsoDesc = opaquePsoDesc;
  970.     alphaTestedPsoDesc.PS = 
  971.     { 
  972.         reinterpret_cast<BYTE*>(mShaders["alphaTestedPS"]->GetBufferPointer()),
  973.         mShaders["alphaTestedPS"]->GetBufferSize()
  974.     };
  975.     alphaTestedPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
  976.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&alphaTestedPsoDesc, IID_PPV_ARGS(&mPSOs["alphaTested"])));
  977.  
  978.     //
  979.     // PSO for horizontal blur
  980.     //
  981.     D3D12_COMPUTE_PIPELINE_STATE_DESC horzBlurPSO = {};
  982.     horzBlurPSO.pRootSignature = mPostProcessRootSignature.Get();
  983.     horzBlurPSO.CS =
  984.     {
  985.         reinterpret_cast<BYTE*>(mShaders["horzBlurCS"]->GetBufferPointer()),
  986.         mShaders["horzBlurCS"]->GetBufferSize()
  987.     };
  988.     horzBlurPSO.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
  989.     ThrowIfFailed(md3dDevice->CreateComputePipelineState(&horzBlurPSO, IID_PPV_ARGS(&mPSOs["horzBlur"])));
  990.  
  991.     //
  992.     // PSO for vertical blur
  993.     //
  994.     D3D12_COMPUTE_PIPELINE_STATE_DESC vertBlurPSO = {};
  995.     vertBlurPSO.pRootSignature = mPostProcessRootSignature.Get();
  996.     vertBlurPSO.CS =
  997.     {
  998.         reinterpret_cast<BYTE*>(mShaders["vertBlurCS"]->GetBufferPointer()),
  999.         mShaders["vertBlurCS"]->GetBufferSize()
  1000.     };
  1001.     vertBlurPSO.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
  1002.     ThrowIfFailed(md3dDevice->CreateComputePipelineState(&vertBlurPSO, IID_PPV_ARGS(&mPSOs["vertBlur"])));
  1003. }
  1004.  
  1005. void BlurApp::BuildFrameResources()
  1006. {
  1007.     for(int i = 0; i < gNumFrameResources; ++i)
  1008.     {
  1009.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  1010.             1, (UINT)mAllRitems.size(), (UINT)mMaterials.size(), mWaves->VertexCount()));
  1011.     }
  1012. }
  1013.  
  1014. void BlurApp::BuildMaterials()
  1015. {
  1016.     auto grass = std::make_unique<Material>();
  1017.     grass->Name = "grass";
  1018.     grass->MatCBIndex = 0;
  1019.     grass->DiffuseSrvHeapIndex = 0;
  1020.     grass->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1021.     grass->FresnelR0 = XMFLOAT3(0.01f, 0.01f, 0.01f);
  1022.     grass->Roughness = .125f;
  1023.  
  1024.     // This is not a good water material definition, but we do not have all the rendering
  1025.     // tools we need (transparency, environment reflection), so we fake it for now.
  1026.     auto water = std::make_unique<Material>();
  1027.     water->Name = "water";
  1028.     water->MatCBIndex = 1;
  1029.     water->DiffuseSrvHeapIndex = 1;
  1030.     water->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 0.5f);
  1031.     water->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1032.     water->Roughness = 0.0f;
  1033.  
  1034.     auto wirefence = std::make_unique<Material>();
  1035.     wirefence->Name = "wirefence";
  1036.     wirefence->MatCBIndex = 2;
  1037.     wirefence->DiffuseSrvHeapIndex = 2;
  1038.     wirefence->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1039.     wirefence->FresnelR0 = XMFLOAT3(0.02f, 0.02f, 0.02f);
  1040.     wirefence->Roughness = 0.2f;
  1041.  
  1042.     mMaterials["grass"] = std::move(grass);
  1043.     mMaterials["water"] = std::move(water);
  1044.     mMaterials["wirefence"] = std::move(wirefence);
  1045. }
  1046.  
  1047. void BlurApp::BuildRenderItems()
  1048. {
  1049.     auto wavesRitem = std::make_unique<RenderItem>();
  1050.     wavesRitem->World = MathHelper::Identity4x4();
  1051.     XMStoreFloat4x4(&wavesRitem->TexTransform, XMMatrixScaling(5.0f, 5.0f, 1.0f));
  1052.     wavesRitem->ObjCBIndex = 0;
  1053.     wavesRitem->Mat = mMaterials["water"].get();
  1054.     wavesRitem->Geo = mGeometries["waterGeo"].get();
  1055.     wavesRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1056.     wavesRitem->IndexCount = wavesRitem->Geo->DrawArgs["grid"].IndexCount;
  1057.     wavesRitem->StartIndexLocation = wavesRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  1058.     wavesRitem->BaseVertexLocation = wavesRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  1059.  
  1060.     mWavesRitem = wavesRitem.get();
  1061.  
  1062.     mRitemLayer[(int)RenderLayer::Transparent].push_back(wavesRitem.get());
  1063.  
  1064.     auto gridRitem = std::make_unique<RenderItem>();
  1065.     gridRitem->World = MathHelper::Identity4x4();
  1066.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(5.0f, 5.0f, 1.0f));
  1067.     gridRitem->ObjCBIndex = 1;
  1068.     gridRitem->Mat = mMaterials["grass"].get();
  1069.     gridRitem->Geo = mGeometries["landGeo"].get();
  1070.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1071.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  1072.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  1073.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  1074.  
  1075.     mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
  1076.  
  1077.     auto boxRitem = std::make_unique<RenderItem>();
  1078.     XMStoreFloat4x4(&boxRitem->World, XMMatrixTranslation(3.0f, 2.0f, -9.0f));
  1079.     boxRitem->ObjCBIndex = 2;
  1080.     boxRitem->Mat = mMaterials["wirefence"].get();
  1081.     boxRitem->Geo = mGeometries["boxGeo"].get();
  1082.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1083.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  1084.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  1085.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  1086.  
  1087.     mRitemLayer[(int)RenderLayer::AlphaTested].push_back(boxRitem.get());
  1088.  
  1089.     mAllRitems.push_back(std::move(wavesRitem));
  1090.     mAllRitems.push_back(std::move(gridRitem));
  1091.     mAllRitems.push_back(std::move(boxRitem));
  1092. }
  1093.  
  1094. void BlurApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  1095. {
  1096.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  1097.     UINT matCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(MaterialConstants));
  1098.  
  1099.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  1100.     auto matCB = mCurrFrameResource->MaterialCB->Resource();
  1101.  
  1102.     // For each render item...
  1103.     for(size_t i = 0; i < ritems.size(); ++i)
  1104.     {
  1105.         auto ri = ritems[i];
  1106.  
  1107.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  1108.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  1109.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  1110.  
  1111.         CD3DX12_GPU_DESCRIPTOR_HANDLE tex(mCbvSrvUavDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  1112.         tex.Offset(ri->Mat->DiffuseSrvHeapIndex, mCbvSrvUavDescriptorSize);
  1113.  
  1114.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  1115.         D3D12_GPU_VIRTUAL_ADDRESS matCBAddress = matCB->GetGPUVirtualAddress() + ri->Mat->MatCBIndex*matCBByteSize;
  1116.  
  1117.         cmdList->SetGraphicsRootDescriptorTable(0, tex);
  1118.         cmdList->SetGraphicsRootConstantBufferView(1, objCBAddress);
  1119.         cmdList->SetGraphicsRootConstantBufferView(3, matCBAddress);
  1120.  
  1121.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  1122.     }
  1123. }
  1124.  
  1125. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> BlurApp::GetStaticSamplers()
  1126. {
  1127.     // Applications usually only need a handful of samplers.  So just define them all up front
  1128.     // and keep them available as part of the root signature.  
  1129.  
  1130.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  1131.         0, // shaderRegister
  1132.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1133.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1134.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1135.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1136.  
  1137.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  1138.         1, // shaderRegister
  1139.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1140.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1141.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1142.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1143.  
  1144.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  1145.         2, // shaderRegister
  1146.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1147.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1148.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1149.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1150.  
  1151.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  1152.         3, // shaderRegister
  1153.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1154.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1155.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1156.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1157.  
  1158.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  1159.         4, // shaderRegister
  1160.         D3D12_FILTER_ANISOTROPIC, // filter
  1161.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1162.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1163.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  1164.         0.0f,                             // mipLODBias
  1165.         8);                               // maxAnisotropy
  1166.  
  1167.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  1168.         5, // shaderRegister
  1169.         D3D12_FILTER_ANISOTROPIC, // filter
  1170.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1171.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1172.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  1173.         0.0f,                              // mipLODBias
  1174.         8);                                // maxAnisotropy
  1175.  
  1176.     return { 
  1177.         pointWrap, pointClamp,
  1178.         linearWrap, linearClamp, 
  1179.         anisotropicWrap, anisotropicClamp };
  1180. }
  1181.  
  1182. float BlurApp::GetHillsHeight(float x, float z)const
  1183. {
  1184.     return 0.3f*(z*sinf(0.1f*x) + x*cosf(0.1f*z));
  1185. }
  1186.  
  1187. XMFLOAT3 BlurApp::GetHillsNormal(float x, float z)const
  1188. {
  1189.     // n = (-df/dx, 1, -df/dz)
  1190.     XMFLOAT3 n(
  1191.         -0.03f*z*cosf(0.1f*x) - 0.3f*cosf(0.1f*z),
  1192.         1.0f,
  1193.         -0.3f*sinf(0.1f*x) + 0.03f*x*sinf(0.1f*z));
  1194.  
  1195.     XMVECTOR unitNormal = XMVector3Normalize(XMLoadFloat3(&n));
  1196.     XMStoreFloat3(&n, unitNormal);
  1197.  
  1198.     return n;
  1199. }
  1200.