Microsoft Visual 2017 Community C++
 Direct3D 11.0( SM 5.0 )
 DirectXTex texture processing library
 XMLLite
 DirectXMath

■Direct3D11 Contact Hardening Soft Shadows using Erosion Prev Top Next
関連ページ:Direct3D11 自作ライブラリ


今回は以前やった Percentage-Closer Soft Shadows の改良版です。パフォーマンスが向上してます。品質は例によって微妙です。
っていうか既存プログラムのソースとかも見直すかも。

参考にした論文はここにありますので参照してください。

一応アルゴリズムについて簡単に説明します。

1.ライトビューで深度マップ作成
 いつものやつです。

2.カメラビューでシャドウマップと距離マップとカラーマップと法線マップの作成
 シャドウマップと距離マップは同一レンダーターゲットとします。シャドウマップをr成分、距離マップはgbの2成分を使用します。
 g成分には レジーバー - ブロッカー の距離を出力します。後の計算で使用し、この距離が長くなるほど影のボケが強くかかるようになります。
 b成分にはz値を出力します。 後の計算で使用し、カメラ位置に近くなるほど影のボケが強くかかるようになります。
 なお今回は前回と異なり影の範囲を拡張する処理をここでは行いません。

3.影のエッジ抽出および半影マップ作成
 今回のアルゴリズムのたぶん肝となるところだと思いますが、最終的にPCFで影をぼかす際、PCFをかける範囲を小さくすることでパフォーマンスの向上を目指します。
 でPCFをかける必要があるところは影の輪郭付近です。
 だったら影の輪郭を抽出してそれをぼかして太らせて、つまり影のボケとなる領域を拡張してそこだけPCFすればいいんじゃね、という理屈です。たぶん。
 でもって影の輪郭抽出はラプラシアンフィルターを使用します。
 半影マップには2.で出力した距離マップの値を使用して計算を行い、その結果を出力します。この値はPCFのサンプリング回数として後で使用します。

4.ミップマップ作成
 3で出力した影のエッジ抽出マップおよび半影マップのミップマップを作成します。

5.最終レンダリング
 Deferred Rendering でライティングするのは前回と同じ。PCFについても基本的に前回と同じです。

なお論文では最後に、品質改善のためにごにょごにょしてますがそこまで実装してません。


@Direct3D 自作の共通ライブラリ一式をここを参照して作成してください。
なお今回ミップマップ作成する処理を追加しているので自作の UMaps::CreateRenderTargetView() メソッドを修正しています。
もしすでに参照している場合はそちらも修正してください。

Aシェーダー系で使用するソースです。
ContactHardeningSoftShadows_Pass0.hlsl ライトビューで深度マップを作成するシェーダーソース
ContactHardeningSoftShadows_Pass1.hlsl シャドウマップを作成するシェーダーソース
ContactHardeningSoftShadows_Pass2.hlsl 影のエッジ抽出および半影マップ作成するシェーダーソース
ContactHardeningSoftShadows_Pass3.hlsl 最終レンダリングするシェーダーソース
ContactHardeningSoftShadows.h ContactHardeningSoftShadowsクラスのヘッダーファイル
ContactHardeningSoftShadows.cpp ContactHardeningSoftShadowsクラスのソースファイル

B個別に使用するソースです。
BackGroundMesh.h 地形メッシュクラスのヘッダーファイル
BackGroundMesh.cpp 地形メッシュクラスのソースファイル
main.cpp main関数のソースファイル


---ContactHardeningSoftShadows_Pass0.hlsl---  ↑

// ************************************************************
// Contact Hardening Soft Shadows    深度マップ作成
// ************************************************************

// 定数バッファ
cbuffer CBuffer : register( b0 )
{
   column_major float4x4 g_matLightWorldViewProj  : packoffset( c0 );    // ライトビューのワールドビュー射影行列
};

// 頂点シェーダーの入力パラメータ
struct VS_IN
{
   float3 pos    : POSITION;    // 頂点座標
   float3 normal : NORMAL;      // 法線ベクトル
   float2 texel  : TEXCOORD;    // テクセル
};

// 頂点シェーダーの出力パラメータ
struct VS_OUT_PS_IN
{
   float4 pos    : SV_POSITION;    // 頂点座標
   float4 posWVP : TEXCOORD0;
};

// 頂点シェーダー
VS_OUT_PS_IN ContactHardeningSoftShadows_Pass0_VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out;
   Out.pos = mul( float4( In.pos, 1 ), g_matLightWorldViewProj );
   Out.posWVP = Out.pos;
   
   return Out;
}

// ピクセルシェーダ
float ContactHardeningSoftShadows_Pass0_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET
{
   // Z値を出力
   return In.posWVP.z;
}


---ContactHardeningSoftShadows_Pass1.hlsl---  ↑


// ************************************************************
// シャドウマップ作成
// ************************************************************

// 定数バッファ
cbuffer CBuffer : register( b0 )
{
   column_major float4x4 g_matLightWorldViewProj : packoffset( c0 );   // ライトビューの正射影行列
   column_major float4x4 g_matCameraWorldViewProj: packoffset( c4 );   // カメラビューの射影行列
   column_major float4x4 g_matCameraWorld        : packoffset( c8 );   // カメラビューのワールド行列
};

Texture2D g_DecalMap : register( t0 );
Texture2D g_DepthMap : register( t1 );

// サンプラーステート
SamplerState g_SamplerDecalMap : register( s0 );
SamplerState g_SamplerDepthMap : register( s1 );

// 頂点シェーダーの入力パラメータ
struct VS_IN
{
   float3 pos    : POSITION;    // 頂点座標
   float3 normal : NORMAL;      // 法線ベクトル
   float2 texel  : TEXCOORD;    // テクセル
};

// 頂点シェーダーの出力パラメータ
struct VS_OUT_PS_IN
{
   float4 pos     : SV_POSITION;    // 頂点座標
   float4 posLWVP : TEXCOORD0;
   float3 normal  : TEXCOORD1;
   float2 texel   : TEXCOORD2;
   float4 posCWVP : TEXCOORD3;
};

// ピクセルシェーダーの出力パラメータ
struct VS_IN_PS_OUT
{
   float4 ShadowAndDistanceMap   : SV_TARGET0;
   float4 ColorMap               : SV_TARGET1;
   float4 NormalMap              : SV_TARGET2;
};

// 頂点シェーダー
VS_OUT_PS_IN ContactHardeningSoftShadows_Pass1_VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out;
   Out.pos = mul( float4( In.pos, 1 ), g_matCameraWorldViewProj );
   Out.posLWVP = mul( float4( In.pos, 1 ), g_matLightWorldViewProj );
   Out.normal = mul( In.normal, (float3x3)g_matCameraWorld );
   Out.texel = In.texel;
   Out.posCWVP = Out.pos;

   return Out;
}

// ピクセルシェーダ
VS_IN_PS_OUT ContactHardeningSoftShadows_Pass1_PS_Main( VS_OUT_PS_IN In )
{
   VS_IN_PS_OUT Out = (VS_IN_PS_OUT)0;
   
   // ライトビューマップ上のテクセル座標
   float2 texel = In.posLWVP.xy / In.posLWVP.w * float2( 0.5f, -0.5f ) + 0.5f;

   // 深度マップ上の深度値( ブロッカー )を取得
   float dBlocker = g_DepthMap.Sample( g_SamplerDepthMap, texel ).r;
   
   // w除算してないため大きめ
   float bias = 5.0f;
   
   // ライトビュー上の深度値( バイアス調整つき )
   float z = In.posLWVP.z - bias;
   
   // シャドウマップ作成( 影の色も考慮する )
   Out.ShadowAndDistanceMap.r = z - dBlocker > 0.0f ? 0.3f : 1.0f;

   // カラーマップ作成
   Out.ColorMap = g_DecalMap.Sample( g_SamplerDecalMap, In.texel );
   
   // 法線マップ作成
   Out.NormalMap = float4( normalize( In.normal ), 0 );
   
   // レシーバー - ブロッカーの距離
   Out.ShadowAndDistanceMap.g = z - dBlocker;

   // 深度値
   Out.ShadowAndDistanceMap.b = In.posCWVP.z;
      
   return Out;
}


