Microsoft Visual Express 2013 for Desktop C++
 Direct3D 11.0( SM 5.0 )
 DirectXTex texture processing library
 XMLLite

■Direct3D11 シャドウマッピング Top Next
関連ページ:なし


今回は既出のシャドウマッピングをやります。シャドウマッピングはより高性能のアルゴリズムがいくつか公開されていますが、よくわからないのでもっとも単純なシャドウマッピングをやります。 そういうわけですので参考にする価値はないでしょう(笑)。

次にVisual Studioのバージョンを Microsoft Visual C++ 2013 Express にアップします。 そのため、DirectX SDK が Microsoft Visual C++ 2012 Express に含まれるようになったのでインクルードとライブラリのパスが変わります。
これまで使用していた単体版DirectX SDKは使用しませんのでパスは指定しないでください。
ついでに Direct3D 自作ライブラリを大幅に修正します。っていうか作り直しました。今まで使ってたクラスはいっさい使いません。 Direct3D に関しては簡略化のために必須ではない処理は削除しました。したがってウィンドウモード⇔フルスクリーンモードの切り替えや省電力モードからの復帰処理などは削除しました。

またDirect3D エクステンションの廃止に伴い、行列やベクトルなどの算術ライブラリが使用できなくなりました。 当サイトでは楽するために既製品のXNAMathライブラリを使用します。
オープンソースでの提供となるので、DirectXTex texture processing libraryからソースをダウンロードしてください。
なおDirect3D エクステンションとXNAMathライブラリの対応表がLiving without D3DXで公開されています。 新 masafumi's Diary様のサイトで知りました。感謝です。

解凍後、DirectXTex/XNAMath配下のファイル一式を、Common/Headerフォルダ配下にコピーしてください。
Commonフォルダは当サイトで使用する自作の共通モジュールが格納されているフォルダです。


@Direct3D 自作の共通ライブラリです。
UCommon.h 共通で使用するヘッダファイル
UException.h 例外処理クラスのヘッダファイル
UDirect3D11.h Direct3Dクラスのヘッダーファイル。
レンダーターゲットビュー、深度ステンシルビュー、アンオーダードアクセスビュー、
およびシェーダーリソースビューを作成するための関数のヘッダーファイル。
UDirect3D11.cpp Direct3Dクラスのソースファイル。
レンダーターゲットビュー、深度ステンシルビュー、アンオーダードアクセスビュー、
およびシェーダーリソースビューを作成するための関数のソースファイル。
UGraphicsPipeline.h グラフィックパイプラインクラスのヘッダーファイル
UGraphicsPipeline.cpp グラフィックパイプラインクラスのソースファイル
UDebugFont.h デバッグ用のテキストを画面上に表示するためのクラスのヘッダファイル。
UDebugFont.cpp デバッグ用のテキストを画面上に表示するためのクラスのソースファイル。
UXMLLoader.h XMLローダークラスのヘッダファイル。
UXMLLoader.cpp XMLローダークラスのソースファイル。daeファイルの読み込みで使用。
UColladaLoader.h daeファイルローダーに特化したクラスのヘッダファイル。
UColladaLoader.cpp daeファイルローダーに特化したクラスのソースファイル。
UD3DMeshDataCreater.h daeファイルからロードしたデータをDirect3Dで扱うデータ形式にコンバートするクラスのヘッダファイル。
UD3DMeshDataCreater.cpp daeファイルからロードしたデータをDirect3Dで扱うデータ形式にコンバートするクラスのソースファイル。
USRViewRenderer.h レンダーターゲットサーフェスへの出力内容を確認するためのデバック用クラスのヘッダファイル。
USRViewRenderer.cpp レンダーターゲットサーフェスへの出力内容を確認するためのデバック用クラスのソースファイル。

Aシェーダー系で使用するソースです。
ShadowMapping_Pass0.hlsl シャドウマッピングのPass0のhlslファイル
ShadowMapping_Pass1.hlsl シャドウマッピングのPass1のhlslファイル
ShadowMapping.h シャドウマッピングクラスのヘッダーファイル
ShadowMapping.cpp シャドウマッピングクラスのソースファイル

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

---UCommon.h---  ↑


#ifndef UCOMMON_H
#define UCOMMON_H

// 拡張機能が使用されています : 右辺値のクラスが左辺値に使用されます。このワーニングを抑制する。
#pragma warning(disable: 4238)

// XMMatrixTranspose()でエラーになるのでSIMD命令セット使わないようにする
#define _XM_NO_INTRINSICS_

#include <windows.h>
#include <tchar.h>
#include <memory>
#include <mmsystem.h>  // timeGetTime()

#pragma comment( lib, "winmm.lib" )   // timeGetTime()

// メモリリーク発生時にデバッガに出力する内容をわかりやすくする
#if defined(DEBUG) || defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC                            // mallocによるメモリリーク検出でCPPファイル名と行数出力指定
#define NEW  new(_NORMAL_BLOCK, __FILE__, __LINE__)  // new によるメモリリーク検出でCPPファイル名と行数出力指定
#else
#define NEW  new
#endif

// メモリ解放
#define SAFE_RELEASE(x) if( x != nullptr ){ x->Release(); x = nullptr; }
#define SAFE_DELETE(x)  if( x != nullptr ){ delete x;  x = nullptr; }
#define SAFE_DELETE_ARRAY(x)  if( x != nullptr ){ delete[] x;  x = nullptr; }
#define SAFE_FREE(x)  if( x != nullptr ){ free( x );  x = nullptr; }

#endif

共通で使用するヘッダーファイルです。

---UException.h---  ↑


#ifndef UEXCEPTION_H
#define UEXCEPTION_H

#include <windows.h>
#include <tchar.h>

class UException
{
public:
   TCHAR m_pErrorStr[1024];

   UException( HRESULT hr, TCHAR* pMsg )
   {
      _stprintf_s( m_pErrorStr, _T("■□■HRESULT:0x%x [ %s ]\n"), hr, pMsg );

#if defined(DEBUG) || defined(_DEBUG)
      // エラーをデバッガに出力
      OutputDebugString( m_pErrorStr );
#endif
   }
};

#endif

カスタム例外処理です。

---UDirect3D11.h---  ↑


#ifndef UDIRECT3D11_H
#define UDIRECT3D11_H

// インクルード
#include "UCommon.h"
#include <d3d11.h>
#include "UException.h"

// xnamath算術ライブラリ
#include "XNAMath/xnamath.h"

// ライブラリの追加
#pragma comment( lib, "dxguid.lib" )
#pragma comment( lib, "d3d11.lib" )
#pragma comment( lib, "dxgi.lib" )
#pragma comment( lib, "d3dcompiler.lib" )  // hlsl をコンパイルする

#define UD3D11_FORMAT        DXGI_FORMAT_R8G8B8A8_UNORM

// 深度ステンシルビューとシェーダーリソースビューのどちらとしても使用できるようにするため型を指定しない
// フォーマットについてはDXGI_FORMAT参照
#define UD3D11_DEPTH_FORMAT  DXGI_FORMAT_R32_TYPELESS

#define DDS_MAGIC 0x20534444 // "DDS "

#define DDS_HEADER_FLAGS_TEXTURE        0x00001007  // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT 
#define DDS_HEADER_FLAGS_MIPMAP         0x00020000  // DDSD_MIPMAPCOUNT
#define DDS_HEADER_FLAGS_VOLUME         0x00800000  // DDSD_DEPTH
#define DDS_HEADER_FLAGS_PITCH          0x00000008  // DDSD_PITCH
#define DDS_HEADER_FLAGS_LINEARSIZE     0x00080000  // DDSD_LINEARSIZE

#define DDS_FOURCC      0x00000004  // DDPF_FOURCC
#define DDS_RGB         0x00000040  // DDPF_RGB
#define DDS_RGBA        0x00000041  // DDPF_RGB | DDPF_ALPHAPIXELS
#define DDS_LUMINANCE   0x00020000  // DDPF_LUMINANCE
#define DDS_ALPHA       0x00000002  // DDPF_ALPHA

class UMaps
{
private:
   struct DDS_PIXELFORMAT
   {
      DWORD dwSize;
      DWORD dwFlags;
      DWORD dwFourCC;
      DWORD dwRGBBitCount;
      DWORD dwRBitMask;
      DWORD dwGBitMask;
      DWORD dwBBitMask;
      DWORD dwABitMask;
   };

   typedef struct
   {
      DWORD dwSize;
      DWORD dwHeaderFlags;
      DWORD dwHeight;
      DWORD dwWidth;
      DWORD dwPitchOrLinearSize;
      DWORD dwDepth;
      DWORD dwMipMapCount;
      DWORD dwReserved1[11];
      DDS_PIXELFORMAT ddspf;
      DWORD dwSurfaceFlags;
      DWORD dwCubemapFlags;
      DWORD dwReserved2[3];
   } DDS_HEADER;

   UMaps();
   bool static IsBitMask(DDS_HEADER* pHeader, DWORD r, DWORD g, DWORD b, DWORD a);

public:
   // DDSファイルをロードしてテクスチャーを作成する
   // R8G8B8A8またはR8G8B8X8フォーマットのみでミップマップは1のみ、ボリュームテクスチャーとキューブマップと圧縮フォーマットは未対応
   void static CreateSRViewFromDDSFile( ID3D11Device* pD3DDevice, const WCHAR* szFileName, ID3D11ShaderResourceView** ppSRV );

   // レンダーターゲットビューを作成する
   void static CreateRenderTargetView( ID3D11Device* pD3DDevice,
                                       DXGI_FORMAT format, UINT Width, UINT Height,
                                       ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView,
                                       UINT ArraySize = 1,
                                       UINT MipmapCount = 1 );

   // ボリュームテクスチャー用のレンダーターゲットビューを作成する
   void static CreateRenderTargetViewOfVolumeTexture( ID3D11Device* pD3DDevice,
                                                      DXGI_FORMAT format, UINT Width, UINT Height, UINT Depth,
                                                      ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView );

   // レンダーターゲットビューからシェーダーリソースビューを作成する
   void static CreateSRViewFromRTView( ID3D11Device* pD3DDevice, ID3D11RenderTargetView* pRTView, ID3D11ShaderResourceView** ppSRView );

   // アンオーダードアクセスビューを作成する
   void static CreateRenderTargetViewOfRWTexture( ID3D11Device* pD3DDevice,
                                                  DXGI_FORMAT format, UINT Width, UINT Height,
                                                  ID3D11UnorderedAccessView** ppUAView, ID3D11ShaderResourceView** ppSRView,
                                                  UINT ArraySize = 1 );

   // アンオーダードアクセスビューからシェーダーリソースビューを作成する
   void static CreateSRViewFromUAView( ID3D11Device* pD3DDevice, ID3D11UnorderedAccessView* pUAView, ID3D11ShaderResourceView** ppSRView );

   // 深度ステンシルビューを作成する
   void static CreateDepthStencilView( ID3D11Device* pD3DDevice,
                                       UINT Width, UINT Height,
                                       ID3D11DepthStencilView** ppDSView, ID3D11ShaderResourceView** ppSRView,
                                       UINT ArraySize = 1 );

   // 深度ステンシルビューからシェーダーリソースビューを作成する
   void static CreateSRViewFromDSView( ID3D11Device* pD3DDevice, ID3D11DepthStencilView* pDSView, ID3D11ShaderResourceView** ppSRView );

   // ノイズマップを作成する
   void static CreateSRViewOfNoiseMap( ID3D11Device* pD3DDevice, UINT Width, UINT Height, DXGI_FORMAT format, ID3D11ShaderResourceView** ppSRView );
};

class UBuffers
{
private:
   UBuffers();
public:
   // バッファを作成する共通関数
   ID3D11Buffer static * CreateBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag, D3D11_BIND_FLAG BindFlag );

   // 頂点バッファを作成する
   inline ID3D11Buffer static * CreateVertexBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag )
   {
      return CreateBuffer( pD3DDevice, pData, size, CPUAccessFlag, D3D11_BIND_VERTEX_BUFFER );
   }

   // インデックスバッファを作成する
   inline ID3D11Buffer static * CreateIndexBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag )
   {
      return CreateBuffer( pD3DDevice, pData, size, CPUAccessFlag, D3D11_BIND_INDEX_BUFFER );
   }
};

class USamplers
{
private:
   USamplers();
public:
   // サンプラーステートを作成する
	ID3D11SamplerState static * CreateSamplerState(ID3D11Device* pD3DDevice,
	                                               D3D11_TEXTURE_ADDRESS_MODE TextureAddressMode,
	                                               D3D11_FILTER Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR,
	                                               D3D11_COMPARISON_FUNC = D3D11_COMPARISON_ALWAYS);
};

class UDirect3D11
{
public:
   HWND                    m_hWnd;
   ID3D11Device*           m_pD3DDevice;               // Direct3D11 デバイス。
   ID3D11DeviceContext*    m_pD3DDeviceContext;        // Direct3D11 デバイスコンテキスト。

private:
   IDXGIAdapter*           m_pAdapter;                 // アダプター
   IDXGISwapChain*         m_pSwapChain;               // スワップチェーン
   ID3D11RenderTargetView* m_pRenderTargetView;        // レンダリングターゲットビュー
   ID3D11DepthStencilView* m_pDepthStencilView;
   BOOL m_UseDepthBuffer, m_UseMultiSample;

   // アダプターを取得
   void CreateAdapter();

   // ウィンドウ作成
   void InitWindow( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode );

   // デバイスの作成
   void CreateDevice();

   // スワップチェーンの作成
   void CreateSwapChain( DXGI_MODE_DESC* pDisplayMode );

   // レンダリングターゲットビューの作成
   void CreateRenderTargetView();

   // 深度ステンシルビューの作成
   void CreateDepthStencilView();

   // ビューポートの作成
   void CreateViewport();

   // ウィンドウアソシエーション
   void SetWindowAssociation();

   // デフォルトのラスタライザを設定
   void SetDefaultRasterize();

   // デフォルトの深度ステンシルステートを設定
   void SetDefaultDepthStencilState();

public:
   UDirect3D11();
   virtual ~UDirect3D11();
   // メモリ解放
   void Invalidate();

   // ディスプレイモード一覧を作成
   void GetDisplayMode( DXGI_MODE_DESC* pModeDesc, UINT* pNum );

   // Direct3Dを作成する
   void CreateDirect3D11( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode,
                          BOOL UseMultisample, BOOL UseDepthBuffer );

   inline void ClearBackBuffer( const FLOAT ColorRGBA[4] )
   {
      m_pD3DDeviceContext->ClearRenderTargetView( m_pRenderTargetView, ColorRGBA );
   }
   inline void ClearDepthStencilView( UINT ClearFlags, FLOAT Depth, UINT8 Stencil )
   {
     if( m_pDepthStencilView ) m_pD3DDeviceContext->ClearDepthStencilView( m_pDepthStencilView, ClearFlags, Depth, Stencil );
   }

   HRESULT Present( UINT SyncInterval, UINT Flags );
};

#endif

Direct3Dの基本となるクラスのヘッダーファイルです。

---UDirect3D11.cpp---  ↑


#include "../../Header/Common/UDirect3D11.h"

bool UMaps::IsBitMask(DDS_HEADER* pHeader, DWORD r, DWORD g, DWORD b, DWORD a)
{
   return pHeader->ddspf.dwRBitMask == r && pHeader->ddspf.dwGBitMask == g && pHeader->ddspf.dwBBitMask == b && pHeader->ddspf.dwABitMask == a;
}

void UMaps::CreateSRViewFromDDSFile( ID3D11Device* pD3DDevice, const WCHAR* szFileName, ID3D11ShaderResourceView** ppSRV )
{
   HRESULT hr = E_FAIL;
   HANDLE hFile = nullptr;
   BYTE* pHeapData = nullptr;
   ID3D11Texture2D* pTex2D = nullptr;

   __try
   {
      // ファイルを開く
      hFile = ::CreateFile( szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr );
      if( INVALID_HANDLE_VALUE == hFile )
      {
         TCHAR errstr[1024];
         _stprintf_s(errstr, _T("LoadTextureDataFromFile()でエラーが発生しました。ファイルを開けません。 -> %s"), szFileName);
         throw(UException(HRESULT_FROM_WIN32(GetLastError()), errstr));
      }

      // ファイルのサイズを取得する
      LARGE_INTEGER FileSize = {0};
      ::GetFileSizeEx( hFile, &FileSize );

      // 32ビット符号なし整数を超えるサイズはエラーとして処理する
      if( FileSize.HighPart > 0 )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。32ビット符号なし整数を超えています。") ) );

      // ファイルサイズがヘッダー+マジックナンバーに満たない
      if( FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(DWORD)) )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ファイルサイズがヘッダー+マジックナンバーに満たない。") ) );

      // ヘッダー領域確保
      pHeapData = new BYTE[ FileSize.LowPart ];

      DWORD BytesRead = 0;

      // ファイルを読む
      if( !::ReadFile( hFile, pHeapData, FileSize.LowPart, &BytesRead, nullptr ) )
         throw( UException( HRESULT_FROM_WIN32( GetLastError() ), _T("LoadTextureDataFromFile()でエラーが発生しました。ファイルを読めません。") ) );

      // 読み込んだデータサイズが不正のためエラー
      if( BytesRead < FileSize.LowPart )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。読み込んだデータサイズが不正。") ) );

      // ファイルの先頭にあるマジックナンバーが 'DDS' 以外のときはファイルフォーマットが異なるためエラー
      DWORD dwMagicNumber = *(DWORD*)( pHeapData );
      if( dwMagicNumber != DDS_MAGIC )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。マジックナンバーが 'DDS' 以外。") ) );

      // ヘッダー領域のポインタを取得
      DDS_HEADER* pHeader = reinterpret_cast<DDS_HEADER*>( pHeapData + sizeof( DWORD ) );

      // サイズチェック
      if( pHeader->dwSize != sizeof(DDS_HEADER) || pHeader->ddspf.dwSize != sizeof(DDS_PIXELFORMAT) )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ヘッダ領域に設定されているサイズが不正。") ) );

      // RGBまたはRGBA の非圧縮フォーマット以外は未対応
      if( !(pHeader->ddspf.dwFlags & DDS_RGB ) )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。RGBまたはRGBAフォーマット以外は未対応。") ) );

      if( pHeader->dwHeaderFlags & DDS_HEADER_FLAGS_VOLUME )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ボリュームテクスチャーは未対応。") ) );

      if( pHeader->dwCubemapFlags != 0 )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。キューブマップは未対応。") ) );

      // マジックナンバー + ヘッダーサイズ
      INT offset = sizeof( DWORD ) + sizeof( DDS_HEADER );
      // データ領域の先頭ポインタを取得
      BYTE* pBitData = pHeapData + offset;

      UINT iWidth = pHeader->dwWidth;
      UINT iHeight = pHeader->dwHeight;
      UINT iMipCount = pHeader->dwMipMapCount;
      if( iMipCount == 0 )
         iMipCount = 1;
      else if( iMipCount > 1 )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。ミップマップは未対応。") ) );

      D3D11_TEXTURE2D_DESC desc = {0};

      desc.ArraySize = 1;

      if( pHeader->ddspf.dwRGBBitCount != 32 )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。32bitフォーマットのみ対応。") ) );

      // R8G8B8A8またはR8G8B8X8のみサポートする
      if( IsBitMask( pHeader, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 ) )
         desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
      else if( IsBitMask( pHeader, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 ) )
         desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
      else
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。不明なフォーマット。") ) );

      desc.Width = iWidth;
      desc.Height = iHeight;
      desc.MipLevels = iMipCount;
      desc.SampleDesc.Count = 1;
      desc.SampleDesc.Quality = 0;
      desc.Usage = D3D11_USAGE_DEFAULT;
      desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
      desc.CPUAccessFlags = 0;
      desc.MiscFlags = 0;

      D3D11_SUBRESOURCE_DATA InitData;

      // 最寄りのバイトに切り上げ
      UINT RowBytes = ( iWidth * 32 + 7 ) / 8;

      // データセット
      InitData.pSysMem = (void*)pBitData;
      // 1行当たりのバイト数
      InitData.SysMemPitch = RowBytes;

      if( FAILED( hr = pD3DDevice->CreateTexture2D( &desc, &InitData, &pTex2D ) ) )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。テクスチャーの作成に失敗した。") ) );

      D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
      ::ZeroMemory( &SRVDesc, sizeof( SRVDesc ) );
      SRVDesc.Format = desc.Format;
      SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
      SRVDesc.Texture2D.MipLevels = desc.MipLevels;
      if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pTex2D, &SRVDesc, ppSRV ) ) )
         throw( UException( -1, _T("LoadTextureDataFromFile()でエラーが発生しました。シェーダーリソースビューの作成に失敗した。") ) );
   }
   __finally
   {
      SAFE_RELEASE( pTex2D );
      SAFE_DELETE_ARRAY( pHeapData );

      if( hFile )
         ::CloseHandle( hFile );
   }
}

// レンダーターゲットビューを作成する
void UMaps::CreateRenderTargetView( ID3D11Device* pD3DDevice,
                                    DXGI_FORMAT format, UINT Width, UINT Height,
                                    ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView,
                                    UINT ArraySize,
                                    UINT MipmapCount )
{
   HRESULT hr = E_FAIL;
   ID3D11Texture2D* pTex2D = nullptr;

   __try
   {
      D3D11_TEXTURE2D_DESC Tex2DDesc;
      ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
      Tex2DDesc.ArraySize        = ArraySize;
      Tex2DDesc.BindFlags        = D3D11_BIND_RENDER_TARGET;
      if( ppSRView ) Tex2DDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
      Tex2DDesc.Usage            = D3D11_USAGE_DEFAULT;
      Tex2DDesc.Format           = format;
      Tex2DDesc.Width            = Width;
      Tex2DDesc.Height           = Height;
      Tex2DDesc.MipLevels        = MipmapCount;    // 最大ミップマップ数。0のときは完全なミップマップチェーンを作成する
      Tex2DDesc.SampleDesc.Count = 1;
      // 1以外の場合はID3D11DeviceContext::GenerateMips()によりミップマップチェーンを作成するためのフラグを設定する
      if (MipmapCount != 1)
         Tex2DDesc.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
      if( FAILED( hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, nullptr, &pTex2D ) ) )
         throw( UException( hr, _T("CreateRenderTargetView()でエラーが発生しました。テクスチャーが作成できません。") ) );

      if( FAILED( hr = pD3DDevice->CreateRenderTargetView( pTex2D, nullptr, ppRTView ) ) )
         throw( UException( hr, _T("CreateRenderTargetView()でエラーが発生しました。レンダーターゲットビューが作成できません。") ) );

      if( ppSRView != nullptr )
         UMaps::CreateSRViewFromRTView( pD3DDevice, *ppRTView, ppSRView );
   }
   __finally
   {
      SAFE_RELEASE( pTex2D );
   }
}

