text: //***************************************************************************************
  // d3dUtil.h by Frank Luna (C) 2015 All Rights Reserved.
  //
  // General helper code.
  //***************************************************************************************
  
  #pragma once
  
  #include <UDX12/UDX12.h>
  #include <UFG/UFG.h>
  #include <UDXRenderer/UDXRenderer.h>
  
  #include <windows.h>
  #include <wrl.h>
  #include <dxgi1_4.h>
  #include <d3d12.h>
  #include <D3Dcompiler.h>
  #include <DirectXMath.h>
  #include <DirectXPackedVector.h>
  #include <DirectXColors.h>
  #include <DirectXCollision.h>
  #include <string>
  #include <memory>
  #include <algorithm>
  #include <vector>
  #include <array>
  #include <unordered_map>
  #include <cstdint>
  #include <fstream>
  #include <sstream>
  #include <cassert>
  #include "MathHelper.h"
  
  #include <UDX12/_deps/DirectXTK12/ResourceUploadBatch.h>
  
  extern const int gNumFrameResources;
  
  inline void d3dSetDebugName(IDXGIObject* obj, const char* name)
  {
      if(obj)
      {
          obj->SetPrivateData(WKPDID_D3DDebugObjectName, lstrlenA(name), name);
      }
  }
  inline void d3dSetDebugName(ID3D12Device* obj, const char* name)
  {
      if(obj)
      {
          obj->SetPrivateData(WKPDID_D3DDebugObjectName, lstrlenA(name), name);
      }
  }
  inline void d3dSetDebugName(ID3D12DeviceChild* obj, const char* name)
  {
      if(obj)
      {
          obj->SetPrivateData(WKPDID_D3DDebugObjectName, lstrlenA(name), name);
      }
  }
  
  struct Light
  {
      DirectX::XMFLOAT3 Strength = { 0.5f, 0.5f, 0.5f };
      float FalloffStart = 1.0f;                          // point/spot light only
      DirectX::XMFLOAT3 Direction = { 0.0f, -1.0f, 0.0f };// directional/spot light only
      float FalloffEnd = 10.0f;                           // point/spot light only
      DirectX::XMFLOAT3 Position = { 0.0f, 0.0f, 0.0f };  // point/spot light only
      float SpotPower = 64.0f;                            // spot light only
  };
  
  #define MaxLights 16
  
  struct MaterialConstants
  {
  	DirectX::XMFLOAT4 DiffuseAlbedo = { 1.0f, 1.0f, 1.0f, 1.0f };
  	DirectX::XMFLOAT3 FresnelR0 = { 0.01f, 0.01f, 0.01f };
  	float Roughness = 0.25f;
  
  	// Used in texture mapping.
  	DirectX::XMFLOAT4X4 MatTransform = MathHelper::Identity4x4();
  };
  
  // Simple struct to represent a material for our demos.  A production 3D engine
  // would likely create a class hierarchy of Materials.
  struct Material
  {
  	// Unique material name for lookup.
  	std::string Name;
  
  	// Index into constant buffer corresponding to this material.
  	int MatCBIndex = -1;
  
  	D3D12_GPU_DESCRIPTOR_HANDLE DiffuseSrvGpuHandle{ 0 };
  
  	D3D12_GPU_DESCRIPTOR_HANDLE NormalSrvGpuHandle{ 0 };
  
  	// Dirty flag indicating the material has changed and we need to update the constant buffer.
  	// Because we have a material constant buffer for each FrameResource, we have to apply the
  	// update to each FrameResource.  Thus, when we modify a material we should set 
  	// NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  	int NumFramesDirty = gNumFrameResources;
  
  	// Material constant buffer data used for shading.
  	DirectX::XMFLOAT4 DiffuseAlbedo = { 1.0f, 1.0f, 1.0f, 1.0f };
  	DirectX::XMFLOAT3 FresnelR0 = { 0.01f, 0.01f, 0.01f };
  	float Roughness = .25f;
  	DirectX::XMFLOAT4X4 MatTransform = MathHelper::Identity4x4();
  };
  
  struct Texture
  {
  	// Unique material name for lookup.
  	std::string Name;
  
  	std::wstring Filename;
  
  	Microsoft::WRL::ComPtr<ID3D12Resource> Resource = nullptr;
  	Microsoft::WRL::ComPtr<ID3D12Resource> UploadHeap = nullptr;
  };
  
  //#ifndef ThrowIfFailed
  //#define ThrowIfFailed(x)                                              \
  //{                                                                     \
  //    HRESULT hr__ = (x);                                               \
  //    std::wstring wfn = AnsiToWString(__FILE__);                       \
  //    if(FAILED(hr__)) { throw Ubpa::DX12::Util::Exception(hr__, L#x, wfn, __LINE__); } \
  //}
  //#endif
  
  #ifndef ReleaseCom
  #define ReleaseCom(x) { if(x){ x->Release(); x = 0; } }
  #endif