---ContactHardeningSoftShadows_Pass2.hlsl---  ↑


// ************************************************************
// Laplacian Filter, penumbra
// ************************************************************

// 定数バッファ
cbuffer cbBuffer0 : register( b0 )
{
   float2 g_TexelSizeOfCameraView : packoffset( c0 );   // 1テクセルサイズ
   float  g_LightSize             : packoffset( c0.z );
};

// テクスチャー
Texture2D g_ShadowAndDistanceMap : register( t0 );

// サンプラーステート
SamplerState  g_Sampler;

// 頂点シェーダーの入力パラメータ
struct VS_IN
{
   float3 pos    : POSITION;   // 頂点座標
   float2 texel  : TEXCOORD;
};

// 頂点シェーダーの出力パラメータ
struct VS_OUT_PS_IN
{
   float4 pos    : SV_POSITION;
   float2 texel  : TEXCOORD;
};

VS_OUT_PS_IN ContactHardeningSoftShadows_Pass2_VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out;

   Out.pos = float4( In.pos, 1.0f );
   Out.texel = In.texel;
   return Out;
}

float2 ContactHardeningSoftShadows_Pass2_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET
{
   float2 Out = (float2)0;
   
   // ラプラシアンフィルター
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel ).r * -8.0f;
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2(  0,  2 ) ).r;
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2(  2,  0 ) ).r;
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2(  0, -2 ) ).r;
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2( -2,  0 ) ).r;
   
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2(  2,  2 ) ).r;
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2( -2, -2 ) ).r;
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2(  2, -2 ) ).r;
   Out.r += g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + g_TexelSizeOfCameraView.xy * float2( -2,  2 ) ).r;
      
   Out.r = abs( Out.r );
   
   float2 dmap = g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel ).gb;
   
   // penumbra
   Out.g = g_LightSize * dmap.r / dmap.g;
   
   return Out;
}


---ContactHardeningSoftShadows_Pass3.hlsl---  ↑


// ************************************************************
// 最終レンダリング
// ************************************************************

// 定数バッファ
cbuffer cbBuffer0 : register( b0 )
{
   float4 g_vecLightPos           : packoffset( c0 );    // ローカル座標系での平行光源の位置ベクトル
   float2 g_TexelSizeOfCameraView : packoffset( c1.x );  // 1テクセルサイズ
   float  g_MaxMipmapLevel        : packoffset( c1.z );
   float  g_CameraZFar            : packoffset( c1.w );
};

// テクスチャー
Texture2D g_ShadowAndDistanceMap    : register( t0 );
Texture2D g_ColorMap                : register( t1 );
Texture2D g_NormalMap               : register( t2 );
Texture2D g_LaplacianMap            : register( t3 );

// サンプラーステート
SamplerState  g_Sampler;

// 頂点シェーダーの入力パラメータ
struct VS_IN
{
   float3 pos    : POSITION;   // 頂点座標
   float2 texel  : TEXCOORD;
};

// 頂点シェーダーの出力パラメータ
struct VS_OUT_PS_IN
{
   float4 pos    : SV_POSITION;
   float2 texel  : TEXCOORD;
};

VS_OUT_PS_IN ContactHardeningSoftShadows_Pass3_VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out;

   Out.pos = float4( In.pos, 1.0f );
   Out.texel = In.texel;
   return Out;
}

float4 ContactHardeningSoftShadows_Pass3_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET
{
   float  shadowMap;
   float4 colorMap = g_ColorMap.Sample( g_Sampler, In.texel ).bgra;
   float3 normalMap = g_NormalMap.Sample( g_Sampler, In.texel ).rgb;
   
   // 影の幅を取得
   float laplacianMap = g_LaplacianMap.SampleLevel( g_Sampler, In.texel, g_MaxMipmapLevel ).r;
   
   // 深度値を取得
   float z = g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel ).b / g_CameraZFar;
   
   if( laplacianMap > 0.01f )
   {
       // ループ回数を取得する
       // 平均値を取得するためミップマップレベル最大値のマップをサンプリングする
       float penumbraMap = g_LaplacianMap.SampleLevel( g_Sampler, In.texel, g_MaxMipmapLevel ).g;
   
       // 最大ループ回数をボケ具合を見て適当に最大値を調整
       penumbraMap = min( penumbraMap, 7 );
       
       int index = penumbraMap;

       float count = 1;
       shadowMap = g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel ).r;

       // PCF
	   [unroll(20)]
	   for( int i=-index; i<=index; i++ )
	   {
	      [unroll(20)]
	      for( int j=-index; j<=index; j++ )
	      {
             // 深度値を取得
             float2 shadowAnddistance = g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel + float2( i, j ) * g_TexelSizeOfCameraView ).rb;
             shadowAnddistance.g /= g_CameraZFar;
             
             // 距離が近いところだけ合成する。バイアスは適当
             if( abs( z - shadowAnddistance.g ) < 0.01f )
             {
                shadowMap += shadowAnddistance.r;
	            count++;
	         }
	      }
	   }
	   
       shadowMap /= count;
   }
   else
   {
      shadowMap = g_ShadowAndDistanceMap.Sample( g_Sampler, In.texel ).r;
   }

   if( length( normalMap ) > 0.1f )
   {
      // ハーフランバート
      float lambert = dot( normalize( g_vecLightPos.xyz ), normalMap );
      lambert = lambert * 0.5f + 0.5f;

      // 影適用
      colorMap *= lambert * shadowMap;
   }
   
   return colorMap;
}

翻訳が怪しいので自信なし。
それとボケ影になってほしくないところにも影になってしまうので深度値の距離が近いところだけPCFするようにしています。

---ContactHardeningSoftShadows.h---  ↑


#pragma once

#include "../Common/UCommon.h"
#include "../Common/UException.h"
#include "../Common/UGraphicsPipeline.h"
#include "../Common/UDirect3D11.h"

class ContactHardeningSoftShadows
{
private:
   // Deferred Rendering するときに使用する頂点定義
   typedef struct _VERTEX
   {
      XMFLOAT3 pos;     // 頂点の座標
      XMFLOAT2 texel;   // テクセル座標
   }VERTEX;

   // Deferred Rendering で使用する頂点バッファ
   ID3D11Buffer* m_pVertexBuffer;

   // 深度マップ作成
   typedef struct _CBUFFER_PASS0
   {
      XMMATRIX matLightWorldViewProj;
   }CBUFFER_PASS0;

   // シャドウマップ作成
   typedef struct _CBUFFER_PASS1
   {
      // ライトビューでのワールドとビューと射影行列
      XMMATRIX matLightWorldViewProj;
      // カメラビューでのワールドとビューと射影行列
      XMMATRIX matCameraWorldViewProj;
      XMMATRIX matWorld;
   }CBUFFER_PASS1;