// ボリュームテクスチャー用のレンダーターゲットビューを作成する
void UMaps::CreateRenderTargetViewOfVolumeTexture( ID3D11Device* pD3DDevice,
                                                   DXGI_FORMAT format, UINT Width, UINT Height, UINT Depth,
                                                   ID3D11RenderTargetView** ppRTView, ID3D11ShaderResourceView** ppSRView )
{
   HRESULT hr = E_FAIL;
   ID3D11Texture3D* pTex3D = nullptr;

   __try
   {
      D3D11_TEXTURE3D_DESC Tex3DDesc;
      ::ZeroMemory( &Tex3DDesc, sizeof( D3D11_TEXTURE3D_DESC ) );
      Tex3DDesc.BindFlags        = D3D11_BIND_RENDER_TARGET;
      if( ppSRView ) Tex3DDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
      Tex3DDesc.Usage            = D3D11_USAGE_DEFAULT;
      Tex3DDesc.Format           = format;
      Tex3DDesc.Width            = Width;
      Tex3DDesc.Height           = Height;
      Tex3DDesc.Depth            = Depth;
      Tex3DDesc.MipLevels        = 1;
      if( FAILED( hr = pD3DDevice->CreateTexture3D( &Tex3DDesc, nullptr, &pTex3D ) ) )
         throw( UException( hr, _T("CreateRenderTargetViewOfVolumeTexture()でエラーが発生しました。テクスチャーが作成できません。") ) );

      if( FAILED( hr = pD3DDevice->CreateRenderTargetView( pTex3D, nullptr, ppRTView ) ) )
         throw( UException( hr, _T("CreateRenderTargetViewOfVolumeTexture()でエラーが発生しました。レンダーターゲットビューが作成できません。") ) );

      if( ppSRView != nullptr )
         UMaps::CreateSRViewFromRTView( pD3DDevice, *ppRTView, ppSRView );
   }
   __finally
   {
      SAFE_RELEASE( pTex3D );
   }
}

// レンダーターゲットビューからシェーダーリソースビューを作成する
void UMaps::CreateSRViewFromRTView( ID3D11Device* pD3DDevice, ID3D11RenderTargetView* pRTView, ID3D11ShaderResourceView** ppSRView )
{
   HRESULT hr = E_FAIL;
   ID3D11Resource* pResource = nullptr;

   __try
   {
      // レンダーターゲットビューからテクスチャーを取得する
      pRTView->GetResource( &pResource );

      // シェーダーリソースビューを作成する
      if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pResource, nullptr, ppSRView ) ) )
         throw( UException( hr, _T("CreateSRViewFromRTView()でエラーが発生しました。シェーダーリソースビューが作成できません。") ) );
   }
   __finally
   {
      SAFE_RELEASE( pResource );
   }
}

// アンオーダードアクセスビューを作成する
void UMaps::CreateRenderTargetViewOfRWTexture( ID3D11Device* pD3DDevice,
                                               DXGI_FORMAT format, UINT Width, UINT Height,
                                               ID3D11UnorderedAccessView** ppUAView, ID3D11ShaderResourceView** ppSRView,
                                               UINT ArraySize )
{
   HRESULT hr = E_FAIL;
   ID3D11Texture2D* pTex2D = nullptr;

   __try
   {
      D3D11_TEXTURE2D_DESC Tex2DDesc;
      ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
      Tex2DDesc.ArraySize        = ArraySize;
      Tex2DDesc.BindFlags        = D3D11_BIND_UNORDERED_ACCESS;
      if( ppSRView ) Tex2DDesc.BindFlags |= 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;
      if( FAILED( hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, nullptr, &pTex2D ) ) )
         throw( UException( hr, _T("CreateRenderTargetViewOfRWTexture()でエラーが発生しました。テクスチャーが作成できません。") ) );

      if( FAILED( hr = pD3DDevice->CreateUnorderedAccessView( pTex2D, nullptr, ppUAView ) ) )
         throw( UException( hr, _T("CreateRenderTargetViewOfRWTexture()でエラーが発生しました。アンオーダードアクセスビューが作成できません。") ) );

      if( ppSRView != nullptr )
         UMaps::CreateSRViewFromUAView( pD3DDevice, *ppUAView, ppSRView );
   }
   __finally
   {
      SAFE_RELEASE( pTex2D );
   }
}

// アンオーダードアクセスビューからシェーダーリソースビューを作成する
void UMaps::CreateSRViewFromUAView( ID3D11Device* pD3DDevice, ID3D11UnorderedAccessView* pUAView, ID3D11ShaderResourceView** ppSRView )
{
   HRESULT hr = E_FAIL;
   ID3D11Resource* pResource = nullptr;

   __try
   {
      // アンオーダードアクセスビューからテクスチャーを取得する
      pUAView->GetResource( &pResource );

      // シェーダーリソースビューを作成する
      if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pResource, nullptr, ppSRView ) ) )
         throw( UException( hr, _T("CreateSRViewFromUAView()でエラーが発生しました。シェーダーリソースビューが作成できません。") ) );
   }
   __finally
   {
      SAFE_RELEASE( pResource );
   }
}

// 深度ステンシルビューを作成する
void UMaps::CreateDepthStencilView( ID3D11Device* pD3DDevice,
                                    UINT Width, UINT Height,
                                    ID3D11DepthStencilView** ppDSView, ID3D11ShaderResourceView** ppSRView,
                                    UINT ArraySize )
{
   HRESULT hr = E_FAIL;
   ID3D11Texture2D* pTex2D = nullptr;

   __try
   {
      D3D11_TEXTURE2D_DESC Tex2DDesc;
      ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
      Tex2DDesc.ArraySize        = ArraySize;
      Tex2DDesc.BindFlags        = D3D11_BIND_DEPTH_STENCIL;
      if( ppSRView ) Tex2DDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
      Tex2DDesc.Usage            = D3D11_USAGE_DEFAULT;
      Tex2DDesc.Format           = DXGI_FORMAT_R32_TYPELESS;
      Tex2DDesc.Width            = Width;
      Tex2DDesc.Height           = Height;
      Tex2DDesc.MipLevels        = 1;
      Tex2DDesc.SampleDesc.Count = 1;

      // 深度バッファ用のテクスチャー作成
      hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, nullptr, &pTex2D );
      if( FAILED( hr ) )
         throw( UException( hr, _T("CreateDepthStencilView()でエラーが発生しました。深度バッファ用のテクスチャー作成エラーです。") ) );

      D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc;

      ::ZeroMemory( &DSVDesc, sizeof( D3D11_DEPTH_STENCIL_VIEW_DESC ) );

      // テクスチャー作成時に指定したフォーマットと互換性があり、深度ステンシルビューとして指定できるフォーマットを指定する
      switch( Tex2DDesc.Format )
      {
      case DXGI_FORMAT_R16_TYPELESS:
        DSVDesc.Format = DXGI_FORMAT_D16_UNORM;
        break;
      case DXGI_FORMAT_R32_TYPELESS:
        DSVDesc.Format = DXGI_FORMAT_D32_FLOAT;
        break;
      case DXGI_FORMAT_R24G8_TYPELESS:
        DSVDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
        break;
      default:
        DSVDesc.Format = DSVDesc.Format;
      }

      switch( ArraySize )
      {
      // 配列なし
      case 1:
         DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
         DSVDesc.Texture2D.MipSlice = 0;
         break;
      // 配列あり
      default:
         DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
         DSVDesc.Texture2DArray.ArraySize = ArraySize;
         DSVDesc.Texture2DArray.MipSlice = 0;
         DSVDesc.Texture2DArray.FirstArraySlice = 0;
         break;
      }
      // 深度ステンシルビューを作成
      hr = pD3DDevice->CreateDepthStencilView( pTex2D, &DSVDesc, ppDSView );
      if( FAILED( hr ) )
         throw( UException( hr, _T("CreateDepthStencilView()でエラーが発生しました。深度ステンシルビューが作成できません。") ) );

      if( ppSRView != nullptr )
         UMaps::CreateSRViewFromDSView( pD3DDevice, *ppDSView, ppSRView );
   }
   __finally
   {
      SAFE_RELEASE( pTex2D );
   }
}

// 深度ステンシルビューからシェーダーリソースビューを作成する
void UMaps::CreateSRViewFromDSView( ID3D11Device* pD3DDevice, ID3D11DepthStencilView* pDSView, ID3D11ShaderResourceView** ppSRView )
{
   HRESULT hr = E_FAIL;
   ID3D11Resource* pResource = nullptr;

   __try
   {
      D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc;
      pDSView->GetDesc( &DSVDesc );

      D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
      ::ZeroMemory( &SRVDesc, sizeof( D3D11_SHADER_RESOURCE_VIEW_DESC ) );

      switch( DSVDesc.ViewDimension )
      {
      case D3D11_DSV_DIMENSION_TEXTURE2D:
         SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
         SRVDesc.Texture2D.MipLevels = 1;
         break;
      case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
         SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY;
         SRVDesc.Texture2DArray.ArraySize = DSVDesc.Texture2DArray.ArraySize;
         SRVDesc.Texture2DArray.MipLevels = 1;
         break;
      }

      switch( DSVDesc.Format )
      {
      case DXGI_FORMAT_D16_UNORM:
        SRVDesc.Format = DXGI_FORMAT_R16_FLOAT;
        break;
      case DXGI_FORMAT_D32_FLOAT:
        SRVDesc.Format = DXGI_FORMAT_R32_FLOAT;
        break;
      case DXGI_FORMAT_D24_UNORM_S8_UINT:
        SRVDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
        break;
      default:
        SRVDesc.Format = DSVDesc.Format;
      }

      // 深度ステンシルビューからテクスチャーを取得する
      pDSView->GetResource( &pResource );

      // シェーダーリソースビューを作成する
      if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pResource, &SRVDesc, ppSRView ) ) )
         throw( UException( hr, _T("CreateSRViewFromDSView()でエラーが発生しました。シェーダーリソースビューが作成できません。") ) );
   }
   __finally
   {
      SAFE_RELEASE( pResource );
   }
}

// ノイズマップを作成する
void UMaps::CreateSRViewOfNoiseMap( ID3D11Device* pD3DDevice, UINT Width, UINT Height, DXGI_FORMAT format, ID3D11ShaderResourceView** ppSRView )
{
   HRESULT hr = E_FAIL;
   ID3D11Texture2D* pTexture2D = nullptr;
   float* pBits = nullptr;
   DWORD BitsCount = 0;

   __try
   {
      D3D11_SUBRESOURCE_DATA SubResourceData;
      ::ZeroMemory( &SubResourceData, sizeof( D3D11_SUBRESOURCE_DATA ) );

      switch( format )
      {
      case DXGI_FORMAT_R32_FLOAT:
         BitsCount = Width * Height;
         pBits = NEW float[ BitsCount ];
         for( DWORD i=0; i<BitsCount; i++ )
            pBits[i] = (float)( rand() % 255 ) / 254.0f;
         SubResourceData.pSysMem = (LPVOID)pBits;
         SubResourceData.SysMemPitch = Width * sizeof( float );
         break;

      case DXGI_FORMAT_R32G32B32A32_FLOAT:
         BitsCount = Width * Height * 4;
         pBits = NEW float[ BitsCount ];
         for( DWORD i=0; i<BitsCount; i++ )
            pBits[i] = (float)( rand() % 255 ) / 254.0f;
         SubResourceData.pSysMem = (LPVOID)pBits;
         SubResourceData.SysMemPitch = Width * sizeof( float ) * 4;
         break;
      default:
         throw( UException( hr, _T("CreateSRViewOfNoiseMap()でエラーが発生しました。未対応のフォーマットが指定されました。") ) );
         break;
      }

      D3D11_TEXTURE2D_DESC Tex2DDesc;
      ::ZeroMemory( &Tex2DDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
      Tex2DDesc.ArraySize        = 1;
      Tex2DDesc.BindFlags        = 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;

      // テクスチャー作成
      if( FAILED( hr = pD3DDevice->CreateTexture2D( &Tex2DDesc, &SubResourceData, &pTexture2D ) ) )
         throw( UException( hr, _T("CreateSRViewOfNoiseMap()でエラーが発生しました。テクスチャーの作成に失敗しました") ) );

      // シェーダーリソースビューを作成
      if( FAILED( hr = pD3DDevice->CreateShaderResourceView( pTexture2D, nullptr, ppSRView ) ) )
         throw( UException( hr, _T("CreateSRViewOfNoiseMap()でエラーが発生しました。シェーダーリソースビューの作成に失敗しました") ) );
    }
   __finally
   {
      SAFE_DELETE_ARRAY( pBits );
      SAFE_RELEASE( pTexture2D );
   }
}

// 頂点、インデックスバッファを作成する
ID3D11Buffer* UBuffers::CreateBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag, D3D11_BIND_FLAG BindFlag )
{
   HRESULT hr = E_FAIL;

   ID3D11Buffer* pBuffer = nullptr;

   // バッファー リソース。
   D3D11_BUFFER_DESC BufferDesc = { 0 };

   // サブリソース
   D3D11_SUBRESOURCE_DATA* resource = nullptr;

   D3D11_USAGE Usage = D3D11_USAGE_DEFAULT;
   UINT CPUAccessFlags = 0;

   __try
   {
      switch( CPUAccessFlag )
      {
      // CPUアクセスを許可しない
      case 0:
         Usage = D3D11_USAGE_DEFAULT;
         CPUAccessFlags = CPUAccessFlag;
         break;
      // CPUアクセスを許可する
      default:
         Usage = D3D11_USAGE_DYNAMIC;
         CPUAccessFlags = CPUAccessFlag;
         break;
      }

      // 初期値を設定する
      if( pData )
      {
         resource = new D3D11_SUBRESOURCE_DATA();
         resource->pSysMem = pData;
         resource->SysMemPitch = 0;
         resource->SysMemSlicePitch = 0;
      }

      // バッファの設定
      BufferDesc.ByteWidth             = size;                      // バッファサイズ
      BufferDesc.Usage                 = Usage;                     // リソース使用法を特定する
      switch( BindFlag )
      {
      case D3D11_BIND_STREAM_OUTPUT:
         BufferDesc.BindFlags          = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT;
         break;
      default:
         BufferDesc.BindFlags          = BindFlag;
         break;
      }
      BufferDesc.CPUAccessFlags        = CPUAccessFlags;            // CPU アクセス
      BufferDesc.MiscFlags             = 0;                         // その他のフラグも設定しない

      // バッファを作成する
      hr = pD3DDevice->CreateBuffer( &BufferDesc, resource, &pBuffer );
      if( FAILED( hr ) )
         throw( UException( hr, _T("CreateBuffer()でエラーが発生しました。バッファ作成エラーです。") ) );
   }
   __finally
   {
      SAFE_DELETE( resource );
   }

   return pBuffer;
}

// サンプラーステートを作成する
ID3D11SamplerState* USamplers::CreateSamplerState(ID3D11Device* pD3DDevice, D3D11_TEXTURE_ADDRESS_MODE TextureAddressMode, D3D11_FILTER Filter, D3D11_COMPARISON_FUNC ComparisonFunc)
{
    HRESULT hr = E_FAIL;
    ID3D11SamplerState* pSamplerState = nullptr;

    // サンプラーステートを作成する
    D3D11_SAMPLER_DESC samplerDesc;
    ::ZeroMemory(&samplerDesc, sizeof(D3D11_SAMPLER_DESC));

    samplerDesc.Filter = Filter;                           // サンプリング時に使用するフィルタ。
    samplerDesc.AddressU = TextureAddressMode;             // 0 〜 1 の範囲外にある u テクスチャー座標の描画方法
    samplerDesc.AddressV = TextureAddressMode;             // 0 〜 1 の範囲外にある v テクスチャー座標
    samplerDesc.AddressW = TextureAddressMode;             // 0 〜 1 の範囲外にある w テクスチャー座標
    samplerDesc.MipLODBias = 0;                            // 計算されたミップマップ レベルからのバイアス
    samplerDesc.MaxAnisotropy = 1;                         // サンプリングに異方性補間を使用している場合の限界値。有効な値は 1 〜 16 。
    samplerDesc.ComparisonFunc = ComparisonFunc;           // 比較オプション。
    samplerDesc.BorderColor[0] = 0;
    samplerDesc.BorderColor[1] = 0;
    samplerDesc.BorderColor[2] = 0;
    samplerDesc.BorderColor[3] = 0;
    samplerDesc.MinLOD = 0;                                // アクセス可能なミップマップの下限値
    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;                // アクセス可能なミップマップの上限値
    hr = pD3DDevice->CreateSamplerState(&samplerDesc, &pSamplerState);
    if (FAILED(hr))
       throw(UException(-1, _T("UIMesh;;CreateSamplerState()でエラーが発生しました。サンプラーステートを作成できません。")));

    return pSamplerState;
}

UDirect3D11::UDirect3D11()
{
   m_hWnd = nullptr;
   m_pD3DDevice = nullptr;
   m_pD3DDeviceContext = nullptr;
   m_pAdapter = nullptr;
   m_pSwapChain = nullptr;
   m_pRenderTargetView = nullptr;
   m_pDepthStencilView = nullptr;
   m_UseDepthBuffer = TRUE;
   m_UseMultiSample = TRUE;
}

UDirect3D11::~UDirect3D11()
{
   Invalidate();
}

// メモリ解放
void UDirect3D11::Invalidate()
{
   ULONG cnt;
   TCHAR s[256];

   if( m_pDepthStencilView )
   {
      cnt = m_pDepthStencilView->Release();
      if( cnt != 0 )
      {
         _stprintf_s( s, _T("■□■ID3D11DepthStencilViewの参照カウンタが不正です。:( %d )\n"), cnt );
         OutputDebugString( s );
      }
      m_pDepthStencilView = nullptr;
   }


   if( m_pRenderTargetView )
   {
      cnt = m_pRenderTargetView->Release();
      if( cnt != 0 )
      {
         _stprintf_s( s, _T("■□■m_pRenderTargetViewの参照カウンタが不正です。:( %d )\n"), cnt );
         OutputDebugString( s );
      }
      m_pRenderTargetView = nullptr;
   }

   if( m_pSwapChain )
   {
      // スワップ チェーンをフルスクリーン モードで解放できないことがあるらしい。
      // フルスクリーンの場合ウィンドウモードに切り替えてから解放する必要があるらしい。
      // DXGI の概要
      BOOL FullScreen;
      m_pSwapChain->GetFullscreenState( &FullScreen, nullptr );
      // フルスクリーンのとき
      if( FullScreen == TRUE )
         m_pSwapChain->SetFullscreenState( FALSE, nullptr );

      cnt = m_pSwapChain->Release();
      if( cnt != 0 )
      {
         _stprintf_s( s, _T("■□■m_pSwapChainの参照カウンタが不正です。:( %d )\n"), cnt );
         OutputDebugString( s );
      }
      m_pSwapChain = nullptr;
   }

   if( m_pD3DDeviceContext )
   {
      cnt = m_pD3DDeviceContext->Release();
      if( cnt != 0 )
      {
         _stprintf_s( s, _T("■□■m_pD3DDeviceContextの参照カウンタが不正です。:( %d )\n"), cnt );
       OutputDebugString( s );
      }
      m_pD3DDeviceContext = nullptr;
   }
   if( m_pD3DDevice )
   {
      cnt = m_pD3DDevice->Release();
      if( cnt != 0 )
      {
         _stprintf_s( s, _T("■□■m_pD3DDeviceの参照カウンタが不正です。:( %d )\n"), cnt );
         OutputDebugString( s );
      }
      m_pD3DDevice = nullptr;
   }

   if( m_pAdapter )
   {
      cnt = m_pAdapter->Release();
      if( cnt != 0 )
      {
         _stprintf_s( s, _T("■□■m_pAdapterの参照カウンタが不正です。:( %d )\n"), cnt );
         OutputDebugString( s );
      }
      m_pAdapter = nullptr;
   }
}

// デフォルトディスプレイのモードを列挙する
void UDirect3D11::GetDisplayMode(DXGI_MODE_DESC* pModeDesc, UINT* pNum)
{
   HRESULT hr = E_FAIL;
   IDXGIOutput* pOutput = nullptr;

   __try
   {
      // アダプターを取得。
      CreateAdapter();

      // アダプターに接続されているプライマリディスプレイを取得。
      hr = m_pAdapter->EnumOutputs( 0, &pOutput );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::GetDisplayMode()でエラーが発生しました。アダプターに接続されているプライマリディスプレイの取得に失敗しました。") ) );

      // ディスプレイモードの一覧を取得
      hr = pOutput->GetDisplayModeList( UD3D11_FORMAT, 0, pNum, pModeDesc );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::GetDisplayMode()でエラーが発生しました。ディスプレイモードの一覧の取得に失敗しました。") ) );

      if( pModeDesc == nullptr )
      {
         // 0 が返ることがあるか不明だが念のため
         if( *pNum == 0 )
            throw( UException( hr, _T("UDirect3D11::GetDisplayMode()でエラーが発生しました。ディスプレイモードが1つも取得できません。") ) );
      }
   }
   __finally
   {
      SAFE_RELEASE( pOutput );
   }
}

// デフォルトアダプターのインターフェースを作成する
// アダプターは1個に限定する
void UDirect3D11::CreateAdapter()
{
   HRESULT hr = E_FAIL;
   IDXGIFactory* pFactory = nullptr;

   if( m_pAdapter == nullptr )
   {
      __try
      {
        // ファクトリを作成する。
        hr = CreateDXGIFactory( __uuidof(IDXGIFactory), (void**)(&pFactory) );
        if( FAILED( hr ) )
           throw( UException( hr, _T("UDirect3D11::CreateAdapter()でエラーが発生しました。ファクトリの作成エラーです。") ) );

        // デフォルトアダプターを取得
        hr = pFactory->EnumAdapters( 0, &m_pAdapter );
        if( FAILED( hr ) )
           throw( UException( hr, _T("UDirect3D11::CreateAdapter()でエラーが発生しました。デフォルトアダプターの作成エラーです。") ) );
      }
      __finally
      {
         SAFE_RELEASE( pFactory );
      }
   }
}

