Microsoft Visual C++ 2010 Express
 Microsoft DirectX SDK (June 2010)
 Direct3D 11.0
 Shader Model 4.0
 FBX SDK 2011.3

■Direct3D 11.0 Light Bloom Prev Top Next
関連ページ:Direct3D 11.0 初期化 Direct3D 11.0 デバック用フォント描画 FBX SDKを使う


今回は Light Bloom をやりますが、その前に2つほど。 ちょっと思うところがあって C++ の基礎を真面目に勉強していこうかと思います。 また2011年にISOによって承認された C++ の新しい規格である C++11 について Visual Studio 2010 で対応しているものについて順次取り入れていこうかと思っています。 ただしさすがに全ソース修正する気にはならないので、新規作成するソースのみ対応します。 そのため全体的にまとまりのないサンプルになりますが、まあそこはサンプルだからというところでご了承ください。


では本題に入ります。今回やるLight Bloom は既に DirectX9 でもやってます。過去の記事はライトブルーム その2を参照してください。 で既出の手順と同じことをやってもしょうがないのでアルゴリズムは変更しています。
今回は次の手順で実装していきます。

1.高輝度部分の抽出
この辺は DirectX9 のサンプルと同じなので省略します。

2.Multiple Gaussian Filter
1で抽出したHDRマップにブラーをかけます。 DirectX9でも似たようなことをやってますが、テクセルのサンプリング数を増やし、重みをガウス関数により計算するようにしています。
でこのガウスフィルターは非常に重いシェーダーなので、あらかじめ縮小バッファにダウンサンプリングしたバッファを用意します。 そして段階的に縮小していくバッファを複数枚用意し、順次ガウスフィルターを適用していきます。 まあこの辺の手法については3Dグラフィックス・マニアックスを参照してください。

3.HDRマップをバックバッファに加算合成
最後に2で作成した複数枚のHDRマップをバックバッファに加算合成します。合成時に適当に重みをかけています。

といった感じです。


LightBloom.hlsl LightBloomのhlslファイル。
LightBloom.h LightBloom.hクラスのヘッダファイル。
LightBloom.cpp LightBloom.hクラスのソースファイル。
main.cpp メイン関数があるソースファイル。

---LightBloom.hlsl---  ↑


// ************************************************************
// Light Bloom
// ************************************************************

// ************************************************************
// 構造体の宣言
// ************************************************************

// フォンシェーディング + HDRマップ描画時に使用する構造体の宣言

struct _VS01
{
   float3 pos    : POSITION;   // 頂点座標
   float3 Normal : NORMAL;     // 法線
   float2 texel  : TEXCOORD;   // テクセル
};

struct VS_PS01
{
   float4 pos       : SV_POSITION;
   float3 Normal    : NORMAL;
   float2 texel     : TEXCOORD0;
   float3 LocalPos  : TEXCOORD1;
};

struct PS_01
{
   float4 BackBuffer   : SV_Target0;   // シーンのレンダリングイメージ
   float4 HDRBuffer    : SV_Target1;   // HDRマップ
};

// ガウスフィルターで使用する構造体の宣言

struct _VS02
{
   float3 pos   : POSITION;   // 頂点座標
   float2 texel : TEXCOORD;   // テクセル
};

struct VS_PS02
{
   float4 pos : SV_POSITION;
   float2 texel[8] : TEXCOORD0;
};

struct _VS03
{
   float3 pos   : POSITION;   // 頂点座標
   float2 texel : TEXCOORD;   // テクセル
};

// 頂点シェーダー - ピクセルシェーダーの構造体

struct VS_PS03
{
   float4 pos   : SV_POSITION;
   float2 texel : TEXCOORD0;
};

// ************************************************************
// 定数バッファ
// ************************************************************

// 定数バッファ1
cbuffer CB_STEP01 : register( b0 )
{
   column_major float4x4 g_matWVP : packoffset( c0 );   // ワールド × ビュー × 射影 行列
   float4 g_vecLight              : packoffset( c4 );   // ローカル座標系での平行光源の方向ベクトル
   float4 g_vecEyePos             : packoffset( c5 );   // ローカル座標系での視点座標
   float  g_FakeHDRPower          : packoffset( c6.x ); // 疑似HDR強度
   float  g_SpecularPower         : packoffset( c6.y ); // スペキュラー強度
};

// 定数バッファ2
cbuffer CB_STEP02 : register( b0 )
{
   float2 g_TexelSize : packoffset( c0 );
   float2 g_Offset : packoffset( c0.z );
   float g_Weight0 : packoffset( c1.x );  // 重み
   float g_Weight1 : packoffset( c1.y );  // 重み
   float g_Weight2 : packoffset( c1.z );  // 重み
   float g_Weight3 : packoffset( c1.w );  // 重み
   float g_Weight4 : packoffset( c2.x );  // 重み
   float g_Weight5 : packoffset( c2.y );  // 重み
   float g_Weight6 : packoffset( c2.z );  // 重み
   float g_Weight7 : packoffset( c2.w );  // 重み
};

// ************************************************************
// テクスチャー
// ************************************************************

Texture2D g_DecalMap      : register( t0 );  // デカールマップ
Texture2D g_HDRHalfMap[4] : register( t0 );  // HDRマップ

// ************************************************************
// サンプラーステート
// ************************************************************

SamplerState  g_Sampler : register( s0 );

// ************************************************************
// フォンシェーディング + HDRマップの描画フェーズ
// ************************************************************

// 頂点シェーダー
VS_PS01 Step01_VS_Main( _VS01 In )
{
   VS_PS01 Out;
   Out.pos    = mul( float4( In.pos, 1.0f ), g_matWVP );
   Out.Normal = In.Normal;
   Out.texel  = In.texel;
   Out.LocalPos = In.pos;

   return Out;
}

// ピクセルシェーダー
PS_01 Step01_PS_Main( VS_PS01 In )
{
   PS_01 Out;

   // デカールマップ
   float4 decalmap = g_DecalMap.Sample( g_Sampler, In.texel );
   
   if( g_FakeHDRPower == 0 )
   {
      // ライティング
      float lambert = dot( -g_vecLight.xyz, In.Normal );
   
      // ハーフランバート
      float halflambert = lambert * 0.5f + 0.5f;
      halflambert *= halflambert;

      // ハーフベクトルを計算する
      float3 half = normalize( -g_vecLight.xyz + normalize( g_vecEyePos.xyz - In.LocalPos ) );

      // 鏡面反射率を計算する
      float specular = max( 0.0f, dot( In.Normal, half ) );
      specular = pow( specular, 20.0f ) * g_SpecularPower;
   
      // シーンのレンダリングイメージを出力
      Out.BackBuffer = float4( decalmap.rgb * halflambert, 1 ) + specular;
   }
   else
   {
      // シーンのレンダリングイメージを出力
      Out.BackBuffer = float4( decalmap.rgb * g_FakeHDRPower, 1 );
   }

   // HDR出力
   Out.HDRBuffer = float4( max( Out.BackBuffer.rgb - 1, 0 ), 1 );
   
   return Out;
}

// ************************************************************
// ダウンサンプリング
// ************************************************************

// 頂点シェーダー
VS_PS03 Step021_VS_Main( _VS02 In )
{
   VS_PS03 Out;
   Out.pos    = float4( In.pos, 1.0f );
   Out.texel  = In.texel;
   return Out;
}

// ピクセルシェーダー
float4 Step021_PS_Main( VS_PS03 In ) : SV_Target0
{
   return g_HDRHalfMap[0].Sample( g_Sampler, In.texel );
}

// ************************************************************
// ガウスフィルター
// ************************************************************

// 頂点シェーダー
VS_PS02 Step022_VS_Main( _VS02 In )
{
   VS_PS02 Out;
   Out.pos    = float4( In.pos, 1.0f );

   Out.texel[0] = In.texel - g_TexelSize * 1.0f;         // 1.0f / TextureSize
   Out.texel[1] = In.texel - g_TexelSize * 3.0f;         // 3.0f / TextureSize
   Out.texel[2] = In.texel - g_TexelSize * 5.0f;         // 5.0f / TextureSize
   Out.texel[3] = In.texel - g_TexelSize * 7.0f;         // 7.0f / TextureSize
   Out.texel[4] = In.texel - g_TexelSize * 9.0f;         // 9.0f / TextureSize
   Out.texel[5] = In.texel - g_TexelSize * 11.0f;         // 11.0f / TextureSize
   Out.texel[6] = In.texel - g_TexelSize * 13.0f;         // 13.0f / TextureSize
   Out.texel[7] = In.texel - g_TexelSize * 15.0f;         // 15.0f / TextureSize
   
   return Out;
}

// ピクセルシェーダー
float4 Step022_PS_Main( VS_PS02 In ) : SV_Target0
{
   float4 Out = 0.0f;

   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[0] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[7] + g_Offset ) ) * g_Weight0;   // 1.0f / TextureSize
   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[1] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[6] + g_Offset ) ) * g_Weight1;   // 3.0f / TextureSize
   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[2] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[5] + g_Offset ) ) * g_Weight2;   // 5.0f / TextureSize
   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[3] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[4] + g_Offset ) ) * g_Weight3;   // 7.0f / TextureSize
   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[4] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[3] + g_Offset ) ) * g_Weight4;   // 9.0f / TextureSize
   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[5] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[2] + g_Offset ) ) * g_Weight5;   // 11.0f / TextureSize
   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[6] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[1] + g_Offset ) ) * g_Weight6;   // 13.0f / TextureSize
   Out += ( g_HDRHalfMap[0].Sample( g_Sampler, In.texel[7] ) + g_HDRHalfMap[0].Sample( g_Sampler, In.texel[0] + g_Offset ) ) * g_Weight7;   // 15.0f / TextureSize

   return Out;
}

// ************************************************************
// 合成
// ************************************************************

// 頂点シェーダー
VS_PS03 Step03_VS_Main( _VS03 In )
{
   VS_PS03 Out;
   Out.pos    = float4( In.pos, 1.0f );
   Out.texel  = In.texel;
   return Out;
}

// ピクセルシェーダー
float4 Step03_PS_Main( VS_PS03 In ) : SV_Target0
{
   float4 Out = 0.0f;
   // 適当に重みをつけて加算合成
   Out += g_HDRHalfMap[0].Sample( g_Sampler, In.texel ) * 0.7f;
   Out += g_HDRHalfMap[1].Sample( g_Sampler, In.texel ) * 0.8f;
   Out += g_HDRHalfMap[2].Sample( g_Sampler, In.texel ) * 0.9f;
   Out += g_HDRHalfMap[3].Sample( g_Sampler, In.texel ) * 1.0f;
   return Out;
}

メッシュの描画ではフォンシェーディングにも対応しています。 したがってハイライトを高輝度として抽出することが可能になっています。 太陽のようにそれ自身が高輝度のものは色にスケーリング値を加算することで疑似的に高輝度としています。

次にダウンサンプリングですが、DirectX9 では IDirect3DDevice9::StretchRect という便利関数があったんですが、Direct3D11 ではどこにいったのやら。 ID3D11DeviceContext::CopySubresourceRegion ではスケーリングできないし。仕方がないのでシェーダーで実装してます。

---LightBloom.h---  ↑

#ifndef LIGHTBLOOM_H
#define LIGHTBLOOM_H

#include "Polygon2DUser.h"

class LIGHTBLOOM
{
private:
   // フォンシェーディング + HDRマップの描画フェーズで使用する構造体定義
   typedef struct _CB_STEP01
   {
      // ワールド × ビュー × 射影 行列
      D3DXMATRIX  matWVP;
      // 平行光源の方向ベクトル
      D3DXVECTOR4 vecLight;
      // 視点座標
      D3DXVECTOR4 vecEyePos;
      // 疑似HDR強度
      float FakeHDRPower;
      // スペキュラー強度
      float SpecularPower;
      float Dummy2;
      float Dummy3;
   }CB_STEP01;

   // MGFで使用する構造体定義
   typedef struct _CB_STEP02
   {
      D3DXVECTOR2 TexelSize;
      D3DXVECTOR2 Offset;
      float Weight[8];
   }CB_STEP02;