   // Laplacian Filter
   typedef struct _CBUFFER_PASS2
   {
      XMFLOAT2 TexelSizeOfCameraView;  // カメラビュー用マップ上での1テクセルサイズ
      float LightSize;
      float Dummy4;
   }CBUFFER_PASS2;

   // Deferred Rendering
   typedef struct _CBUFFER_PASS3
   {
      XMFLOAT4 vecLightDir;
      XMFLOAT2 TexelSizeOfCameraView;  // カメラビュー用マップ上での1テクセルサイズ
      float MaxMipmapLevel;
      float CameraZFar;
   }CBUFFER_PASS3;

   // ライトビュー空間上の深度マップ
   ID3D11DepthStencilView* m_pDSViewOfLightViewDepthMap;
   ID3D11RenderTargetView* m_pRTViewOfLightViewDepthMap;
   ID3D11ShaderResourceView* m_pSRViewOfLightViewDepthMap;

   // カメラビュー空間上の深度マップ
   ID3D11DepthStencilView* m_pDSViewOfCameraViewDepthMap;

   // カメラビュー空間上でのシャドウマップと距離マップ
   // r:シャドウマップ、g:ライトビューでのレシーバー - ブロッカーの距離、b:カメラビューでの深度値
   ID3D11RenderTargetView* m_pRTViewOfShadowAndDistanceMap;
   ID3D11ShaderResourceView* m_pSRViewOfShadowAndDistanceMap;

   // カメラビュー空間上でのカラーマップ
   ID3D11RenderTargetView* m_pRTViewOfColorMap;
   ID3D11ShaderResourceView* m_pSRViewOfColorMap;

   // カメラビュー空間上での法線マップ
   ID3D11RenderTargetView* m_pRTViewOfNormalMap;
   ID3D11ShaderResourceView* m_pSRViewOfNormalMap;

   // r:ラプラシアンフィルター、g:penumbraマップ
   ID3D11RenderTargetView* m_pRTViewOfLaplacianFilterMap;
   ID3D11ShaderResourceView* m_pSRViewOfLaplacianFilterMap;

   // サンプラーステート
   ID3D11SamplerState* m_pSamplerState;

   // レンダーターゲットと深度ステンシルとビューポートのバックアップ
   ID3D11RenderTargetView* m_pOldRTView;
   ID3D11DepthStencilView* m_pOldDSView;
   D3D11_VIEWPORT m_pOldViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
   UINT m_ViewportCount;

   // シェーダー用定数バッファ
   ID3D11Buffer* m_pConstantBuffers[4];

   UGraphicsPipeline* m_pGraphicsPipeline[4];

   DWORD m_LightViewWidth, m_LightViewHeight, m_CameraViewWidth, m_CameraViewHeight;

   UINT m_MaxMipmapLevel;
   float m_LightSize;
   float m_CameraZFar;

   int m_Pass;

   XMFLOAT4 m_VecLightPos;

   XMMATRIX m_MatLightView;
   XMMATRIX m_MatLightProj;
   XMMATRIX m_MatCameraView;
   XMMATRIX m_MatCameraProj;

   // ラプラシアンフィルターによるシャドウマップのエッジ抽出およびpenumbra( 半影マップ )およびラプラシアンフィルターのミップマップ作成
   void RenderLaplacianFilterAndPenumbraMap(ID3D11DeviceContext* pD3DDeviceContext);

   void RenderDeferredRendering(ID3D11DeviceContext* pD3DDeviceContext);

public:
   ContactHardeningSoftShadows();
   virtual ~ContactHardeningSoftShadows();
   void Invalidate();
   void Create(ID3D11Device* pD3DDevice, DWORD LightViewWidth, DWORD LightViewHeight, DWORD CameraViewWidth, DWORD CameraViewHeight );
   void Begin(XMFLOAT4* pVecLightPos, XMMATRIX* pMatLightProj, XMMATRIX* pMatCameraView, XMMATRIX* pMatCameraProj, float CameraZFar);
   void BeginPass(ID3D11DeviceContext* pD3DDeviceContext, UINT Pass);
   void SetConstantBuffers(ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld);
   void EndPass(ID3D11DeviceContext* pD3DDeviceContext);
   void End();
   inline UINT GetMaxPass(){ return 2; };
   inline const ID3D11ShaderResourceView* GetDepthMap(){ return m_pSRViewOfLightViewDepthMap; };
   inline const ID3D11ShaderResourceView* GetShadowAndDistanceMap(){ return m_pSRViewOfShadowAndDistanceMap; };
   inline const ID3D11ShaderResourceView* GetColorMap(){ return m_pSRViewOfColorMap; };
   inline const ID3D11ShaderResourceView* GetNormalMap(){ return m_pSRViewOfNormalMap; };
   inline const ID3D11ShaderResourceView* GetLaplacianFilterMap(){ return m_pSRViewOfLaplacianFilterMap; };
};

---ContactHardeningSoftShadows.cpp---  ↑


#include "../../Header/Shader/ContactHardeningSoftShadows.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass0_VS_Main.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass0_PS_Main.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass1_VS_Main.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass1_PS_Main.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass2_VS_Main.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass2_PS_Main.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass3_VS_Main.h"
#include "../../HLSL/ContactHardeningSoftShadows_Pass3_PS_Main.h"

ContactHardeningSoftShadows::ContactHardeningSoftShadows()
{
   m_pVertexBuffer = nullptr;
   m_pDSViewOfLightViewDepthMap = nullptr;
   m_pRTViewOfLightViewDepthMap = nullptr;
   m_pSRViewOfLightViewDepthMap = nullptr;
   m_pDSViewOfCameraViewDepthMap = nullptr;
   m_pRTViewOfShadowAndDistanceMap = nullptr;
   m_pSRViewOfShadowAndDistanceMap = nullptr;
   m_pRTViewOfColorMap = nullptr;
   m_pSRViewOfColorMap = nullptr;
   m_pRTViewOfNormalMap = nullptr;
   m_pSRViewOfNormalMap = nullptr;
   m_pRTViewOfLaplacianFilterMap = nullptr;
   m_pSRViewOfLaplacianFilterMap = nullptr;
   m_pSamplerState = nullptr;
   for (UINT i = 0; i<_countof(m_pConstantBuffers); i++)
   {
      m_pConstantBuffers[i] = nullptr;
   }
   for (UINT i = 0; i<_countof(m_pGraphicsPipeline); i++)
   {
      m_pGraphicsPipeline[i] = nullptr;
   }

   // 1以上を設定すること
   m_MaxMipmapLevel = 5;

   m_LightSize = 3.0f;

   m_Pass = -2;
}

ContactHardeningSoftShadows::~ContactHardeningSoftShadows()
{
   for (UINT i = 0; i<_countof(m_pGraphicsPipeline); i++)
   {
      SAFE_DELETE(m_pGraphicsPipeline[i]);
   }
   for (UINT i = 0; i<_countof(m_pConstantBuffers); i++)
   {
      SAFE_RELEASE(m_pConstantBuffers[i]);
   }
   SAFE_RELEASE(m_pSamplerState);
   SAFE_RELEASE(m_pSRViewOfLaplacianFilterMap);
   SAFE_RELEASE(m_pRTViewOfLaplacianFilterMap);
   SAFE_RELEASE(m_pSRViewOfNormalMap);
   SAFE_RELEASE(m_pRTViewOfNormalMap);
   SAFE_RELEASE(m_pSRViewOfColorMap);
   SAFE_RELEASE(m_pRTViewOfColorMap);
   SAFE_RELEASE(m_pSRViewOfShadowAndDistanceMap);
   SAFE_RELEASE(m_pRTViewOfShadowAndDistanceMap);
   SAFE_RELEASE(m_pDSViewOfCameraViewDepthMap);
   SAFE_RELEASE(m_pSRViewOfLightViewDepthMap);
   SAFE_RELEASE(m_pRTViewOfLightViewDepthMap);
   SAFE_RELEASE(m_pDSViewOfLightViewDepthMap);
   SAFE_RELEASE(m_pVertexBuffer);
}