// ウィンドウの作成 および Direct3Dの初期化
void UDirect3D11::CreateDirect3D11( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode,
                                     BOOL UseMultisample, BOOL UseDepthBuffer )
{
   m_UseMultiSample = UseMultisample;
   m_UseDepthBuffer = UseDepthBuffer;

   __try
   {
      // ウィンドウを作成
      InitWindow( AppName, hInstance, WndProc, pDisplayMode );

      // アダプターを取得。
      CreateAdapter();

      // デバイスの作成
      CreateDevice();

      // スワップチェーンの作成
      CreateSwapChain( pDisplayMode );

      // レンダリングターゲットビューの作成
      CreateRenderTargetView();

      // 深度ステンシルビューの作成
      CreateDepthStencilView();

      // レンダーターゲットビューの設定
      m_pD3DDeviceContext->OMSetRenderTargets( 1, &m_pRenderTargetView, m_pDepthStencilView );

      // ビューポート作成
      CreateViewport();

      // 表示モードの自動切換えを無効にする。
      // 自動切換えを有効にする場合はこの関数をコメントアウトする。
      // しかしコメントアウトした場合、初期起動をフルスクリーンモードにしたとき正しく動作してくれない。
      SetWindowAssociation();

      // デフォルトのラスタライザを設定する
      SetDefaultRasterize();

      // デフォルトの深度ステンシルステートを設定する
      SetDefaultDepthStencilState();
   }
   __finally
   {
      SAFE_RELEASE( m_pAdapter );
   }
}

// ウィンドウ作成
void UDirect3D11::InitWindow( TCHAR* AppName, HINSTANCE hInstance, WNDPROC WndProc, DXGI_MODE_DESC* pDisplayMode )
{
   // ウィンドウモード
   DWORD WindowStyle = WS_BORDER | WS_CAPTION | WS_SYSMENU;

   WNDCLASSEX wc;
   wc.cbSize        = sizeof(WNDCLASSEX);
   wc.style         = CS_VREDRAW | CS_HREDRAW;
   wc.lpfnWndProc   = WndProc;
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = sizeof(DWORD);
   wc.hCursor       = ::LoadCursor(nullptr, IDC_ARROW);
   wc.hIcon         = nullptr;
   wc.hIconSm       = nullptr;
   wc.lpszMenuName  = nullptr;
   wc.lpszClassName = AppName;
   wc.hbrBackground = (HBRUSH)::GetStockObject( BLACK_BRUSH );
   wc.hInstance     = hInstance;
   ::RegisterClassEx(&wc);

   RECT rc;
   ::SetRect( &rc, 0, 0, pDisplayMode->Width, pDisplayMode->Height );
   // ウィンドウモードのときタイトルバーを考慮して表示領域を設定するために必要なサイズを取得する
   ::AdjustWindowRect( &rc, WindowStyle, FALSE );

   // ウィンドウを作成
   m_hWnd = ::CreateWindow(
                           wc.lpszClassName,
                           wc.lpszClassName,
                           WindowStyle,
                           0,
                           0,
                           rc.right - rc.left,
                           rc.bottom - rc.top,
                           nullptr,
                           nullptr,
                           hInstance,
                           nullptr
                        );

   if( m_hWnd == nullptr )
      throw( UException( -1, _T("UDirect3D11::InitWindow()でエラーが発生しました。ウィンドウが作成できません。") ) );
}

// デバイスの作成
void UDirect3D11::CreateDevice()
{
   HRESULT hr = E_FAIL;

   // デバイス作成時に使用するビデオカードの性能一覧
   // Direct3D11.0の SM 5.0 のみサポートする
   D3D_FEATURE_LEVEL FeatureLevel[] =  {
                                          D3D_FEATURE_LEVEL_11_0,  // Direct3D 11.0 SM 5
                                       };

#if defined(DEBUG) || defined(_DEBUG)
   // デバッグコンパイルの場合、デバッグレイヤーを有効にする。
   // ソフトウェア レイヤー
   UINT createDeviceFlag = D3D11_CREATE_DEVICE_DEBUG;
#else
   UINT createDeviceFlag = 0;
#endif

   D3D_FEATURE_LEVEL level;
   // デバイスを作成する。
   hr = D3D11CreateDevice(
            m_pAdapter,                 // 使用するアダプターを設定。nullptrの場合はデフォルトのアダプター。
            D3D_DRIVER_TYPE_UNKNOWN,    // D3D_DRIVER_TYPEのいずれか。ドライバーの種類。pAdapterが nullptr 以外の場合は、D3D_DRIVER_TYPE_UNKNOWNを指定する。
            nullptr,                    // ソフトウェアラスタライザを実装するDLLへのハンドル。D3D_DRIVER_TYPE を D3D_DRIVER_TYPE_SOFTWARE に設定している場合は nullptr にできない。
            createDeviceFlag,           // D3D11_CREATE_DEVICE_FLAGの組み合わせ。デバイスを作成時に使用されるパラメータ。
            FeatureLevel,               // D3D_FEATURE_LEVELのポインタ
            1,                          // D3D_FEATURE_LEVEL配列の要素数
            D3D11_SDK_VERSION,          // DirectX SDKのバージョン。この値は固定。
            &m_pD3DDevice,              // 初期化されたデバイス
            &level,                     // 採用されたフィーチャーレベル
            &m_pD3DDeviceContext        // 初期化されたデバイスコンテキスト
                           );
   if( FAILED( hr ) )
      throw( UException( hr, _T("UDirect3D11::CreateDevice()でエラーが発生しました。デバイスの作成エラーです。") ) );

   // アダプターの情報を取得
   DXGI_ADAPTER_DESC desc;
   m_pAdapter->GetDesc( &desc );

   // DirectXのバージョン、シェーダモデルのバージョンと採用したアダプターの名前をデバックウィンドウに出力
   TCHAR s[256];
   _stprintf_s( s, _T("■□■デバイスの作成に成功!! Direct3D(11.0) SM(5) %s\n"), desc.Description );
   OutputDebugString( s );
}

// スワップチェーンの作成
void UDirect3D11::CreateSwapChain( DXGI_MODE_DESC* pDisplayMode )
{
   HRESULT hr = E_FAIL;
   TCHAR s[256];
   IDXGIFactory* pFactory = nullptr;
   DXGI_SWAP_CHAIN_DESC sd;

   __try
   {
      ::ZeroMemory( &sd, sizeof(sd) );
      ::CopyMemory( &(sd.BufferDesc), pDisplayMode, sizeof( DXGI_MODE_DESC ) );

      sd.BufferDesc.Format = UD3D11_FORMAT;                            // バックバッファフォーマット
      // バックバッファのサーフェス使用法および CPU アクセス オプションを表す DXGI_USAGE 列挙型のメンバー
      sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;                // バックバッファにレンダリング可能にする。
      // スワップ チェーンのバッファー数を表す値。
      sd.BufferCount = 1;
      // 出力ウィンドウへの HWND ハンドル。このメンバーを nullptr にはできない。
      sd.OutputWindow = m_hWnd;
      // 出力がウィンドウ モードの場合は TRUE。それ以外の場合は FALSE。
      // 初期起動時の表示モードはウィンドウモードに固定とする。
      sd.Windowed = TRUE;
      // サーフェスのスワップ処理後にバックバッファの内容を保持するか。
      sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;                        // バックバッファの内容を保持しない。
      // スワップ チェーンの動作のオプション。
      sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;               // フルスクリーンモードに切り替えると、アプリケーション ウィンドウのサイズに合わせて解像度が変更される。

      // ファクトリーを作成する
      // CreateDXGIFactoryで作成したファクトリーを使用すると実行できるがワーニングエラーになるので IDXGIAdapter から作成する。
      hr = m_pAdapter->GetParent( __uuidof(IDXGIFactory), (void**)&pFactory );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::CreateSwapChain()でエラーが発生しました。ファクトリーの取得エラーです。") ) );

      // マルチサンプリングの設定
      // マルチサンプルを使用しない場合の設定
      sd.SampleDesc.Count = 1;
      sd.SampleDesc.Quality = 0;

      int startMultisample;

      // サンプリング数が最大のものを採用する
      if( m_UseMultiSample == TRUE )
        startMultisample = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
      // マルチサンプルを無効にする。
      else
        startMultisample = 1;

      UINT Quality = 0;
      for( int i=startMultisample; i>=0; i-- )
      {
        // サポートするクォリティレベルの最大値を取得する
        hr = m_pD3DDevice->CheckMultisampleQualityLevels( pDisplayMode->Format, (UINT)i, &Quality );
        if( FAILED( hr ) )
           throw( UException( hr, _T("UDirect3D11::CreateSwapChain()でエラーが発生しました。サポートするクォリティレベルの最大値の取得エラーです。") ) );

        // 0 以外のときフォーマットとサンプリング数の組み合わせをサポートする
        // オンラインヘルプではCheckMultisampleQualityLevelsの戻り値が 0 のときサポートされないとかかれているが
        // pNumQualityLevels の戻り値が 0 かで判断する。
        // Direct3D 10 版 のオンラインヘルプにはそうかかれているので、オンラインヘルプの間違い。
        if( Quality != 0 )
        {
          sd.SampleDesc.Count = i;
          sd.SampleDesc.Quality = Quality - 1;

          // スワップチェーンを作成する。
          hr = pFactory->CreateSwapChain( m_pD3DDevice, &sd, &m_pSwapChain );
          _stprintf_s( s, _T("■□■マルチサンプル:Count(%d) Quality(%d)"), sd.SampleDesc.Count, sd.SampleDesc.Quality );
          if( SUCCEEDED( hr ) )
          {
             if( sd.SampleDesc.Count == 1 )
                m_UseMultiSample = FALSE;

             _tcscat_s( s, _T(" ⇒ OK\n") ); 
             OutputDebugString( s );
             break;
          }
          else
          {
             _tcscat_s( s, _T(" ⇒ NG\n") ); 
             OutputDebugString( s );
          }
        }
      }
      if( m_pSwapChain == nullptr )
        throw( UException( -1, _T("UDirect3D11::CreateSwapChain()でエラーが発生しました。スワップチェーンが作成できませんでした") ) );

      _stprintf_s( s, _T( "■□■ディスプレイモード:解像度( %d : %d ) リフレッシュレート( %d / %d )\n" ),
                     pDisplayMode->Width, pDisplayMode->Height,
                     pDisplayMode->RefreshRate.Denominator, pDisplayMode->RefreshRate.Numerator );
      OutputDebugString( s );
   }
   __finally
   {
      SAFE_RELEASE( pFactory );
   }
}

// レンダリングターゲットビューの作成
void UDirect3D11::CreateRenderTargetView()
{
   HRESULT hr = E_FAIL;
   ID3D11Texture2D* pBackBuffer = nullptr;

   __try
   {
      // スワップチェーンからバックバッファを取得する
      hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&pBackBuffer );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::CreateRenderTargetView()でエラーが発生しました。スワップチェーンからバックバッファの取得エラーです。") ) );

      // レンダリングターゲットビューの作成
      hr = m_pD3DDevice->CreateRenderTargetView( pBackBuffer, nullptr, &m_pRenderTargetView );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::CreateRenderTargetView()でエラーが発生しました。レンダリングターゲットビューの作成エラーです。") ) );
   }   
   __finally
   {
      SAFE_RELEASE( pBackBuffer );
   }
}

// 深度ステンシルビューの作成
void UDirect3D11::CreateDepthStencilView()
{
   HRESULT hr = E_FAIL;
   ID3D11Texture2D* pBackBuffer = nullptr;
   ID3D11Texture2D* pDepthBuffer = nullptr;
   D3D11_TEXTURE2D_DESC descDS;
   D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
   DXGI_SWAP_CHAIN_DESC chainDesc;

   if( m_UseDepthBuffer == FALSE )
      return;

   __try
   {
      // スワップチェーンの設定を取得する
      hr = m_pSwapChain->GetDesc( &chainDesc );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::CreateDepthStencilView()でエラーが発生しました。スワップチェーンの設定の取得エラーです。") ) );

      ::ZeroMemory( &descDS, sizeof( D3D11_TEXTURE2D_DESC ) );
      descDS.Width              = chainDesc.BufferDesc.Width;   // バックバッファと同じにする。
      descDS.Height             = chainDesc.BufferDesc.Height;  // バックバッファと同じにする。
      descDS.MipLevels          = 1;                            // ミップマップを作成しない
      descDS.ArraySize          = 1;                            // テクスチャーの配列数
      descDS.Format             = UD3D11_DEPTH_FORMAT;          // フォーマット
      descDS.SampleDesc.Count   = chainDesc.SampleDesc.Count;   // バックバッファと同じにする。
      descDS.SampleDesc.Quality = chainDesc.SampleDesc.Quality; // バックバッファと同じにする。
      descDS.Usage              = D3D11_USAGE_DEFAULT;          // GPU による読み取りおよび書き込みアクセスを必要とするリソース。
      descDS.BindFlags          = D3D11_BIND_DEPTH_STENCIL |    // 深度ステンシルバッファとして作成する
                                  D3D11_BIND_SHADER_RESOURCE;   // シェーダーリソースビューとして作成する
      descDS.CPUAccessFlags     = 0;                            // CPU アクセスが不要。
      descDS.MiscFlags          = 0;                            // その他のフラグも設定しない。
      // 深度バッファ用のテクスチャー作成
      hr = m_pD3DDevice->CreateTexture2D( &descDS, nullptr, &pDepthBuffer );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::CreateDepthStencilView()でエラーが発生しました。深度バッファ用のテクスチャー作成エラーです。") ) );

      ::ZeroMemory( &descDSV, sizeof( D3D11_DEPTH_STENCIL_VIEW_DESC ) );

      // テクスチャー作成時に指定したフォーマットと互換性があり、深度ステンシルビューとして指定できるフォーマットを指定する
      switch( descDS.Format )
      {
      // 8ビットフォーマットは使用できない?
      case DXGI_FORMAT_R8_TYPELESS:
        descDSV.Format = DXGI_FORMAT_R8_UNORM;
        break;
      case DXGI_FORMAT_R16_TYPELESS:
        descDSV.Format = DXGI_FORMAT_D16_UNORM;
        break;
      case DXGI_FORMAT_R32_TYPELESS:
        descDSV.Format = DXGI_FORMAT_D32_FLOAT;
        break;
      case DXGI_FORMAT_R24G8_TYPELESS:
        descDSV.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
        break;
      default:
        descDSV.Format = descDS.Format;
      }

      // マルチサンプルを使用している場合
      if( chainDesc.SampleDesc.Count > 1 )
         descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
      // マルチサンプルを使用していない場合
      else
         descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;

      descDSV.Texture2D.MipSlice = 0;

      // 深度ステンシルビューを作成
      hr = m_pD3DDevice->CreateDepthStencilView( pDepthBuffer, &descDSV, &m_pDepthStencilView );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::CreateDepthStencilView()でエラーが発生しました。深度ステンシルビューの作成エラーです。") ) );
   }
   __finally
   {
      SAFE_RELEASE( pDepthBuffer );
      SAFE_RELEASE( pBackBuffer );
   }
}

// ビューポートの作成
void UDirect3D11::CreateViewport()
{
   HRESULT hr = E_FAIL;

   DXGI_SWAP_CHAIN_DESC chainDesc;
   // スワップチェーンの設定を取得する
   hr = m_pSwapChain->GetDesc( &chainDesc );
   if( FAILED( hr ) ) 
      throw( UException( hr, _T("UDirect3D11::CreateViewport()でエラーが発生しました。スワップチェーンの設定の取得エラーです。") ) );

   D3D11_VIEWPORT Viewport[1];   
   Viewport[0].TopLeftX = 0;
   Viewport[0].TopLeftY = 0;
   Viewport[0].Width    = (FLOAT)chainDesc.BufferDesc.Width;
   Viewport[0].Height   = (FLOAT)chainDesc.BufferDesc.Height;
   Viewport[0].MinDepth = 0.0f;
   Viewport[0].MaxDepth = 1.0f;
   m_pD3DDeviceContext->RSSetViewports( 1, Viewport );
}

// ウィンドウアソシエーション
void UDirect3D11::SetWindowAssociation()
{
   HRESULT hr = E_FAIL;
   IDXGIFactory* pFactory = nullptr;

   __try
   {
      // ファクトリーを作成する
      // CreateDXGIFactoryで作成したファクトリーを使用すると実行できるがワーニングエラーになるので IDXGIAdapter から作成する。
      hr = m_pAdapter->GetParent( __uuidof(IDXGIFactory), (void**)&pFactory );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::SetWindowAssociation()でエラーが発生しました。ファクトリーの取得エラーです。") ) );
   
      // 表示モードの自動切換えを無効にする。
      hr = pFactory->MakeWindowAssociation( m_hWnd, DXGI_MWA_NO_WINDOW_CHANGES );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::SetWindowAssociation()でエラーが発生しました。ウィンドウアソシエーションの作成エラーです。") ) );
   }
   __finally
   {
      SAFE_RELEASE( pFactory );
   }
}

// デフォルトのラスタライザを設定
void UDirect3D11::SetDefaultRasterize()
{
   HRESULT hr = E_FAIL;
   ID3D11RasterizerState* g_pRasterState = nullptr;
   D3D11_RASTERIZER_DESC rsState;

   __try
   {
      rsState.FillMode = D3D11_FILL_SOLID;    // ポリゴン面描画
      rsState.CullMode = D3D11_CULL_BACK;     // 裏面を描画しない
      rsState.FrontCounterClockwise = TRUE;   // 反時計回りを表面
      rsState.DepthBias = 0;
      rsState.DepthBiasClamp = 0;
      rsState.SlopeScaledDepthBias = 0;
      rsState.DepthClipEnable = TRUE;
      rsState.ScissorEnable = FALSE;          // シザー矩形無効

      // スワップチェーンのマルチサンプリングの設定にあわせる
      DXGI_SWAP_CHAIN_DESC swapDesc;
      m_pSwapChain->GetDesc( &swapDesc );
      if( swapDesc.SampleDesc.Count != 1 )
        rsState.MultisampleEnable = TRUE;
      else
        rsState.MultisampleEnable = FALSE;

      rsState.AntialiasedLineEnable = FALSE;
      hr = m_pD3DDevice->CreateRasterizerState( &rsState, &g_pRasterState );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UDirect3D11::SetDefaultRasterize()でエラーが発生しました。ラスタライザステートの作成エラーです。") ) );

      m_pD3DDeviceContext->RSSetState( g_pRasterState );
   }
   __finally
   {
      SAFE_RELEASE( g_pRasterState );
   }
}

// デフォルトの深度ステンシルステートを設定
void UDirect3D11::SetDefaultDepthStencilState()
{
   HRESULT hr = E_FAIL;
   ID3D11DepthStencilState* pDepthStencilState = nullptr;
   D3D11_DEPTH_STENCIL_DESC dsState;

   __try
   {
      ::ZeroMemory( &dsState, sizeof( D3D11_DEPTH_STENCIL_DESC ) );
      dsState.DepthEnable = TRUE;
      dsState.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
      dsState.DepthFunc = D3D11_COMPARISON_LESS;
      dsState.StencilEnable = FALSE;

      hr = m_pD3DDevice->CreateDepthStencilState( &dsState, &pDepthStencilState );
      if( FAILED( hr ) ) 
         throw( UException( hr, _T("UDirect3D11::SetDefaultDepthStencilState()でエラーが発生しました。深度ステンシルステートの作成エラーです。") ) );

      m_pD3DDeviceContext->OMSetDepthStencilState( pDepthStencilState, 0 );
   }
   __finally
   {
      SAFE_RELEASE( pDepthStencilState );
   }
}

HRESULT UDirect3D11::Present( UINT SyncInterval, UINT Flags )
{
   HRESULT hr = E_FAIL;
   if( FAILED( hr = m_pSwapChain->Present( SyncInterval, Flags ) ) )
      throw( UException( hr, _T("UDirect3D11::Present()でエラーが発生しました。") ) );

   return hr;
}

当サイトでは例外処理が発生した後にリソースの解放を行うために、__finally句を使用しています。
finally句は他言語では標準で定義されていますが、実はC++には定義されていません。ここで使用しているものも実はWindows依存の拡張機能です。
本来こういったものは使用すべきではないのですが、自分はWindows専門ですし、エラー処理が楽ちんになるので使うことにします。

※と書きましたが、オブジェクト アンワインディングが必要な関数内で __try を使用できません。というエラーがうっとうしいのでそのうちやめるかも。

---UGraphicsPipeline.h---  ↑

#ifndef UGRAPHICS_PIPELINE_H
#define UGRAPHICS_PIPELINE_H

#include "UCommon.h"
#include <D3Dcompiler.h>
#include "UException.h"
#include "UDirect3D11.h"

class UGraphicsPipeline
{
private:
   // 入力レイアウト
   ID3D11InputLayout* m_pLayout;

   // 頂点シェーダー
   // とりあえずストリームアウトプットは考慮しない
   ID3D11VertexShader* m_pVertexShader;

   // ハルシェーダー
   ID3D11HullShader* m_pHullShader;

   // ドメインシェーダー
   ID3D11DomainShader* m_pDomainShader;

   // ジオメトリシェーダー
   ID3D11GeometryShader* m_pGeometryShader;

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

   // ラスタライザステート
   ID3D11RasterizerState* m_pRasterizerState;

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

   // ブレンドステート
   ID3D11BlendState* m_pBlendState;

public:
   enum class UEBLEND_STATE
   {
      NONE = 0,
      ADD = 1,
      ALIGNMENT = 2,
      DEPTH_TEST = 3,
   };

   enum class UEACCESS_FLAG
   {
      CPU_NONE_GPU_READWRITE = 0,   // CPUによるアクセスなし、GPUによる読込みと書込み.
      UPDATE_SUBRESOURCE = 1,       // ID3D11DeviceContext::UpdateSubresource()を使用してコピーを行う場合
      CPU_WRITE_GPU_READ = 2,       // CPUによる書込み、GPUによる読込み
   };

   UGraphicsPipeline();
   virtual ~UGraphicsPipeline();
   void Invalidate();

   // 頂点シェーダーをファイルから作成する
   void CreateVertexShaderFromFile( ID3D11Device* pD3DDevice,
                                    TCHAR pSrcFile[], CHAR pFunctionName[],
                                    D3D11_INPUT_ELEMENT_DESC pInputElementDescs[], UINT NumElements );

   // 頂点シェーダーをメモリから作成する
   void CreateVertexShaderFromMemory( ID3D11Device* pD3DDevice,
                                      BYTE* pShader, size_t size,
                                      D3D11_INPUT_ELEMENT_DESC pInputElementDescs[], UINT NumElements );