   // フォンシェーディング + HDRマップの描画フェーズで使用するリソースの構造体定義
   typedef struct _STEP01
   {
      // 入力レイアウト
      ID3D11InputLayout* pLayout;

      // 頂点シェーダー
      ID3D11VertexShader* pVertexShader;

      // ピクセルシェーダー
      ID3D11PixelShader* pPixelShader;

      // 定数バッファ
      ID3D11Buffer* pConstantBuffers;

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

      typedef struct ALPHA
      {
         // 深度ステンシルステート
         ID3D11DepthStencilState*  pDepthStencilState;
         // ブレンドステート
         ID3D11BlendState* pBlendState;
      };

      ALPHA AlphaNone;  // 不透明メッシュの描画で使用する
      ALPHA AlphaAdd;   // 太陽などの高輝度メッシュで使用する
   }STEP01;

   // MGFフェーズで使用するリソースの構造体定義
   typedef struct _STEP02
   {
      // 入力レイアウト
      ID3D11InputLayout* pLayout;

      // 頂点シェーダー
      // Index0:ダウンサンプリング
      // Index1:MGF
      ID3D11VertexShader* pVertexShader[2];

      // ピクセルシェーダー
      // Index0:ダウンサンプリング
      // Index1:MGF
      ID3D11PixelShader* pPixelShader[2];

      // 定数バッファ
      ID3D11Buffer* pConstantBuffers;

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

      // 深度ステンシルステート
      ID3D11DepthStencilState*  pDepthStencilState;

      // ブレンドステート
      ID3D11BlendState* pBlendState;
   }STEP02;

   // HDRマップ合成で使用するリソースの構造体定義
   typedef struct _STEP03
   {
      // 入力レイアウト
      ID3D11InputLayout* pLayout;

      // 頂点シェーダー
      ID3D11VertexShader* pVertexShader;

      // ピクセルシェーダー
      ID3D11PixelShader* pPixelShader;

      // 定数バッファ
      ID3D11Buffer* pConstantBuffers;

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

      // 深度ステンシルステート
      ID3D11DepthStencilState*  pDepthStencilState;

      // ブレンドステート
      ID3D11BlendState* pBlendState;
   }STEP03;

   // 宣言

   // ダウンサンプリング用レンダーターゲットビュー
   ID3D11RenderTargetView* pRTViewDownSample;

   // MGF用のレンダーターゲットビューの最大作成可能枚数
   static const UINT RTVMAXCOUNT = 4;

   // MGF用のレンダーターゲットビュー
   ID3D11RenderTargetView* pRTViewXGF[RTVMAXCOUNT];
   ID3D11RenderTargetView* pRTViewYGF[RTVMAXCOUNT];

   // 有効なMGF用レンダーターゲットビューの枚数
   UINT RTVCount;

   CPolygon2D m_Polygon2D;

   STEP01 m_Step01;
   STEP02 m_Step02;
   STEP03 m_Step03;

private:
   // 共通項目の初期化
   HRESULT InitCommon( ID3D11Device* pD3DDevice, UINT ScreenWidth, UINT ScreenHeight );
   // フォンシェーディング + HDRマップの描画フェーズの初期化
   HRESULT InitStep01( ID3D11Device* pD3DDevice
                     , const BYTE* pVSStep01Shader, size_t VSStep01Size
                     , const BYTE* pPSStep01Shader, size_t PSStep01Size
                     );
   // MGFフェーズの初期化
   HRESULT InitStep02( ID3D11Device* pD3DDevice
                     , const BYTE* pVSStep021Shader, size_t VSStep021Size
                     , const BYTE* pPSStep021Shader, size_t PSStep021Size
                     , const BYTE* pVSStep022Shader, size_t VSStep022Size
                     , const BYTE* pPSStep022Shader, size_t PSStep022Size
                     );
   // HDRマップ合成フェーズの初期化
   HRESULT InitStep03( ID3D11Device* pD3DDevice
                     , const BYTE* pVSStep03Shader, size_t VSStep03Size
                     , const BYTE* pPSStep03Shader, size_t PSStep03Size
                     );

   // MGFの定数バッファを設定する
   HRESULT SetCBStep02( ID3D11DeviceContext* pD3DDeviceContext
                      , const D3DXVECTOR2* pTextureSize
                      , float Dispersion
                      ) const;

   // レンダーターゲットサーフェスを作成する
   HRESULT CreateRenderTargetView( ID3D11Device* pD3DDevice
                                 , ID3D11RenderTargetView** ppRTView
                                 , UINT Width, UINT Height
                                 , DXGI_FORMAT Format
                                 ) const;

   // レンダーターゲットサーフェスからシェーダーリソースビューを取得する
   ID3D11ShaderResourceView* GetSRViewFromRTView( ID3D11Device* pD3DDevice, ID3D11RenderTargetView* pRTView ) const;

   // レンダーターゲットビューの縦横のサイズを取得
   D3DXVECTOR2 GetRTViewSize( ID3D11RenderTargetView* pRTView ) const;
   // シェーダーリソースビューの縦横のサイズを取得
   D3DXVECTOR2 GetSRViewSize( ID3D11ShaderResourceView* pSRView ) const;

public:
   LIGHTBLOOM();
   ~LIGHTBLOOM();

   // 初期化
   HRESULT Init( ID3D11Device* pD3DDevice
               // hlslファイルのファイル名
               , const TCHAR pSrcFile[]
               // フォンシェーディング + HDRマップ描画フェーズ
               , const CHAR pVSStep01FunctionName[], const CHAR pPSStep01FunctionName[]
               // MGF
               , const CHAR pVSStep021FunctionName[], const CHAR pPSStep021FunctionName[]
               , const CHAR pVSStep022FunctionName[], const CHAR pPSStep022FunctionName[]
               // HDRマップ合成フェーズ
               , const CHAR pVSStep03FunctionName[], const CHAR pPSStep03FunctionName[]
               , UINT ScreenWidth, UINT ScreenHeight
               );
   HRESULT Init( ID3D11Device* pD3DDevice
               // フォンシェーディング + HDRマップ描画フェーズ
               , const BYTE* pVSStep01Shader, size_t VSStep01Size
               , const BYTE* pPSStep01Shader, size_t PSStep01Size
               // MGFフェーズ
               , const BYTE* pVSStep021Shader, size_t VSStep012Size
               , const BYTE* pPSStep021Shader, size_t PSStep012Size
               , const BYTE* pVSStep022Shader, size_t VSStep022Size
               , const BYTE* pPSStep022Shader, size_t PSStep022Size
               // HDRマップ合成フェーズ
               , const BYTE* pVSStep03Shader, size_t VSStep03Size
               , const BYTE* pPSStep03Shader, size_t PSStep03Size
               , UINT ScreenWidth, UINT ScreenHeight
               );

   // フォンシェーディング + HDRマップの描画フェーズの開始処理
   HRESULT BeginStep01( ID3D11DeviceContext* pD3DDeviceContext, BOOL BlendEnable ) const;
   // フォンシェーディング + HDRマップの描画フェーズで使用する定数バッファを設定
   HRESULT SetCBStep01( ID3D11DeviceContext* pD3DDeviceContext
                      , const D3DXMATRIX* p_matWVP
                      , const D3DXVECTOR4* p_vecLight, const D3DXVECTOR4* p_vecEyePos
                      , ID3D11ShaderResourceView* pDecalMap
                      , float FakeHDRPower, float SpecularPower
                      ) const;
   // フォンシェーディング + HDRマップの描画フェーズの終了処理
   HRESULT EndStep01( ID3D11DeviceContext* pD3DDeviceContext ) const;

   // MGFフェーズの描画関数
   HRESULT RenderStep02( ID3D11DeviceContext* pD3DDeviceContext
                       , ID3D11ShaderResourceView* pSRViewHDRMap[1]
                       , float Dispersion
                       ) const;

   // HDRマップ合成フェーズの描画関数
   HRESULT RenderStep03( ID3D11DeviceContext* pD3DDeviceContext ) const;

   // テスト用
   ID3D11ShaderResourceView* GetSRView( ID3D11DeviceContext* pD3DDeviceContext, UINT Index ) const;
};

#endif

あいかわらず長いな...コーディング量減らすために次回から設計し直すかも。

---LightBloom.cpp---  ↑

#include "DX11User.h"
#include "LightBloom.h"

LIGHTBLOOM::LIGHTBLOOM()
{
   m_Step01.pLayout = nullptr;
   m_Step01.pVertexShader = nullptr;
   m_Step01.pPixelShader = nullptr;
   m_Step01.pConstantBuffers = nullptr;
   m_Step01.pSamplerState = nullptr;
   m_Step01.AlphaNone.pDepthStencilState = nullptr;
   m_Step01.AlphaNone.pBlendState = nullptr;
   m_Step01.AlphaAdd.pDepthStencilState = nullptr;
   m_Step01.AlphaAdd.pBlendState = nullptr;

   m_Step02.pLayout = nullptr;
   for( UINT i=0; i<_countof( m_Step02.pVertexShader ); i++ )
      m_Step02.pVertexShader[i] = nullptr;
   for( UINT i=0; i<_countof( m_Step02.pPixelShader ); i++ )
      m_Step02.pPixelShader[i] = nullptr;
   m_Step02.pConstantBuffers = nullptr;
   m_Step02.pSamplerState = nullptr;
   m_Step02.pDepthStencilState = nullptr;
   m_Step02.pBlendState = nullptr;

   m_Step03.pLayout = nullptr;
   m_Step03.pVertexShader = nullptr;
   m_Step03.pPixelShader = nullptr;
   m_Step03.pConstantBuffers = nullptr;
   m_Step03.pSamplerState = nullptr;
   m_Step03.pDepthStencilState = nullptr;
   m_Step03.pBlendState = nullptr;

   RTVCount = 0;

   pRTViewDownSample = nullptr;

   for( UINT i=0; i<RTVMAXCOUNT; i++ )
   {
      pRTViewXGF[i] = nullptr;
      pRTViewYGF[i] = nullptr;
   }
}

LIGHTBLOOM::~LIGHTBLOOM()
{
   SAFE_RELEASE( m_Step01.pLayout );
   SAFE_RELEASE( m_Step01.pVertexShader );
   SAFE_RELEASE( m_Step01.pPixelShader );
   SAFE_RELEASE( m_Step01.pConstantBuffers );
   SAFE_RELEASE( m_Step01.pSamplerState );
   SAFE_RELEASE( m_Step01.AlphaNone.pDepthStencilState );
   SAFE_RELEASE( m_Step01.AlphaNone.pBlendState );
   SAFE_RELEASE( m_Step01.AlphaAdd.pDepthStencilState );
   SAFE_RELEASE( m_Step01.AlphaAdd.pBlendState );

   SAFE_RELEASE( m_Step02.pLayout );
   for( UINT i=0; i<_countof( m_Step02.pVertexShader ); i++ )
      SAFE_RELEASE( m_Step02.pVertexShader[i] );
   for( UINT i=0; i<_countof( m_Step02.pPixelShader ); i++ )
      SAFE_RELEASE( m_Step02.pPixelShader[i] );
   SAFE_RELEASE( m_Step02.pConstantBuffers );
   SAFE_RELEASE( m_Step02.pSamplerState );
   SAFE_RELEASE( m_Step02.pDepthStencilState );
   SAFE_RELEASE( m_Step02.pBlendState );

   SAFE_RELEASE( m_Step03.pLayout );
   SAFE_RELEASE( m_Step03.pVertexShader );
   SAFE_RELEASE( m_Step03.pPixelShader );
   SAFE_RELEASE( m_Step03.pConstantBuffers );
   SAFE_RELEASE( m_Step03.pSamplerState );
   SAFE_RELEASE( m_Step03.pDepthStencilState );
   SAFE_RELEASE( m_Step03.pBlendState );

   SAFE_RELEASE( pRTViewDownSample );
   for( UINT i=0; i<RTVMAXCOUNT; i++ )
   {
      SAFE_RELEASE( pRTViewXGF[i] );
      SAFE_RELEASE( pRTViewYGF[i] );
   }
}