void ContactHardeningSoftShadows::Create(ID3D11Device* pD3DDevice, DWORD LightViewWidth, DWORD LightViewHeight, DWORD CameraViewWidth, DWORD CameraViewHeight)
{
   m_LightViewWidth = LightViewWidth;
   m_LightViewHeight = LightViewHeight;
   m_CameraViewWidth = CameraViewWidth;
   m_CameraViewHeight = CameraViewHeight;

   m_Pass = -2;

   for (UINT i = 0; i<_countof(m_pGraphicsPipeline); i++)
   {
      m_pGraphicsPipeline[i] = NEW UGraphicsPipeline();
   }

   // ラスタライザーステートを作成する
   m_pGraphicsPipeline[0]->CreateRasterizerState(pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK);

   // 深度ステンシルステートを有効にする
   m_pGraphicsPipeline[0]->CreateDepthStencilState(pD3DDevice, TRUE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL);

   // ブレンドステートを作成する
   UGraphicsPipeline::UEBLEND_STATE BlendStateType[1] = { UGraphicsPipeline::UEBLEND_STATE::NONE };
   m_pGraphicsPipeline[0]->CreateBlendState(pD3DDevice, BlendStateType, 1);

   D3D11_INPUT_ELEMENT_DESC layout[] = {
      { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
      { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
      { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
   };

   // *******************************************************************************************************
   // ライトビューで深度マップ作成
   // *******************************************************************************************************

   // シェーダーを作成する
#if defined(DEBUG) || defined(_DEBUG)
   m_pGraphicsPipeline[0]->CreateVertexShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass0.hlsl"), "ContactHardeningSoftShadows_Pass0_VS_Main", layout, _countof(layout));
   m_pGraphicsPipeline[0]->CreatePixelShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass0.hlsl"), "ContactHardeningSoftShadows_Pass0_PS_Main");
#else
   m_pGraphicsPipeline[0]->CreateVertexShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass0_VS_Main, sizeof(g_ContactHardeningSoftShadows_Pass0_VS_Main), layout, _countof(layout));
   m_pGraphicsPipeline[0]->CreatePixelShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass0_PS_Main, sizeof(g_ContactHardeningSoftShadows_Pass0_PS_Main));
#endif

   // 深度ステンシルバッファを作成する
   UMaps::CreateDepthStencilView(pD3DDevice, m_LightViewWidth, m_LightViewHeight, &m_pDSViewOfLightViewDepthMap, nullptr);
   UMaps::CreateRenderTargetView(pD3DDevice, DXGI_FORMAT_R16_FLOAT, m_LightViewWidth, m_LightViewHeight, &m_pRTViewOfLightViewDepthMap, &m_pSRViewOfLightViewDepthMap);

   // 定数バッファを作成する
   m_pConstantBuffers[0] = m_pGraphicsPipeline[0]->CreateConstantBuffer(pD3DDevice, nullptr, sizeof(ContactHardeningSoftShadows::CBUFFER_PASS0), D3D11_CPU_ACCESS_WRITE);

   // *******************************************************************************************************
   // カメラビューでシャドウマップ作成
   // *******************************************************************************************************

   // シェーダーを作成する
#if defined(DEBUG) || defined(_DEBUG)
   m_pGraphicsPipeline[1]->CreateVertexShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass1.hlsl"), "ContactHardeningSoftShadows_Pass1_VS_Main", layout, _countof(layout));
   m_pGraphicsPipeline[1]->CreatePixelShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass1.hlsl"), "ContactHardeningSoftShadows_Pass1_PS_Main");
#else
   m_pGraphicsPipeline[1]->CreateVertexShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass1_VS_Main, sizeof(g_ContactHardeningSoftShadows_Pass1_VS_Main), layout, _countof(layout));
   m_pGraphicsPipeline[1]->CreatePixelShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass1_PS_Main, sizeof(g_ContactHardeningSoftShadows_Pass1_PS_Main));
#endif

   // 深度ステンシルバッファを作成する
   UMaps::CreateDepthStencilView(pD3DDevice, m_CameraViewWidth, m_CameraViewHeight, &m_pDSViewOfCameraViewDepthMap, nullptr);

   // r:シャドウマップ、g:ライトビューでのレシーバー - ブロッカーの距離、b:カメラビューでの深度値
   UMaps::CreateRenderTargetView(pD3DDevice, DXGI_FORMAT_R16G16B16A16_FLOAT, m_CameraViewWidth, m_CameraViewHeight, &m_pRTViewOfShadowAndDistanceMap, &m_pSRViewOfShadowAndDistanceMap);

   // カラーマップを作成する
   UMaps::CreateRenderTargetView(pD3DDevice, DXGI_FORMAT_R8G8B8A8_UNORM, m_CameraViewWidth, m_CameraViewHeight, &m_pRTViewOfColorMap, &m_pSRViewOfColorMap);

   // 法線マップを作成する
   UMaps::CreateRenderTargetView(pD3DDevice, DXGI_FORMAT_R16G16B16A16_FLOAT, m_CameraViewWidth, m_CameraViewHeight, &m_pRTViewOfNormalMap, &m_pSRViewOfNormalMap);

   // サンプラーステートを作成する
   m_pSamplerState = USamplers::CreateSamplerState(pD3DDevice, D3D11_TEXTURE_ADDRESS_CLAMP);

   // 定数バッファを作成する
   m_pConstantBuffers[1] = m_pGraphicsPipeline[1]->CreateConstantBuffer(pD3DDevice, nullptr, sizeof(ContactHardeningSoftShadows::CBUFFER_PASS1), D3D11_CPU_ACCESS_WRITE);

   // *******************************************************************************************************
   // ラプラシアンフィルターとPenumbraマップ作成
   // *******************************************************************************************************

   // ラスタライザーステートを作成する
   m_pGraphicsPipeline[2]->CreateRasterizerState(pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK);

   // 深度ステンシルステートを無効にする
   m_pGraphicsPipeline[2]->CreateDepthStencilState(pD3DDevice, FALSE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ZERO);

   // ブレンドステートを作成する
   UGraphicsPipeline::UEBLEND_STATE BlendStateType2[1] = { UGraphicsPipeline::UEBLEND_STATE::NONE };
   m_pGraphicsPipeline[2]->CreateBlendState(pD3DDevice, BlendStateType2, 1);

   D3D11_INPUT_ELEMENT_DESC layout2[] = {
      { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
      { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
   };

   // 頂点のデータ
   VERTEX v[] = {
      XMFLOAT3(1, 1, 0), XMFLOAT2(1, 0),
      XMFLOAT3(-1, 1, 0), XMFLOAT2(0, 0),
      XMFLOAT3(1, -1, 0), XMFLOAT2(1, 1),
      XMFLOAT3(-1, -1, 0), XMFLOAT2(0, 1)
   };
   // 頂点バッファを作成する
   m_pVertexBuffer = UBuffers::CreateVertexBuffer(pD3DDevice, v, sizeof(v), 0);

   // シェーダーを作成する
#if defined(DEBUG) || defined(_DEBUG)
   m_pGraphicsPipeline[2]->CreateVertexShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass2.hlsl"), "ContactHardeningSoftShadows_Pass2_VS_Main", layout2, _countof(layout2));
   m_pGraphicsPipeline[2]->CreatePixelShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass2.hlsl"), "ContactHardeningSoftShadows_Pass2_PS_Main");
#else
   m_pGraphicsPipeline[2]->CreateVertexShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass2_VS_Main, sizeof(g_ContactHardeningSoftShadows_Pass2_VS_Main), layout2, _countof(layout2));
   m_pGraphicsPipeline[2]->CreatePixelShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass2_PS_Main, sizeof(g_ContactHardeningSoftShadows_Pass2_PS_Main));