   // ハルシェーダーをファイルから作成する
   void CreateHullShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[]);

   // ハルシェーダーをメモリから作成する
   void CreateHullShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size);

   // ドメインシェーダーをファイルから作成する
   void CreateDomainShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[]);

   // ドメインシェーダーをメモリから作成する
   void CreateDomainShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size);

   // ジオメトリシェーダーをファイルから作成する
   void CreateGeometryShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[] );
   
   // ジオメトリシェーダーをメモリから作成する
   void CreateGeometryShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size );


   // ピクセルシェーダーをファイルから作成する
   void CreatePixelShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR pFunctionName[] );
   
   // ピクセルシェーダーをメモリから作成する
   void CreatePixelShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size );

   // ラスタライザステートを作成
   void CreateRasterizerState( ID3D11Device* pD3DDevice, D3D11_CULL_MODE CullMode, D3D11_FILL_MODE FillMode = D3D11_FILL_SOLID );

   // 深度ステンシルステートを作成
   void CreateDepthStencilState( ID3D11Device* pD3DDevice, BOOL DepthEnable, D3D11_DEPTH_WRITE_MASK DepthWriteEnabled, D3D11_COMPARISON_FUNC DepthFunc = D3D11_COMPARISON_LESS );

   // ブレンドステートを作成
   void CreateBlendState( ID3D11Device* pD3DDevice, UEBLEND_STATE* BlendStateType, UINT BlendStateTypeLength, BOOL AlphaToCoverageEnable = FALSE );

   // 定数バッファを作成する
   ID3D11Buffer* CreateConstantBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag );
   
   // 頂点シェーダーをデバイスに設定する
   inline void SetVertexShader( ID3D11DeviceContext* pD3DDeviceContext )
   {
      // 入力アセンブラー ステージを設定
      pD3DDeviceContext->IASetInputLayout( m_pLayout );
      // 頂点シェーダーをデバイスに設定する。
      pD3DDeviceContext->VSSetShader( m_pVertexShader, nullptr, 0 );
   }

   // ハルシェーダーをデバイスに設定する
   inline void SetHullShader( ID3D11DeviceContext* pD3DDeviceContext )
   {
      pD3DDeviceContext->HSSetShader( m_pHullShader, nullptr, 0 );
   }

   // ドメインシェーダーをデバイスに設定する
   inline void SetDomainShader( ID3D11DeviceContext* pD3DDeviceContext )
   {
      pD3DDeviceContext->DSSetShader( m_pDomainShader, nullptr, 0 );
   }

   // ジオメトリシェーダーをデバイスに設定する
   inline void SetGeometryShader( ID3D11DeviceContext* pD3DDeviceContext )
   {
      pD3DDeviceContext->GSSetShader( m_pGeometryShader, nullptr, 0 );
   }

   // ピクセルシェーダーをデバイスに設定する
   inline void SetPixelShader( ID3D11DeviceContext* pD3DDeviceContext )
   {
      pD3DDeviceContext->PSSetShader( m_pPixelShader, nullptr, 0 );
   }

   // ラスタライザステートをデバイスに設定する
   inline void SetRasterizerState( ID3D11DeviceContext* pD3DDeviceContext )
   {
      pD3DDeviceContext->RSSetState( m_pRasterizerState );
   }

   // 深度ステンシルステートをデバイスに設定する
   inline void SetDepthStencilState( ID3D11DeviceContext* pD3DDeviceContext )
   {
      pD3DDeviceContext->OMSetDepthStencilState( m_pDepthStencilState, 0 );
   }

   // ブレンドステートをデバイスに設定する
   inline void SetBlendState( ID3D11DeviceContext* pD3DDeviceContext )
   {
      pD3DDeviceContext->OMSetBlendState( m_pBlendState, nullptr, 0xffffffff );
   }
};

#endif

グラフィックパイプライン処理に関連する機能をもつクラスのヘッダファイルです。

---UGraphicsPipeline.cpp---  ↑


#include "../../Header/Common/UGraphicsPipeline.h"

UGraphicsPipeline::UGraphicsPipeline()
{
   m_pLayout = nullptr;
   m_pVertexShader = nullptr;
   m_pHullShader = nullptr;
   m_pDomainShader = nullptr;
   m_pGeometryShader = nullptr;
   m_pPixelShader = nullptr;
   m_pRasterizerState = nullptr;
   m_pDepthStencilState = nullptr;
   m_pBlendState = nullptr;
}

UGraphicsPipeline::~UGraphicsPipeline()
{
   Invalidate();
}

void UGraphicsPipeline::Invalidate()
{
   SAFE_RELEASE( m_pLayout );
   SAFE_RELEASE( m_pVertexShader );
   SAFE_RELEASE( m_pHullShader );
   SAFE_RELEASE( m_pDomainShader );
   SAFE_RELEASE( m_pGeometryShader );
   SAFE_RELEASE( m_pPixelShader );
   SAFE_RELEASE( m_pRasterizerState );
   SAFE_RELEASE( m_pDepthStencilState );
   SAFE_RELEASE( m_pBlendState );
}

// 頂点シェーダーをファイルから作成する
void UGraphicsPipeline::CreateVertexShaderFromFile( ID3D11Device* pD3DDevice,
                                                    TCHAR pSrcFile[], CHAR pFunctionName[],
                                                    D3D11_INPUT_ELEMENT_DESC pLayoutDesc[], UINT NumElements )
{
   HRESULT hr = E_FAIL;
   CHAR* Profile = "vs_5_0";

   ID3DBlob* pBlob = nullptr;

   // 行列を列優先で設定し、古い形式の記述を許可しないようにする
   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

   __try
   {
      // ファイルを元にエフェクトをコンパイルする
      if( FAILED( hr = D3DCompileFromFile( pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr ) ) )
      {
         TCHAR errstr[1024];
         _stprintf_s(errstr, _T("UGraphicsPipeline::CreateVertexShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile);
         throw(UException(hr, errstr));
      }

      // 頂点シェーダーをメモリから作成する
      CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), pLayoutDesc, NumElements );
   }
   __finally
   {
      SAFE_RELEASE( pBlob );
   }
}

// 頂点シェーダーをメモリから作成する
void UGraphicsPipeline::CreateVertexShaderFromMemory( ID3D11Device* pD3DDevice,
                                                       BYTE* pShader, size_t size,
                                                       D3D11_INPUT_ELEMENT_DESC m_pLayoutDesc[], UINT NumElements )
{
   HRESULT hr = E_FAIL;

   // コンパイル済みシェーダーから、頂点シェーダー オブジェクトを作成する
   if( FAILED( hr = pD3DDevice->CreateVertexShader( pShader, size, nullptr, &m_pVertexShader ) ) )
      throw( UException( hr, _T("UGraphicsPipeline::CreateVertexShaderFromMemory()でエラーが発生しました。頂点シェーダーの作成エラーです。") ) );

   // シェーダーで使用される入力バッファーを記述するための入力レイアウトオブジェクトを作成する。
   if( FAILED( hr = pD3DDevice->CreateInputLayout( m_pLayoutDesc, NumElements, pShader, size, &m_pLayout ) ) )
      throw( UException( hr, _T("UGraphicsPipeline::CreateVertexShaderFromMemory()でエラーが発生しました。入力レイアウトの作成エラーです。") ) );
}