// 共通項目の初期化
HRESULT LIGHTBLOOM::InitCommon( ID3D11Device* pD3DDevice, UINT ScreenWidth, UINT ScreenHeight )
{
   HRESULT hr = E_FAIL;

   // 2Dポリクラスの作成処理
   hr = m_Polygon2D.Create( pD3DDevice );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 縮小バッファを作成
   // *****************************************************************************************************************

   UINT Width = ScreenWidth / 4;
   UINT Height = ScreenHeight / 4;

   // ダウンサンプリング用の縮小バッファを作成。 1 / 4 サイズ。
   hr = CreateRenderTargetView( pD3DDevice, &pRTViewDownSample, Width, Height, DXGI_FORMAT_R16G16B16A16_FLOAT );
   if( FAILED( hr ) )
      goto EXIT;

   // MGF用の縮小バッファは 1 / 2 サイズに段階的に縮小していき、最大4枚まで作成する
   for( UINT i=0; i<RTVMAXCOUNT; i++ )
   {
      // 縮小
      Width /= 2;

      // レンダーターゲットビューを作成
      hr = CreateRenderTargetView( pD3DDevice, &pRTViewXGF[i], Width, Height, DXGI_FORMAT_R16G16B16A16_FLOAT );
      if( FAILED( hr ) )
         goto EXIT;

      // 縮小
      Height /= 2;

      // レンダーターゲットビューを作成
      hr = CreateRenderTargetView( pD3DDevice, &pRTViewYGF[i], Width, Height, DXGI_FORMAT_R16G16B16A16_FLOAT );
      if( FAILED( hr ) )
         goto EXIT;

      RTVCount++;

      // 小さすぎるので終了
      if( Width < 16 || Height < 16 )
         break;
   }
   
#if defined(DEBUG) || defined(_DEBUG)
   const UINT DebugStrMaxCount = 512;
   TCHAR DebugStr[DebugStrMaxCount];
   _stprintf_s( DebugStr, DebugStrMaxCount, _T("■□■ RenderTargetViewCount:%d ■□■\n"), RTVCount );
   OutputDebugString( DebugStr );
#endif

   hr = S_OK;
EXIT:
   return hr;
}

// フォンシェーディング + HDRマップの描画フェーズの初期化
HRESULT LIGHTBLOOM::InitStep01( ID3D11Device* pD3DDevice
                              , const BYTE* pVSStep01Shader, size_t VSStep01Size
                              , const BYTE* pPSStep01Shader, size_t PSStep01Size
                              )
{
   HRESULT hr = E_FAIL;
   D3D11_BUFFER_DESC BufferDesc;

   if( pD3DDevice == nullptr )
      goto EXIT;

   // *****************************************************************************************************************
   // 頂点シェーダーの作成
   // *****************************************************************************************************************

   hr = pD3DDevice->CreateVertexShader( pVSStep01Shader, VSStep01Size, nullptr, &m_Step01.pVertexShader );
   if( FAILED( hr ) )
      goto EXIT;

   // 入力レイアウトは固定設定にしておく
   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 },
   };
   hr = pD3DDevice->CreateInputLayout( layout, _countof( layout ), pVSStep01Shader, VSStep01Size, &m_Step01.pLayout );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // ピクセルェーダーの作成
   // *****************************************************************************************************************

   hr = pD3DDevice->CreatePixelShader( pPSStep01Shader, PSStep01Size, nullptr, &m_Step01.pPixelShader );
   if( FAILED( hr ) ) 
      goto EXIT;

   // *****************************************************************************************************************
   // 定数バッファを作成
   // *****************************************************************************************************************

   ::ZeroMemory( &BufferDesc, sizeof( BufferDesc ) );
   BufferDesc.ByteWidth             = sizeof( CB_STEP01 );       // バッファサイズ
   BufferDesc.Usage                 = D3D11_USAGE_DYNAMIC;       // リソース使用法を特定する
   BufferDesc.BindFlags             = D3D11_BIND_CONSTANT_BUFFER;// バッファの種類
   BufferDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_WRITE;    // CPU アクセスする
   BufferDesc.MiscFlags             = 0;                         // その他のフラグも設定しない
   hr = pD3DDevice->CreateBuffer( &BufferDesc, nullptr, &m_Step01.pConstantBuffers );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // サンプラーステートの作成
   // *****************************************************************************************************************

   D3D11_SAMPLER_DESC samplerDesc;
   samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;  // サンプリング時に使用するフィルタ。
   samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;     // 0 〜 1 の範囲外にある u テクスチャー座標の描画方法
   samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;     // 0 〜 1 の範囲外にある v テクスチャー座標
   samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;     // 0 〜 1 の範囲外にある w テクスチャー座標
   samplerDesc.MipLODBias = 0;                            // 計算されたミップマップ レベルからのバイアス
   samplerDesc.MaxAnisotropy = 1;                         // サンプリングに異方性補間を使用している場合の限界値。有効な値は 1 〜 16 。
   samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;  // 比較オプション。
   ::CopyMemory( samplerDesc.BorderColor, &D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), sizeof( D3DXVECTOR4 ) ); // 境界色
   samplerDesc.MinLOD = 0;                                // アクセス可能なミップマップの下限値
   samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;                // アクセス可能なミップマップの上限値
   hr = pD3DDevice->CreateSamplerState( &samplerDesc, &m_Step01.pSamplerState );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 深度ステンシルステートの作成
   // *****************************************************************************************************************

   // 深度ステンシルステートを作成する
   D3D11_DEPTH_STENCIL_DESC ddsDesc;
   ::ZeroMemory( &ddsDesc, sizeof( ddsDesc ) );
   ddsDesc.DepthEnable = TRUE;                            // 深度テストを有効
   ddsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;   // 深度バッファへの書き込みを行う
   ddsDesc.DepthFunc = D3D11_COMPARISON_LESS;
   ddsDesc.StencilEnable = FALSE;
   hr = pD3DDevice->CreateDepthStencilState( &ddsDesc, &m_Step01.AlphaNone.pDepthStencilState );
   if( FAILED( hr ) )
      goto EXIT;

   ::ZeroMemory( &ddsDesc, sizeof( ddsDesc ) );
   ddsDesc.DepthEnable = TRUE;                            // 深度テストを有効
   ddsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;   // 深度バッファへの書き込みを行わない
   ddsDesc.DepthFunc = D3D11_COMPARISON_LESS;
   ddsDesc.StencilEnable = FALSE;
   hr = pD3DDevice->CreateDepthStencilState( &ddsDesc, &m_Step01.AlphaAdd.pDepthStencilState );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // ブレンドステートの作成
   // *****************************************************************************************************************

   D3D11_BLEND_DESC BlendDesc;
   ::ZeroMemory( &BlendDesc, sizeof( BlendDesc ) );
   BlendDesc.AlphaToCoverageEnable = FALSE;
   BlendDesc.IndependentBlendEnable = FALSE;
   // アルファブレンドを無効
   BlendDesc.RenderTarget[0].BlendEnable = FALSE;
   BlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
   BlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
   BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
   hr = pD3DDevice->CreateBlendState( &BlendDesc, &m_Step01.AlphaNone.pBlendState );
   if( FAILED( hr ) )
      goto EXIT;

   ::ZeroMemory( &BlendDesc, sizeof( BlendDesc ) );
   BlendDesc.AlphaToCoverageEnable = FALSE;
   BlendDesc.IndependentBlendEnable = FALSE;
   // 疑似HDRのための加算合成
   BlendDesc.RenderTarget[0].BlendEnable = TRUE;
   BlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
   BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
   hr = pD3DDevice->CreateBlendState( &BlendDesc, &m_Step01.AlphaAdd.pBlendState );
   if( FAILED( hr ) )
      goto EXIT;

   hr = S_OK;

EXIT:
   return hr;
}

// MGFフェーズの初期化
HRESULT LIGHTBLOOM::InitStep02( ID3D11Device* pD3DDevice
                              , const BYTE* pVSStep021Shader, size_t VSStep021Size
                              , const BYTE* pPSStep021Shader, size_t PSStep021Size
                              , const BYTE* pVSStep022Shader, size_t VSStep022Size
                              , const BYTE* pPSStep022Shader, size_t PSStep022Size
                              )
{
   HRESULT hr = E_FAIL;
   D3D11_BUFFER_DESC BufferDesc;
   D3DX11_IMAGE_LOAD_INFO info;

   if( pD3DDevice == nullptr ) 
      goto EXIT;

   // *****************************************************************************************************************
   // 頂点シェーダーの作成
   // *****************************************************************************************************************

   // ダウンサンプリング用
   hr = pD3DDevice->CreateVertexShader( pVSStep021Shader, VSStep021Size, nullptr, &m_Step02.pVertexShader[0] );
   if( FAILED( hr ) )
      goto EXIT;

   // MGF用
   hr = pD3DDevice->CreateVertexShader( pVSStep022Shader, VSStep022Size, nullptr, &m_Step02.pVertexShader[1] );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 入力レイアウトの作成
   // *****************************************************************************************************************

   D3D11_INPUT_ELEMENT_DESC* pInputElement = NULL;
   UINT InputElementCount;
   m_Polygon2D.GetInputElement( &pInputElement, &InputElementCount );
   hr = pD3DDevice->CreateInputLayout( pInputElement, InputElementCount, pVSStep021Shader, VSStep021Size, &m_Step02.pLayout );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // ピクセルェーダーの作成
   // *****************************************************************************************************************

   // ダウンサンプリング用
   hr = pD3DDevice->CreatePixelShader( pPSStep021Shader, PSStep021Size, nullptr, &m_Step02.pPixelShader[0] );
   if( FAILED( hr ) )
      goto EXIT;

   // MGF用
   hr = pD3DDevice->CreatePixelShader( pPSStep022Shader, PSStep022Size, nullptr, &m_Step02.pPixelShader[1] );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 定数バッファを作成
   // *****************************************************************************************************************

   ::ZeroMemory( &BufferDesc, sizeof( BufferDesc ) );
   BufferDesc.ByteWidth             = sizeof( CB_STEP02 );       // バッファサイズ
   BufferDesc.Usage                 = D3D11_USAGE_DYNAMIC;       // リソース使用法を特定する
   BufferDesc.BindFlags             = D3D11_BIND_CONSTANT_BUFFER;// バッファの種類
   BufferDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_WRITE;    // CPU アクセスする
   BufferDesc.MiscFlags             = 0;                         // その他のフラグも設定しない
   hr = pD3DDevice->CreateBuffer( &BufferDesc, nullptr, &m_Step02.pConstantBuffers );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // サンプラーステートの作成
   // *****************************************************************************************************************

   D3D11_SAMPLER_DESC samplerDesc;
   samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
   samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;    // ブラーをかけるので CLAMP にする
   samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;    // ブラーをかけるので CLAMP にする
   samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;    // ブラーをかけるので CLAMP にする
   samplerDesc.MipLODBias = 0;                            // 計算されたミップマップ レベルからのバイアス
   samplerDesc.MaxAnisotropy = 1;                         // サンプリングに異方性補間を使用している場合の限界値。有効な値は 1 〜 16 。
   samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;  // 比較オプション。
   ::CopyMemory( samplerDesc.BorderColor, &D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), sizeof( D3DXVECTOR4 ) ); // 境界色
   samplerDesc.MinLOD = 0;                                // アクセス可能なミップマップの下限値
   samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;                // アクセス可能なミップマップの上限値
   hr = pD3DDevice->CreateSamplerState( &samplerDesc, &m_Step02.pSamplerState );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 深度ステンシルステートの作成
   // *****************************************************************************************************************

   // 深度ステンシルステートを作成する
   D3D11_DEPTH_STENCIL_DESC ddsDesc;
   ::ZeroMemory( &ddsDesc, sizeof( ddsDesc ) );
   ddsDesc.DepthEnable = FALSE;                            // 深度テストを無効
   ddsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;   // 深度バッファへの書き込みを行わない
   ddsDesc.DepthFunc = D3D11_COMPARISON_LESS;
   ddsDesc.StencilEnable = FALSE;
   hr = pD3DDevice->CreateDepthStencilState( &ddsDesc, &m_Step02.pDepthStencilState );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // ブレンドステートの作成
   // *****************************************************************************************************************

   D3D11_BLEND_DESC BlendDesc;
   ::ZeroMemory( &BlendDesc, sizeof( BlendDesc ) );
   BlendDesc.AlphaToCoverageEnable = FALSE;
   BlendDesc.IndependentBlendEnable = FALSE;
   // アルファブレンド無効
   BlendDesc.RenderTarget[0].BlendEnable = FALSE;
   BlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
   BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
   hr = pD3DDevice->CreateBlendState( &BlendDesc, &m_Step02.pBlendState );
   if( FAILED( hr ) )
      goto EXIT;

   hr = S_OK;