#endif

   // ラプラシアンフィルターとpenumbraマップを作成する
   UMaps::CreateRenderTargetView(pD3DDevice, DXGI_FORMAT_R16G16_FLOAT, m_CameraViewWidth, m_CameraViewHeight, &m_pRTViewOfLaplacianFilterMap, &m_pSRViewOfLaplacianFilterMap, 1, m_MaxMipmapLevel);

   // 定数バッファを作成する
   m_pConstantBuffers[2] = m_pGraphicsPipeline[2]->CreateConstantBuffer(pD3DDevice, nullptr, sizeof(ContactHardeningSoftShadows::CBUFFER_PASS2), D3D11_CPU_ACCESS_WRITE);

   // *******************************************************************************************************
   // 最終レンダリング
   // *******************************************************************************************************

   // ラスタライザーステートを作成する
   m_pGraphicsPipeline[3]->CreateRasterizerState(pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK);

   // 深度ステンシルステートを無効にする
   m_pGraphicsPipeline[3]->CreateDepthStencilState(pD3DDevice, FALSE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ZERO);

   // ブレンドステートを作成する
   UGraphicsPipeline::UEBLEND_STATE BlendStateType3[1] = { UGraphicsPipeline::UEBLEND_STATE::NONE };
   m_pGraphicsPipeline[3]->CreateBlendState(pD3DDevice, BlendStateType3, 1);

   // シェーダーを作成する
#if defined(DEBUG) || defined(_DEBUG)
   m_pGraphicsPipeline[3]->CreateVertexShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass3.hlsl"), "ContactHardeningSoftShadows_Pass3_VS_Main", layout2, _countof(layout2));
   m_pGraphicsPipeline[3]->CreatePixelShaderFromFile(pD3DDevice, _T("../HLSL/ContactHardeningSoftShadows_Pass3.hlsl"), "ContactHardeningSoftShadows_Pass3_PS_Main");
#else
   m_pGraphicsPipeline[3]->CreateVertexShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass3_VS_Main, sizeof(g_ContactHardeningSoftShadows_Pass3_VS_Main), layout2, _countof(layout2));
   m_pGraphicsPipeline[3]->CreatePixelShaderFromMemory(pD3DDevice, (LPBYTE)g_ContactHardeningSoftShadows_Pass3_PS_Main, sizeof(g_ContactHardeningSoftShadows_Pass3_PS_Main));
#endif

   // 定数バッファを作成する
   m_pConstantBuffers[3] = m_pGraphicsPipeline[3]->CreateConstantBuffer(pD3DDevice, nullptr, sizeof(ContactHardeningSoftShadows::CBUFFER_PASS3), D3D11_CPU_ACCESS_WRITE);
}

void ContactHardeningSoftShadows::Begin(XMFLOAT4* pVecLightPos, XMMATRIX* pMatLightProj, XMMATRIX* pMatCameraView, XMMATRIX* pMatCameraProj, float CameraZFar)
{
   if (m_Pass != -2)
   {
      throw(UException(-1, _T("ContactHardeningSoftShadows::Begin()はCreate()またはEnd()実行後に使用してください")));
   }

   m_VecLightPos = *pVecLightPos;

   m_MatLightView = XMMatrixLookAtLH(XMLoadFloat3((XMFLOAT3*)&m_VecLightPos), XMLoadFloat3(&XMFLOAT3(0, 0, 0)), XMLoadFloat3(&XMFLOAT3(0, 1, 0)));
   m_MatLightProj = *pMatLightProj;
   m_MatCameraView = *pMatCameraView;
   m_MatCameraProj = *pMatCameraProj;
   m_CameraZFar = CameraZFar;

   m_Pass = -1;
}