// ハルシェーダーをファイルから作成する
void UGraphicsPipeline::CreateHullShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR  pFunctionName[])
{
   HRESULT hr = E_FAIL;
   CHAR* Profile = "hs_5_0";

   ID3DBlob* pBlob = nullptr;

   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

   __try
   {
      // ファイルを元にエフェクトをコンパイルする
      if (FAILED(hr = D3DCompileFromFile(pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr)))
      {
         TCHAR errstr[1024];
         _stprintf_s(errstr, _T("UGraphicsPipeline::CreateHullShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile);
         throw(UException(hr, errstr));
      }

      // ハルシェーダーをメモリから作成する
      CreateHullShaderFromMemory(pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize());
   }
   __finally
   {
      SAFE_RELEASE(pBlob);
   }
}

// ハルシェーダーをメモリから作成する
void UGraphicsPipeline::CreateHullShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size)
{
   HRESULT hr = E_FAIL;

   // コンパイル済みシェーダーから、ハルシェーダー オブジェクトを作成する
   if (FAILED(hr = pD3DDevice->CreateHullShader(pShader, size, nullptr, &m_pHullShader)))
      throw(UException(hr, _T("UGraphicsPipeline::CreateHullShaderFromMemory()でエラーが発生しました。ハルシェーダーの作成エラーです。")));
}
// ドメインシェーダーをファイルから作成する
void UGraphicsPipeline::CreateDomainShaderFromFile(ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR  pFunctionName[])
{
   HRESULT hr = E_FAIL;
   CHAR* Profile = "ds_5_0";

   ID3DBlob* pBlob = nullptr;

   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

   __try
   {
      // ファイルを元にエフェクトをコンパイルする
      if (FAILED(hr = D3DCompileFromFile(pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr)))
      {
         TCHAR errstr[1024];
         _stprintf_s(errstr, _T("UGraphicsPipeline::CreateDomainShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile);
         throw(UException(hr, errstr));
      }

      // ドメインシェーダーをメモリから作成する
      CreateDomainShaderFromMemory(pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize());
   }
   __finally
   {
      SAFE_RELEASE(pBlob);
   }
}

// ドメインシェーダーをメモリから作成する
void UGraphicsPipeline::CreateDomainShaderFromMemory(ID3D11Device* pD3DDevice, BYTE* pShader, size_t size)
{
   HRESULT hr = E_FAIL;

   // コンパイル済みシェーダーから、ドメインシェーダー オブジェクトを作成する
   if (FAILED(hr = pD3DDevice->CreateDomainShader(pShader, size, nullptr, &m_pDomainShader)))
      throw(UException(hr, _T("UGraphicsPipeline::CreateDomainShaderFromMemory()でエラーが発生しました。ドメインシェーダーの作成エラーです。")));
}

// ジオメトリシェーダーをファイルから作成する
void UGraphicsPipeline::CreateGeometryShaderFromFile( ID3D11Device* pD3DDevice, TCHAR pSrcFile[], CHAR  pFunctionName[] )
{
   HRESULT hr = E_FAIL;
   CHAR* Profile = "gs_5_0";

   ID3DBlob* pBlob = nullptr;

   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

   __try
   {
      // ファイルを元にエフェクトをコンパイルする
      if( FAILED( hr = D3DCompileFromFile( pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr ) ) )
      {
         TCHAR errstr[1024];
         _stprintf_s(errstr, _T("UGraphicsPipeline::CreateGeometryShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile);
         throw(UException(hr, errstr));
      }

      // ピクセルシェーダーをメモリから作成する
      CreateGeometryShaderFromMemory( pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize() );
   }
   __finally
   {
      SAFE_RELEASE( pBlob );
   }
}

// ジオメトリシェーダーをメモリから作成する
void UGraphicsPipeline::CreateGeometryShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size )
{
   HRESULT hr = E_FAIL;

   // コンパイル済みシェーダーから、ジオメトリシェーダー オブジェクトを作成する
   if( FAILED( hr = pD3DDevice->CreateGeometryShader( pShader, size, nullptr, &m_pGeometryShader ) ) )
      throw( UException( hr, _T("UGraphicsPipeline::CreateGeometryShaderFromMemory()でエラーが発生しました。ジオメトリシェーダーの作成エラーです。") ) );
}

// ピクセルシェーダーをファイルから作成する
void UGraphicsPipeline::CreatePixelShaderFromFile( ID3D11Device* pD3DDevice,
                                                    TCHAR pSrcFile[],
                                                    CHAR  pFunctionName[]
)
{
   HRESULT hr = E_FAIL;
   CHAR* Profile = "ps_5_0";

   ID3DBlob* pBlob = nullptr;

   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

   __try
   {
      // ファイルを元にエフェクトをコンパイルする
      if( FAILED( hr = D3DCompileFromFile( pSrcFile, nullptr, nullptr, pFunctionName, Profile, Flag1, 0, &pBlob, nullptr ) ) )
      {
         TCHAR errstr[1024];
         _stprintf_s(errstr, _T("UGraphicsPipeline::CreatePixelShaderFromFile()でエラーが発生しました。エフェクトファイルのコンパイルエラーです。 -> %s"), pSrcFile);
         throw(UException(hr, errstr));
      }

      // ピクセルシェーダーをメモリから作成する
      CreatePixelShaderFromMemory( pD3DDevice, (LPBYTE)pBlob->GetBufferPointer(), pBlob->GetBufferSize() );
   }
   __finally
   {
      SAFE_RELEASE( pBlob );
   }
}

// ピクセルシェーダーをメモリから作成する
void UGraphicsPipeline::CreatePixelShaderFromMemory( ID3D11Device* pD3DDevice, BYTE* pShader, size_t size )
{
   HRESULT hr = E_FAIL;

   // コンパイル済みシェーダーから、ピクセルシェーダー オブジェクトを作成する
   if( FAILED( hr = pD3DDevice->CreatePixelShader( pShader, size, nullptr, &m_pPixelShader ) ) )
      throw( UException( hr, _T("UGraphicsPipeline::CreatePixelShaderFromMemory()でエラーが発生しました。ピクセルシェーダーの作成エラーです。") ) );
}

// ラスタライザステートを作成
void UGraphicsPipeline::CreateRasterizerState( ID3D11Device* pD3D11Device, D3D11_CULL_MODE CullMode, D3D11_FILL_MODE FillMode )
{
   HRESULT hr;

   D3D11_RASTERIZER_DESC RasterizerDesc;

   ::ZeroMemory( &RasterizerDesc, sizeof( RasterizerDesc ) );
   RasterizerDesc.FillMode = FillMode;            // ポリゴン面描画
   RasterizerDesc.CullMode = CullMode;            // 指定の方向を向いている三角形をカリングする
   RasterizerDesc.FrontCounterClockwise = TRUE;   // 反時計回りを表面
   RasterizerDesc.DepthBias = 0;
   RasterizerDesc.DepthBiasClamp = 0;
   RasterizerDesc.SlopeScaledDepthBias = 0;
   RasterizerDesc.DepthClipEnable = TRUE;
   RasterizerDesc.ScissorEnable = FALSE;          // シザー矩形無効
   RasterizerDesc.MultisampleEnable = FALSE;
   RasterizerDesc.AntialiasedLineEnable = FALSE;

   SAFE_RELEASE( m_pRasterizerState );

   if( FAILED( hr = pD3D11Device->CreateRasterizerState( &RasterizerDesc, &m_pRasterizerState ) ) )
      throw( UException( hr, _T("UGraphicsPipeline::CreateRasterizerState()でエラーが発生しました。ID3D11RasterizerStateインターフェースの作成エラーです。") ) );
}

// 深度ステンシルステートを作成
void UGraphicsPipeline::CreateDepthStencilState( ID3D11Device* pD3DDevice, BOOL DepthEnable, D3D11_DEPTH_WRITE_MASK DepthWriteEnabled, D3D11_COMPARISON_FUNC DepthFunc )
{
   HRESULT hr;

   D3D11_DEPTH_STENCIL_DESC DSDesc;

   DSDesc.DepthEnable = DepthEnable;           // 深度テストを行うか
   DSDesc.DepthWriteMask = DepthWriteEnabled;  // 深度バッファへの書き込みを行うか
   DSDesc.DepthFunc = DepthFunc;
   DSDesc.StencilEnable = FALSE;

   SAFE_RELEASE( m_pDepthStencilState );

   if( FAILED( hr = pD3DDevice->CreateDepthStencilState( &DSDesc, &m_pDepthStencilState ) ) )
      throw( UException( hr, _T("UGraphicsPipeline::CreateDepthStencilState()でエラーが発生しました。ID3D11DepthStencilStateインターフェースの作成エラーです。") ) );
}

// ブレンドステートを作成
void UGraphicsPipeline::CreateBlendState( ID3D11Device* pD3DDevice, UEBLEND_STATE* BlendStateType, UINT BlendStateTypeLength, BOOL AlphaToCoverageEnable )
{
   HRESULT hr;
   D3D11_BLEND_DESC BlendDesc;

   if( BlendStateTypeLength == 0 || BlendStateTypeLength >= 8 )
      throw( UException( -1, _T("UGraphicsPipeline::CreateBlendState()でエラーが発生しました。仮引数が不正です。") ) );

   ::ZeroMemory( &BlendDesc, sizeof( BlendDesc ) );
   BlendDesc.AlphaToCoverageEnable = AlphaToCoverageEnable;

   if( BlendStateTypeLength == 1 )
      BlendDesc.IndependentBlendEnable = FALSE;
   else
      BlendDesc.IndependentBlendEnable = TRUE;

   for( UINT i=0; i<BlendStateTypeLength; i++ )
   {
      switch( BlendStateType[i] )
      {
     case UEBLEND_STATE::NONE:
         BlendDesc.RenderTarget[i].BlendEnable = FALSE;
         BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
         BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
         BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
         BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
         break;

     // 加算合成
      case UEBLEND_STATE::ADD:
         BlendDesc.RenderTarget[i].BlendEnable = TRUE;
         BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
         BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
         BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
         BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
         break;

     // 線形合成
     case UEBLEND_STATE::ALIGNMENT:
         BlendDesc.RenderTarget[i].BlendEnable = TRUE;
         BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_SRC_ALPHA;
         BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
         BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
         BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
         BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
         BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
         break;
         
     // 深度テスト
     case UEBLEND_STATE::DEPTH_TEST:
         BlendDesc.RenderTarget[i].BlendEnable = TRUE;
         BlendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_MIN;      // 最前面の深度値で上書きするために最小値を選択
         BlendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ONE;
         BlendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_MIN;
         BlendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
         break;
      }
   }

   SAFE_RELEASE( m_pBlendState );

   if( FAILED( hr = pD3DDevice->CreateBlendState( &BlendDesc, &m_pBlendState ) ) )
      throw( UException( hr, _T("UGraphicsPipeline::CreateBlendState()でエラーが発生しました。ID3D11BlendStateインターフェースの作成エラーです。") ) );
}

// 定数バッファを作成する
ID3D11Buffer* UGraphicsPipeline::CreateConstantBuffer( ID3D11Device* pD3DDevice, void* pData, size_t size, UINT CPUAccessFlag )
{
   HRESULT hr = E_FAIL;

   ID3D11Buffer* pBuffer = nullptr;

   // バッファー リソース。
   D3D11_BUFFER_DESC BufferDesc = { 0 };

   // サブリソース
   D3D11_SUBRESOURCE_DATA* resource = nullptr;

   D3D11_USAGE Usage = D3D11_USAGE_DEFAULT;
   UINT CPUAccessFlags = 0;

   __try
   {
      switch( CPUAccessFlag )
      {
      // CPUアクセスを許可しない
      case 0:
         Usage = D3D11_USAGE_DEFAULT;
         CPUAccessFlags = CPUAccessFlag;
         break;
      // CPUアクセスを許可する
      default:
         Usage = D3D11_USAGE_DYNAMIC;
         CPUAccessFlags = CPUAccessFlag;
         break;
      }

      // 初期値を設定する
      if( pData )
      {
         resource = new D3D11_SUBRESOURCE_DATA();
         resource->pSysMem = pData;
         resource->SysMemPitch = 0;
         resource->SysMemSlicePitch = 0;
      }

      // バッファの設定
      BufferDesc.ByteWidth             = size;                       // バッファサイズ
      BufferDesc.Usage                 = Usage;                      // リソース使用法を特定する
      BufferDesc.BindFlags             = D3D11_BIND_CONSTANT_BUFFER; // バッファの種類
      BufferDesc.CPUAccessFlags        = CPUAccessFlags;             // CPU アクセス
      BufferDesc.MiscFlags             = 0;                          // その他のフラグも設定しない

      // バッファを作成する
      hr = pD3DDevice->CreateBuffer( &BufferDesc, resource, &pBuffer );
      if( FAILED( hr ) )
         throw( UException( hr, _T("UGraphicsPipeline::CreateConstantBuffer()でエラーが発生しました。バッファ作成エラーです。") ) );
   }
   __finally
   {
      SAFE_DELETE( resource );
   }

   return pBuffer;
}

Direct3D エクステンションの廃止に伴い、D3DX11CreateShaderResourceViewFromFile()が使えなくなったので、自分で作成しました。
といっても実際にはMicrosoft DirectX SDK (June 2010) のサンプルソースを、基本パクってステップ数を減らすために機能制限しただけだったりします。
ですので、汎用的に使用できる機能が必要でしたら DirectX SDK (June 2010) のソースを使うなり、自分でコーディングするなりしてください。

ちなみにここで公開しているソースは R8G8B8A8 または R8G8B8X8 フォーマットのみサポートし、ミップマップ、キューブマップ、ボリュームマップ、圧縮フォーマットには対応していません。

---UDebugFont.h---  ↑


#ifndef UDRAWFONT_H
#define UDRAWFONT_H

#include "UCommon.h"
#include "UException.h"
#include "UGraphicsPipeline.h"
#include "UDirect3D11.h"
#include "../../HLSL/DebugFont_VS_Main.h"
#include "../../HLSL/DebugFont_PS_Main.h"

class UDebugFont
{
private:
   // 頂点定義
   typedef struct _VERTEX
   {
      XMFLOAT3 pos;     // 頂点の座標
      XMFLOAT2 texel;   // テクセル座標
   }VERTEX;

   // 定数バッファの定義
   typedef struct _CONSTANT_BUFFER
   {
      XMFLOAT2 Position;    // スクリーン座標系上での表示位置
      XMFLOAT2 TexelOffset; // テクスチャー上のテクセル位置を指定するオフセット値
      XMFLOAT4 Color;       // 頂点カラー

      _CONSTANT_BUFFER(){};
      _CONSTANT_BUFFER( XMFLOAT2 position, XMFLOAT2 texelOffset, XMFLOAT4 color )
      {
         ::CopyMemory( &Position, &position, sizeof( XMFLOAT2 ) );
         ::CopyMemory( &TexelOffset, &texelOffset, sizeof( XMFLOAT2 ) );
         ::CopyMemory( &Color, &color, sizeof( XMFLOAT4 ) );
      };
   }CONSTANT_BUFFER;

   // 頂点バッファ
   ID3D11Buffer* m_pVertexBuffer;

   // シェーダーリソースビュー
   ID3D11ShaderResourceView* m_pSRView;

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

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

   UGraphicsPipeline* m_pGraphicsPipeline;

   float m_FontWidth;   // ポリゴンの横幅
   float m_FontHeight;  // ポリゴンの縦幅
   static const int m_FontCnt = 95;     // テクスチャー上のフォント数

   TCHAR m_pStr[512];
   XMFLOAT2 m_Position;
   XMFLOAT4 m_Color;

public:
   UDebugFont();
   virtual ~UDebugFont();
   void Invalidate();

   // 作成処理
   // フォントサイズは、射影空間上での幅で指定する。1を指定するとスクリーンいっぱい分の大きさとなる
   // フォントサイズは作成時に設定した値を後で変更できない.
   void CreateMesh( ID3D11Device* pD3DDevice, float FontWidth, float FontHeight );

   // 文字は半角英数字と半角記号のみサポートする.それ以外の文字をパラメータに渡した場合の動作は保証しない.
   // 表示位置は射影空間上での座標で設定する
   void NextFrame( TCHAR* pStr, XMFLOAT2* pPosition, XMFLOAT4* pColor );

   // デバック用のテキストを描画する
   void Render( ID3D11DeviceContext* pD3DDeviceContext );
};


// **********************************************************************************
// FPS描画クラス
// **********************************************************************************

class UFPS : private UDebugFont
{
private:
   DWORD m_PrevTime;      // 前回時間
   WORD  m_FrameCounter;  // FPS合計数
   DWORD m_Frame;         // FPS計測値

public:
   UFPS();
   virtual ~UFPS();
   void Invalidate();
   void CreateMesh( ID3D11Device* pD3DDevice );
   void NextFrame();
   void Render( ID3D11DeviceContext* pD3DDeviceContext );
};

#endif

DDSファイルのフォント画像をテクスチャーとしてデバック用のテキストを画面上に表示します。デバック用なので日本語には対応していません。
シェーダーソースはコンパイル済みのバイナリデータを使用しています。
テクスチャーは過去記事にアップしてますので使いたい人は使ってください。

シェーダーソースはコンパイルしたバイナリデータをDebugFont_VS_Main.hとDebugFont_PS_Main.hに出力してインクルードしてください。

---UDebugFont.cpp---  ↑


#include "../../Header/Common/UDebugFont.h"

/*
cbuffer cbBuffer : register( b0 )
{
   // 表示位置とテクセルのオフセット値
   float4 g_Position    : packoffset( c0 );
   // 頂点カラー
   float4 g_Color       : packoffset( c1 );
};

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

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

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

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

// 頂点シェーダー
VS_OUT_PS_IN DebugFont_VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out;

   float3 v = In.pos + float3( g_Position.xy, 0 );
   Out.pos   = float4( v, 1 );
   Out.texel = In.texel + g_Position.zw;
   Out.color = g_Color;
   return Out;
}

// ピクセルシェーダ
float4 DebugFont_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET
{
   float4 col = g_Tex.Sample( g_Sampler, In.texel );
   return float4( col.rgb * In.color.rgb, col.a );
}
*/

UDebugFont::UDebugFont()
{
   m_pVertexBuffer = nullptr;
   m_pSRView = nullptr;
   m_pSamplerState = nullptr;
   m_pConstantBuffers = nullptr;
   m_pGraphicsPipeline = nullptr;
   m_pStr[0] = '\0';
}

UDebugFont::~UDebugFont()
{
   Invalidate();
}

void UDebugFont::Invalidate()
{
   m_pStr[0] = '\0';
   SAFE_DELETE( m_pGraphicsPipeline );
   SAFE_RELEASE( m_pSamplerState );
   SAFE_RELEASE( m_pSRView );
   SAFE_RELEASE( m_pVertexBuffer );
   SAFE_RELEASE( m_pConstantBuffers );
}

void UDebugFont::CreateMesh( ID3D11Device* pD3DDevice, float FontWidth, float FontHeight )
{
   D3D11_INPUT_ELEMENT_DESC layout[] = {
         { "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 },
   };

   m_pGraphicsPipeline = NEW UGraphicsPipeline();

   // シェーダーを作成する
   m_pGraphicsPipeline->CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)g_DebugFont_VS_Main, sizeof( g_DebugFont_VS_Main ), layout, _countof( layout ) );
   m_pGraphicsPipeline->CreatePixelShaderFromMemory(  pD3DDevice, (LPBYTE)g_DebugFont_PS_Main, sizeof( g_DebugFont_PS_Main ) );

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

   // 深度ステンシルステートを作成する
   m_pGraphicsPipeline->CreateDepthStencilState( pD3DDevice, FALSE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL );

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

   m_FontWidth  = FontWidth;             // ポリゴンの横幅
   m_FontHeight = FontHeight;            // ポリゴンの縦幅
   float TU = 1.0f / (float)m_FontCnt;   // 1フォント当たりのテクセルの横幅

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

   // デカールマップをロード
   UMaps::CreateSRViewFromDDSFile( pD3DDevice, _T("../Resource\\DebugFont.dds"), &m_pSRView );

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

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

void UDebugFont::NextFrame( TCHAR* pStr, XMFLOAT2* pPosition, XMFLOAT4* pColor )
{
   _tcscpy_s( m_pStr, pStr );
   ::CopyMemory( &m_Position, pPosition, sizeof( XMFLOAT2 ) );
   ::CopyMemory( &m_Color, pColor, sizeof( XMFLOAT4 ) );
}

void UDebugFont::Render( ID3D11DeviceContext* pD3DDeviceContext )
{
   HRESULT hr = E_FAIL;

   if (_tcsclen(m_pStr) == 0)
      return;

   XMFLOAT2 pos = m_Position;
   
   // 各種グラフィックパイプラインを設定
   m_pGraphicsPipeline->SetVertexShader( pD3DDeviceContext );
   m_pGraphicsPipeline->SetHullShader( pD3DDeviceContext );
   m_pGraphicsPipeline->SetDomainShader( pD3DDeviceContext );
   m_pGraphicsPipeline->SetGeometryShader( pD3DDeviceContext );
   m_pGraphicsPipeline->SetPixelShader( pD3DDeviceContext );
   m_pGraphicsPipeline->SetRasterizerState( pD3DDeviceContext );
   m_pGraphicsPipeline->SetDepthStencilState( pD3DDeviceContext );
   m_pGraphicsPipeline->SetBlendState( pD3DDeviceContext );

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

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

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

   // デカールマップを設定する
   pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView );

   D3D11_MAPPED_SUBRESOURCE mappedResource;
   UDebugFont::CONSTANT_BUFFER* cBuffer;

   // 文字数分ループ
   for( int i=0; i<(int)_tcsclen( m_pStr ); i++ )
   {
      if (m_pStr[i] == '\n')
      {
         pos.x = m_Position.x;
         pos.y -= m_FontHeight;
         continue;
      }

      if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) )
         throw( UException( hr, _T("UDebugFont::RenderDebugText()でエラーが発生しました。ロックできません") ) );

      cBuffer = (UDebugFont::CONSTANT_BUFFER*)(mappedResource.pData);

      // 表示位置
      ::CopyMemory( &cBuffer->Position, &pos, sizeof( XMFLOAT2 ) );

      // テクセル
      cBuffer->TexelOffset.x = (float)( m_pStr[i] - 32 ) / m_FontCnt; // TU
      cBuffer->TexelOffset.y = 0.0f;                                  // TV

      // 頂点カラー
      ::CopyMemory( &cBuffer->Color, &m_Color, sizeof( XMFLOAT4 ) );

      pD3DDeviceContext->Unmap( m_pConstantBuffers, 0 );

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

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

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

      pos.x += m_FontWidth;
   }
}


// **********************************************************************************
// FPS描画クラス
// **********************************************************************************

UFPS::UFPS()
{
   m_PrevTime = ::timeGetTime();
   m_FrameCounter = 0;
   m_Frame = 0;
}

UFPS::~UFPS()
{
   Invalidate();
}

void UFPS::Invalidate()
{
   UDebugFont::Invalidate();
}

void UFPS::CreateMesh( ID3D11Device* pD3DDevice )
{
   UDebugFont::CreateMesh( pD3DDevice, 0.03f, 0.08f );
}

void UFPS::NextFrame()
{
   DWORD now = ::timeGetTime();
   TCHAR fps[20];

   if( now - m_PrevTime > 1000 )
   {
      m_PrevTime = now;
      m_Frame = m_FrameCounter;
      m_FrameCounter = 0;
   }
   else
      m_FrameCounter++;

   _stprintf_s( fps, _T("FPS : %d"), m_Frame );

   UDebugFont::NextFrame( fps, &XMFLOAT2( -0.97f, 0.95f ), &XMFLOAT4( 1, 1, 1, 1 ) );
}

void UFPS::Render( ID3D11DeviceContext* pD3DDeviceContext )
{
   UDebugFont::Render( pD3DDeviceContext );
}

---UXMLLoader.h---  ↑


#ifndef XMLLOADER_H
#define XMLLOADER_H

#include <vector>
#include <string>
#include <shlwapi.h>

// XMLLiteを使うため
#include <xmllite.h>

#include "UCommon.h"
#include "UException.h"

#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "xmllite.lib")

class UXMLLoader
{
public:
   // IXmlReaderの内部文字コードがWCHARっぽいので合わせる
   typedef struct _XMLPATH
   {
      LPCWSTR pTagName;            // タグ名
      LPCWSTR pAttribute;          // 属性名
      LPCWSTR pAttributeValue;     // 属性値
   }XMLPATH;

private:
   IXmlReader* m_pReader;
   IStream* m_pStream;

   // xml を読み込む開始位置を先頭に移動する
   void MoveSeekTop();

   // ノード検索
   bool CheckNodeHit( XMLPATH* pXmlPath );

   // 現在のノード内にある属性名で検索し、属性値を出力する
   bool GetAttributeValue( LPCWSTR pAttribute, std::wstring* pValue );

   // テキストを取得する
   bool GetText( std::wstring* pValue );

public:
   UXMLLoader();
   virtual ~UXMLLoader();
   void Invalidate();

   // Xmlファイルの読込み
   void Load( TCHAR* pFileName );

   // ノード検索と、検索結果を取得

   // 引数の XMLPATH はこんな感じでタグ名、属性名、属性値を設定する
   // XMLPATH XmlPath[] = { 
   //                        { L"COLLADA", nullptr, nullptr },
   //                        { L"library_geometries", nullptr, nullptr },
   //                        { L"geometry", L"id", InstanceGeometryName.data() },
   //                        { L"mesh", nullptr, nullptr },
   //                    };

   // ノードの検索パターン
   // 1.タグ名のみのときはタグ名のみで検索する
   // 2.タグ名、属性名、属性値のすべてが設定されているときは、タグ名、属性名、属性値で検索する

   // インデックスの最後の検索パターン
   // 1.タグ名のみのときは、タグ名で最後の検索を行い取得したノードのTextを出力する
   // 2.タグ名と属性名が設定されているときは、タグ名と属性名で最後の検索を行い取得した属性値を出力する
   // 3.タグ名と属性名と属性値のすべて設定されているときは、タグ名と属性名と属性値で最後の検索を行い取得したTextを出力する

   void GetElementsByNodeName( XMLPATH* pXmlPath, UINT XmlPathCount, std::vector<std::wstring>* pDataList );
};

#endif

自作のXMLローダーです。XMLLiteを使用してXMLファイルをロードし、XMLPATH構造体 にパスを設定することで検索を行います。 既出ですが、XMLファイルのロードの特化させるために修正しました。

---UXMLLoader.cpp---  ↑


#include "../../Header/Common/UXMLLoader.h"

UXMLLoader::UXMLLoader()
{
   m_pReader = nullptr;
   m_pStream = nullptr;
}

UXMLLoader::~UXMLLoader()
{
   Invalidate();
}

void UXMLLoader::Invalidate()
{
   SAFE_RELEASE( m_pStream );
   SAFE_RELEASE( m_pReader );
}

void UXMLLoader::Load( TCHAR* pFileName )
{
   HRESULT hr = E_FAIL;

   // メモリ開放
   Invalidate();

   if( FAILED( hr = ::CreateXmlReader( __uuidof(IXmlReader), (void**)(&m_pReader), 0 ) ) )
      throw( UException( hr, _T("UXMLLoader::LoadXML()でエラーが発生しました。xmlファイルの読み込みに失敗しました。") ) );

   if( FAILED( hr = ::SHCreateStreamOnFile( pFileName, STGM_READ, &m_pStream ) ) )
      throw( UException( hr, _T("UXMLLoader::LoadXML()でエラーが発生しました。ファイルが見つかりません。") ) );

   if( FAILED( hr = m_pReader->SetInput( m_pStream ) ) )
      throw( UException( hr, _T("UXMLLoader::LoadXML()でエラーが発生しました。IXmlReader::SetInput()でエラーが発生しました。") ) );
}

// xml を読み込む開始位置を先頭に移動する
void UXMLLoader::MoveSeekTop()
{
   HRESULT hr = E_FAIL;

   LARGE_INTEGER li = { 0, 0 };

   if( FAILED( hr = m_pStream->Seek( li, tagSTREAM_SEEK::STREAM_SEEK_SET, nullptr ) ) )
      throw( UException( hr, _T("UXMLLoader::SetSeekTop()でエラーが発生しました。IStream::Seek()でエラーが発生しました。") ) );

   if( FAILED( hr = m_pReader->SetInput( m_pStream ) ) )
      throw( UException( hr, _T("UXMLLoader::SetSeekTop()でエラーが発生しました。IxmlReader::SetInput()でエラーが発生しました。") ) );
}

// 現在のノード内にある属性名で検索し、値を出力する
bool UXMLLoader::GetAttributeValue( LPCWSTR pAttribute, std::wstring* pValue )
{
   HRESULT hr;
   LPCWSTR pwszValue = nullptr;

   pValue->clear();

   // IXmlReader内の現在のノード内にある属性名で検索する
   hr = m_pReader->MoveToAttributeByName( pAttribute, nullptr );
   switch( hr )
   {
   // 属性名がみつからない
   case S_FALSE:
      return false;
      break;

   case E_FAIL:
      throw( UException( hr, _T("UXMLLoader::GetAttributeValue()でエラーが発生しました。IXmlReader::MoveToAttributeByName()でエラーが発生しました。") ) );
      break;
   }

   // 属性値を取得
   if( FAILED( hr = m_pReader->GetValue( &pwszValue, nullptr ) ) )
      throw( UException( hr, _T("UXMLLoader::GetAttributeValue()でエラーが発生しました。IXmlReader::GetValue()でエラーが発生しました。") ) );

   pValue->append( pwszValue );

   return true;
}

// ノード検索
bool UXMLLoader::CheckNodeHit( XMLPATH* pXmlPath )
{
   HRESULT hr = E_FAIL;
   LPCWSTR pwszLocalName;

   std::wstring pValue;
   pValue.clear();

   // 要素名を取得
   // pwszLocalNameはノード移動するとメモリを再利用するため無効になる
   if( FAILED( hr = m_pReader->GetLocalName( &pwszLocalName, nullptr ) ) )
      throw( UException( hr, _T("UXMLLoader::HitNode()でエラーが発生しました。IXmlReader::GetLocalName()でエラーが発生しました。") ) );

   // タグ名が一致する場合
   if( wcscmp( pXmlPath->pTagName, pwszLocalName ) == 0 )
   {
      // 検索条件に属性名が指定されていないので検索終了
      if( pXmlPath->pAttribute == nullptr )
         return true;

      // 検索条件に属性名が設定されているので属性値で検索する
      else
      {
         // 属性名で検索し、属性値を取得する
         if( GetAttributeValue( pXmlPath->pAttribute, &pValue ) == true )
         {
            // 検索条件に属性値がある
            if( pXmlPath->pAttributeValue != nullptr )
            {
               // 属性値が一致した
               if( wcscmp( pXmlPath->pAttributeValue, pValue.data() ) == 0 )
                  return true;
            }
            // 検索条件に属性値が設定されていない
            else
               return true;
         }
      }
   }

   return false;
}

// テキストを取得する
bool UXMLLoader::GetText( std::wstring* pValue )
{
   HRESULT hr = E_FAIL;
   LPCWSTR pwszValue = nullptr;
   XmlNodeType nodeType;
   pValue->clear();

   // 読み込み
   while( m_pReader->Read( &nodeType ) == S_OK )
   {
      switch( nodeType )
      {
      case XmlNodeType::XmlNodeType_Text:
         // 値を取得する
         if( FAILED( hr = m_pReader->GetValue( &pwszValue, nullptr ) ) )
            throw( UException( hr, _T("UXMLLoader::GetText()でエラーが発生しました。IXmlReader::GetValue()でエラーが発生しました。") ) );

         pValue->append( pwszValue );
         return true;
         break;
      // 終了タグ
      case XmlNodeType::XmlNodeType_EndElement:
         return false;
         break;
      }
   }
   
   return false;
}

// ノード検索
void UXMLLoader::GetElementsByNodeName( XMLPATH* pXmlPath, UINT XmlPathCount, std::vector<std::wstring>* pDataList )
{
   HRESULT hr = E_FAIL;
   XmlNodeType nodeType;

   // 現在の階層
   UINT NowDepth = 0;

   // ヒットしたところの階層
   int HitDepth = -1;

   std::wstring value;

   pDataList->clear();

   // シークを先頭に移動
   MoveSeekTop();

   // 読み込み
   while( m_pReader->Read( &nodeType ) == S_OK )
   {
      switch( nodeType )
      {
      case XmlNodeType::XmlNodeType_Element:
         // 階層を取得( 最小値は 0 )
         if( FAILED( hr = m_pReader->GetDepth( &NowDepth ) ) )
            throw( UException( hr, _T("UXMLLoader::GetElementsByNodeName()でエラーが発生しました。IXmlReader::GetDepth()でエラーが発生しました。") ) );

         // 階層がXMLPATHの要素数を越えている場合は、確実に対象外なのでスキップする
         if( NowDepth >= XmlPathCount )
            continue;
         
         // タグ名または、属性値が一致した
         if( CheckNodeHit( &pXmlPath[NowDepth] ) == true )
         {
            // 上の階層で一致しているとき
            if( HitDepth + 1 >= (int)NowDepth )
            {
               // 検索条件が最後の階層のとき
               if( NowDepth + 1 == XmlPathCount )
               {
                  // テキストを出力する場合 
                  if( pXmlPath[NowDepth].pAttribute == nullptr ||                                                 // 検索条件に属性名が指定されていないとき
                     pXmlPath[NowDepth].pAttribute != nullptr && pXmlPath[NowDepth].pAttributeValue != nullptr ) // 検索条件に属性名と属性値が指定されているとき
                  {
                     // テキストを取得する
                     if( GetText( &value ) == true )
                     {
                        // 値を出力する
                        pDataList->push_back( value.data() );
                     }
                  }
                  // 属性値を出力する場合
                  else if( pXmlPath[NowDepth].pAttribute != nullptr && pXmlPath[NowDepth].pAttributeValue == nullptr )
                  {
                     if( GetAttributeValue( pXmlPath[NowDepth].pAttribute, &value ) == true )
                     {
                        pDataList->push_back( value.data() );
                     }
                  }
                  else
                     throw( UException( hr, _T("UXMLLoader::GetElementsByNodeName()でエラーが発生しました。pXmlPathの検索条件が不正です。") ) );
               }

               HitDepth = NowDepth;
            }
         }

         // 検索対象の要素名が見つからない
         else
         {
            if( HitDepth >= (int)( NowDepth ) )
               HitDepth =  (int)( NowDepth ) - 1;   // レベルダウン
         }
         break;
      }
   }
}

---UColladaLoader.h---  ↑


#ifndef UCOLLADA_LOADER_H
#define UCOLLADA_LOADER_H

#include "UXMLLoader.h"
#include "UCommon.h"
#include "UException.h"

// XNAMath
#include "XNAMath/xnamath.h"

class UColladaLoader
{
public:
   // 頂点エレメントの格納方法の種類の一覧
   enum class COLLADA_GEOMETRY
   {
      UNKNOWN   = 0,
      POLYGONS  = 1,
      POLYLIST  = 2,
      TRIANGLES = 3,
      TRIFANS   = 4,
      TRISTRIPS = 5,
   };

   // COLLADAから取得したデータを格納する構造体
   typedef struct _COLLADA_DATA
   {
      // 頂点エレメントごとにデータを格納するための構造体
      typedef struct _VERTEX_ELEMENT
      {
         // 頂点エレメントの種類
         std::wstring Semantic;

         // 頂点エレメントで必要となるデータ数。例えば頂点座標の場合 x, y, z で 3 。
         UINT Stride;

         // 実データ。Stride数分使用する。
         std::vector<XMFLOAT4> Vector;

         // インデックスデータを示す
         std::vector<UINT> Index;

      }VERTEX_ELEMENT;

      // ジオメトリ名
      std::wstring InstanceGeometryName;

      // 頂点エレメントの格納方法の種類
      UColladaLoader::COLLADA_GEOMETRY GeometryType;

      // 1ポリゴンの頂点数を示す配列。
      std::vector<UINT> VCount;

      // 頂点エレメントごとのデータ配列
      std::vector<VERTEX_ELEMENT> VertexElement;

      // マテリアル名
      std::wstring InstanceMaterialName;

      // テクスチャーへのパス。とりあえず1つのみとする。
      std::wstring ImageFileName;

      // サンプラーステートはとりあえず考慮しない

   }COLLADA_DATA;
   
   std::vector<COLLADA_DATA> m_ColladaData;

private:
   UXMLLoader m_XMLLoader;

   // ジオメトリの種類を取得
   UColladaLoader::COLLADA_GEOMETRY CheckGeometryType( std::wstring* pInstanceGeometry );

   // target や url 属性値の頭の#を取り除く
   void GetID( std::wstring* Target );

   // 文字列をばらす
   void Split( std::vector<std::wstring>* pInStr, wchar_t Delimiter, std::vector<std::wstring>* pOutStr );

   //// inputタグの属性値を取得
   // bool GetInputData( std::vector<std::wstring>* pSemanticArray
   //            , std::vector<std::wstring>* pSourceArray
   //            , std::vector<std::wstring>* pOffsetArray
   //            , LPCWSTR pSearchSemantic
   //            , std::wstring* pSource
   //            , UINT* pOffset );

   // Polylistデータを取得
   void GetPolylist( std::wstring* pInstanceGeometry );

   // Triangleデータを取得
   void GetTriangles(std::wstring* pInstanceGeometry);

public:
   UColladaLoader();
   virtual ~UColladaLoader();
   void Invalidate();
   void LoadMesh( TCHAR* pFileName );
};

#endif

DAEファイルのローダーです。

---UColladaLoader.cpp---  ↑


#include "../../Header/Common/UColladaLoader.h"

UColladaLoader::UColladaLoader()
{
}

UColladaLoader::~UColladaLoader()
{
   Invalidate();
}

void UColladaLoader::Invalidate()
{
   m_ColladaData.clear();
}

// target や url 属性値の頭の#を取り除く
void UColladaLoader::GetID( std::wstring* Target )
{
   int ind;

   if( Target->length() > 0 )
   {
      // 第二引数は開始位置
      // 戻り値が-1のとき見つからない
      if( ( ind = Target->find( '#', 0 ) ) == 0 )
         Target->erase( 0, 1 );
   }
}

// 文字列を分割する
void UColladaLoader::Split( std::vector<std::wstring>* pInStr, wchar_t Delimiter, std::vector<std::wstring>* pOutStr ) 
{
   UINT index1 = 0;
   UINT index2 = 0;
   
   for( UINT i=0; i<pInStr->size(); i++ )
   {
      index1 = index2 = 0;
      while( index2 != std::wstring::npos )
      {
         index2 = (*pInStr)[i].find( Delimiter, index1 );

         if( index2 != std::wstring::npos )
         {
            std::wstring str = (*pInStr)[i].substr( index1, index2 - index1 ).data();
            if( str.length() > 0 )
               pOutStr->push_back( str.data() );
         }
         else
         {
            std::wstring str = (*pInStr)[i].substr( index1 ).data();
            if( str.length() > 0 )
               pOutStr->push_back( str.data() );
         }

         index1 = index2 + 1;
      }
   }
}

UColladaLoader::COLLADA_GEOMETRY UColladaLoader::CheckGeometryType( std::wstring* pInstanceGeometry )
{
   std::wstring InstanceGeometryName = *pInstanceGeometry;

   // 頭の#を取り除く
   GetID( &InstanceGeometryName );

   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                                       { L"COLLADA", nullptr, nullptr },
                                       { L"library_geometries", nullptr, nullptr },
                                       { L"geometry", L"id", InstanceGeometryName.data() },
                                       { L"mesh", nullptr, nullptr },
                                       { L"polylist", L"count", nullptr },
                                    };
      std::vector<std::wstring> check;
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &check );
      if( check.size() == 1 )
         return UColladaLoader::COLLADA_GEOMETRY::POLYLIST;
      else
      {
         UXMLLoader::XMLPATH XmlPath[] = {
            { L"COLLADA", nullptr, nullptr },
            { L"library_geometries", nullptr, nullptr },
            { L"geometry", L"id", InstanceGeometryName.data() },
            { L"mesh", nullptr, nullptr },
            { L"triangles", L"count", nullptr },
         };
         std::vector<std::wstring> check;
         m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &check);
         if (check.size() == 1)
            return UColladaLoader::COLLADA_GEOMETRY::TRIANGLES;
      }
   }

   return UColladaLoader::COLLADA_GEOMETRY::UNKNOWN;
}