EXIT:
   return hr;
}

// HDRマップを合成するフェーズの初期化
HRESULT LIGHTBLOOM::InitStep03( ID3D11Device* pD3DDevice
                              , const BYTE* pVSStep03Shader, size_t VSStep03Size
                              , const BYTE* pPSStep03Shader, size_t PSStep03Size
                              )
{
   HRESULT hr = E_FAIL;
   //D3D11_BUFFER_DESC BufferDesc;
   D3DX11_IMAGE_LOAD_INFO info;

   if( pD3DDevice == nullptr ) 
      goto EXIT;

   // *****************************************************************************************************************
   // 頂点シェーダーの作成
   // *****************************************************************************************************************

   hr = pD3DDevice->CreateVertexShader( pVSStep03Shader, VSStep03Size, nullptr, &m_Step03.pVertexShader );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 入力レイアウトの作成
   // *****************************************************************************************************************

   D3D11_INPUT_ELEMENT_DESC* pInputElement = NULL;
   UINT InputElementCount;
   m_Polygon2D.GetInputElement( &pInputElement, &InputElementCount );
   hr = pD3DDevice->CreateInputLayout( pInputElement, InputElementCount, pVSStep03Shader, VSStep03Size, &m_Step03.pLayout );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // ピクセルェーダーの作成
   // *****************************************************************************************************************

   hr = pD3DDevice->CreatePixelShader( pPSStep03Shader, PSStep03Size, nullptr, &m_Step03.pPixelShader );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 定数バッファを作成
   // *****************************************************************************************************************

   // なし

   // *****************************************************************************************************************
   // サンプラーステートの作成
   // *****************************************************************************************************************

   D3D11_SAMPLER_DESC samplerDesc;
   samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
   samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
   samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
   samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
   samplerDesc.MipLODBias = 0;                            // 計算されたミップマップ レベルからのバイアス
   samplerDesc.MaxAnisotropy = 1;                         // サンプリングに異方性補間を使用している場合の限界値。有効な値は 1 〜 16 。
   samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;  // 比較オプション。
   ::CopyMemory( samplerDesc.BorderColor, &D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), sizeof( D3DXVECTOR4 ) ); // 境界色
   samplerDesc.MinLOD = 0;                                // アクセス可能なミップマップの下限値
   samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;                // アクセス可能なミップマップの上限値
   hr = pD3DDevice->CreateSamplerState( &samplerDesc, &m_Step03.pSamplerState );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // 深度ステンシルステートの作成
   // *****************************************************************************************************************

   // 深度ステンシルステートを作成する
   D3D11_DEPTH_STENCIL_DESC ddsDesc;
   ::ZeroMemory( &ddsDesc, sizeof( ddsDesc ) );
   ddsDesc.DepthEnable = FALSE;                            // 深度テストを無効
   ddsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;   // 深度バッファへの書き込みを行わない
   ddsDesc.DepthFunc = D3D11_COMPARISON_LESS;
   ddsDesc.StencilEnable = FALSE;
   hr = pD3DDevice->CreateDepthStencilState( &ddsDesc, &m_Step03.pDepthStencilState );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // ブレンドステートの作成
   // *****************************************************************************************************************

   D3D11_BLEND_DESC BlendDesc;
   ::ZeroMemory( &BlendDesc, sizeof( BlendDesc ) );
   BlendDesc.AlphaToCoverageEnable = FALSE;
   BlendDesc.IndependentBlendEnable = FALSE;
   // 加算合成
   BlendDesc.RenderTarget[0].BlendEnable = TRUE;
   BlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
   BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
   BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
   BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
   hr = pD3DDevice->CreateBlendState( &BlendDesc, &m_Step03.pBlendState );
   if( FAILED( hr ) )
      goto EXIT;

   hr = S_OK;

EXIT:
   return hr;
}

// 初期化
HRESULT LIGHTBLOOM::Init( ID3D11Device* pD3DDevice
                         // hlsl ファイル名
                        , const TCHAR pSrcFile[]
                         // フォンシェーディング + HDRマップ描画フェーズ
                        , const CHAR pVSStep01FunctionName[], const CHAR pPSStep01FunctionName[]
                         // MGFフェーズ
                        , const CHAR pVSStep021FunctionName[], const CHAR pPSStep021FunctionName[]
                        , const CHAR pVSStep022FunctionName[], const CHAR pPSStep022FunctionName[]
                         // HDRマップを合成するフェーズ
                        , const CHAR pVSStep03FunctionName[], const CHAR pPSStep03FunctionName[]
                        , UINT ScreenWidth, UINT ScreenHeight
                        )
{
   HRESULT hr = E_FAIL;

   ID3D10Blob* pBlob[4] = { nullptr, nullptr, nullptr, nullptr };

   // *****************************************************************************************************************
   // 共通項目の初期化
   // *****************************************************************************************************************

   hr = InitCommon( pD3DDevice, ScreenWidth, ScreenHeight );
   if( FAILED( hr ) )
      goto EXIT;

   UINT Flag1 = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR | D3D10_SHADER_ENABLE_STRICTNESS;
#if defined(DEBUG) || defined(_DEBUG)
   Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL0;
#else
   Flag1 |= D3D10_SHADER_OPTIMIZATION_LEVEL3;
#endif

   // *****************************************************************************************************************
   // フォンシェーディング + HDRマップの描画フェーズ用のシェーダーソースのコンパイル
   // *****************************************************************************************************************

   // 頂点シェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pVSStep01FunctionName, "vs_4_0", Flag1, 0, nullptr, &pBlob[0], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;

   // ピクセルシェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pPSStep01FunctionName, "ps_4_0", Flag1, 0, nullptr, &pBlob[1], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;

   // 初期化
   hr = InitStep01( pD3DDevice
                  , reinterpret_cast<LPBYTE>( pBlob[0]->GetBufferPointer() ), pBlob[0]->GetBufferSize()
                  , reinterpret_cast<LPBYTE>( pBlob[1]->GetBufferPointer() ), pBlob[1]->GetBufferSize()
                  );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // MGFフェーズ用のシェーダーソースのコンパイル
   // *****************************************************************************************************************

   // ダウンサンプリング用

   // 頂点シェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pVSStep021FunctionName, "vs_4_0", Flag1, 0, nullptr, &pBlob[0], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;
   // ピクセルシェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pPSStep021FunctionName, "ps_4_0", Flag1, 0, nullptr, &pBlob[1], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;

   // MGF用

   // 頂点シェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pVSStep022FunctionName, "vs_4_0", Flag1, 0, nullptr, &pBlob[2], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;
   // ピクセルシェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pPSStep022FunctionName, "ps_4_0", Flag1, 0, nullptr, &pBlob[3], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;

   // 初期化
   hr = InitStep02( pD3DDevice
                  , reinterpret_cast<LPBYTE>( pBlob[0]->GetBufferPointer() ), pBlob[0]->GetBufferSize()
                  , reinterpret_cast<LPBYTE>( pBlob[1]->GetBufferPointer() ), pBlob[1]->GetBufferSize()
                  , reinterpret_cast<LPBYTE>( pBlob[2]->GetBufferPointer() ), pBlob[2]->GetBufferSize()
                  , reinterpret_cast<LPBYTE>( pBlob[3]->GetBufferPointer() ), pBlob[3]->GetBufferSize()
                  );
   if( FAILED( hr ) )
      goto EXIT;

   // *****************************************************************************************************************
   // HDRマップを合成するフェーズ用のシェーダーソースのコンパイル
   // *****************************************************************************************************************

   // 頂点シェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pVSStep03FunctionName, "vs_4_0", Flag1, 0, nullptr, &pBlob[0], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;
   // ピクセルシェーダーのコンパイル
   hr = D3DX11CompileFromFile( pSrcFile, nullptr, nullptr, pPSStep03FunctionName, "ps_4_0", Flag1, 0, nullptr, &pBlob[1], nullptr, nullptr );
   if( FAILED( hr ) )
      goto EXIT;

   // 初期化
   hr = InitStep03( pD3DDevice
                  , reinterpret_cast<LPBYTE>( pBlob[0]->GetBufferPointer() ), pBlob[0]->GetBufferSize()
                  , reinterpret_cast<LPBYTE>( pBlob[1]->GetBufferPointer() ), pBlob[1]->GetBufferSize()
                  );
   if( FAILED( hr ) )
      goto EXIT;

   hr = S_OK;

EXIT:
   return hr;
}

// 初期化
HRESULT LIGHTBLOOM::Init( ID3D11Device* pD3DDevice
                        // フォンシェーディング + HDRマップ 描画フェーズ
                        , const BYTE* pVSStep01Shader, size_t VSStep01Size
                        , const BYTE* pPSStep01Shader, size_t PSStep01Size
                        // MGFフェーズ
                        , const BYTE* pVSStep021Shader, size_t VSStep021Size
                        , const BYTE* pPSStep021Shader, size_t PSStep021Size
                        , const BYTE* pVSStep022Shader, size_t VSStep022Size
                        , const BYTE* pPSStep022Shader, size_t PSStep022Size
                        // HDRマップを合成するフェーズ
                        , const BYTE* pVSStep03Shader, size_t VSStep03Size
                        , const BYTE* pPSStep03Shader, size_t PSStep03Size
                        , UINT ScreenWidth, UINT ScreenHeight
                        )
{
   HRESULT hr = E_FAIL;

   // フォンシェーディング + HDRマップ 描画フェーズ用の初期化
   hr = InitStep01( pD3DDevice, pVSStep01Shader, VSStep01Size, pPSStep01Shader, PSStep01Size );
   if( FAILED( hr ) )
      goto EXIT;

   // MGFフェーズの初期化
   hr = InitStep02( pD3DDevice
                  , pVSStep021Shader, VSStep021Size
                  , pPSStep021Shader, PSStep021Size
                  , pVSStep022Shader, VSStep022Size
                  , pPSStep022Shader, PSStep022Size
                  );
   if( FAILED( hr ) )
      goto EXIT;

   // HDRマップを合成するフェーズの初期化
   hr = InitStep03( pD3DDevice
                  , pVSStep03Shader, VSStep03Size
                  , pPSStep03Shader, PSStep03Size
                  );
   if( FAILED( hr ) )
      goto EXIT;

   // 共通項目の初期化
   hr = InitCommon( pD3DDevice, ScreenWidth, ScreenHeight );
   if( FAILED( hr ) )
      goto EXIT;

   hr = S_OK;

EXIT:
   return hr;
}