void ContactHardeningSoftShadows::BeginPass(ID3D11DeviceContext* pD3DDeviceContext, UINT Pass)
{
   if (m_Pass != -1)
   {
      throw(UException(-1, _T("ContactHardeningSoftShadows::BeginPass()はBegin()またはEndPass()実行後に使用してください")));
   }

   m_Pass = (int)Pass;

   switch (m_Pass)
   {
      // ライトビューでの深度マップ作成
      case 0:
      {
         // レンダーターゲットを退避
         pD3DDeviceContext->OMGetRenderTargets(1, &m_pOldRTView, &m_pOldDSView);
         // レンダーターゲットを切り替え
         pD3DDeviceContext->OMSetRenderTargets(1, &m_pRTViewOfLightViewDepthMap, m_pDSViewOfLightViewDepthMap);

         // ビューポートの退避
         pD3DDeviceContext->RSGetViewports(&m_ViewportCount, nullptr);
         pD3DDeviceContext->RSGetViewports(&m_ViewportCount, &m_pOldViewport[0]);

         // ビューポートの切り替え
         D3D11_VIEWPORT Viewport[1];
         Viewport[0].TopLeftX = 0;
         Viewport[0].TopLeftY = 0;
         Viewport[0].Width = (float)m_LightViewWidth;
         Viewport[0].Height = (float)m_LightViewHeight;
         Viewport[0].MinDepth = 0.0f;
         Viewport[0].MaxDepth = 1.0f;
         pD3DDeviceContext->RSSetViewports(1, Viewport);

         float ClearWhite[] = { 1, 1, 1, 1 };
         pD3DDeviceContext->ClearRenderTargetView(m_pRTViewOfLightViewDepthMap, ClearWhite);

         // 深度バッファをクリアする。
         pD3DDeviceContext->ClearDepthStencilView(m_pDSViewOfLightViewDepthMap, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
      }
      break;

      // シャドウマップ、カラーマップ、法線マップ、距離マップ 作成
      case 1:
      {
         ID3D11RenderTargetView* pRTView[] = { m_pRTViewOfShadowAndDistanceMap, m_pRTViewOfColorMap, m_pRTViewOfNormalMap };
         // レンダーターゲットを切り替え
         pD3DDeviceContext->OMSetRenderTargets(_countof(pRTView), pRTView, m_pDSViewOfCameraViewDepthMap);

         float ClearBlack[] = { 0, 0, 0, 0 };
         float ClearBlue[] = { 1, 0.7f, 0.4f, 1.0f };  // bgra?

         pD3DDeviceContext->ClearRenderTargetView(m_pRTViewOfShadowAndDistanceMap, ClearBlack);
         pD3DDeviceContext->ClearRenderTargetView(m_pRTViewOfColorMap, ClearBlue);
         pD3DDeviceContext->ClearRenderTargetView(m_pRTViewOfNormalMap, ClearBlack);
         pD3DDeviceContext->PSSetSamplers(1, 1, &m_pSamplerState);

         pD3DDeviceContext->ClearDepthStencilView(m_pDSViewOfCameraViewDepthMap, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

         pD3DDeviceContext->PSSetShaderResources(1, 1, &m_pSRViewOfLightViewDepthMap);
      }
      break;

      default:
      {
         throw(UException(-1, _T("ContactHardeningSoftShadows::BeginPass()で無効なPassが指定されました")));
      }
   }

   // 各種ステートを設定する
   m_pGraphicsPipeline[0]->SetRasterizerState(pD3DDeviceContext);
   m_pGraphicsPipeline[0]->SetDepthStencilState(pD3DDeviceContext);
   m_pGraphicsPipeline[0]->SetBlendState(pD3DDeviceContext);

   // 各種グラフィックパイプラインを設定
   m_pGraphicsPipeline[m_Pass]->SetVertexShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetHullShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetDomainShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetGeometryShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetPixelShader(pD3DDeviceContext);
}

void ContactHardeningSoftShadows::SetConstantBuffers(ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld)
{
   HRESULT hr = E_FAIL;

   if (m_Pass == -1)
   {
      throw(UException(-1, _T("ContactHardeningSoftShadows::SetConstantBuffers()はBeginPass()実行に使用してください")));
   }

   switch (m_Pass)
   {
      case 0:
      {
         XMMATRIX matLightWorldViewProj = XMMatrixTranspose(*pMatWorld * m_MatLightView * m_MatLightProj);

         // 定数バッファを作成する
         D3D11_MAPPED_SUBRESOURCE mappedResource;
         if (FAILED(hr = pD3DDeviceContext->Map(m_pConstantBuffers[m_Pass], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)))
            throw(UException(-1, _T("ContactHardeningSoftShadows::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。")));

         ContactHardeningSoftShadows::CBUFFER_PASS0* cbuffer = (ContactHardeningSoftShadows::CBUFFER_PASS0*)mappedResource.pData;
         ::CopyMemory(&cbuffer->matLightWorldViewProj, &matLightWorldViewProj, sizeof(XMMATRIX));
         pD3DDeviceContext->Unmap(m_pConstantBuffers[m_Pass], 0);

         // 定数バッファを設定
         pD3DDeviceContext->VSSetConstantBuffers(0, 1, &m_pConstantBuffers[m_Pass]);
      }
      break;

      case 1:
      {
         // ライトビューのワールド行列とビュー行列と射影行列
         XMMATRIX matLightWorldViewProj = XMMatrixTranspose(*pMatWorld * m_MatLightView * m_MatLightProj);

         // カメラビューのワールド行列とビュー行列と射影行列
         XMMATRIX matCameraWorldViewProj = XMMatrixTranspose(*pMatWorld * m_MatCameraView * m_MatCameraProj);

         // カメラビューのワールド行列( ローカル座標系の法線ベクトルの座標変換のため逆転置行列 )
         XMMATRIX matWorld = XMMatrixInverse(nullptr, *pMatWorld);

         // 定数バッファを設定する
         D3D11_MAPPED_SUBRESOURCE mappedResource;
         if (FAILED(hr = pD3DDeviceContext->Map(m_pConstantBuffers[m_Pass], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)))
            throw(UException(-1, _T("PercentageCloserSoftShadows::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。")));
         ContactHardeningSoftShadows::CBUFFER_PASS1* cbuffer = (ContactHardeningSoftShadows::CBUFFER_PASS1*)mappedResource.pData;
         ::CopyMemory(&cbuffer->matLightWorldViewProj, &matLightWorldViewProj, sizeof(XMMATRIX));
         ::CopyMemory(&cbuffer->matCameraWorldViewProj, &matCameraWorldViewProj, sizeof(XMMATRIX));
         ::CopyMemory(&cbuffer->matWorld, &matWorld, sizeof(XMMATRIX));
         pD3DDeviceContext->Unmap(m_pConstantBuffers[m_Pass], 0);

         pD3DDeviceContext->VSSetConstantBuffers(0, 1, &m_pConstantBuffers[m_Pass]);
      }
      break;
   }
}

void ContactHardeningSoftShadows::EndPass(ID3D11DeviceContext* pD3DDeviceContext)
{
   switch (m_Pass)
   {
      case 0:
         // ビューポートを戻す
         pD3DDeviceContext->RSSetViewports(m_ViewportCount, m_pOldViewport);
         break;

      case 1:
      {
         m_Pass++;

         // ラプラシアンフィルターによるシャドウマップのエッジ抽出およびpenumbra( 半影マップ )およびラプラシアンフィルターのミップマップ作成
         RenderLaplacianFilterAndPenumbraMap(pD3DDeviceContext);

         // レンダーターゲットビューと深度ステンシルビューを戻す
         pD3DDeviceContext->OMSetRenderTargets(1, &m_pOldRTView, m_pOldDSView);
         SAFE_RELEASE(m_pOldRTView);
         SAFE_RELEASE(m_pOldDSView);

         m_Pass++;

         // 最終レンダリング
         RenderDeferredRendering(pD3DDeviceContext);
      }
      break;
   }

   m_Pass = -1;
}

void ContactHardeningSoftShadows::End()
{
   m_Pass = -2;
}

// *******************************************************************************************************
// ラプラシアンフィルターによるシャドウマップのエッジ抽出およびpenumbra( 半影マップ )およびラプラシアンフィルターのミップマップ作成
// *******************************************************************************************************
void ContactHardeningSoftShadows::RenderLaplacianFilterAndPenumbraMap(ID3D11DeviceContext* pD3DDeviceContext)
{
   HRESULT hr;

   // ポストエフェクトのため深度マップ不要
   pD3DDeviceContext->OMSetRenderTargets(1, &m_pRTViewOfLaplacianFilterMap, nullptr);

   float ClearColor[] = { 0, 0, 0, 0 };
   pD3DDeviceContext->ClearRenderTargetView(m_pRTViewOfLaplacianFilterMap, ClearColor);

   pD3DDeviceContext->PSSetShaderResources(0, 1, &m_pSRViewOfShadowAndDistanceMap);

   pD3DDeviceContext->PSSetSamplers(0, 1, &m_pSamplerState);

   // 各種ステートを設定する
   m_pGraphicsPipeline[m_Pass]->SetRasterizerState(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetDepthStencilState(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetBlendState(pD3DDeviceContext);

   // 各種グラフィックパイプラインを設定
   m_pGraphicsPipeline[m_Pass]->SetVertexShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetHullShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetDomainShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetGeometryShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetPixelShader(pD3DDeviceContext);

   XMFLOAT2 TexelSizeOfCameraView = XMFLOAT2(1.0f / (float)m_CameraViewWidth, 1.0f / (float)m_CameraViewHeight);

   // 定数バッファを設定する
   D3D11_MAPPED_SUBRESOURCE mappedResource;
   if (FAILED(hr = pD3DDeviceContext->Map(m_pConstantBuffers[m_Pass], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)))
      throw(UException(-1, _T("PercentageCloserSoftShadows::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。")));
   ContactHardeningSoftShadows::CBUFFER_PASS2* cbuffer = (ContactHardeningSoftShadows::CBUFFER_PASS2*)mappedResource.pData;
   ::CopyMemory(&cbuffer->TexelSizeOfCameraView, &TexelSizeOfCameraView, sizeof(XMFLOAT2));
   cbuffer->LightSize = m_LightSize;
   pD3DDeviceContext->Unmap(m_pConstantBuffers[m_Pass], 0);

   pD3DDeviceContext->PSSetConstantBuffers(0, 1, &m_pConstantBuffers[m_Pass]);

   // 頂点バッファ設定
   UINT stride = sizeof(VERTEX);
   UINT offset = 0;
   pD3DDeviceContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);

   // プリミティブ タイプおよびデータの順序に関する情報を設定
   pD3DDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

   // 描画
   pD3DDeviceContext->Draw(4, 0);

   // ラプラシアンフィルターのミップマップチェーンを作成し、エッジを太らせる
   pD3DDeviceContext->GenerateMips(m_pSRViewOfLaplacianFilterMap);
}

// *******************************************************************************************************
// 最終レンダリング
// *******************************************************************************************************
void ContactHardeningSoftShadows::RenderDeferredRendering(ID3D11DeviceContext* pD3DDeviceContext)
{
   HRESULT hr;
   
   ID3D11ShaderResourceView* pSRView[] = { m_pSRViewOfShadowAndDistanceMap, m_pSRViewOfColorMap, m_pSRViewOfNormalMap, m_pSRViewOfLaplacianFilterMap };
   pD3DDeviceContext->PSSetShaderResources(0, _countof(pSRView), pSRView);

   pD3DDeviceContext->PSSetSamplers(0, 1, &m_pSamplerState);

   // 各種ステートを設定する
   m_pGraphicsPipeline[m_Pass]->SetRasterizerState(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetDepthStencilState(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetBlendState(pD3DDeviceContext);

   // 各種グラフィックパイプラインを設定
   m_pGraphicsPipeline[m_Pass]->SetVertexShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetHullShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetDomainShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetGeometryShader(pD3DDeviceContext);
   m_pGraphicsPipeline[m_Pass]->SetPixelShader(pD3DDeviceContext);

   XMFLOAT2 TexelSizeOfCameraView = XMFLOAT2(1.0f / (float)m_CameraViewWidth, 1.0f / (float)m_CameraViewHeight);

   // 定数バッファを設定する
   D3D11_MAPPED_SUBRESOURCE mappedResource;
   if (FAILED(hr = pD3DDeviceContext->Map(m_pConstantBuffers[m_Pass], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)))
      throw(UException(-1, _T("PercentageCloserSoftShadows::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。")));
   ContactHardeningSoftShadows::CBUFFER_PASS3* cbuffer = (ContactHardeningSoftShadows::CBUFFER_PASS3*)mappedResource.pData;
   ::CopyMemory(&cbuffer->vecLightDir, &m_VecLightPos, sizeof(XMFLOAT4));
   ::CopyMemory(&cbuffer->TexelSizeOfCameraView, &TexelSizeOfCameraView, sizeof(XMFLOAT2));
   cbuffer->MaxMipmapLevel = (float)m_MaxMipmapLevel - 1.0f;
   cbuffer->CameraZFar = m_CameraZFar;
   pD3DDeviceContext->Unmap(m_pConstantBuffers[m_Pass], 0);

   pD3DDeviceContext->PSSetConstantBuffers(0, 1, &m_pConstantBuffers[m_Pass]);

   // 頂点バッファ設定
   UINT stride = sizeof(VERTEX);
   UINT offset = 0;
   pD3DDeviceContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);

   // プリミティブ タイプおよびデータの順序に関する情報を設定
   pD3DDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

   // 描画
   pD3DDeviceContext->Draw(4, 0);

   ID3D11ShaderResourceView* pNull[] = { nullptr, nullptr, nullptr, nullptr };
   pD3DDeviceContext->PSSetShaderResources(0, _countof(pNull), pNull);
}

---main.cpp---  ↑


#include "../Header/Common/UCommon.h"
#include "../Header/Common/UException.h"
#include "../Header/Common/UDirect3D11.h"
#include "../Header/Common/UDebugFont.h"
#if defined(DEBUG) || defined(_DEBUG)
#include "../Header/Common/USRViewRenderer.h"
#endif
#include "../Header/Shader/ContactHardeningSoftShadows.h"

#include "../Header/Mesh/BackGroundMesh.h"

// アプリケーション名
TCHAR* AppName = _T("Direct3D11 Contact Hardening Soft Shadows using Erosion");

// Direct3D関連の自作クラス
UDirect3D11* g_pDirect3D11 = nullptr;

ContactHardeningSoftShadows* g_pContactHardeningSoftShadows = nullptr;

BackGroundMesh* g_pBackGroundMesh = nullptr;

UDebugFont* g_pDebugFont = nullptr;
UFPS* g_pFPS = nullptr;

#if defined(DEBUG) || defined(_DEBUG)
USRViewRenderer* g_pSRViewRenderer[] = { nullptr, nullptr, nullptr, nullptr };
#endif

DWORD g_Width = 640, g_Height = 480;
DWORD g_LightViewWidth = 1024, g_LightViewHeight = 1024;
float g_LightZFar = 3500.0f, g_LightZNear = 2000.0f;
float g_CameraZFar = 2000.0f, g_CameraZNear = 10.0f;

// カメラビューのビュー行列
XMMATRIX g_MatCameraView = XMMatrixIdentity();

// カメラービュー射影行列
XMMATRIX g_MatCameraProj = XMMatrixPerspectiveFovLH(XM_PI / 5.0f, (float)g_Width / (float)g_Height, g_CameraZNear, g_CameraZFar);

// ライトービュー射影行列
XMMATRIX g_MatLightProj = XMMatrixPerspectiveFovLH(XM_PI / 5.0f, (float)g_LightViewWidth / (float)g_LightViewHeight, g_LightZNear, g_LightZFar);

// 平行光源の位置ベクトル
XMFLOAT4 g_VecLightPos = XMFLOAT4(1200.0f, 1900.0f, 1500.0f, 0);

// メモリ解放
void Invalidate()
{
#if defined(DEBUG) || defined(_DEBUG)
   for (int i = 0; i<_countof(g_pSRViewRenderer); i++)
   {
      SAFE_DELETE_ARRAY(g_pSRViewRenderer[i]);
   }
#endif
   SAFE_DELETE(g_pContactHardeningSoftShadows);
   SAFE_DELETE(g_pFPS);
   SAFE_DELETE(g_pDebugFont);
   SAFE_DELETE(g_pBackGroundMesh);
   SAFE_DELETE(g_pDirect3D11);
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
{
   switch (msg)
   {
   case WM_KEYUP:
      // アプリ終了
      if (wParam == VK_ESCAPE)
         ::DestroyWindow(hWnd);
      break;

   case WM_DESTROY:
      ::PostQuitMessage(0);
      break;

   default:
      return ::DefWindowProc(hWnd, msg, wParam, lParam);
   }

   return 0L;
}

// Direct3Dの作成
void CreateDirect3D(HINSTANCE hInstance)
{
   DXGI_MODE_DESC* pModeDescArray = nullptr;

   __try
   {
      DXGI_MODE_DESC  ModeDesc;
      UINT num;

      // ディスプレイモード一覧の数を取得する
      g_pDirect3D11->GetDisplayMode(nullptr, &num);

      pModeDescArray = NEW DXGI_MODE_DESC[num];
      // ディスプレイモード一覧を取得する
      g_pDirect3D11->GetDisplayMode(pModeDescArray, &num);

      bool find = false;
      for (UINT i = 0; i<num; i++)
      {
         // 適切な解像度のディスプレイモードを検索する
         if (pModeDescArray[i].Width == g_Width && pModeDescArray[i].Height == g_Height)
         {
            find = true;
            ::CopyMemory(&ModeDesc, &pModeDescArray[i], sizeof(DXGI_MODE_DESC));
            break;
         }
      }

      if (find == false)
         throw(UException(-1, _T("InitDirect3D()でエラーが発生しました。適切なディスプレイモードの解像度を取得できません。")));

      // ウィンドウの作成およびDirect3D の作成
      g_pDirect3D11->CreateDirect3D11(AppName, hInstance, WndProc, &ModeDesc, TRUE, TRUE);

      g_pDebugFont->CreateMesh(g_pDirect3D11->m_pD3DDevice, 0.03f, 0.08f);

      // FPS描画クラス
      g_pFPS->CreateMesh(g_pDirect3D11->m_pD3DDevice);

#if defined(DEBUG) || defined(_DEBUG)
      for (int i = _countof(g_pSRViewRenderer) - 1; i >= 0; i--)
      {
         g_pSRViewRenderer[_countof(g_pSRViewRenderer) - i - 1]->Create(g_pDirect3D11->m_pD3DDevice, 1.0f - (300.0f / (float)g_Width) * (i + 1), 1.0f, 1.0f - (300.0f / (float)g_Width) * (i), 1.0f - 300.0f / (float)g_Height);
      }
#endif
   }
   __finally
   {
      SAFE_DELETE_ARRAY(pModeDescArray);
   }
}

void CreateGraphicePipeline()
{
   g_pContactHardeningSoftShadows->Create(g_pDirect3D11->m_pD3DDevice, g_LightViewWidth, g_LightViewHeight, g_Width, g_Height);
}

// メッシュを作成する
void CreateMesh()
{
   g_pBackGroundMesh = NEW BackGroundMesh();
   g_pBackGroundMesh->CreateMesh(g_pDirect3D11->m_pD3DDevice);
}

void CreateResource(HINSTANCE hInstance)
{
   // Direct3D 関連自作クラスのインスタンスを作成
   // CreateDirect3D()関数内でインスタンスの作成を行うと、C2712 エラーが発生するのでここで行う。
   g_pDirect3D11 = NEW UDirect3D11();

   g_pContactHardeningSoftShadows = NEW ContactHardeningSoftShadows();

   g_pDebugFont = NEW UDebugFont();
   g_pFPS = NEW UFPS();

#if defined(DEBUG) || defined(_DEBUG)
   for (int i = 0; i<_countof(g_pSRViewRenderer); i++)
   {
      g_pSRViewRenderer[i] = NEW USRViewRenderer();
   }
#endif

   // Direct3Dの作成
   CreateDirect3D(hInstance);

   // グラフィックパイプラインリソースの作成
   CreateGraphicePipeline();

   // リソースの作成
   CreateMesh();
}

void NextFrame()
{
   // ビュー行列
   if (GetKeyState(VK_UP) & 0x8000)
      g_MatCameraView *= XMMatrixTranslation(0, 0, -1.2f);
   if (GetKeyState(VK_DOWN) & 0x8000)
      g_MatCameraView *= XMMatrixTranslation(0, 0, 1.2f);
   if (GetKeyState(VK_RIGHT) & 0x8000)
      g_MatCameraView *= XMMatrixRotationY(-0.015f);
   if (GetKeyState(VK_LEFT) & 0x8000)
      g_MatCameraView *= XMMatrixRotationY(0.015f);
   if (GetKeyState('Q') & 0x8000)
      g_MatCameraView *= XMMatrixRotationX(0.015f);
   if (GetKeyState('A') & 0x8000)
      g_MatCameraView *= XMMatrixRotationX(-0.015f);

   g_pFPS->NextFrame();
   g_pBackGroundMesh->NextFrame();
}

// 描画処理
HRESULT Render()
{
   HRESULT hr = E_FAIL;

   static float ClearColor[4] = { 0.3f, 0.3f, 1.0f, 1.0f };

   // バックバッファをクリアする。
   g_pDirect3D11->ClearBackBuffer(ClearColor);

   // 深度バッファをクリアする。
   g_pDirect3D11->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

   g_pContactHardeningSoftShadows->Begin(&g_VecLightPos, &g_MatLightProj, &g_MatCameraView, &g_MatCameraProj, g_CameraZFar);
   {
      for (UINT i = 0; i < g_pContactHardeningSoftShadows->GetMaxPass(); i++)
      {
         g_pContactHardeningSoftShadows->BeginPass(g_pDirect3D11->m_pD3DDeviceContext, i);
         {
            g_pContactHardeningSoftShadows->SetConstantBuffers(g_pDirect3D11->m_pD3DDeviceContext, g_pBackGroundMesh->GetMatWorld());
            g_pBackGroundMesh->Render(g_pDirect3D11->m_pD3DDeviceContext);
         }
         g_pContactHardeningSoftShadows->EndPass(g_pDirect3D11->m_pD3DDeviceContext);
      }
   }
   g_pContactHardeningSoftShadows->End();

#if defined(DEBUG) || defined(_DEBUG)
   int SrvRGB[] = { 0, 0, 0, 0 };
   int SrvRGB1[] = { 0, 0, 0, 0 };
   int SrvRGB2[] = { 2, 1, 0, 0 };
   int SrvRGB3[] = { 0, 1, 2, 0 };

   g_pSRViewRenderer[0]->SetSRView(g_pContactHardeningSoftShadows->GetLaplacianFilterMap(), SrvRGB);
   g_pSRViewRenderer[0]->Render(g_pDirect3D11->m_pD3DDeviceContext);

   g_pSRViewRenderer[1]->SetSRView(g_pContactHardeningSoftShadows->GetShadowAndDistanceMap(), SrvRGB1);
   g_pSRViewRenderer[1]->Render(g_pDirect3D11->m_pD3DDeviceContext);

   g_pSRViewRenderer[2]->SetSRView(g_pContactHardeningSoftShadows->GetColorMap(), SrvRGB2);
   g_pSRViewRenderer[2]->Render(g_pDirect3D11->m_pD3DDeviceContext);

   g_pSRViewRenderer[3]->SetSRView(g_pContactHardeningSoftShadows->GetNormalMap(), SrvRGB3);
   g_pSRViewRenderer[3]->Render(g_pDirect3D11->m_pD3DDeviceContext);

   g_pDebugFont->Render(g_pDirect3D11->m_pD3DDeviceContext);
#endif

   g_pFPS->Render(g_pDirect3D11->m_pD3DDeviceContext);

   // レンダリングされたイメージをユーザーに表示。
   if (FAILED(hr = g_pDirect3D11->Present(0, 0)))
      throw(UException(hr, _T("IDXGISwapChain::Present()が失敗しました")));

   return hr;
}

// メイン関数
int APIENTRY _tWinMain(HINSTANCE hInstance,
   HINSTANCE,
   LPTSTR,
   INT)
{
   // メモリリーク検出
   //   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | CRTDBG_CHECK_ALWAYS_DF );
   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_EVERY_1024_DF);

   MSG msg = { 0 };

   try
   {
      CreateResource(hInstance);

      ::ShowWindow(g_pDirect3D11->m_hWnd, SW_SHOW);
      ::UpdateWindow(g_pDirect3D11->m_hWnd);

      // メッセージループ
      do
      {
         if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
         {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
         }
         else
         {
            NextFrame();
            Render();
         }
      } while (msg.message != WM_QUIT);
   }
   catch (UException ex)
   {
      ::MessageBox(nullptr, ex.m_pErrorStr, _T("エラー"), MB_OK);
   }

   Invalidate();

   ::UnregisterClass(AppName, hInstance);

   return msg.wParam;
}

今後、あまり趣味プロに時間取れなくなりそうな予感。はあ。

Prev Top Next
inserted by FC2 system