// Polylist
void UColladaLoader::GetPolylist( std::wstring* pInstanceGeometry )
{
   COLLADA_DATA polylist;

   polylist.InstanceGeometryName = *pInstanceGeometry;

   // 頭の#を取り除く
   GetID( &polylist.InstanceGeometryName );

   // ***************************************************************************************
   // ジオメトリ種別を設定
   // ***************************************************************************************
   polylist.GeometryType = UColladaLoader::COLLADA_GEOMETRY::POLYLIST;

   // ***************************************************************************************
   // polylistの下のsemanticを取得
   // ***************************************************************************************
   std::vector<std::wstring> inputSemantic;
   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                              { L"COLLADA", nullptr, nullptr },
                              { L"library_geometries", nullptr, nullptr },
                              { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                              { L"mesh", nullptr, nullptr },
                              { L"polylist", nullptr, nullptr },
                              { L"input", L"semantic", nullptr },
                           };
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &inputSemantic );
   }
   if( inputSemantic.empty() == true )
      throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。semantic属性が見つかりません。") ) );

   // ***************************************************************************************
   // sourceを取得
   // ***************************************************************************************
   std::vector<std::wstring> inputSource;
   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                                       { L"COLLADA", nullptr, nullptr },
                                       { L"library_geometries", nullptr, nullptr },
                                       { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                       { L"mesh", nullptr, nullptr },
                                       { L"polylist", nullptr, nullptr },
                                       { L"input", L"source", nullptr },
                                    };
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &inputSource );
   }
   if( inputSource.empty() == true )
      throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。source属性が見つかりません。") ) );

   // 頭の#を取り除く
   for( UINT i=0; i<inputSource.size(); i++ )
      GetID( &inputSource[i] );

   // ***************************************************************************************
   // offset を取得
   // ***************************************************************************************
   std::vector<std::wstring> inputOffset;
   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                                       { L"COLLADA", nullptr, nullptr },
                                       { L"library_geometries", nullptr, nullptr },
                                       { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                       { L"mesh", nullptr, nullptr },
                                       { L"polylist", nullptr, nullptr },
                                       { L"input", L"offset", nullptr },
                                    };
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &inputOffset );
   }
   if( inputSemantic.empty() == true )
      throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。offset属性が見つかりません。") ) );

   if( inputSemantic.size() != inputSource.size() )
      throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。semanticとsourceの要素数が一致しません。") ) );

   if( inputSemantic.size() != inputOffset.size() )
      throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。semanticとoffsetの要素数が一致しません。") ) );

   // ***************************************************************************************
   // vcountデータを取得
   // ***************************************************************************************
   std::vector<std::wstring> vcount;
   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                                       { L"COLLADA", nullptr, nullptr },
                                       { L"library_geometries", nullptr, nullptr },
                                       { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                       { L"mesh", nullptr, nullptr },
                                       { L"polylist", nullptr, nullptr },
                                       { L"vcount", nullptr, nullptr },
                                    };
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &vcount );
   }
   if( vcount.size() != 1 )
      throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。vcountの要素数が不正です。") ) );

   // ' ' でばらす
   {
      std::vector<std::wstring> temp1;
      Split( &vcount, ' ', &temp1 );
      for( UINT i=0; i<temp1.size(); i++ )
         polylist.VCount.push_back( _wtoi( temp1[i].data() ) );
   }

   // ***************************************************************************************
   // pデータを取得
   // ***************************************************************************************
   std::vector<std::wstring> p;
   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                                       { L"COLLADA", nullptr, nullptr },
                                       { L"library_geometries", nullptr, nullptr },
                                       { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                       { L"mesh", nullptr, nullptr },
                                       { L"polylist", nullptr, nullptr },
                                       { L"p", nullptr, nullptr },
                                    };
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &p );
   }
   if( p.size() != 1 )
      throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。pの要素数が不正です。") ) );

   // ' ' でばらす
   std::vector<UINT> uIndex;
   {
      std::vector<std::wstring> temp1;
      Split( &p, ' ', &temp1 );
      for( UINT i=0; i<temp1.size(); i++ )
         uIndex.push_back( _wtoi( temp1[i].data() ) );
   }
   
   UINT SemanticSize = inputSemantic.size();
   
   for( UINT i=0; i<SemanticSize; i++ )
   {
      std::wstring source;
      UINT offset = _wtoi( inputOffset[i].data() );
      std::vector<std::wstring> float_array, stride;
      COLLADA_DATA::VERTEX_ELEMENT element;

      element.Semantic = inputSemantic[i].data();

      // "VERTEX"のときはsemantic="POSITION"にあるsourceが頂点エレメントの名称となる
      if( wcscmp( element.Semantic.data(), L"VERTEX" ) == 0 )
      {
         std::vector<std::wstring> sourceArray;
         {
            source = inputSource[i];
            GetID( &source );

            UXMLLoader::XMLPATH XmlPath[] = { 
                                             { L"COLLADA", nullptr, nullptr },
                                             { L"library_geometries", nullptr, nullptr },
                                             { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                             { L"mesh", nullptr, nullptr },
                                             { L"vertices", L"id", source.data() },
                                             { L"input", L"source", nullptr },    // ここはsemantic="POSITION"のみだという前提
                                          };
            m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &sourceArray );
         }
         if( sourceArray.size() != 1 )
            throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。vertices要素のinput要素の数が不正です。") ) );

         source = sourceArray[0];
      }
      // "VERTEX"以外のときはそのまま
      else
      {
         source = inputSource[i];
      }

     GetID( &source );

      // ***************************************************************************************
      // strideを取得しelementにセットする
      // ***************************************************************************************
      {
         UXMLLoader::XMLPATH XmlPath[] = { 
                                          { L"COLLADA", nullptr, nullptr },
                                          { L"library_geometries", nullptr, nullptr },
                                          { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                          { L"mesh", nullptr, nullptr },
                                          { L"source", L"id", source.data() },
                                          { L"technique_common", nullptr, nullptr },
                                          { L"accessor", L"stride", nullptr },
                                       };
         m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &stride );
      }
      if( stride.size() != 1 )
         throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。stride要素の数が不正です。") ) );

      element.Stride = _wtoi( stride[0].data() );

      // ***************************************************************************************
      // 実データを取得しelementにセットする
      // ***************************************************************************************
      {
         UXMLLoader::XMLPATH XmlPath[] = { 
                                          { L"COLLADA", nullptr, nullptr },
                                          { L"library_geometries", nullptr, nullptr },
                                          { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                          { L"mesh", nullptr, nullptr },
                                          { L"source", L"id", source.data() },
                                          { L"float_array", nullptr, nullptr },
                                       };
         m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &float_array );
      }
      if( float_array.size() != 1 )
         throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。float_array要素の数が不正です。") ) );

     {
        std::vector<std::wstring> temp1;
        Split( &float_array, ' ', &temp1 );
        float VectorElement[4];
        for( UINT i=0; i<temp1.size(); i+=element.Stride )
        {
           for( UINT j=0; j<element.Stride; j++ )
              VectorElement[j] = (float)_wtof( temp1[i+j].data() );

           element.Vector.push_back( VectorElement );
        }
     }

     std::vector<std::wstring> count;
      {
         UXMLLoader::XMLPATH XmlPath[] = { 
                                          { L"COLLADA", nullptr, nullptr },
                                          { L"library_geometries", nullptr, nullptr },
                                          { L"geometry", L"id", polylist.InstanceGeometryName.data() },
                                          { L"mesh", nullptr, nullptr },
                                          { L"source", L"id", source.data() },
                                          { L"technique_common", nullptr, nullptr },
                                          { L"accessor", L"count", nullptr },
                               };
         m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &count );
      }
      if( count.size() != 1 )
         throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。count要素の数が不正です。") ) );

     if( element.Vector.size() != (unsigned int)_wtoi( count[0].data() ) )
         throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。エレメントの要素数が一致しません。") ) );

      // ***************************************************************************************
      // インデックスデータをelementにセット
      // ***************************************************************************************
      for( UINT j=offset; j<uIndex.size(); j+=SemanticSize )
      {
         element.Index.push_back( uIndex[j] );
      }

     // polylistにセットする
      polylist.VertexElement.push_back( element );
   }

   // ***************************************************************************************
   // マテリアルインスタンス名を取得
   // ***************************************************************************************
   std::vector<std::wstring> instance_material;
   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                                       { L"COLLADA", nullptr, nullptr },
                                       { L"library_visual_scenes", nullptr, nullptr },
                                       { L"visual_scene", nullptr, nullptr },
                                       { L"node", nullptr, nullptr },
                                       { L"instance_geometry", L"url", pInstanceGeometry->data() },
                                       { L"bind_material", nullptr, nullptr },
                                       { L"technique_common", nullptr, nullptr },
                                       { L"instance_material", L"target", nullptr },
                                    };
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &instance_material );
   }
   // とりあえず1個のみとする
   if( instance_material.size() == 1 )
   {
      polylist.InstanceMaterialName = instance_material[0];

      // 頭の#を取り除く
      GetID( &instance_material[0] );

      // ***************************************************************************************
      // インスタンスエフェクト名を取得
      // ***************************************************************************************
      std::vector<std::wstring> instance_effect;
      {
         UXMLLoader::XMLPATH XmlPath[] = { 
                                          { L"COLLADA", nullptr, nullptr },
                                          { L"library_materials", nullptr, nullptr },
                                          { L"material", L"id", instance_material[0].data() },
                                          { L"instance_effect", L"url", nullptr },
                                       };
         m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &instance_effect );
      }
      // とりあえず1個のみとする
      if( instance_effect.size() != 1 )
         throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。instance_effect要素の数が不正です。") ) );

      // 頭の#を取り除く
      GetID( &instance_effect[0] );

      // ***************************************************************************************
      // ライブラリエフェクトからサーフェイス名を取得
      // ***************************************************************************************
      std::vector<std::wstring> surfaceName;
      {
         UXMLLoader::XMLPATH XmlPath[] = { 
                                          { L"COLLADA", nullptr, nullptr },
                                          { L"library_effects", nullptr, nullptr },
                                          { L"effect", L"id", instance_effect[0].data() },
                                          { L"profile_COMMON", nullptr, nullptr },
                                          { L"newparam", nullptr, nullptr },
                                          { L"surface", nullptr, nullptr },
                                          { L"init_from", nullptr, nullptr },
                                       };
         m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &surfaceName );
      }
      // とりあえず1個のみとする
      if( surfaceName.size() != 1 )
         throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。init_formを取得できません") ) );

      // ***************************************************************************************
      // ライブラリイメージ名を取得
      // ***************************************************************************************
      std::vector<std::wstring> library_images;
      {
         UXMLLoader::XMLPATH XmlPath[] = { 
                                          { L"COLLADA", nullptr, nullptr },
                                          { L"library_images", nullptr, nullptr },
                                          { L"image", L"id", surfaceName[0].data() },
                                          { L"init_from", nullptr, nullptr },
                                       };
         m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &library_images );
      }
      // とりあえず1個のみとする
      if( library_images.size() != 1 )
         throw( UException( -1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。library_images要素の数が不正です。") ) );

      // ***************************************************************************************
      // テクスチャーファイル名を格納
      // ***************************************************************************************
      polylist.ImageFileName = library_images[0];
   }
   else if (instance_material.size() > 1)
      throw(UException(-1, _T("CColladaLoader::GetPolylist()でエラーが発生しました。instance_material要素の数が不正です。")));

   // データ格納
   m_ColladaData.push_back( polylist );
}

// Triangles
void UColladaLoader::GetTriangles(std::wstring* pInstanceGeometry)
{
   COLLADA_DATA triangles;

   triangles.InstanceGeometryName = *pInstanceGeometry;

   // 頭の#を取り除く
   GetID(&triangles.InstanceGeometryName);

   // ***************************************************************************************
   // ジオメトリ種別を設定
   // ***************************************************************************************
   triangles.GeometryType = UColladaLoader::COLLADA_GEOMETRY::TRIANGLES;

   // ***************************************************************************************
   // trianglesの下のsemanticを取得
   // ***************************************************************************************
   std::vector<std::wstring> inputSemantic;
   {
      UXMLLoader::XMLPATH XmlPath[] = {
         { L"COLLADA", nullptr, nullptr },
         { L"library_geometries", nullptr, nullptr },
         { L"geometry", L"id", triangles.InstanceGeometryName.data() },
         { L"mesh", nullptr, nullptr },
         { L"triangles", nullptr, nullptr },
         { L"input", L"semantic", nullptr },
      };
      m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &inputSemantic);
   }
   if (inputSemantic.empty() == true)
      throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。semantic属性が見つかりません。")));

   // ***************************************************************************************
   // sourceを取得
   // ***************************************************************************************
   std::vector<std::wstring> inputSource;
   {
      UXMLLoader::XMLPATH XmlPath[] = {
         { L"COLLADA", nullptr, nullptr },
         { L"library_geometries", nullptr, nullptr },
         { L"geometry", L"id", triangles.InstanceGeometryName.data() },
         { L"mesh", nullptr, nullptr },
         { L"triangles", nullptr, nullptr },
         { L"input", L"source", nullptr },
      };
      m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &inputSource);
   }
   if (inputSource.empty() == true)
      throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。source属性が見つかりません。")));

   // 頭の#を取り除く
   for (UINT i = 0; i<inputSource.size(); i++)
      GetID(&inputSource[i]);

   // ***************************************************************************************
   // offset を取得
   // ***************************************************************************************
   std::vector<std::wstring> inputOffset;
   {
      UXMLLoader::XMLPATH XmlPath[] = {
         { L"COLLADA", nullptr, nullptr },
         { L"library_geometries", nullptr, nullptr },
         { L"geometry", L"id", triangles.InstanceGeometryName.data() },
         { L"mesh", nullptr, nullptr },
         { L"triangles", nullptr, nullptr },
         { L"input", L"offset", nullptr },
      };
      m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &inputOffset);
   }
   if (inputSemantic.empty() == true)
      throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。offset属性が見つかりません。")));

   if (inputSemantic.size() != inputSource.size())
      throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。semanticとsourceの要素数が一致しません。")));

   if (inputSemantic.size() != inputOffset.size())
      throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。semanticとoffsetの要素数が一致しません。")));

   // ***************************************************************************************
   // pデータを取得
   // ***************************************************************************************
   std::vector<std::wstring> p;
   {
      UXMLLoader::XMLPATH XmlPath[] = {
         { L"COLLADA", nullptr, nullptr },
         { L"library_geometries", nullptr, nullptr },
         { L"geometry", L"id", triangles.InstanceGeometryName.data() },
         { L"mesh", nullptr, nullptr },
         { L"triangles", nullptr, nullptr },
         { L"p", nullptr, nullptr },
      };
      m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &p);
   }
   if (p.size() != 1)
      throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。pの要素数が不正です。")));

   // ' ' でばらす
   std::vector<UINT> uIndex;
   {
      std::vector<std::wstring> temp1;
      Split(&p, ' ', &temp1);
      for (UINT i = 0; i<temp1.size(); i++)
         uIndex.push_back(_wtoi(temp1[i].data()));

      // ***************************************************************************************
      // vcountデータを取得
      // ***************************************************************************************

      if (temp1.size() % ( inputSemantic.size() * 3 ) != 0)
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。vcountの計算に失敗しました。")));

      // Trianglesの場合は3角ポリゴンのみのはず
      UINT vcountSize = temp1.size() / (inputSemantic.size() * 3);
      {
         for (UINT i = 0; i<vcountSize; i++)
            triangles.VCount.push_back(3);
      }
   }

   UINT SemanticSize = inputSemantic.size();

   for (UINT i = 0; i<SemanticSize; i++)
   {
      std::wstring source;
      UINT offset = _wtoi(inputOffset[i].data());
      std::vector<std::wstring> float_array, stride;
      COLLADA_DATA::VERTEX_ELEMENT element;

      element.Semantic = inputSemantic[i].data();

      // "VERTEX"のときはsemantic="POSITION"にあるsourceが頂点エレメントの名称となる
      if (wcscmp(element.Semantic.data(), L"VERTEX") == 0)
      {
         std::vector<std::wstring> sourceArray;
         {
            source = inputSource[i];
            GetID(&source);

            UXMLLoader::XMLPATH XmlPath[] = {
               { L"COLLADA", nullptr, nullptr },
               { L"library_geometries", nullptr, nullptr },
               { L"geometry", L"id", triangles.InstanceGeometryName.data() },
               { L"mesh", nullptr, nullptr },
               { L"vertices", L"id", source.data() },
               { L"input", L"source", nullptr },    // ここはsemantic="POSITION"のみだという前提
            };
            m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &sourceArray);
         }
         if (sourceArray.size() != 1)
            throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。vertices要素のinput要素の数が不正です。")));

         source = sourceArray[0];
      }
      // "VERTEX"以外のときはそのまま
      else
      {
         source = inputSource[i];
      }

      GetID(&source);

      // ***************************************************************************************
      // strideを取得しelementにセットする
      // ***************************************************************************************
      {
         UXMLLoader::XMLPATH XmlPath[] = {
            { L"COLLADA", nullptr, nullptr },
            { L"library_geometries", nullptr, nullptr },
            { L"geometry", L"id", triangles.InstanceGeometryName.data() },
            { L"mesh", nullptr, nullptr },
            { L"source", L"id", source.data() },
            { L"technique_common", nullptr, nullptr },
            { L"accessor", L"stride", nullptr },
         };
         m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &stride);
      }
      if (stride.size() != 1)
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。stride要素の数が不正です。")));

      element.Stride = _wtoi(stride[0].data());

      // ***************************************************************************************
      // 実データを取得しelementにセットする
      // ***************************************************************************************
      {
         UXMLLoader::XMLPATH XmlPath[] = {
            { L"COLLADA", nullptr, nullptr },
            { L"library_geometries", nullptr, nullptr },
            { L"geometry", L"id", triangles.InstanceGeometryName.data() },
            { L"mesh", nullptr, nullptr },
            { L"source", L"id", source.data() },
            { L"float_array", nullptr, nullptr },
         };
         m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &float_array);
      }
      if (float_array.size() != 1)
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。float_array要素の数が不正です。")));

      {
         std::vector<std::wstring> temp1;
         Split(&float_array, ' ', &temp1);
         float VectorElement[4];
         for (UINT i = 0; i<temp1.size(); i += element.Stride)
         {
            for (UINT j = 0; j<element.Stride; j++)
               VectorElement[j] = (float)_wtof(temp1[i + j].data());

            element.Vector.push_back(VectorElement);
         }
      }

      std::vector<std::wstring> count;
      {
         UXMLLoader::XMLPATH XmlPath[] = {
            { L"COLLADA", nullptr, nullptr },
            { L"library_geometries", nullptr, nullptr },
            { L"geometry", L"id", triangles.InstanceGeometryName.data() },
            { L"mesh", nullptr, nullptr },
            { L"source", L"id", source.data() },
            { L"technique_common", nullptr, nullptr },
            { L"accessor", L"count", nullptr },
         };
         m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &count);
      }
      if (count.size() != 1)
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。count要素の数が不正です。")));

      if (element.Vector.size() != (unsigned int)_wtoi(count[0].data()))
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。エレメントの要素数が一致しません。")));

      // ***************************************************************************************
      // インデックスデータをelementにセット
      // ***************************************************************************************
      for (UINT j = offset; j<uIndex.size(); j += SemanticSize)
      {
         element.Index.push_back(uIndex[j]);
      }

      // trianglesにセットする
      triangles.VertexElement.push_back(element);
   }

   // ***************************************************************************************
   // マテリアルインスタンス名を取得
   // ***************************************************************************************
   std::vector<std::wstring> instance_material;
   {
      UXMLLoader::XMLPATH XmlPath[] = {
         { L"COLLADA", nullptr, nullptr },
         { L"library_visual_scenes", nullptr, nullptr },
         { L"visual_scene", nullptr, nullptr },
         { L"node", nullptr, nullptr },
         { L"instance_geometry", L"url", pInstanceGeometry->data() },
         { L"bind_material", nullptr, nullptr },
         { L"technique_common", nullptr, nullptr },
         { L"instance_material", L"target", nullptr },
      };
      m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &instance_material);
   }
   // とりあえず1個のみとする
   if (instance_material.size() == 1)
   {
      triangles.InstanceMaterialName = instance_material[0];

      // 頭の#を取り除く
      GetID(&instance_material[0]);

      // ***************************************************************************************
      // インスタンスエフェクト名を取得
      // ***************************************************************************************
      std::vector<std::wstring> instance_effect;
      {
         UXMLLoader::XMLPATH XmlPath[] = {
            { L"COLLADA", nullptr, nullptr },
            { L"library_materials", nullptr, nullptr },
            { L"material", L"id", instance_material[0].data() },
            { L"instance_effect", L"url", nullptr },
         };
         m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &instance_effect);
      }
      // とりあえず1個のみとする
      if (instance_effect.size() != 1)
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。instance_effect要素の数が不正です。")));

      // 頭の#を取り除く
      GetID(&instance_effect[0]);

      // ***************************************************************************************
      // ライブラリエフェクトからサーフェイス名を取得
      // ***************************************************************************************
      std::vector<std::wstring> surfaceName;
      {
         UXMLLoader::XMLPATH XmlPath[] = {
            { L"COLLADA", nullptr, nullptr },
            { L"library_effects", nullptr, nullptr },
            { L"effect", L"id", instance_effect[0].data() },
            { L"profile_COMMON", nullptr, nullptr },
            { L"newparam", nullptr, nullptr },
            { L"surface", nullptr, nullptr },
            { L"init_from", nullptr, nullptr },
         };
         m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &surfaceName);
      }
      // とりあえず1個のみとする
      if (surfaceName.size() != 1)
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。init_formを取得できません")));

      // ***************************************************************************************
      // ライブラリイメージ名を取得
      // ***************************************************************************************
      std::vector<std::wstring> library_images;
      {
         UXMLLoader::XMLPATH XmlPath[] = {
            { L"COLLADA", nullptr, nullptr },
            { L"library_images", nullptr, nullptr },
            { L"image", L"id", surfaceName[0].data() },
            { L"init_from", nullptr, nullptr },
         };
         m_XMLLoader.GetElementsByNodeName(XmlPath, _countof(XmlPath), &library_images);
      }
      // とりあえず1個のみとする
      if (library_images.size() != 1)
         throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。library_images要素の数が不正です。")));

      // ***************************************************************************************
      // テクスチャーファイル名を格納
      // ***************************************************************************************
      triangles.ImageFileName = library_images[0];
   }
   else
      throw(UException(-1, _T("CColladaLoader::GetTriangles()でエラーが発生しました。instance_material要素の数が不正です。")));

   // データ格納
   m_ColladaData.push_back(triangles);
}