// シェーダーにバインド可能なレンダーターゲットビューを作成する
HRESULT LIGHTBLOOM::CreateRenderTargetView( ID3D11Device* pD3DDevice, ID3D11RenderTargetView** ppRTView, UINT Width, UINT Height, DXGI_FORMAT Format ) const
{
   HRESULT hr = E_FAIL;

   ID3D11Texture2D* pTexture2D = nullptr;

   D3D11_TEXTURE2D_DESC Tex2DDesc;
   D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;

   if( Width == 0 || Height == 0 )
      goto EXIT;

   ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
   Tex2DDesc.ArraySize        = 1;
   Tex2DDesc.BindFlags        = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
   Tex2DDesc.Usage            = D3D11_USAGE_DEFAULT;
   Tex2DDesc.Format           = Format;
   Tex2DDesc.Width            = Width;
   Tex2DDesc.Height           = Height;
   Tex2DDesc.MipLevels        = 1;
   Tex2DDesc.SampleDesc.Count = 1;
   Tex2DDesc.SampleDesc.Quality = 0;

   ::ZeroMemory( &RTVDesc, sizeof( D3D11_RENDER_TARGET_VIEW_DESC ) );
   RTVDesc.Format = Tex2DDesc.Format;
   RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
   RTVDesc.Texture2D.MipSlice = 0;

   hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, nullptr, &pTexture2D );
   if( FAILED( hr ) )
      goto EXIT;

   hr = pD3DDevice->CreateRenderTargetView( pTexture2D, &RTVDesc, ppRTView );
   if( FAILED( hr ) )
      goto EXIT;
   
   SAFE_RELEASE( pTexture2D );

   hr = S_OK;
EXIT:
   return hr;
}

// レンダーターゲットビューからシェーダーリソースビューを作成する
ID3D11ShaderResourceView* LIGHTBLOOM::GetSRViewFromRTView( ID3D11Device* pD3DDevice, ID3D11RenderTargetView* pRTView ) const
{
   ID3D11Resource* pResource = NULL;
   ID3D11ShaderResourceView* pSRView = NULL;

   if( pRTView == nullptr )
      return pSRView;

   pRTView->GetResource( &pResource );
   pD3DDevice->CreateShaderResourceView( pResource, NULL, &pSRView );
   SAFE_RELEASE( pResource );

   return pSRView;
}

// レンダーターゲットビューの縦横のサイズを取得
D3DXVECTOR2 LIGHTBLOOM::GetRTViewSize( ID3D11RenderTargetView* pRTView ) const
{
   D3DXVECTOR2 Size = D3DXVECTOR2( 0, 0 );

   if( pRTView == nullptr )
      goto EXIT;

   ID3D11Resource* pResource = nullptr;
   pRTView->GetResource( &pResource );
   ID3D11Texture2D* pTexture = reinterpret_cast<ID3D11Texture2D*>(pResource);
   D3D11_TEXTURE2D_DESC Desc;
   pTexture->GetDesc( &Desc );
   Size = D3DXVECTOR2( (float)Desc.Width, (float)Desc.Height );
   SAFE_RELEASE( pResource );

EXIT:
   return Size;
}

// シェーダーリソースビューの縦横のサイズを取得
D3DXVECTOR2 LIGHTBLOOM::GetSRViewSize( ID3D11ShaderResourceView* pSRView ) const
{
   D3DXVECTOR2 Size = D3DXVECTOR2( 0, 0 );

   if( pSRView == nullptr )
      goto EXIT;

   ID3D11Resource* pResource = nullptr;
   pSRView->GetResource( &pResource );
   ID3D11Texture2D* pTexture = reinterpret_cast<ID3D11Texture2D*>(pResource);
   D3D11_TEXTURE2D_DESC Desc;
   pTexture->GetDesc( &Desc );
   Size = D3DXVECTOR2( (float)Desc.Width, (float)Desc.Height );
   SAFE_RELEASE( pResource );

EXIT:
   return Size;
}

// フォンシェーディング + HDRマップの描画関数
HRESULT LIGHTBLOOM::BeginStep01( ID3D11DeviceContext* pD3DDeviceContext, BOOL BlendEnable ) const
{
   HRESULT hr = E_FAIL;

   // *****************************************************************************************************************
   // 入力アセンブラー ステージを設定
   // *****************************************************************************************************************

   pD3DDeviceContext->IASetInputLayout( m_Step01.pLayout );

   // *****************************************************************************************************************
   // シェーダーをデバイスに設定
   // *****************************************************************************************************************

   // 頂点シェーダーをデバイスに設定する。
   pD3DDeviceContext->VSSetShader( m_Step01.pVertexShader, nullptr, 0 );

   // ハルシェーダーを無効にする。
   pD3DDeviceContext->HSSetShader( nullptr, nullptr, 0 );

   // ドメインシェーダーを無効にする。
   pD3DDeviceContext->DSSetShader( nullptr, nullptr, 0 );

   // ジオメトリシェーダーを無効にする。
   pD3DDeviceContext->GSSetShader( nullptr, nullptr, 0 );
   
   // ピクセルシェーダーをデバイスに設定する
   pD3DDeviceContext->PSSetShader( m_Step01.pPixelShader, nullptr, 0 );
   // ピクセルシェーダーにサンプラーステートを設定する。
   pD3DDeviceContext->PSSetSamplers( 0, 1, &m_Step01.pSamplerState );

   // コンピュートシェーダーを無効にする。
   pD3DDeviceContext->CSSetShader( nullptr, nullptr, 0 );

   // *****************************************************************************************************************
   // 出力結合ステージを設定
   // *****************************************************************************************************************

   if( !BlendEnable )
   {
      // ブレンドステートを設定
      pD3DDeviceContext->OMSetBlendState( m_Step01.AlphaNone.pBlendState, 0, 0xffffffff );
      // 深度ステンシルステートを設定
      pD3DDeviceContext->OMSetDepthStencilState( m_Step01.AlphaNone.pDepthStencilState, 0 );
   }
   else
   {
      // ブレンドステートを設定
      pD3DDeviceContext->OMSetBlendState( m_Step01.AlphaAdd.pBlendState, 0, 0xffffffff );
      // 深度ステンシルステートを設定
      pD3DDeviceContext->OMSetDepthStencilState( m_Step01.AlphaAdd.pDepthStencilState, 0 );
   }

   hr = S_OK;
//EXIT:
   return hr;
}

// フォンシェーディング + HDRマップの描画フェーズの定数バッファの設定
HRESULT LIGHTBLOOM::SetCBStep01( ID3D11DeviceContext* pD3DDeviceContext
                               , const D3DXMATRIX* p_matWVP
                               , const D3DXVECTOR4* p_vecLight, const D3DXVECTOR4* p_vecEyePos
                               , ID3D11ShaderResourceView* const pDecalMap
                               , float FakeHDRPower, float SpecularPower
                               )const
{
   HRESULT hr = E_FAIL;

   // *****************************************************************************************************************
   // 定数バッファを設定
   // *****************************************************************************************************************

   D3D11_MAPPED_SUBRESOURCE mappedResource;
   CB_STEP01* cbuffer;

   hr = pD3DDeviceContext->Map( m_Step01.pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
   if( FAILED( hr ) ) goto EXIT;
   cbuffer = reinterpret_cast<CB_STEP01*>(mappedResource.pData);

   ::CopyMemory( &cbuffer->matWVP, p_matWVP, sizeof( D3DXMATRIX ));
   if( p_vecLight != nullptr )
      ::CopyMemory( &cbuffer->vecLight, p_vecLight, sizeof( D3DXVECTOR4 ));
   if( p_vecEyePos != nullptr )
      ::CopyMemory( &cbuffer->vecEyePos, p_vecEyePos, sizeof( D3DXVECTOR4 ));
   cbuffer->FakeHDRPower = FakeHDRPower;
   cbuffer->SpecularPower = SpecularPower;
   pD3DDeviceContext->Unmap( m_Step01.pConstantBuffers, 0 );

   // *****************************************************************************************************************
   // 定数バッファをデバイスに設定
   // *****************************************************************************************************************

   // 頂点シェーダーに定数バッファを設定する
   pD3DDeviceContext->VSSetConstantBuffers( 0, 1, &m_Step01.pConstantBuffers );

   // ピクセルシェーダーに定数バッファを設定する
   pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_Step01.pConstantBuffers );
   // デカールマップを設定する
   pD3DDeviceContext->PSSetShaderResources( 0, 1, &pDecalMap );

   hr = S_OK;
EXIT:
   return hr;
}

// フォンシェーディング + HDRマップの描画フェーズの終了処理( 何もしない )
HRESULT LIGHTBLOOM::EndStep01( ID3D11DeviceContext* /*pD3DDeviceContext*/ )const
{
   HRESULT hr = E_FAIL;

   hr = S_OK;

//EXIT:
   return hr;
}

// MGFの定数バッファを設定する
HRESULT LIGHTBLOOM::SetCBStep02( ID3D11DeviceContext* pD3DDeviceContext
                               , const D3DXVECTOR2* pTexelSize
                               , float Dispersion )const
{
   HRESULT hr = E_FAIL;

   if( Dispersion < 0.0f )
   {
      OutputDebugString( _T("■□■ Dispersionが 0.0f 未満です。LIGHTBLOOM::SetCBStep02の引数の値を確認してください。■□■\n") );
      goto EXIT;
   }

   // *****************************************************************************************************************
   // 定数バッファをデバイスに設定
   // *****************************************************************************************************************

   D3D11_MAPPED_SUBRESOURCE mappedResource;
   CB_STEP02* cbuffer;

   hr = pD3DDeviceContext->Map( m_Step02.pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
   if( FAILED( hr ) )
      goto EXIT;

   cbuffer = reinterpret_cast<CB_STEP02*>(mappedResource.pData);

   // 1テクセルサイズ
   if( pTexelSize->x != 0 )
   {
      cbuffer->TexelSize.x = 1.0f / pTexelSize->x;
      cbuffer->Offset.x = 16.0f * cbuffer->TexelSize.x;
   }
   else
   {
      cbuffer->TexelSize.x = 0;
      cbuffer->Offset.x = 0;
   }
   if( pTexelSize->y != 0 )
   {
      cbuffer->TexelSize.y = 1.0f / pTexelSize->y;
      cbuffer->Offset.y = 16.0f * cbuffer->TexelSize.y;
   }
   else
   {
      cbuffer->TexelSize.y = 0;
      cbuffer->Offset.y = 0;
   }
   const UINT Division = 8;
   float total = 0.0f;

   // ガウス関数による重みの計算
   for( UINT i=0; i<Division; i++ )
   {
      // 重み
      float pos = static_cast<float>( i ) * 2.0f;
      // expfはeを底とする指数を計算する
      cbuffer->Weight[i] = expf( -pos * pos * Dispersion );
      total += cbuffer->Weight[i];
   }

   // 重みの規格化
   for( UINT i=0; i<Division; i++ )
      cbuffer->Weight[i] = cbuffer->Weight[i] / total * 0.5f;

   pD3DDeviceContext->Unmap( m_Step02.pConstantBuffers, 0 );

   // 頂点シェーダーに定数バッファを設定する
   pD3DDeviceContext->VSSetConstantBuffers( 0, 1, &m_Step02.pConstantBuffers );

   // ピクセルシェーダーに定数バッファを設定する
   pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_Step02.pConstantBuffers );

   hr = S_OK;
EXIT:
   return hr;
}

