//***************************************************************************************
// NormalMapApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
//***************************************************************************************
#include "../../Common/d3dApp.h"
#include "../../Common/MathHelper.h"
#include "../../Common/UploadBuffer.h"
#include "../../Common/GeometryGenerator.h"
#include "../../Common/Camera.h"
#include "FrameResource.h"
using Microsoft::WRL::ComPtr;
using namespace DirectX;
using namespace DirectX::PackedVector;
#pragma comment(lib, "d3dcompiler.lib")
#pragma comment(lib, "D3D12.lib")
const int gNumFrameResources = 3;
// Lightweight structure stores parameters to draw a shape. This will
// vary from app-to-app.
struct RenderItem
{
RenderItem() = default;
RenderItem(const RenderItem& rhs) = delete;
// World matrix of the shape that describes the object's local space
// relative to the world space, which defines the position, orientation,
// and scale of the object in the world.
XMFLOAT4X4 World = MathHelper::Identity4x4();
XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
// Dirty flag indicating the object data has changed and we need to update the constant buffer.
// Because we have an object cbuffer for each FrameResource, we have to apply the
// update to each FrameResource. Thus, when we modify obect data we should set
// NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
int NumFramesDirty = gNumFrameResources;
// Index into GPU constant buffer corresponding to the ObjectCB for this render item.
UINT ObjCBIndex = -1;
Material* Mat = nullptr;
MeshGeometry* Geo = nullptr;
// Primitive topology.
D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
// DrawIndexedInstanced parameters.
UINT IndexCount = 0;
UINT StartIndexLocation = 0;
int BaseVertexLocation = 0;
};
enum class RenderLayer : int
{
Opaque = 0,
Sky,
Wave,
Count
};
class NormalMapApp : public D3DApp
{
public:
NormalMapApp(HINSTANCE hInstance);
NormalMapApp(const NormalMapApp& rhs) = delete;
NormalMapApp& operator=(const NormalMapApp& rhs) = delete;
~NormalMapApp();
virtual bool Initialize()override;
private:
virtual void OnResize()override;
virtual void Update(const GameTimer& gt)override;
virtual void Draw(const GameTimer& gt)override;
virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
void OnKeyboardInput(const GameTimer& gt);
void AnimateMaterials(const GameTimer& gt);
void UpdateObjectCBs(const GameTimer& gt);
void UpdateMaterialBuffer(const GameTimer& gt);
void UpdateMainPassCB(const GameTimer& gt);
void LoadTextures();
void BuildRootSignature();
void BuildDescriptorHeaps();
void BuildShadersAndInputLayout();
void BuildShapeGeometry();
void BuildPSOs();
void BuildFrameResources();
void BuildMaterials();
void BuildRenderItems();
void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
private:
std::vector<std::unique_ptr<FrameResource>> mFrameResources;
FrameResource* mCurrFrameResource = nullptr;
int mCurrFrameResourceIndex = 0;
UINT mCbvSrvDescriptorSize = 0;
ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
// List of all the render items.
std::vector<std::unique_ptr<RenderItem>> mAllRitems;
// Render items divided by PSO.
std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
UINT mSkyTexHeapIndex = 0;
PassConstants mMainPassCB;
Camera mCamera;
POINT mLastMousePos;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
try
{
NormalMapApp theApp(hInstance);
if(!theApp.Initialize())
return 0;
return theApp.Run();
}
catch(DxException& e)
{
MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
return 0;
}
}
NormalMapApp::NormalMapApp(HINSTANCE hInstance)
: D3DApp(hInstance)
{
}
NormalMapApp::~NormalMapApp()
{
if(md3dDevice != nullptr)
FlushCommandQueue();
}
bool NormalMapApp::Initialize()
{
if(!D3DApp::Initialize())
return false;
// Reset the command list to prep for initialization commands.
ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
// Get the increment size of a descriptor in this heap type. This is hardware specific,
// so we have to query this information.
mCbvSrvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
mCamera.SetPosition(0.0f, 2.0f, -15.0f);
LoadTextures();
BuildRootSignature();
BuildDescriptorHeaps();
BuildShadersAndInputLayout();
BuildShapeGeometry();
BuildMaterials();
BuildRenderItems();
BuildFrameResources();
BuildPSOs();
// Execute the initialization commands.
ThrowIfFailed(mCommandList->Close());
ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
// Wait until initialization is complete.
FlushCommandQueue();
return true;
}
void NormalMapApp::OnResize()
{
D3DApp::OnResize();
mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
}
void NormalMapApp::Update(const GameTimer& gt)
{
OnKeyboardInput(gt);
// Cycle through the circular frame resource array.
mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
// Has the GPU finished processing the commands of the current frame resource?
// If not, wait until the GPU has completed commands up to this fence point.
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);
}
AnimateMaterials(gt);
UpdateObjectCBs(gt);
UpdateMaterialBuffer(gt);
UpdateMainPassCB(gt);
}
void NormalMapApp::Draw(const GameTimer& gt)
{
auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
// Reuse the memory associated with command recording.
// We can only reset when the associated command lists have finished execution on the GPU.
ThrowIfFailed(cmdListAlloc->Reset());
// A command list can be reset after it has been added to the command queue via ExecuteCommandList.
// Reusing the command list reuses memory.
ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
mCommandList->RSSetViewports(1, &mScreenViewport);
mCommandList->RSSetScissorRects(1, &mScissorRect);
// Indicate a state transition on the resource usage.
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOUR
评论0
最新资源