void UColladaLoader::LoadMesh( TCHAR* pFileName )
{
   if( pFileName == nullptr )
      throw( UException( -1,  _T("UColladaLoader::LoadMesh()でエラーが発生しました。pFileNameがNULLです。") ) );

   Invalidate();

   // daeファイルの読み込み
   m_XMLLoader.Load( pFileName );

   const std::wstring Version = L"1.4.1";

   // ***************************************************************************************
   // バージョンチェック
   // ***************************************************************************************
   std::vector<std::wstring> VersionData;
   {
      UXMLLoader::XMLPATH XmlPath[] = { { L"COLLADA", L"version", nullptr }, };

      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &VersionData );
   }
   if( VersionData.empty() == true )
      throw( UException( -1,  _T("UColladaLoader::LoadMesh()でエラーが発生しました。COLLADAのバージョンを取得できません。") ) );

   if( wcscmp( VersionData[0].data(), Version.data() ) != 0 )
      throw( UException( -1,  _T("UColladaLoader::LoadMesh()でエラーが発生しました。未対応のCOLLADAのバージョンです。") ) );

   // ***************************************************************************************
   // ジオメトリインスタンス名を取得
   // ***************************************************************************************
   std::vector<std::wstring> instance_geometry;
   {
      UXMLLoader::XMLPATH XmlPath[] = { 
                              { L"COLLADA", nullptr, nullptr },
                              { L"library_visual_scenes", nullptr, nullptr },
                              { L"visual_scene", nullptr, nullptr },
                              { L"node", nullptr, nullptr },
                              { L"instance_geometry", L"url", nullptr },
                           };
      m_XMLLoader.GetElementsByNodeName( XmlPath, _countof( XmlPath ), &instance_geometry );
   }
   if( instance_geometry.empty() == true )
      throw( UException( -1,  _T("UColladaLoader::LoadMesh()でエラーが発生しました。instance_geometryを取得できません。") ) );

   // ***************************************************************************************
   // ジオメトリ情報を取得
   // ***************************************************************************************
   for( UINT i=0; i<instance_geometry.size(); i++ )
   {
      UColladaLoader::COLLADA_GEOMETRY type = CheckGeometryType( &instance_geometry[i] );

      switch( type )
      {
      case UColladaLoader::COLLADA_GEOMETRY::POLYLIST:
         GetPolylist( &instance_geometry[i] );
         break;
      case UColladaLoader::COLLADA_GEOMETRY::TRIANGLES:
         GetTriangles(&instance_geometry[i]);
         break;
      default:
         throw(UException(-1, _T("UColladaLoader::LoadMesh()でエラーが発生しました。不明なメッシュタイプです。")));
      }
   }
}

---UD3DMeshDataCreater.h---  ↑


#ifndef UD3DMESHDATA_CREATER_H
#define UD3DMESHDATA_CREATER_H

#include "UColladaLoader.h"
#include "UCommon.h"
#include "UException.h"

// XNAMath
#include "XNAMath/xnamath.h"

class UD3DMeshDataCreater
{
public:
   typedef struct _VERTEX
   {
      XMFLOAT3 Position;
      XMFLOAT3 Normal;
      XMFLOAT2 Texcoord;
   }VERTEX;

private:
   UColladaLoader m_ColladaLoader;

   void SetTrianglePolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex );
   void SetTriangle2ndPolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex );

public:
   UD3DMeshDataCreater();
   virtual ~UD3DMeshDataCreater();
   void Invalidate();

   // COLLADAフォーマットのdaeファイルを読み込む
   void LoadMesh( TCHAR* pFileName );

   inline UINT GetMeshCount(){ return m_ColladaLoader.m_ColladaData.size(); };

   // 頂点座標を取得する
   // 頂点バッファ作成後、自分でメモリ開放する必要があるので注意
   void GetVertexes( UINT MeshIndex, VERTEX** ppVertices, ULONG* pCount );

   // テクスチャーのパスを取得する
   std::wstring GetTextureFileName( UINT MeshIndex );
};

#endif

UColladaLoaderクラスで読み込んだメッシュ情報を Direct3D で扱うデータ形式にコンバートします。

---UD3DMeshDataCreater.cpp---  ↑


#include "../../Header/Common/UD3DMeshDataCreater.h"

UD3DMeshDataCreater::UD3DMeshDataCreater()
{
}

UD3DMeshDataCreater::~UD3DMeshDataCreater()
{
}

void UD3DMeshDataCreater::Invalidate()
{
}

// COLLADAフォーマットのdaeファイルを読み込む
void UD3DMeshDataCreater::LoadMesh( TCHAR* pFileName )
{
   m_ColladaLoader.LoadMesh( pFileName );
}

void UD3DMeshDataCreater::SetTrianglePolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex )
{
   ULONG VertexIndex;

   for( int j=2; j>=0; j-- )
   { 
      // 頂点エレメントのループ
      for( UINT k=0; k<ElementMaxCount; k++ )
      {
         if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"VERTEX" ) == 0 )
         {
            VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + j];
            ::CopyMemory( &( pVertices[*pIndex].Position), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );
         }

         else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"NORMAL" ) == 0 )
         {
            VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + j];
            ::CopyMemory( &( pVertices[*pIndex].Normal), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );
         }
         else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"TEXCOORD" ) == 0 )
         {
            VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + j];
            ::CopyMemory( &( pVertices[*pIndex].Texcoord), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) );
         }
      }
      ( *pIndex )++;
   }
}

void UD3DMeshDataCreater::SetTriangle2ndPolygon( VERTEX* pVertices, UINT MeshIndex, UINT ElementMaxCount, ULONG* pIndex, ULONG PIndex )
{
   ULONG VertexIndex;

   for( UINT k=0; k<ElementMaxCount; k++ )
   {
      if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"VERTEX" ) == 0 )
      {        
         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 0];
         ::CopyMemory( &( pVertices[(*pIndex) + 0].Position ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );

         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 3];
         ::CopyMemory( &( pVertices[(*pIndex) + 1].Position ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );

         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 2];
         ::CopyMemory( &( pVertices[(*pIndex) + 2].Position ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );
      }

      else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"NORMAL" ) == 0 )
      {
         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 0];
         ::CopyMemory( &( pVertices[(*pIndex) + 0].Normal ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );

         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 3];
         ::CopyMemory( &( pVertices[(*pIndex) + 1].Normal ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );

         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 2];
         ::CopyMemory( &( pVertices[(*pIndex) + 2].Normal ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT3 ) );
      }
      else if( wcscmp( m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Semantic.data(), L"TEXCOORD" ) == 0 )
      {
         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 0];
         ::CopyMemory( &( pVertices[(*pIndex) + 0].Texcoord ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) );

         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 3];
         ::CopyMemory( &( pVertices[(*pIndex) + 1].Texcoord ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) );

         VertexIndex = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Index[PIndex + 2];
         ::CopyMemory( &( pVertices[(*pIndex) + 2].Texcoord ), &m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement[k].Vector[VertexIndex], sizeof( XMFLOAT2 ) );               
      }
   }

   (*pIndex) += 3;
}

// 頂点座標を取得する
// 頂点バッファ作成後、自分でメモリ開放する必要があるので注意
void UD3DMeshDataCreater::GetVertexes( UINT MeshIndex, VERTEX** ppVertices, ULONG* pCount )
{
   *pCount = 0;

   if( ppVertices != nullptr )
      *ppVertices = nullptr;

   if( GetMeshCount() <= MeshIndex )
      throw( UException( -1, _T("UD3DMeshDataCreater::GetVertexes()でエラーが発生しました。MeshIndexが不正です。") ) );
 
   ULONG VcountCnt = m_ColladaLoader.m_ColladaData[MeshIndex].VCount.size();

   // 総頂点数を取得
   ULONG MaxVCount = 0;
   for( ULONG i=0; i<VcountCnt; i++ )
   {
      // 三角ポリゴンの場合
      if( m_ColladaLoader.m_ColladaData[MeshIndex].VCount[i] == 3 )
         MaxVCount += 3;
      // 四角ポリゴンの場合、三角ポリゴン2個に展開する
      else if( m_ColladaLoader.m_ColladaData[MeshIndex].VCount[i] == 4 )
         MaxVCount += 6;
      // 以外はエラー
      else
         throw( UException( -1, _T("UD3DMeshDataCreater::GetVertexes()でエラーが発生しました。頂点数数が3,4以外です。") ) );
   }
   UINT ElementMaxCount = m_ColladaLoader.m_ColladaData[MeshIndex].VertexElement.size();

   *pCount = MaxVCount;
   *ppVertices = NEW VERTEX[MaxVCount];
   ULONG PIndex = 0, Index = 0;

   // インデックスで頂点を共有しない方針で配列に設定していく...

   for( ULONG i=0; i<VcountCnt; i++ )
   {
      switch( m_ColladaLoader.m_ColladaData[MeshIndex].VCount[i] )
      {
      // 三角ポリゴンの場合
      case 3:
         SetTrianglePolygon( *ppVertices, MeshIndex, ElementMaxCount, &Index, PIndex );
         PIndex += 3;
         break;

      // 四角ポリゴンの場合
      case 4:
         // 三角ポリゴン1つめ
         SetTrianglePolygon( *ppVertices, MeshIndex, ElementMaxCount, &Index, PIndex );

         // 三角ポリゴン2つめ
         SetTriangle2ndPolygon( *ppVertices, MeshIndex, ElementMaxCount, &Index, PIndex );
         PIndex += 4;
         break;
      }
   }

   if( MaxVCount != Index )
      throw( UException( -1, _T("UD3DMeshDataCreater::GetVertexes()でエラーが発生しました。設定後の頂点数が不正です。") ) );

   // 右手座標系を左手座標系に変換
   for (ULONG i = 0; i<MaxVCount; i++)
   {
      (*ppVertices)[i].Position.z *= -1.0f;
      (*ppVertices)[i].Normal.z *= -1.0f;
      (*ppVertices)[i].Texcoord.y *= -1.0f;
   }
   VERTEX temp;
   for (ULONG i = 0; i<MaxVCount; i+=3)
   {
      ::CopyMemory(&temp, &((*ppVertices)[i + 1]), sizeof(VERTEX));
      ::CopyMemory(&((*ppVertices)[i + 1]), &((*ppVertices)[i + 2]), sizeof(VERTEX));
      ::CopyMemory(&((*ppVertices)[i + 2]), &temp, sizeof(VERTEX));
   }
}

// テクスチャーのパスを取得する
std::wstring UD3DMeshDataCreater::GetTextureFileName( UINT MeshIndex )
{
   if( GetMeshCount() <= MeshIndex )
      throw( UException( -1, _T("UD3DMeshDataCreater::GetTextureFileName()でエラーが発生しました。MeshIndexが不正です。") ) );
 
   return m_ColladaLoader.m_ColladaData[MeshIndex].ImageFileName;
}

COLLADAローダー系各種クラスは以前作成したときと大きな変更点はないです。したがって適当さもそのまま残ってますので、あんまり参考にしないように。
SDKのバージョンアップに合わせて、こっちのプログラムを修正するのがいやで自作しただけなので。

---USRViewRenderer.h---  ↑


#ifndef USRVIEW_RENDERER_H
#define USRVIEW_RENDERER_H

#include "UCommon.h"
#include "UException.h"
#include "UGraphicsPipeline.h"
#include "UDirect3D11.h"
#include "../../HLSL/SRViewRenderer_VS_Main.h"
#include "../../HLSL/SRViewRenderer_PS_Main.h"

// XNAMath
#include "XNAMath/xnamath.h"

class USRViewRenderer 
{
private:
   // 頂点定義
   typedef struct _VERTEX
   {
      XMFLOAT3 pos;     // 頂点の座標
      XMFLOAT2 texel;   // テクセル座標
   }VERTEX;

   typedef struct _CBUFFER
   {
      int SrcRGBA[4];
      int Dimension;
      float VolumeLevel;
      int Dummy2;
      int Dummy3;
   }CBUFFER;

   // 頂点バッファ
   ID3D11Buffer* m_pVertexBuffer;

   // シェーダーリソースビュー
   ID3D11ShaderResourceView* m_pSRView;

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

   // グラフィックパイプライン
   UGraphicsPipeline* m_pGraphicsPipeline;

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

   int   m_SrcRGBA[4];    // レンダーターゲットの出力先の成分を変更する。
   float m_VolumeLevel;

public:
   USRViewRenderer();
   virtual ~USRViewRenderer();
   void Invalidate();
   // 表示領域は射影空間上での座標系で指定する。つまり( -1.0f 〜 1.0f )
   void Create( ID3D11Device* pD3DDevice, float Left, float Top, float Right, float Bottom );
   void SetSRView( const ID3D11ShaderResourceView* pSRView, int SrcRGBA[4], float VolumeLevel = 0.0f );
   void Render( ID3D11DeviceContext* pD3DDeviceContext );
};

#endif

レンダーターゲットサーフェスに出力した中間データをデバッグ用に出力するためのクラスです。

シェーダーソースはコンパイルしたバイナリデータをSRViewRenderer_VS_Main.hとSRViewRenderer_PS_Main.hに出力してインクルードしてください。
2Dテクスチャー、2Dテクスチャー配列、ボリュームテクスチャーに対応しています。

---USRViewRenderer.cpp---  ↑


#include "../../Header/Common/USRViewRenderer.h"

/*

// 定数バッファ
cbuffer CBuffer : register( b0 )
{
   int4  g_SrcRGBA     : packoffset( c0 );
   int   g_Dimension   : packoffset( c1.x );
   float g_VolumeLevel : packoffset( c1.y );
};

// テクスチャー
Texture2D g_Tex0 : register( t0 );
Texture2DArray g_Tex1 : register( t1 );
Texture3D g_Tex2 : register( t2 );

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

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

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

// 頂点シェーダー
VS_OUT_PS_IN SRViewRenderer_VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out;

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

// ピクセルシェーダ
float4 SRViewRenderer_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET
{
   float4 col = 0;
   float4 colRet = 0;
   switch( g_Dimension )
   {
      case 4:
         col = g_Tex0.Sample( g_Sampler, In.texel );
         break;
      case 5:
         col = g_Tex1.Sample( g_Sampler, float3( In.texel, g_VolumeLevel ) );
         break;
      case 8:
         col = g_Tex2.Sample( g_Sampler, float3( In.texel, g_VolumeLevel ) );
         break;
   }
   for( int i=0; i<4; i++ )
      colRet[i] = col[g_SrcRGBA[i]];
   return colRet;
}

*/

USRViewRenderer::USRViewRenderer()
{
   m_pVertexBuffer = nullptr;
   m_pSRView = nullptr;
   m_pSamplerState = nullptr;
   m_pGraphicsPipeline = nullptr;
   m_pConstantBuffers = nullptr;
}

USRViewRenderer::~USRViewRenderer()
{
   Invalidate();
}

void USRViewRenderer::Invalidate()
{
   SAFE_RELEASE( m_pConstantBuffers );
   SAFE_DELETE( m_pGraphicsPipeline );
   SAFE_RELEASE( m_pSamplerState );
   SAFE_RELEASE( m_pVertexBuffer );
}

void USRViewRenderer::Create( ID3D11Device* pD3DDevice, float Left, float Top, float Right, float Bottom )
{
   D3D11_INPUT_ELEMENT_DESC layout[] = {
         { "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 },
   };

   m_pGraphicsPipeline = NEW UGraphicsPipeline();

   // シェーダーを作成する
   m_pGraphicsPipeline->CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)g_SRViewRenderer_VS_Main, sizeof( g_SRViewRenderer_VS_Main ), layout, _countof( layout ) );
   m_pGraphicsPipeline->CreatePixelShaderFromMemory(  pD3DDevice, (LPBYTE)g_SRViewRenderer_PS_Main, sizeof( g_SRViewRenderer_PS_Main ) );

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

   // 深度ステンシルステートを作成する
   m_pGraphicsPipeline->CreateDepthStencilState( pD3DDevice, FALSE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL );

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

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

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

   // 定数バッファを作成する
   m_pConstantBuffers = m_pGraphicsPipeline->CreateConstantBuffer( pD3DDevice, nullptr, sizeof( CBUFFER ), D3D11_CPU_ACCESS_WRITE );
}

void USRViewRenderer::SetSRView( const ID3D11ShaderResourceView* pSRView, int SrcRGBA[4], float VolumeLevel )
{
   m_pSRView = const_cast<ID3D11ShaderResourceView*>( pSRView );

   ::CopyMemory( m_SrcRGBA, SrcRGBA, sizeof( int ) * _countof( m_SrcRGBA ) );
   m_VolumeLevel = VolumeLevel;
};

void USRViewRenderer::Render( ID3D11DeviceContext* pD3DDeviceContext )
{
   if( m_pSRView == nullptr )
      return;

   HRESULT hr = E_FAIL;

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

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

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

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

   // シェーダーリソースビューから情報取得
   D3D11_SHADER_RESOURCE_VIEW_DESC Desc;
   m_pSRView->GetDesc( &Desc );

   D3D11_MAPPED_SUBRESOURCE mappedResource;

   if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) )
      throw( UException( hr, _T("USRViewRenderer::Render()でエラーが発生しました。ロックできません") ) );

   CBUFFER* cBuffer = (CBUFFER*)(mappedResource.pData);
   ::CopyMemory( cBuffer->SrcRGBA, m_SrcRGBA, sizeof( int ) * _countof( m_SrcRGBA ) );
   cBuffer->Dimension = Desc.ViewDimension;
   cBuffer->VolumeLevel = m_VolumeLevel;
   pD3DDeviceContext->Unmap( m_pConstantBuffers, 0 );

   // 定数バッファを設定
   pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers );

   // デカールマップを設定する
   switch( Desc.ViewDimension )
   {
   case D3D11_SRV_DIMENSION_TEXTURE2D:
      pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView );
      break;

   case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
      pD3DDeviceContext->PSSetShaderResources( 1, 1, &m_pSRView );
      break;

   case D3D11_SRV_DIMENSION_TEXTURE3D:
      pD3DDeviceContext->PSSetShaderResources( 2, 1, &m_pSRView );
      break;
   }

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

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

---ShadowMapping_Pass0.hlsl---  ↑


// ************************************************************
// Shadow Mapping Pass0
// ************************************************************

// 定数バッファ
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;
};

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

ライトビューの正射影空間上での深度値を出力するシェーダーソースです。
レンダーターゲットビューへの出力をおこなわないので、ピクセルシェーダーは不要です。

---ShadowMapping_Pass1.hlsl---  ↑


// ************************************************************
// Shadow Mapping Pass1
// ************************************************************

// 定数バッファ
cbuffer CBuffer : register( b0 )
{
   column_major float4x4 g_matCameraWorldViewProj   : packoffset( c0 );   // カメラビューの射影行列
   column_major float4x4 g_matLightWorldViewProj   : packoffset( c4 );   // ライトビューの正射影行列
   float4 g_vecLightPos              : packoffset( c8 );   // ローカル座標系での平行光源の位置ベクトル
   float4 g_DepthMapSize             : packoffset( c9 );   // 深度マップのサイズ
};

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

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

// 深度マップ
Texture2D g_DepthMap : register( t1 );

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

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

// 頂点シェーダー
VS_OUT_PS_IN ShadowMapping_Pass1_VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out;

   Out.pos = mul( float4( In.pos, 1.0f ), g_matCameraWorldViewProj );
   Out.posLWVP = mul( float4( In.pos, 1.0f ), g_matLightWorldViewProj );
   Out.normal = In.normal;
   Out.texel = In.texel;

   return Out;
}

// ピクセルシェーダ
float4 ShadowMapping_Pass1_PS_Main( VS_OUT_PS_IN In ) : SV_TARGET
{
   float shadowColor;
   
   // テクセルを計算
   float2 texel = float2( In.posLWVP.x / In.posLWVP.w * 0.5f + 0.5f, In.posLWVP.y / In.posLWVP.w * -0.5f + 0.5f );
   
   // 深度マップの範囲外はとりあえず影なしにする
   if( texel.x < 0 || texel.x > 1 || texel.y < 0 || texel.y > 1 )
      shadowColor = 1.0f;
   else
   {
      // 深度マップから深度値を取得
      float sm = g_DepthMap.Load( float3( texel * g_DepthMapSize.xy, 0 ) ).r;
   
      // 現在の深度値と深度マップ上の深度値を比較
      if( sm < In.posLWVP.z / In.posLWVP.w - 0.002f )
         shadowColor = 0.3f;
      else
         shadowColor = 1.0f;
   }
   
   // ハーフランバート
   float lambert = dot( g_vecLightPos.xyz, In.normal );
   lambert = lambert * 0.5f + 0.5f;

   // デカールマップ
   float4 decalmap = g_DecalMap.Sample( g_Sampler, In.texel );

   return ( decalmap * min( lambert, shadowColor ) ).bgra;
}

シャドウマッピングの最終パスです。シェーディングはハーフランバートです。