// MGF描画関数
HRESULT LIGHTBLOOM::RenderStep02( ID3D11DeviceContext* pD3DDeviceContext
                                , ID3D11ShaderResourceView* pSRViewHDRMap[1]
                                , float Dispersion
                                )const
{
   HRESULT hr = E_FAIL;

   ID3D11Device* pD3D11Device = nullptr;
   pD3DDeviceContext->GetDevice( &pD3D11Device );

   ID3D11RenderTargetView* pOldRTV = nullptr;
   ID3D11DepthStencilView* pOldDSV = nullptr;
   ID3D11ShaderResourceView* pSRV = nullptr;
   D3DXVECTOR2 Size;
   
   UINT ViewportNum = 0;
   D3D11_VIEWPORT* pOldViewport;
   D3D11_VIEWPORT NewViewport[1];

   // *****************************************************************************************************************
   // 入力アセンブラー ステージを設定
   // *****************************************************************************************************************

   // 入力レイアウト設定
   pD3DDeviceContext->IASetInputLayout( m_Step02.pLayout );

   // 頂点バッファはCPolygon2Dクラス内部で設定するのでここでは設定しない

   // *****************************************************************************************************************
   // シェーダーをデバイスに設定
   // *****************************************************************************************************************

   // ハルシェーダーを無効にする。
   pD3DDeviceContext->HSSetShader( nullptr, nullptr, 0 );

   // ドメインシェーダーを無効にする
   pD3DDeviceContext->DSSetShader( nullptr, nullptr, 0 );

   // ジオメトリシェーダーを無効にする。
   pD3DDeviceContext->GSSetShader( nullptr, nullptr, 0 );

   // ピクセルシェーダーにサンプラーステートを設定する。
   pD3DDeviceContext->PSSetSamplers( 0, 1, &m_Step02.pSamplerState );

   // コンピュートシェーダーを無効にする。
   pD3DDeviceContext->CSSetShader( nullptr, nullptr, 0 );

   // *****************************************************************************************************************
   // 出力結合ステージを設定
   // *****************************************************************************************************************

   // ブレンドステートを設定
   pD3DDeviceContext->OMSetBlendState( m_Step02.pBlendState, 0, 0xffffffff );

   // 深度ステンシルステートを設定
   pD3DDeviceContext->OMSetDepthStencilState( m_Step02.pDepthStencilState, 0 );

   // レンダーターゲットを退避
   pD3DDeviceContext->OMGetRenderTargets( 1, &pOldRTV, &pOldDSV );

   // ビューポートを退避
   pD3DDeviceContext->RSGetViewports( &ViewportNum, nullptr );
   pOldViewport = NEW D3D11_VIEWPORT[ViewportNum];
   pD3DDeviceContext->RSGetViewports( &ViewportNum, pOldViewport );

   // *****************************************************************************************************************
   // ダウンサンプリング
   // *****************************************************************************************************************

   // 頂点シェーダーをデバイスに設定する。
   pD3DDeviceContext->VSSetShader( m_Step02.pVertexShader[0], nullptr, 0 );

   // ピクセルシェーダーをデバイスに設定する。
   pD3DDeviceContext->PSSetShader( m_Step02.pPixelShader[0], nullptr, 0 );

   // レンダーターゲットビューから縦横のサイズを取得
   Size = GetRTViewSize( pRTViewDownSample );

   // ビューポートのサイズを変更する
   NewViewport[0].TopLeftX = 0;
   NewViewport[0].TopLeftY = 0;
   NewViewport[0].Width    = Size.x;
   NewViewport[0].Height   = Size.y;
   NewViewport[0].MinDepth = 0.0f;
   NewViewport[0].MaxDepth = 1.0f;
   pD3DDeviceContext->RSSetViewports( 1, NewViewport );

   // レンダーターゲットを切り替える
   pD3DDeviceContext->OMSetRenderTargets( 1, &pRTViewDownSample, nullptr );

   // HDRマップのシェーダーリソースビューをピクセルシェーダーに設定する
   pD3DDeviceContext->PSSetShaderResources( 0, 1, &pSRViewHDRMap[0] );

   // 描画
   m_Polygon2D.Render( pD3DDeviceContext );

   // *****************************************************************************************************************
   // 縮小しつつガウスフィルターを適用する
   // *****************************************************************************************************************

   // 頂点シェーダーをデバイスに設定する。
   pD3DDeviceContext->VSSetShader( m_Step02.pVertexShader[1], nullptr, 0 );

   // ピクセルシェーダーをデバイスに設定する。
   pD3DDeviceContext->PSSetShader( m_Step02.pPixelShader[1], nullptr, 0 );

   for( UINT i=0; i<RTVCount; i++ )
   {
      // *****************************************************************************************************************
      // x方向にガウスフィルターを適用する
      // *****************************************************************************************************************

      // レンダーターゲットビューから縦横のサイズを取得
      Size = GetRTViewSize( pRTViewXGF[i] );

      // ビューポートのサイズを変更する
      NewViewport[0].TopLeftX = 0;
      NewViewport[0].TopLeftY = 0;
      NewViewport[0].Width    = Size.x;
      NewViewport[0].Height   = Size.y;
      NewViewport[0].MinDepth = 0.0f;
      NewViewport[0].MaxDepth = 1.0f;
      pD3DDeviceContext->RSSetViewports( 1, NewViewport );

      // レンダーターゲットを切り替える
      pD3DDeviceContext->OMSetRenderTargets( 1, &pRTViewXGF[i], nullptr );

      // ガウスフィルターを適用するシェーダーリソースビューをデバイスに設定する
      if( i )
         pSRV = GetSRViewFromRTView( pD3D11Device, pRTViewYGF[i-1] );
      else
         pSRV = GetSRViewFromRTView( pD3D11Device, pRTViewDownSample );

      // シェーダーリソースビューをピクセルシェーダーに設定する
      pD3DDeviceContext->PSSetShaderResources( 0, 1, &pSRV );

      // シェーダーリソースビューのサイズを取得
      Size = GetSRViewSize( pSRV );

      // 定数バッファを設定
      SetCBStep02( pD3DDeviceContext, &D3DXVECTOR2( Size.x, 0 ), Dispersion );

      // 描画
      m_Polygon2D.Render( pD3DDeviceContext );

      SAFE_RELEASE( pSRV );

      // *****************************************************************************************************************
      // y方向にガウスフィルターを適用する
      // *****************************************************************************************************************

      // レンダーターゲットビューから縦横のサイズを取得
      Size = GetRTViewSize( pRTViewYGF[i] );

      // ビューポートのサイズを変更する
      NewViewport[0].TopLeftX = 0;
      NewViewport[0].TopLeftY = 0;
      NewViewport[0].Width    = Size.x;
      NewViewport[0].Height   = Size.y;
      NewViewport[0].MinDepth = 0.0f;
      NewViewport[0].MaxDepth = 1.0f;
      pD3DDeviceContext->RSSetViewports( 1, NewViewport );

      // レンダーターゲットを切り替える
      pD3DDeviceContext->OMSetRenderTargets( 1, &pRTViewYGF[i], nullptr );

      pSRV = GetSRViewFromRTView( pD3D11Device, pRTViewXGF[i] );

      // シェーダーリソースビューをピクセルシェーダーに設定する
      pD3DDeviceContext->PSSetShaderResources( 0, 1, &pSRV );

      // シェーダーリソースビューのサイズを取得
      Size = GetSRViewSize( pSRV );

      // 定数バッファを設定
      SetCBStep02( pD3DDeviceContext, &D3DXVECTOR2( 0, Size.y ), Dispersion );

      // 描画
      m_Polygon2D.Render( pD3DDeviceContext );

      SAFE_RELEASE( pSRV );
   }

   // レンダーターゲットを戻す
   pD3DDeviceContext->OMSetRenderTargets( 1, &pOldRTV, pOldDSV );
   SAFE_RELEASE( pOldRTV );
   SAFE_RELEASE( pOldDSV );

   // ビューポートを戻す
   pD3DDeviceContext->RSSetViewports( ViewportNum, pOldViewport );
   SAFE_DELETE_ARRAY( pOldViewport );

   SAFE_RELEASE( pD3D11Device );

   hr = S_OK;
//EXIT:
   return hr;
}

// HDRマップ合成用関数
HRESULT LIGHTBLOOM::RenderStep03( ID3D11DeviceContext* pD3DDeviceContext )const
{
   HRESULT hr = E_FAIL;

   ID3D11Device* pD3D11Device = nullptr;
   pD3DDeviceContext->GetDevice( &pD3D11Device );

   ID3D11ShaderResourceView* pSRV[ RTVMAXCOUNT ];
   for( UINT i=0; i<RTVMAXCOUNT; i++ )
      pSRV[i] = nullptr;
   for( UINT i=0; i<RTVCount; i++ )
      pSRV[i] = GetSRViewFromRTView( pD3D11Device, pRTViewYGF[i] );
   
   // *****************************************************************************************************************
   // 入力アセンブラー ステージを設定
   // *****************************************************************************************************************

   // 入力レイアウト設定
   pD3DDeviceContext->IASetInputLayout( m_Step03.pLayout );

   // 頂点バッファはCPolygon2Dクラス内部で設定するのでここでは設定しない

   // *****************************************************************************************************************
   // シェーダーをデバイスに設定
   // *****************************************************************************************************************

   // 頂点シェーダーをデバイスに設定する。
   pD3DDeviceContext->VSSetShader( m_Step03.pVertexShader, nullptr, 0 );

   // ハルシェーダーを無効にする。
   pD3DDeviceContext->HSSetShader( nullptr, nullptr, 0 );

   // ドメインシェーダーを無効にする
   pD3DDeviceContext->DSSetShader( nullptr, nullptr, 0 );

   // ジオメトリシェーダーを無効にする。
   pD3DDeviceContext->GSSetShader( nullptr, nullptr, 0 );

   // ピクセルシェーダーをデバイスに設定する。
   pD3DDeviceContext->PSSetShader( m_Step03.pPixelShader, nullptr, 0 );
   // ピクセルシェーダーにサンプラーステートを設定する。
   pD3DDeviceContext->PSSetSamplers( 0, 1, &m_Step03.pSamplerState );

   // コンピュートシェーダーを無効にする。
   pD3DDeviceContext->CSSetShader( nullptr, nullptr, 0 );

   // *****************************************************************************************************************
   // 出力結合ステージを設定
   // *****************************************************************************************************************

   // ブレンドステートを設定
   pD3DDeviceContext->OMSetBlendState( m_Step03.pBlendState, 0, 0xffffffff );

   // 深度ステンシルステートを設定
   pD3DDeviceContext->OMSetDepthStencilState( m_Step03.pDepthStencilState, 0 );

   pD3DDeviceContext->PSSetShaderResources( 0, RTVCount, pSRV );

   // *****************************************************************************************************************
   // 描画
   // *****************************************************************************************************************

   m_Polygon2D.Render( pD3DDeviceContext );

   for( UINT i=0; i<RTVMAXCOUNT; i++ )
      SAFE_RELEASE( pSRV[i] );

   ID3D11ShaderResourceView* pSRVNull[ RTVMAXCOUNT ];
   for( UINT i=0; i<RTVMAXCOUNT; i++ )
      pSRVNull[i] = nullptr;
   pD3DDeviceContext->PSSetShaderResources( 0, RTVMAXCOUNT, pSRVNull );

   SAFE_RELEASE( pD3D11Device );

   hr = S_OK;
//EXIT:
   return hr;
}

// テスト用
ID3D11ShaderResourceView* LIGHTBLOOM::GetSRView( ID3D11DeviceContext* pD3DDeviceContext, UINT Index ) const
{
   ID3D11Device* pD3D11Device = nullptr;
   pD3DDeviceContext->GetDevice( &pD3D11Device );

   ID3D11ShaderResourceView* pSRV = nullptr;

   if( RTVCount > Index )
      pSRV = GetSRViewFromRTView( pD3D11Device, pRTViewYGF[Index] );

   SAFE_RELEASE( pD3D11Device );

   return pSRV;
}

LIGHTBLOOM::GetSRView()は縮小バッファの描画内容を確認するためのメンバ関数です。通常使用しません。

あと詳しく説明しませんが C++11 で正式に規格化された nullptr を使用するようにしました。

---main.cpp---  ↑

#include "../../USER/DX11User.h"
#include "../../USER/D3D11User.h"
#include "../../USER/DebugFontUser.h"
#include "../../USER/LightBloom.h"

// FBX SDK 用
#include "../../USER/MeshUser.h"
#include "../../USER/FBXSDKMeshLoaderUser.h"

// シェーダーオブジェクトを作成するとき、ファイルから読むか、メモリから読むかを切り替える
#if defined(DEBUG) || defined(_DEBUG)
#define UNCOMPILED_SHADER     // ファイルを読み込んでコンパイルする

#else
// Light Bloom
#include "../../USER/HLSL/LIGHTBLOOM_Step01_VS_Main.h"
#include "../../USER/HLSL/LIGHTBLOOM_Step01_PS_Main.h"
#include "../../USER/HLSL/LIGHTBLOOM_Step021_VS_Main.h"
#include "../../USER/HLSL/LIGHTBLOOM_Step021_PS_Main.h"
#include "../../USER/HLSL/LIGHTBLOOM_Step022_VS_Main.h"
#include "../../USER/HLSL/LIGHTBLOOM_Step022_PS_Main.h"
#include "../../USER/HLSL/LIGHTBLOOM_Step03_VS_Main.h"
#include "../../USER/HLSL/LIGHTBLOOM_Step03_PS_Main.h"
#endif

// アプリケーション名
TCHAR* AppName = _T("DX11_Tutrial 175 Light Bloom");

// Direct3D関連の自作クラス
D3D11USER* g_pD3D11User = nullptr;

// デバッグ専用のテキスト描画する自作クラス
CDebugFont* g_pDebugFontUser = nullptr;

// FBX メッシュローダー
FBXSDK_MESHLOADER_USER* g_pMeshLoader = nullptr;

// メッシュオブジェクト
BASE_MESH_USER*         g_pMeshPlane = nullptr;
BASE_MESH_USER*         g_pMeshObject = nullptr;
BASE_MESH_USER*         g_pMeshSun = nullptr;

// Light Bloomクラス
LIGHTBLOOM* g_pLightBloom = nullptr;

// レンダーターゲットサーフェス
ID3D11RenderTargetView* g_pRTView[1] = { nullptr };

// 平行光源の方向ベクトル
D3DXVECTOR4 g_vecLight = D3DXVECTOR4( -0.3f, -0.8f, -1.0f, 0.0f );

// 連続入力されたかを判定する際に使用するキーボード入力バッファ
BYTE g_KeyBuffer[256];

// ビュー行列
D3DXMATRIX g_matView;

// 節電モードの制御に使用する変数。
bool Activate = true;    // ウィンドウがアクティブか
bool StandBy = false;    // スタンバイ状態か

bool ScreenShot = false; // スクリーンショットを作成するかフラグ

// ビュー行列からビルボード用の行列を作成
D3DXMATRIX GetBillBoardMatrix( const D3DXMATRIX* pMatView ) 
{
   D3DXMATRIX BillBoardMatrix;

   // ビュー行列から逆行列を作成する
   D3DXMatrixInverse( &BillBoardMatrix, NULL, pMatView );

   // 回転のみ考慮するので平行移動は無効にする
   BillBoardMatrix._41 = BillBoardMatrix._42 = BillBoardMatrix._43 = 0.0f;

   return BillBoardMatrix;
}

// リソースの初期化
HRESULT Init()
{
   HRESULT hr = E_FAIL;

   // デバッグ専用フォント出力クラスの作成処理
   // デバックコンパイル時のみ使用する
#if defined(DEBUG) || defined(_DEBUG)
   g_pDebugFontUser = NEW CDebugFont();
   hr = g_pDebugFontUser->Create( g_pD3D11User->m_D3DDevice, 0.015f, 0.04f );
   if( FAILED( hr ) )
   {
      ::MessageBox( nullptr, _T("デバックフォントクラス初期化エラー"), _T("初期化エラー"), MB_OK );
      goto EXIT;
   }
#endif

   // 自作のメッシュローダーの初期化
   g_pMeshLoader = NEW FBXSDK_MESHLOADER_USER();
   hr = g_pMeshLoader->Initialize( g_pD3D11User->m_D3DDevice );
   if( FAILED( hr ) )
      goto EXIT;

   // 頂点情報を取得する
   hr = g_pMeshLoader->LoadMeshData( _T("Res/Plane.fbx"), &g_pMeshPlane );
   if( FAILED( hr ) )
      goto EXIT;

   hr = g_pMeshLoader->LoadMeshData( _T("Res/Object.fbx"), &g_pMeshObject );
   if( FAILED( hr ) )
      goto EXIT;

   hr = g_pMeshLoader->LoadMeshData( _T("Res/Sun.fbx"), &g_pMeshSun );
   if( FAILED( hr ) )
      goto EXIT;

   // シェーダー系クラスの初期化
   g_pLightBloom = NEW LIGHTBLOOM();

   // バックバッファのサイズ
   DXGI_SWAP_CHAIN_DESC SwapchainDesc;
   g_pD3D11User->m_SwapChain->GetDesc( &SwapchainDesc );

#ifndef UNCOMPILED_SHADER
   hr = g_pLightBloom->Init( g_pD3D11User->m_D3DDevice
                           , g_Step01_VS_Main, sizeof( g_Step01_VS_Main )
                           , g_Step01_PS_Main, sizeof( g_Step01_PS_Main )
                           , g_Step021_VS_Main, sizeof( g_Step021_VS_Main )
                           , g_Step021_PS_Main, sizeof( g_Step021_PS_Main )
                           , g_Step022_VS_Main, sizeof( g_Step022_VS_Main )
                           , g_Step022_PS_Main, sizeof( g_Step022_PS_Main )
                           , g_Step03_VS_Main, sizeof( g_Step03_VS_Main )
                           , g_Step03_PS_Main, sizeof( g_Step03_PS_Main )
                           , SwapchainDesc.BufferDesc.Width, SwapchainDesc.BufferDesc.Height
                           );
   if( FAILED( hr ) )
      goto EXIT;
#else
   hr = g_pLightBloom->Init( g_pD3D11User->m_D3DDevice
                           , _T("../../USER/HLSL/LightBloom.hlsl")
                           , "Step01_VS_Main", "Step01_PS_Main"
                           , "Step021_VS_Main", "Step021_PS_Main"
                           , "Step022_VS_Main", "Step022_PS_Main"
                           , "Step03_VS_Main", "Step03_PS_Main"
                           , SwapchainDesc.BufferDesc.Width, SwapchainDesc.BufferDesc.Height
                           );
   if( FAILED( hr ) )
      goto EXIT;
#endif

   // HDRマップ
   hr = g_pD3D11User->CreateRenderTargetView( &g_pRTView[0], nullptr, DXGI_FORMAT_R16G16B16A16_FLOAT );
   if( FAILED( hr ) )
      goto EXIT;

   // キーボード入力バッファの初期化
   ::ZeroMemory( g_KeyBuffer, sizeof( BYTE ) * _countof( g_KeyBuffer ) );

   // ビュー行列
   D3DXMatrixLookAtLH( &g_matView, &D3DXVECTOR3( 0.0f, 4.0f, -20.0f ), &D3DXVECTOR3( 0.0f, 4.0f, 0.0f ), &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );

   hr = S_OK;

EXIT:
   return hr;
}

// メモリ開放
void Invalidate()
{
   SAFE_DELETE( g_pLightBloom );
   SAFE_DELETE( g_pMeshSun );
   SAFE_DELETE( g_pMeshObject );
   SAFE_DELETE( g_pMeshPlane );
   SAFE_DELETE( g_pMeshLoader );
   for( int i=0; i<_countof( g_pRTView ); i++ )
      SAFE_RELEASE( g_pRTView[i] );
   SAFE_DELETE( g_pDebugFontUser );
   SAFE_DELETE( g_pD3D11User );
}

// メッシュ描画
HRESULT RenderMesh( D3DXMATRIX* pMatView, D3DXMATRIX* pMatProj )
{
   HRESULT hr = E_FAIL;

   D3DXMATRIX matScaling, matTranslation, matWorld, matWVP, matInv, matWV;
   D3DXVECTOR4 vec4LightDir, vec4EyePos;
   ID3D11ShaderResourceView* pDecalMap = nullptr;

   UINT stride = sizeof( MESH_USER::VERTEX_USER );
   UINT offset = 0;

   // 定数バッファを設定する
   {
      // ワールド行列

      // スケーリング行列
      D3DXMatrixScaling( &matScaling, 1.0f, 1.0f, 1.0f );
      // 平行移動行列
      D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, 0.0f );
      // ワールド座標系の行列の合成
      matWorld = matScaling * matTranslation;

      // 行列を合成
      matWVP = matWorld * (*pMatView) * (*pMatProj);
      // シェーダー内では列優先にしているので転置行列を作成する。
      D3DXMatrixTranspose( &matWVP, &matWVP );

      // 平行光源の方向ベクトル

      // ワールド行列の逆行列を作成
      D3DXMatrixInverse( &matInv, nullptr, &matWorld );
      D3DXVec4Transform( &vec4LightDir, &g_vecLight, &matInv );
      D3DXVec3Normalize( (D3DXVECTOR3*)&vec4LightDir, (D3DXVECTOR3*)&vec4LightDir );

      // 視点座標
      matWV = matWorld * (*pMatView);
      D3DXMatrixInverse( &matInv, nullptr, &matWV );
      D3DXVec4Transform( &vec4EyePos, &D3DXVECTOR4( 0, 0, 0, 1 ), &matInv );
   }

   // *****************************************************************************************************************
   // 地面の描画
   // *****************************************************************************************************************

   for( UINT i=0; i<g_pMeshPlane->MeshCount; i++ )
   {
      // 頂点バッファ設定
      g_pD3D11User->m_D3DDeviceContext->IASetVertexBuffers( 0, 1, &g_pMeshPlane->MeshUser[i].VertexBuffer, &stride, &offset );

      // インデックスバッファ設定
      g_pD3D11User->m_D3DDeviceContext->IASetIndexBuffer( g_pMeshPlane->MeshUser[i].IndexBuffer, DXGI_FORMAT_R32_UINT, 0 );
  
      // デカールマップを取得
      g_pMeshPlane->MeshUser[i].GetTexture( _T("DiffuseColor"), &pDecalMap );

      // 定数バッファとシェーダーリソースビューを設定する
      hr = g_pLightBloom->SetCBStep01( g_pD3D11User->m_D3DDeviceContext, &matWVP, &vec4LightDir, &vec4EyePos, pDecalMap, 0, 0 );
      if( FAILED( hr ) )
         goto EXIT;

      // インデックスバッファを使用した描画
      g_pD3D11User->m_D3DDeviceContext->DrawIndexed( g_pMeshPlane->MeshUser[i].IndexesCount, 0, 0 );
   }

   // *****************************************************************************************************************
   // オブジェクトの描画
   // *****************************************************************************************************************

   // 頂点バッファ設定
   g_pD3D11User->m_D3DDeviceContext->IASetVertexBuffers( 0, 1, &g_pMeshObject->MeshUser[0].VertexBuffer, &stride, &offset );

   // インデックスバッファ設定
   g_pD3D11User->m_D3DDeviceContext->IASetIndexBuffer( g_pMeshObject->MeshUser[0].IndexBuffer, DXGI_FORMAT_R32_UINT, 0 );
  
   // デカールマップを取得
   pDecalMap = nullptr;
   g_pMeshObject->MeshUser[0].GetTexture( _T("DiffuseColor"), &pDecalMap );

   // 定数バッファとシェーダーリソースビューを設定する
   hr = g_pLightBloom->SetCBStep01( g_pD3D11User->m_D3DDeviceContext, &matWVP, &vec4LightDir, &vec4EyePos, pDecalMap, 0, 6 );
   if( FAILED( hr ) )
      goto EXIT;

   // インデックスバッファを使用した描画
   g_pD3D11User->m_D3DDeviceContext->DrawIndexed( g_pMeshObject->MeshUser[0].IndexesCount, 0, 0 );

   hr = S_OK;
EXIT:
   return hr;
}