---ShadowMapping.h---  ↑


#ifndef SHADOW_MAPPING_H
#define SHADOW_MAPPING_H

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

// XNAMath
#include "../Common/XNAMath/xnamath.h"

class ShadowMapping
{
private:
   // Direct3D用定数バッファ設定用構造体
   typedef struct _CBUFFER_PASS0
   {
      XMMATRIX matLightWorldViewProj;
   }CBUFFER_PASS0;

   typedef struct _CBUFFER_PASS1
   {
      XMMATRIX matCameraWorldViewProj;
      XMMATRIX matLightWorldViewProj;
      XMFLOAT4 vecLightDir;
      XMFLOAT4 vecShadowMapSize;
   }CBUFFER_PASS1;

   ID3D11DepthStencilView* m_pDSView;
   ID3D11ShaderResourceView* m_pSRView;

   ID3D11RenderTargetView* m_pOldRTView;
   ID3D11DepthStencilView* m_pOldDSView;
   D3D11_VIEWPORT m_pOldViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
   UINT m_ViewportCount;

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

   UGraphicsPipeline* m_pGraphicsPipeline[2];

   DWORD m_Width, m_Height;
   
   int m_Pass;
   
   XMMATRIX m_MatLightViewProj;
   XMMATRIX m_MatCameraViewProj;
   XMFLOAT4 m_VecLightPos;
   
public:
   ShadowMapping();
   virtual ~ShadowMapping();
   void Invalidate();
   void Create( ID3D11Device* pD3DDevice, DWORD Width, DWORD Height );
   void BeginPass( ID3D11DeviceContext* pD3DDeviceContext, UINT Pass,
                   XMFLOAT4* pVecLightPos, XMMATRIX* pMatLightProj, XMMATRIX* pMatCameraView, XMMATRIX* pMatCameraProj );
   void SetConstantBuffers( ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld );
   void EndPass( ID3D11DeviceContext* pD3DDeviceContext );
   inline UINT GetMaxPass(){ return 2; };
   inline const ID3D11ShaderResourceView* GetDepthMap(){ return m_pSRView; };
};

#endif

シャドウマッピングクラスのヘッダーファイルです。

---ShadowMapping.cpp---  ↑


#include "../../Header/Shader/ShadowMapping.h"
#include "../../HLSL/ShadowMapping_Pass0_VS_Main.h"
#include "../../HLSL/ShadowMapping_Pass1_VS_Main.h"
#include "../../HLSL/ShadowMapping_Pass1_PS_Main.h"

ShadowMapping::ShadowMapping()
{
   m_pDSView = nullptr;
   m_pSRView = nullptr;
   for( int i=0; i<_countof( m_pGraphicsPipeline ); i++ )
   {
      m_pGraphicsPipeline[i] = nullptr;
      m_pConstantBuffers[i] = nullptr;
   }
   
   m_Pass = -1;
}

ShadowMapping::~ShadowMapping()
{
   for( int i=0; i<_countof( m_pGraphicsPipeline ); i++ )
   {
      SAFE_DELETE( m_pGraphicsPipeline[i] );
      SAFE_RELEASE( m_pConstantBuffers[i] );
   }
   SAFE_RELEASE( m_pSRView );
   SAFE_RELEASE( m_pDSView );
}

void ShadowMapping::Create( ID3D11Device* pD3DDevice, DWORD Width, DWORD Height )
{
   m_Width = Width;
   m_Height = Height;

   m_Pass = -1;

   // *******************************************************************************************************
   // パス0用のUGraphicsPipelineの作成
   // *******************************************************************************************************

   m_pGraphicsPipeline[0] = 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/ShadowMapping_Pass0.hlsl"), "ShadowMapping_Pass0_VS_Main", layout, _countof( layout ) );
#else
   m_pGraphicsPipeline[0]->CreateVertexShaderFromMemory( pD3DDevice, (LPBYTE)g_ShadowMapping_Pass0_VS_Main, sizeof( g_ShadowMapping_Pass0_VS_Main ), layout, _countof( layout ) );
#endif
   
   // 深度ステンシルバッファを作成する
   UMaps::CreateDepthStencilView( pD3DDevice, m_Width, m_Height, &m_pDSView, &m_pSRView );
  
   // 定数バッファを作成する
   m_pConstantBuffers[0] = m_pGraphicsPipeline[0]->CreateConstantBuffer( pD3DDevice, nullptr, sizeof( ShadowMapping::CBUFFER_PASS0 ), D3D11_CPU_ACCESS_WRITE );

   // *******************************************************************************************************
   // パス1用のUGraphicsPipelineの作成
   // シェーダーと定数バッファ以外はパス0の使いまわし
   // *******************************************************************************************************

   m_pGraphicsPipeline[1] = NEW UGraphicsPipeline();

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

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

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

   m_Pass = (int)Pass;

   switch( m_Pass )
   {
   case 0:
      {
         // レンダーターゲットビューと深度ステンシルビューとビューポートを切り替える

         pD3DDeviceContext->OMGetRenderTargets( 1, &m_pOldRTView, &m_pOldDSView );
         pD3DDeviceContext->OMSetRenderTargets( 0, nullptr, m_pDSView );

         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_Width;
         Viewport[0].Height   = (FLOAT)m_Height;
         Viewport[0].MinDepth = 0.0f;
         Viewport[0].MaxDepth = 1.0f;
         pD3DDeviceContext->RSSetViewports( 1, Viewport );

         // レンダーターゲットビューは使用しないのでクリアの必要なし。

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

         m_VecLightPos = *pVecLightPos;
         
         // ライトビュー × 射影行列を作成
         XMMATRIX matLightView = XMMatrixLookAtLH(XMLoadFloat3((XMFLOAT3*)&m_VecLightPos), XMLoadFloat3(&XMFLOAT3(0, 0, 0)), XMLoadFloat3(&XMFLOAT3(0, 1, 0)));
         m_MatLightViewProj = matLightView * (*pMatLightProj);

         m_MatCameraViewProj = XMMatrixIdentity();
      }
      break;

   case 1:
      {
         // 深度マップをシェーダーに設定
         pD3DDeviceContext->PSSetShaderResources( 1, 1, &m_pSRView );

         // ライトビューはPass0と同じにするためここでは設定しない

         // カメラビュー × 射影行列を作成
         m_MatCameraViewProj = (*pMatCameraView) * (*pMatCameraProj);
      }
      break;
   default:
      throw(UException(-1, _T("ShadowMapping::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 ShadowMapping::SetConstantBuffers( ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld )
{
   HRESULT hr = E_FAIL;

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

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

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

         ShadowMapping::CBUFFER_PASS0* cbuffer = (ShadowMapping::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] );
         pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers[m_Pass] );
      }
      break;

   case 1:
      {
         XMMATRIX matCameraWorldViewProj, matLightWorldViewProj;

         matCameraWorldViewProj = (*pMatWorld) * m_MatCameraViewProj;
         matCameraWorldViewProj = XMMatrixTranspose( matCameraWorldViewProj );

         matLightWorldViewProj = (*pMatWorld) * m_MatLightViewProj;
         matLightWorldViewProj = XMMatrixTranspose( matLightWorldViewProj );

         // メッシュ基準のローカル座標系上での平行光源の方向ベクトルを計算する
         XMMATRIX matInv = XMMatrixInverse( nullptr, *pMatWorld );
         XMVECTOR v = XMVector4Transform( XMLoadFloat4( &m_VecLightPos ), matInv );
         XMVECTOR nv = XMVector3Normalize( v );
         XMFLOAT4 localLightPos;
         XMStoreFloat4( &localLightPos, nv );
         
         XMFLOAT4 shadowMapSize = XMFLOAT4( (float)m_Width, (float)m_Height, 0, 0 );

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

         ShadowMapping::CBUFFER_PASS1* cbuffer = (ShadowMapping::CBUFFER_PASS1*)mappedResource.pData;

         ::CopyMemory( &cbuffer->matCameraWorldViewProj, &matCameraWorldViewProj, sizeof( XMMATRIX ));
         ::CopyMemory( &cbuffer->matLightWorldViewProj, &matLightWorldViewProj, sizeof( XMMATRIX ));
         ::CopyMemory( &cbuffer->vecLightDir, &localLightPos, sizeof( XMFLOAT4 ));
         ::CopyMemory( &cbuffer->vecShadowMapSize, &shadowMapSize, sizeof( XMFLOAT4 ));

         pD3DDeviceContext->Unmap( m_pConstantBuffers[m_Pass], 0 );

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

void ShadowMapping::EndPass( ID3D11DeviceContext* pD3DDeviceContext )
{
   switch( m_Pass )
   {
   case 0:
      // レンダーターゲットビューと深度ステンシルビューとビューポートを戻す

      pD3DDeviceContext->OMSetRenderTargets( 1, &m_pOldRTView, m_pOldDSView );
      SAFE_RELEASE( m_pOldRTView );
      SAFE_RELEASE( m_pOldDSView );

      pD3DDeviceContext->RSSetViewports( m_ViewportCount, m_pOldViewport );
      break;

   case 1:
      ID3D11ShaderResourceView* pNull[1] = { nullptr };
      pD3DDeviceContext->PSSetShaderResources( 1, _countof( pNull ), pNull );
      break;
   }

   m_Pass = -1;
}

DirectX 9 と異なり深度バッファの内容を参照できるようになったので、Pass0で行う深度マップ作成処理ではレンダーターゲットサーフェスを使用しません。

---F14Mesh.h---  ↑


#ifndef F14MESH_H
#define F14MESH_H

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

#include "../Common/XNAMath/xnamath.h"

class F14Mesh 
{
private:
   // 頂点バッファ
   ID3D11Buffer* m_pVertexBuffer;

   // インデックスバッファ
   // 未使用

   // シェーダーリソースビュー
   ID3D11ShaderResourceView* m_pSRView;

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

   UD3DMeshDataCreater m_MeshDataCreater;

   XMMATRIX m_MatWorld[4];

   UD3DMeshDataCreater::VERTEX* m_pVertex;
   ULONG m_VertexCount;

public:
   F14Mesh();
   virtual ~F14Mesh();
   void Invalidate();
   void CreateMesh( ID3D11Device* pD3DDevice );
   void NextFrame();
   inline XMMATRIX* GetMatWorld( UINT Index ){ return &m_MatWorld[Index]; };
   inline UINT GetMaxCount(){ return _countof( m_MatWorld ); };
   void Render( ID3D11DeviceContext* pD3DDeviceContext );
};

#endif

---F14Mesh.cpp---  ↑


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

F14Mesh::F14Mesh()
{
   m_pVertexBuffer = nullptr;
   m_pSRView = nullptr;
   m_pSamplerState = nullptr;
   m_pVertex = nullptr;
   m_VertexCount = 0;
}

F14Mesh::~F14Mesh()
{
   Invalidate();
}

void F14Mesh::Invalidate()
{
   m_VertexCount = 0;
   SAFE_DELETE_ARRAY( m_pVertex );
   SAFE_RELEASE( m_pSamplerState );
   SAFE_RELEASE( m_pSRView );
   SAFE_RELEASE( m_pVertexBuffer );
}

void F14Mesh::CreateMesh( ID3D11Device* pD3DDevice )
{
   // COLLADAデータを取得
   m_MeshDataCreater.LoadMesh( _T("../Resource/f14.dae") );

   UINT MeshIndex = 0;

   m_MeshDataCreater.GetVertexes( MeshIndex, &m_pVertex, &m_VertexCount );

   // 頂点バッファを作成する
   m_pVertexBuffer = UBuffers::CreateVertexBuffer( pD3DDevice, m_pVertex, sizeof( UD3DMeshDataCreater::VERTEX ) * m_VertexCount, 0 );
  
   // サンプラーステートを作成する
   m_pSamplerState = USamplers::CreateSamplerState( pD3DDevice, D3D11_TEXTURE_ADDRESS_WRAP );

   // テクスチャーを作成する
   UMaps::CreateSRViewFromDDSFile( pD3DDevice, m_MeshDataCreater.GetTextureFileName( MeshIndex ).data(), &m_pSRView );

   SAFE_DELETE_ARRAY( m_pVertex );
}

void F14Mesh::NextFrame()
{
   XMMATRIX matScaling, matXRotation, matTranslate;

   matScaling = XMMatrixScaling( 20, 20, 20 );
   static float XRotation = 0;
   XRotation += 0.0005f;
   if( XRotation > 2 * XM_PI )
      XRotation -= 2 * XM_PI;
   matXRotation = XMMatrixRotationX( XRotation );

   for( int i=0; i<_countof( m_MatWorld ); i++ )
   {
      matTranslate = XMMatrixTranslation( 0, 10.0f + 30.0f - (float)i * 10.0f, 80.0f - (float)i * 70.0f );
      matXRotation = XMMatrixRotationX( XRotation + (float)i * 0.8f );
      m_MatWorld[i] = matScaling * matXRotation * matTranslate;
   }
}

void F14Mesh::Render( ID3D11DeviceContext* pD3DDeviceContext )
{
   // 頂点バッファ設定
   UINT stride = sizeof( UD3DMeshDataCreater::VERTEX );
   UINT offset = 0;
   pD3DDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

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

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

   // デカールマップを設定する
   pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView );

   // インデックスバッファを使用しない描画
   pD3DDeviceContext->Draw( m_VertexCount, 0 );
}

---PlaneMesh.h---  ↑


#ifndef PLANEMESH_H
#define PLANEMESH_H

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

#include "../Common/XNAMath/xnamath.h"

class PlaneMesh 
{
private:
   // 頂点バッファ
   ID3D11Buffer* m_pVertexBuffer;

   // インデックスバッファ
   ID3D11Buffer* m_pIndexBuffer;

   // シェーダーリソースビュー
   ID3D11ShaderResourceView* m_pSRView;

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

   XMMATRIX m_MatWorld;

   ULONG m_VertexCount, m_IndexCount;

public:
   PlaneMesh();
   virtual ~PlaneMesh();
   void Invalidate();
   void CreateMesh( ID3D11Device* pD3DDevice, UINT WidthNum = 0, UINT HeightNum = 0 );
   void NextFrame();
   inline XMMATRIX* GetMatWorld(){ return &m_MatWorld; };
   void Render( ID3D11DeviceContext* pD3DDeviceContext, D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
};

#endif

---PlaneMesh.cpp---  ↑


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

PlaneMesh::PlaneMesh()
{
   m_pVertexBuffer = nullptr;
   m_pIndexBuffer = nullptr;
   m_pSRView = nullptr;
   m_pSamplerState = nullptr;
   m_VertexCount = 0;
   m_IndexCount = 0;
}

PlaneMesh::~PlaneMesh()
{
   Invalidate();
}

void PlaneMesh::Invalidate()
{
   m_IndexCount = 0;
   m_VertexCount = 0;
   SAFE_RELEASE( m_pSamplerState );
   SAFE_RELEASE( m_pSRView );
   SAFE_RELEASE(m_pIndexBuffer);
   SAFE_RELEASE( m_pVertexBuffer );
}

void PlaneMesh::CreateMesh( ID3D11Device* pD3DDevice, UINT WidthNum, UINT HeightNum )
{
   m_VertexCount = 0;
   m_IndexCount = 0;

   UINT widthNum = 1;
   if (WidthNum != 0)
   {
      widthNum = WidthNum;
   }

   UINT heightNum = 1;
   if (HeightNum != 0)
   {
      heightNum = HeightNum;
   }

   m_VertexCount = (widthNum + 1) * (heightNum + 1);

   UD3DMeshDataCreater::VERTEX* vertexes = NEW UD3DMeshDataCreater::VERTEX[m_VertexCount];

   float OnePolyWidthSize = 2000.0f / (float)widthNum;
   float OnePolyOneHeightSize = 2000.0f / (float)heightNum;

   float OneTexelWidthSize = 10.0f / (float)widthNum;
   float OneTexelHeightSize = 10.0f / (float)heightNum;

   for (ULONG i = 0; i < heightNum + 1; i++)
   {
      for (ULONG j = 0; j < widthNum + 1; j++)
      {
         ULONG index = i * (widthNum + 1) + j;
         vertexes[index].Position = XMFLOAT3(-1000.0f + OnePolyWidthSize * (float)(j), 0.0f, 1000.0f - OnePolyOneHeightSize * (float)i);
         vertexes[index].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
         vertexes[index].Texcoord = XMFLOAT2(0.0f + (float)(j)* OneTexelWidthSize, 0.0f + (float)(i)* OneTexelHeightSize);
      }
   }

   // 頂点バッファを作成する
   m_pVertexBuffer = UBuffers::CreateVertexBuffer( pD3DDevice, vertexes, sizeof( UD3DMeshDataCreater::VERTEX ) * m_VertexCount, 0 );

   SAFE_DELETE_ARRAY(vertexes);

   m_IndexCount = widthNum * heightNum * 6;
   ULONG* indexes = NEW ULONG[m_IndexCount];
   ULONG index = 0;
   for (ULONG i = 0; i < heightNum; i++)
   {
      for (ULONG j = 0; j < widthNum; j++)
      {
         indexes[index++] = (j + 1) + i * (widthNum + 1);   // 右上
         indexes[index++] = j + i * (widthNum + 1);         // 左上
         indexes[index++] = j + (i + 1) * (widthNum + 1);   //左下

         indexes[index++] = (j + 1) + i * (widthNum + 1);        // 右上
         indexes[index++] = j + (i + 1) * (widthNum + 1);        //左下
         indexes[index++] = (j + 1) + (i + 1) * (widthNum + 1);  //右下
      }
   }

   // インデックスバッファを作成する
   m_pIndexBuffer = UBuffers::CreateIndexBuffer(pD3DDevice, indexes, sizeof(ULONG) * m_IndexCount, 0);

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

   // テクスチャーを作成する
   UMaps::CreateSRViewFromDDSFile( pD3DDevice, _T("../Resource/Plane.dds"), &m_pSRView );
}

void PlaneMesh::NextFrame()
{
   XMMATRIX matTranslate;

   matTranslate = XMMatrixTranslation( 0.0f, -20.0f, 0.0f );
   m_MatWorld = matTranslate;
}

void PlaneMesh::Render( ID3D11DeviceContext* pD3DDeviceContext, D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology )
{
   // 頂点バッファ設定
   UINT stride = sizeof( UD3DMeshDataCreater::VERTEX );
   UINT offset = 0;
   pD3DDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

   // インデックスバッファ設定
   pD3DDeviceContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
   
   // プリミティブ タイプおよびデータの順序に関する情報を設定
   pD3DDeviceContext->IASetPrimitiveTopology( PrimitiveTopology );

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

   // デカールマップを設定する
   pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView );

   // インデックスバッファを使用する描画
   pD3DDeviceContext->DrawIndexed(m_IndexCount, 0, 0);
}

---main.cpp---  ↑


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

// アプリケーション名
TCHAR* AppName = _T("Direct3D11 Shadow Mapping");

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

ShadowMapping* g_pShadowMapping = nullptr;

F14Mesh* g_pF14Mesh = nullptr;
PlaneMesh* g_pPlaneMesh = nullptr;

UFPS* g_pFPS = nullptr;

#if defined(DEBUG) || defined(_DEBUG)
USRViewRenderer* g_pSRViewRenderer = nullptr;
#endif

DWORD g_Width = 640, g_Height = 480;

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

// 射影行列
XMMATRIX g_MatCameraProj = XMMatrixPerspectiveFovLH( XM_PI / 5.0f, (float)g_Width / (float)g_Height, 0.01f, 500.0f );

// 正行列
XMMATRIX g_MatLightOrtho = XMMatrixOrthographicLH( (float)300, (float)300, 1.0f, 800.0f );

// 平行光源の位置ベクトル
XMFLOAT4 g_VecLightPos = XMFLOAT4( 20.0f, 200.0f, 300.0f, 0 );

// メモリ解放
void Invalidate()
{
#if defined(DEBUG) || defined(_DEBUG)
   SAFE_DELETE( g_pSRViewRenderer );
#endif
   SAFE_DELETE( g_pFPS );
   SAFE_DELETE( g_pShadowMapping );
   SAFE_DELETE( g_pPlaneMesh );
   SAFE_DELETE( g_pF14Mesh );
   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 );

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

#if defined(DEBUG) || defined(_DEBUG)
      g_pSRViewRenderer->Create( g_pDirect3D11->m_pD3DDevice, 1.0f - 400.0f / (float)g_Width, 1.0f, 1.0f, 1.0f - 400.0f / (float)g_Height );
#endif
   }
   __finally
   {
      SAFE_DELETE_ARRAY( pModeDescArray );
   }
}

void CreateGraphicePipeline()
{
   g_pShadowMapping->Create( g_pDirect3D11->m_pD3DDevice, 1024, 1024 );
}

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

   g_pPlaneMesh = NEW PlaneMesh();
   g_pPlaneMesh->CreateMesh( g_pDirect3D11->m_pD3DDevice );
}

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

   g_pShadowMapping = NEW ShadowMapping();

   g_pFPS = NEW UFPS();

#if defined(DEBUG) || defined(_DEBUG)
   g_pSRViewRenderer = NEW USRViewRenderer();
#endif

   // Direct3Dの作成
   CreateDirect3D( hInstance );

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

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

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

   g_pFPS->NextFrame();

   g_pF14Mesh->NextFrame();
   g_pPlaneMesh->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 );

   for( UINT i=0; i<g_pShadowMapping->GetMaxPass(); i++ )
   {
      g_pShadowMapping->BeginPass( g_pDirect3D11->m_pD3DDeviceContext, i, &g_VecLightPos, &g_MatLightOrtho, &g_MatCameraView, &g_MatCameraProj );

      for( UINT j=0; j<g_pF14Mesh->GetMaxCount(); j++ )
      {
         // 定数バッファを設定
         g_pShadowMapping->SetConstantBuffers( g_pDirect3D11->m_pD3DDeviceContext, g_pF14Mesh->GetMatWorld(j) );
         // レンダリング
         g_pF14Mesh->Render( g_pDirect3D11->m_pD3DDeviceContext );
      }

      // 定数バッファを設定
      g_pShadowMapping->SetConstantBuffers( g_pDirect3D11->m_pD3DDeviceContext, g_pPlaneMesh->GetMatWorld() );
      // レンダリング
      g_pPlaneMesh->Render( g_pDirect3D11->m_pD3DDeviceContext );

      g_pShadowMapping->EndPass( g_pDirect3D11->m_pD3DDeviceContext );
   }

#if defined(DEBUG) || defined(_DEBUG)
   int SrvRGB[] = { 0, 1, 2, 3 };
   g_pSRViewRenderer->SetSRView( g_pShadowMapping->GetDepthMap(), SrvRGB );
   g_pSRViewRenderer->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;
}


web拍手 by FC2

Top Next

inserted by FC2 system