HRESULT RenderSun( D3DXMATRIX* pMatView, D3DXMATRIX* pMatProj, D3DXVECTOR3* pLightDir )
{
   HRESULT hr = E_FAIL;

   D3DXMATRIX matScaling, matTranslation, matWorld, matWVP, matBillboard;
   ID3D11ShaderResourceView* pDecalMap = nullptr;
   D3DXVECTOR3 LightPos;
   UINT stride = sizeof( MESH_USER::VERTEX_USER );
   UINT offset = 0;

   // *****************************************************************************************************************
   // 太陽の描画
   // *****************************************************************************************************************

   // 頂点バッファ設定
   g_pD3D11User->m_D3DDeviceContext->IASetVertexBuffers( 0, 1, &g_pMeshSun->MeshUser[0].VertexBuffer, &stride, &offset );

   // インデックスバッファ設定
   g_pD3D11User->m_D3DDeviceContext->IASetIndexBuffer( g_pMeshSun->MeshUser[0].IndexBuffer, DXGI_FORMAT_R32_UINT, 0 );
  
   // デカールマップを取得
   pDecalMap = nullptr;
   g_pMeshSun->MeshUser[0].GetTexture( _T("DiffuseColor"), &pDecalMap );

   // 定数バッファとシェーダーリソースビューを設定する
   {
      matBillboard = GetBillBoardMatrix( pMatView );

      // ワールド行列

      // スケーリング行列
      D3DXMatrixScaling( &matScaling, 2.0f, 2.0f, 1.0f );
      // 平行移動行列
      LightPos = - *pLightDir * 10.0f;
      D3DXMatrixTranslation( &matTranslation, LightPos.x, LightPos.y, LightPos.z );
      // ワールド座標系の行列の合成
      matWorld = matScaling * matTranslation;

      // 行列を合成
      matWVP = matBillboard * matWorld * (*pMatView) * (*pMatProj);
      // シェーダー内では列優先にしているので転置行列を作成する。
      D3DXMatrixTranspose( &matWVP, &matWVP );

      // 定数バッファとシェーダーリソースビューを設定する
      hr = g_pLightBloom->SetCBStep01( g_pD3D11User->m_D3DDeviceContext, &matWVP, nullptr, nullptr, pDecalMap, 5.0f, 0 );
      if( FAILED( hr ) )
         goto EXIT;
   }

   // インデックスバッファを使用した描画
   g_pD3D11User->m_D3DDeviceContext->DrawIndexed( g_pMeshSun->MeshUser[0].IndexesCount, 0, 0 );

   hr = S_OK;
EXIT:
   return hr;
}

// 描画処理
HRESULT Render()
{
   HRESULT hr = E_FAIL;
   D3DXMATRIX matProj, m, matInvProj;
   float Zfar = 100.0f;
   float BackBufferClearColor[4] = { 0.3f, 0.3f, 0.9f, 1.0f };
   float HDRMapClearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

   // バックバッファをクリア
   g_pD3D11User->m_D3DDeviceContext->ClearRenderTargetView( g_pD3D11User->m_RenderTargetView, BackBufferClearColor ); 

   // 深度バッファをクリア
   if( g_pD3D11User->m_DepthStencilView )
      g_pD3D11User->m_D3DDeviceContext->ClearDepthStencilView( g_pD3D11User->m_DepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );

   // 射影行列
   D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 5.0f, 4.0f / 3.0f, 1.0f, Zfar );

   // ビュー行列
   D3DXMatrixIdentity( &m );
   if( g_KeyBuffer[VK_RIGHT] )
   {
      D3DXMatrixRotationY( &m, -0.001f );
      g_matView = g_matView * m;
   }
   if( g_KeyBuffer[VK_LEFT] )
   {
      D3DXMatrixRotationY( &m, 0.001f );
      g_matView = g_matView * m;
   }
   if( g_KeyBuffer[VK_UP] )
   {
      D3DXMatrixTranslation( &m, 0, 0, -0.01f );
      g_matView = g_matView * m;
   }
   if( g_KeyBuffer[VK_DOWN] )
   {
      D3DXMatrixTranslation( &m, 0, 0, 0.01f );
      g_matView = g_matView * m;
   }
   if( g_KeyBuffer['W'] )
   {
      D3DXMatrixRotationX( &m, 0.001f );
      g_matView = g_matView * m;
   }
   if( g_KeyBuffer['S'] )
   {
      D3DXMatrixRotationX( &m, -0.001f );
      g_matView = g_matView * m;
   }

   // 三角ポリゴン描画
   g_pD3D11User->m_D3DDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

   // レンダーターゲットサーフェスをクリア
   g_pD3D11User->m_D3DDeviceContext->ClearRenderTargetView( g_pRTView[0], HDRMapClearColor ); 

   ID3D11RenderTargetView* pRTView[2] = { g_pD3D11User->m_RenderTargetView, g_pRTView[0] };

   // レンダーターゲットサーフェスを切り替える
   g_pD3D11User->m_D3DDeviceContext->OMSetRenderTargets( 2, pRTView, g_pD3D11User->m_DepthStencilView );

   // *****************************************************************************************************************
   // メッシュの描画
   // *****************************************************************************************************************

   g_pLightBloom->BeginStep01( g_pD3D11User->m_D3DDeviceContext, FALSE );
   {
      // メッシュを描画
      RenderMesh( &g_matView, &matProj );
   }
   g_pLightBloom->EndStep01( g_pD3D11User->m_D3DDeviceContext );

   g_pLightBloom->BeginStep01( g_pD3D11User->m_D3DDeviceContext, TRUE );
   {
      // メッシュを描画
      RenderSun( &g_matView, &matProj, (D3DXVECTOR3*)&g_vecLight );
   }
   g_pLightBloom->EndStep01( g_pD3D11User->m_D3DDeviceContext );

   pRTView[0] = g_pD3D11User->m_RenderTargetView;
   pRTView[1] = nullptr;

   // レンダーターゲットサーフェスを戻す
   g_pD3D11User->m_D3DDeviceContext->OMSetRenderTargets( 2, pRTView, g_pD3D11User->m_DepthStencilView );

   ID3D11ShaderResourceView* pSRV[1] = { nullptr };

   // シェーダーリソースビューを作成
   pSRV[0] = g_pD3D11User->GetSRViewFromRTView( g_pRTView[0] );

   // *****************************************************************************************************************
   // MGFの描画
   // *****************************************************************************************************************

   hr = g_pLightBloom->RenderStep02( g_pD3D11User->m_D3DDeviceContext, pSRV, 0.05f );
   if( FAILED( hr ) )
      goto EXIT;

   for( int i=0; i<_countof( pSRV ); i++ )
      SAFE_RELEASE( pSRV[i] );

   // *****************************************************************************************************************
   // HDRマップの合成
   // *****************************************************************************************************************

   hr = g_pLightBloom->RenderStep03( g_pD3D11User->m_D3DDeviceContext );
   if( FAILED( hr ) )
      goto EXIT;

   if( g_pDebugFontUser )
   {
      // デバッグ専用フォント描画
      hr = g_pDebugFontUser->RenderFPS( g_pD3D11User->m_D3DDeviceContext, 0, 0 );
      if( FAILED( hr ) )
         goto EXIT;
   }

   // レンダリングされたイメージをユーザーに表示。
   hr = g_pD3D11User->m_SwapChain->Present( 0, 0 );
   if( FAILED( hr ) )
      goto EXIT;

   if( ScreenShot )
   {
      // スクリーンショット作成
      hr = g_pD3D11User->CreateScreenShot();
      if( FAILED( hr ) )
         goto EXIT;
      ScreenShot = false;
   }

   hr = S_OK;

EXIT:
   return hr;
}

// 節電処理および描画処理
HRESULT PowerSavingAndRender()
{
   HRESULT hr = E_FAIL;

   switch( StandBy )
   {
   // スタンバイモード
   case  true:
      // テストのみ行い、描画処理は行わない。
      hr = g_pD3D11User->m_SwapChain->Present( 0, DXGI_PRESENT_TEST );
      switch( hr )
      {
      // いまだスタンバイ中。。。
      case DXGI_STATUS_OCCLUDED:
         // 電源管理によるスリープ状態の場合ここにくる。
         // フルスクリーンモード時にスクリーンセーバーが起動時した場合は、表示モードが強制的にウィンドウモードに変更されるためここにこない。
         goto EXIT;
         break;
      case S_OK:
         // フルスクリーンモード時にスクリーンセーバーが起動時した場合は表示モードが強制的にウィンドウモードに変更される。
         // ウィンドウモードの場合スタンバイから復帰してしまうため、ウィンドウがアクティブになったときに復帰するようにする。
         if( Activate == true )
         {
            // たまにウィンドウが表示されないときがあるので表示するようにする
            ::ShowWindow( g_pD3D11User->m_hWnd, SW_SHOW );
            StandBy = false;
         }
         break;
      default:
         goto EXIT;
         break;
      }
      break;
   // スタンバイモードでない
   case false:
      // 描画処理
      hr = Render();
      if( FAILED( hr ) ) goto EXIT;

      switch( hr )
      {
      case DXGI_STATUS_OCCLUDED:
         // スタンバイモードへ移行
         // フルスクリーンモード時のスクリーンセーバー起動時、
         // スリープ状態に移行した時に発生する。
         StandBy = true;
         goto EXIT;
         break;
      case S_OK:
         break;
      default:
         goto EXIT;
         break;
      }
      break;
   }

   hr = S_OK;

EXIT:

   return hr;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam )
{
   switch( msg )
   {
   case WM_KEYDOWN:
      g_KeyBuffer[wParam] = 1;
      break;

   case WM_KEYUP:
      g_KeyBuffer[wParam] = 0;

      // アプリ終了
      switch( wParam )
      {
      case VK_ESCAPE:
         ::DestroyWindow( hWnd );
         break;

      // F2キーを押すと、ウィンドウモードを切り替える。
      // 自動的にウィンドウモードを切り替える機能もあるが、ウィンドウスタイルを自由に変更するために自分で実装することにした。
      case VK_F2:
         g_pD3D11User->ChangeWindowMode();
         break;

      // スクリーンショットを作成する
      case VK_SNAPSHOT:
         ScreenShot = true;
         break;
      }
      break;

   case WM_ACTIVATE:
      Activate = true;
      break;

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

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

   return 0L;
}

// メイン関数
int APIENTRY _tWinMain( HINSTANCE hInstance,
                        HINSTANCE,
                        LPTSTR,
                        INT )
{
   HRESULT hr = E_FAIL;
   MSG msg;
   ::ZeroMemory(&msg, sizeof(MSG));

   // メモリリーク検出
   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_EVERY_1024_DF);

   // 表示モードを記述するための構造体。
   DXGI_MODE_DESC sd;

   // Direct3D 関連自作クラスのインスタンスを作成
   g_pD3D11User = NEW D3D11USER();

   // ディスプレイモード一覧を取得する。
   // 取得した値はクラス内部に保持される。
   hr = g_pD3D11User->GetDisplayMode();
   if( FAILED( hr ) )
   {
      ::MessageBox( nullptr, _T("ディスプレイモード取得エラー"), _T("初期化エラー"), MB_OK );
      goto EXIT;
   }
   // とりあえず最初に見つかったディスプレイモードを選択する
   CopyMemory( &sd, &g_pD3D11User->m_DisplayModeDesc[0], sizeof( DXGI_MODE_DESC ) );

   // ウィンドウの作成およびDirect3D の初期化
   // マルチサンプルを無効にする
   hr = g_pD3D11User->InitD3D11( AppName, hInstance, WndProc, &sd, TRUE, TRUE, FALSE, TRUE );
   if( FAILED( hr ) )
   {
      ::MessageBox( nullptr, _T("Direct3D 11.0 初期化エラー"), _T("初期化エラー"), MB_OK );
      goto EXIT;
   }

   // リソースの初期化
   hr = Init();
   if( FAILED( hr ) )
   {
      ::MessageBox( nullptr, _T("リソース初期化エラー"), _T("初期化エラー"), MB_OK );
      goto EXIT;
   }
   
   ::ShowWindow(g_pD3D11User->m_hWnd, SW_SHOW);
   ::UpdateWindow(g_pD3D11User->m_hWnd);

   // メッセージループ
   do
   { 
      if( ::PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
      {
         ::TranslateMessage(&msg); 
         ::DispatchMessage(&msg); 
      }
      else
      {
         hr = PowerSavingAndRender();
         if( FAILED( hr ) )
            ::DestroyWindow( g_pD3D11User->m_hWnd );
      }
   }while( msg.message != WM_QUIT );

EXIT:
   if( g_pD3D11User && g_pD3D11User->m_hWnd )
      ::DestroyWindow( g_pD3D11User->m_hWnd );

   ::UnregisterClass( AppName, hInstance );

   return msg.wParam;
}

今回はここまで

そういえば FBX SDK ですが 2013.2 にバージョンアップされています。 そのまま使用できそうならバージョンアップしようかと思いましたが大量にエラーが発生したのでやめました。 ダウンロードサイトに過去バージョンがアップされていないようなので気が向いたら対応するかも。


web拍手 by FC2

Prev Top Next

inserted by FC2 system