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

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


今回は Gooch Shading をやりますが、その前に1つほど。前回もいくつか今後の方針について書きましたが、今回もその辺について記述しておきます。

当サイトでは Direct3D エクステンション を使用してサンプルを作成しています。 しかし新 masafumi's Diaryに記述されている記事によると Direct3D11.1 から Direct3D エクステンション が廃止になるとのことです。DXUT はもともと使ってないのでどうでもいいですが。
原文を確認してませんが、ここは情報を信じることにして当サイトのサンプルも 脱 Direct3D エクステンション を目指すことにします。 とはいえ、いきなりすべて対応するのも大変なので、段階的に対応していきます。今回はシェーダーのコンパイル関数である、D3DX11CompileFromFile() を廃止し、自作しました。


次に今回のサンプルでコーディング規約などについて変更した点について列挙します。

1.CGraphicsPiplineクラスの追加
コーディング量を減らすためにグラフィックパイプラインでメインで使用する各種インターフェースの管理クラスを作成しました。 今後は各種シェーダークラス内ではインターフェースのポインタは保持せず、CGraphicsPiplineクラス側に管理してもらうことになります。 また各種インターフェースの作成、およびデバイスへの設定もこのクラスで行います。
定数バッファ、シェーダーリソースビューなどはシェーダーの種類によって、データ構造や使用数が変わるので対象外としました。

2.例外処理の実装
これまではエラーが発生したら goto で関数の最後にジャンプしてメモリを開放して、エラーコードを返す方法をとってきました。
しかし、これからは簡単にエラーの内容をメッセージボックスに表示できるようにするために例外処理で実装することにします。 基本的にエラーはすべて例外処理で対処しますが、アプリケーションを終了させずに復旧可能な場合は、これまで通りエラーコードを返す方法をとっていこうかと思っています。

3.スマートポインタの実装
new してインスタンスを作成したものについてはスマートポインタである std::shared_ptr を使用することで自動的にメモリから開放されるようにしました。
ハンドルや Direct3D の各種インターフェースについても開放されるように実装していますが、スマートポインタで実装する方法について検討中です。

4.ID3D10BlobのRelease()
ID3D10Blobの開放をしないとばっちりメモリリークしたので使い終わったら開放するようにします。 内部的に文字列長を動的に確保していると思われるので、そりゃ開放しなきゃだめだわな。

5.D3DX11CompileFromFile()関数の廃止
先に説明したとおりD3DX11CompileFromFile()関数を廃止し、自作しました。 といってもhlslファイルを読み込む処理を実装して、ついでにコンパイルエラーが発生したらエラーの内容を確認できるようにしただけですが。

こんなところです。D3D11USERクラスやFBXのローダーもいずれは修正したいですが今回は変更していません。


最後に Gooch Shading についてですが、たいしたことはやってないので説明は省略します。
元ネタはNVIDIA Shader Libraryです。
ちなみに WebGL のサンプル作成のときに、Gooch Shading を 半球ライティングと勘違いしたのは秘密です(笑)。


Exception.h 例外処理の内容を保持するクラスのヘッダファイル。今後のサンプルでも使用する。
GraphicsPipeline.h グラフィックパイプラインクラスのヘッダファイル。今後のサンプルでも使用する。
GraphicsPipeline.cpp グラフィックパイプラインクラスのソースファイル。今後のサンプルでも使用する。
Gooch.hlsl Gooch Shadingのhlslファイル。
Gooch.h Gooch Shadingクラスのヘッダファイル。
Gooch.cpp Gooch Shadingクラスのソースファイル。
main.cpp メイン関数があるソースファイル。

---Exception.h---  ↑


#ifndef EXCEPTION_H
#define EXCEPTION_H

#include <tchar.h>
#include <stdio.h>

class CException
{
private:
   static const int MaxString = 1024;
public:
   TCHAR m_pErrorStr[CException::MaxString];
   inline CException( const TCHAR* pHeader, const TCHAR* pBody, const TCHAR* pFooter )
   {
      _stprintf_s( m_pErrorStr, CException::MaxString, _T("%s\n%s\n%s\n"), pHeader, pBody, pFooter );
   }
};

#endif

---GraphicsPipeline.h---  ↑

#ifndef GRAPHICS_PIPELINE_H
#define GRAPHICS_PIPELINE_H

#include <D3Dcompiler.h>

class CGraphicsPipline
{
private:
   // 入力レイアウト
   ID3D11InputLayout* pLayout;

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

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

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

   // ジオメトリシェーダー
   // とりあえずストリームアウトプットは考慮しない
   ID3D11GeometryShader* pGeometryShader;

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

   // コンピュートシェーダー
   ID3D11ComputeShader* pComputeShader;

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

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

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

public:
   enum BLENDSTATTYPE
   {
      BLEND_NONE = 0,
      BLEND_ADD = 1,
   };

   CGraphicsPipline();
   virtual ~CGraphicsPipline();
   void Invalidate();

   // hlsl ファイルを読み込んでコンパイルする関数
   // なおDirect3D エクステンションは廃止するため自作
   void ShaderCompileFromFile( const TCHAR pSrcFile[]         // hlslファイルのファイル名
                             , const CHAR pFunctionName[]     // 実行開始する関数名
                             , const CHAR pVersion[]          // シェーダーモデルのバージョン
                             , ID3D10Blob** pBlob
                             );

   // 頂点シェーダーを作成
   void CreateVertexShader( ID3D11Device* pD3DDevice
                          , const BYTE* pShader, size_t BytecodeLength
                          , const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, UINT NumElements
                          );
   // ハルシェーダーを作成
   void CreateHullShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength );
   // ドメインシェーダーを作成
   void CreateDomainShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength );
   // ジオメトリシェーダーを作成
   void CreateGeometryShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength );
   // ピクセルシェーダーを作成
   void CreatePixelShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength );
   // コンピュートシェーダーを作成
   void CreateComputeShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength );

   // ラスタライザステートを作成
   void CreateRasterizerState( ID3D11Device* pD3DDevice, IDXGISwapChain* pSwapChain, D3D11_CULL_MODE CullMode );

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

   // ブレンドステートを作成
   void CreateBlendState( ID3D11Device* pD3DDevice, const BLENDSTATTYPE* BlendStateType, UINT BlendStateTypeLength );

   // 頂点シェーダーをデバイスに設定する
   inline void SetVertexShader( ID3D11DeviceContext* pD3DDeviceContext ) const
   {
      // 入力アセンブラー ステージを設定
      pD3DDeviceContext->IASetInputLayout( pLayout );
      // 頂点シェーダーをデバイスに設定する。
      pD3DDeviceContext->VSSetShader( pVertexShader, nullptr, 0 );
   }

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

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

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

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

   // コンピュートシェーダーをデバイスに設定する
   inline void SetComputeShader( ID3D11DeviceContext* pD3DDeviceContext ) const
   {
      pD3DDeviceContext->CSSetShader( pComputeShader, nullptr, 0 );
   }

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

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

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

#endif

---GraphicsPipeline.cpp---  ↑

#include "DX11User.h"
#include "D3D11User.h"
#include "Exception.h"
#include "GraphicsPipeline.h"

CGraphicsPipline::CGraphicsPipline()
{
   pLayout = nullptr;
   pVertexShader = nullptr;
   pHullShader = nullptr;
   pDomainShader = nullptr;
   pGeometryShader = nullptr;
   pPixelShader = nullptr;
   pComputeShader = nullptr;
   pRasterizerState = nullptr;
   pDepthStencilState = nullptr;
   pBlendState = nullptr;
}

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

void CGraphicsPipline::Invalidate()
{
   SAFE_RELEASE( pLayout );
   SAFE_RELEASE( pVertexShader );
   SAFE_RELEASE( pHullShader );
   SAFE_RELEASE( pDomainShader );
   SAFE_RELEASE( pGeometryShader );
   SAFE_RELEASE( pPixelShader );
   SAFE_RELEASE( pComputeShader );
   SAFE_RELEASE( pRasterizerState );
   SAFE_RELEASE( pDepthStencilState );
   SAFE_RELEASE( pBlendState );
}

// HLSLファイルをコンパイル
// なおDirect3D エクステンションは廃止するため自作
void CGraphicsPipline::ShaderCompileFromFile( const TCHAR pSrcFile[]         // hlslファイルのファイル名 )
                                             , const CHAR pFunctionName[]     // 実行開始する関数名
                                             , const CHAR pVersion[]          // シェーダーモデルのバージョン
                                             , ID3D10Blob** pBlob
                                             )
{
   HANDLE hfile = nullptr;
   DWORD FileSize = 0;
   std::shared_ptr<BYTE> Bytecode;
   ID3D10Blob* pErrorMsgs = 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
   {
      // hlsl ファイルのハンドルを取得
      hfile = ::CreateFile( pSrcFile
                          , GENERIC_READ, FILE_SHARE_READ
                          , nullptr
                          , OPEN_EXISTING
                          , FILE_ATTRIBUTE_NORMAL
                          , nullptr
                          );
      if( hfile == INVALID_HANDLE_VALUE )
      {
         throw( CException( _T("CGraphicsPipline::ShaderCompileFromFile()でエラーが発生しました。"), _T("hlslファイルが存在しません。"), _T("") ) );
      }

      // ファイルのサイズを取得
      FileSize = ::GetFileSize( hfile, nullptr );
      if( FileSize == -1 || FileSize == 0 )
      {
         throw( CException( _T("CGraphicsPipline::ShaderCompileFromFile()でエラーが発生しました。"), _T("hlslファイルが0バイトです。"), _T("") ) );
      }

      // 領域確保
      std::shared_ptr<BYTE> Bytecode ( NEW BYTE[ FileSize ] );

      // ファイル読み込み
      DWORD NumberOfBytesRead;
      if( ::ReadFile( hfile, Bytecode.get(), FileSize, &NumberOfBytesRead, nullptr ) == FALSE )
      {
         throw( CException( _T("CGraphicsPipline::ShaderCompileFromFile()でエラーが発生しました。"), _T("hlslファイルの読み込みに失敗しました。"), _T("") ) );
      }

      // コンパイル
      if( FAILED( D3DCompile( reinterpret_cast<void*>( Bytecode.get() )
                            , FileSize
                            , nullptr, nullptr, nullptr
                            , pFunctionName
                            , pVersion
                            , Flag1, 0
                            , pBlob
                            , &pErrorMsgs
                            ) ) )
      {
#ifdef _UNICODE
         // ErrorMsgsはshift-jisっぽいのでunicodeに変換する
         int StrLen = ::MultiByteToWideChar( CP_ACP, 0, reinterpret_cast<CHAR*>( pErrorMsgs->GetBufferPointer() ), pErrorMsgs->GetBufferSize(), nullptr, 0 );
         if( StrLen == 0 )
            throw( CException( _T("CGraphicsPipline::ShaderCompileFromFile()でエラーが発生しました。"), _T("hlslファイルのコンパイルに失敗しました。"), _T("エラー内容は不明です。") ) );

         std::shared_ptr<TCHAR> ConvErrorStr( NEW TCHAR[StrLen] );

         if( ::MultiByteToWideChar( CP_ACP, 0, reinterpret_cast<char*>( pErrorMsgs->GetBufferPointer() ), pErrorMsgs->GetBufferSize(), ConvErrorStr.get(), StrLen ) == 0 )
            throw( CException( _T("CGraphicsPipline::ShaderCompileFromFile()でエラーが発生しました。"), _T("hlslファイルのコンパイルに失敗しました。"), _T("エラー内容は不明です。") ) );
         
         throw( CException( _T("CGraphicsPipline::ShaderCompileFromFile()でエラーが発生しました。"), _T("hlslファイルのコンパイルに失敗しました。"), ConvErrorStr.get() ) );
#else
         throw( CException( _T("CGraphicsPipline::ShaderCompileFromFile()でエラーが発生しました。"), _T("hlslファイルのコンパイルに失敗しました。"), reinterpret_cast<TCHAR*>( pErrorMsgs->GetBufferPointer() ) ) );
#endif
      }
   }
   catch( CException ex )
   {
      if( hfile )
         ::CloseHandle( hfile );
      SAFE_RELEASE( pErrorMsgs );
      throw( ex );
   }

   if( hfile )
      ::CloseHandle( hfile );                                             
}

// 頂点シェーダーを作成
void CGraphicsPipline::CreateVertexShader( ID3D11Device* pD3DDevice
                                          , const BYTE* pShader, size_t BytecodeLength
                                          , const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, UINT NumElements
                                          )
{
   SAFE_RELEASE( pLayout );
   SAFE_RELEASE( pVertexShader );

   // 入力レイアウトを作成
   if( FAILED( pD3DDevice->CreateInputLayout( pInputElementDescs, NumElements, pShader, BytecodeLength, &pLayout ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateVertexShader()でエラーが発生しました。"), _T("CreateInputLayout()が失敗しました。"), _T("") ) );
   }

   // 頂点シェーダーを作成
   if( FAILED( pD3DDevice->CreateVertexShader( pShader, BytecodeLength, nullptr, &pVertexShader ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateVertexShader()でエラーが発生しました。"), _T("CreateVertexShader()が失敗しました。"), _T("") ) );
   }
}

// ハルシェーダーを作成
void CGraphicsPipline::CreateHullShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength )
{
   SAFE_RELEASE( pHullShader );

   // ハルシェーダーを作成
   if( FAILED( pD3DDevice->CreateHullShader( pShader, BytecodeLength, nullptr, &pHullShader ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateHullShader()でエラーが発生しました。"), _T("CreateHullShader()が失敗しました。"), _T("") ) );
   }
}

// ドメインシェーダーを作成
void CGraphicsPipline::CreateDomainShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength )
{
   SAFE_RELEASE( pDomainShader );

   // ドメインシェーダーを作成
   if( FAILED( pD3DDevice->CreateDomainShader( pShader, BytecodeLength, nullptr, &pDomainShader ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateDomainShader()でエラーが発生しました。"), _T("CreateDomainShader()が失敗しました。"), _T("") ) );
   }
}

// ジオメトリシェーダーを作成
void CGraphicsPipline::CreateGeometryShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength )
{
   SAFE_RELEASE( pGeometryShader );

   // ジオメトリシェーダーを作成
   if( FAILED( pD3DDevice->CreateGeometryShader( pShader, BytecodeLength, nullptr, &pGeometryShader ) ) )
   {
      throw( CException( _T("CGraphicsPipline::pGeometryShader()でエラーが発生しました。"), _T("pGeometryShader()が失敗しました。"), _T("") ) );
   }
}

// ピクセルシェーダーを作成
void CGraphicsPipline::CreatePixelShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength )
{
   SAFE_RELEASE( pPixelShader );

   // ピクセルシェーダーを作成
   if( FAILED( pD3DDevice->CreatePixelShader( pShader, BytecodeLength, nullptr, &pPixelShader ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreatePixelShader()でエラーが発生しました。"), _T("CreatePixelShader()が失敗しました。"), _T("") ) );
   }
}

// コンピュートシェーダーを作成
void CGraphicsPipline::CreateComputeShader( ID3D11Device* pD3DDevice, const BYTE* pShader, size_t BytecodeLength )
{
   SAFE_RELEASE( pComputeShader );

   // コンピュートシェーダーを作成
   if( FAILED( pD3DDevice->CreateComputeShader( pShader, BytecodeLength, nullptr, &pComputeShader ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateComputeShader()でエラーが発生しました。"), _T("CreateComputeShader()が失敗しました。"), _T("") ) );
   }
}

// ラスタライザステートを作成
void CGraphicsPipline::CreateRasterizerState( ID3D11Device* pD3D11Device, IDXGISwapChain* pSwapChain, D3D11_CULL_MODE CullMode )
{
   D3D11_RASTERIZER_DESC RasterizerDesc;

   DXGI_SWAP_CHAIN_DESC swapDesc;
   BOOL MultisampleEnable;
   pSwapChain->GetDesc( &swapDesc );
   if( swapDesc.SampleDesc.Count != 1 )
      MultisampleEnable = TRUE;
   else
      MultisampleEnable = FALSE;

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

   SAFE_RELEASE( pRasterizerState );

   if( FAILED( pD3D11Device->CreateRasterizerState( &RasterizerDesc, &pRasterizerState ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateRasterizerState()でエラーが発生しました。"), _T("CreateRasterizerState()が失敗しました。"), _T("") ) );
   }
}

// 深度ステンシルステートを作成
void CGraphicsPipline::CreateDepthStencilState( ID3D11Device* pD3DDevice, BOOL DepthEnable, D3D11_DEPTH_WRITE_MASK DepthWriteEnabled )
{
   D3D11_DEPTH_STENCIL_DESC DSDesc;

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

   SAFE_RELEASE( pDepthStencilState );

   if( FAILED( pD3DDevice->CreateDepthStencilState( &DSDesc, &pDepthStencilState ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateDepthStencilState()でエラーが発生しました。"), _T("CreateDepthStencilState()が失敗しました。"), _T("") ) );
   }
}

// ブレンドステートを作成
void CGraphicsPipline::CreateBlendState( ID3D11Device* pD3DDevice, const BLENDSTATTYPE* BlendStateType, UINT BlendStateTypeLength )
{
   D3D11_BLEND_DESC BlendDesc;

   if( BlendStateTypeLength == 0 || BlendStateTypeLength >= 8 )
   {
      throw( CException( _T("CGraphicsPipline::CreateBlendState()でエラーが発生しました。"), _T("BlendStateTypeLengthが不正値です。"), _T("") ) );
   }

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

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

   for( UINT i=0; i<BlendStateTypeLength; i++ )
   {
      switch( BlendStateType[i] )
      {
      case BLENDSTATTYPE::BLEND_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 BLENDSTATTYPE::BLEND_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;
      }   
   }

   SAFE_RELEASE( pBlendState );

   if( FAILED( pD3DDevice->CreateBlendState( &BlendDesc, &pBlendState ) ) )
   {
      throw( CException( _T("CGraphicsPipline::CreateBlendState()でエラーが発生しました。"), _T("CreateBlendState()が失敗しました。"), _T("") ) );
   }
}

---Gooch.hlsl---  ↑

// ************************************************************
// Gooch Shading
// ************************************************************

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

// Gooch描画時に使用する構造体の宣言

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

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

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

// 定数バッファ1
cbuffer CB_STEP01 : register( b0 )
{
   column_major float4x4 g_matWVP : packoffset( c0 );   // ワールド × ビュー × 射影 行列
   float4 g_vecLight              : packoffset( c4 );   // ローカル座標系での平行光源の方向ベクトル
   float4 g_vecEyePos             : packoffset( c5 );   // ローカル座標系での視点座標
   float4 g_vecLiteColor          : packoffset( c6 );   // 明度のうち明るい色
   float4 g_vecDarkColor          : packoffset( c7 );   // 明度のうち暗い色
   float4 g_vecWarmColor          : packoffset( c8 );   // 色相のうち暖色系の色
   float4 g_vecCoolColor          : packoffset( c9 );   // 色相のうち寒色系の色
   float  g_SpecularPower         : packoffset( c10.x );  // スペキュラー強度
};

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

Texture2D g_DecalMap      : register( t0 );  // デカールマップ

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

SamplerState  g_Sampler : register( s0 );

// ************************************************************
// シェーダーソース
// ************************************************************

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

   return Out;
}

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

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

   // 鏡面反射率を計算する
   float specular = max( 0.0f, dot( In.Normal, half ) );
   specular = pow( specular, 20.0f ) * g_SpecularPower;
   
   // ハーフランバート
   float lambert = dot( -g_vecLight.xyz, In.Normal );
   lambert = lambert * 0.5f + 0.5f;

   float3 surfColor = lerp( g_vecDarkColor.rgb, g_vecLiteColor.rgb, lambert );  // 明度を線形合成
   float3 toneColor = lerp( g_vecCoolColor.rgb, g_vecWarmColor.rgb, lambert );  // 寒色系と暖色系を線形合成
   float3 DiffuseContrib = ( surfColor + toneColor ) * 0.5f;   // 合成

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

   Out = float4( decalmap.rgb * DiffuseContrib, 1 ) + specular;
   
   return Out;
}

NVIDIA のサンプルとすこーし違うけど、基本的に同じです。ただ明度の調整値はいらない気がする...

---Gooch.h---  ↑

#ifndef GOOCH_H
#define GOOCH_H

#include "GraphicsPipeline.h"

class CGooch
{
private:   
   typedef struct _STEP01
   {
      // 定数バッファの構造体
      typedef struct _CBUFFER
      {
         // ワールド × ビュー × 射影 行列
         D3DXMATRIX  matWVP;

         // 平行光源の方向ベクトル
         D3DXVECTOR4 vecLight;
         // 視点座標
         D3DXVECTOR4 vecEyePos;

         // 明度のうち明るい色
         D3DXVECTOR4 vecLiteColor;
         // 明度のうち暗い色
         D3DXVECTOR4 vecDarkColor;
         // 色相のうち暖色系の色
         D3DXVECTOR4 vecWarmColor;
         // 色相のうち寒色系の色
         D3DXVECTOR4 vecCoolColor;

         // スペキュラー強度
         float SpecularPower;
         float Dummy1;
         float Dummy2;
         float Dummy3;
      }CBUFFER;
      // 定数バッファ
      ID3D11Buffer* pConstantBuffers;

      // グラフィックパイプライン上でメインで使用する各種インターフェースの管理クラス
      CGraphicsPipline GraphicsPipline;
   }STEP01;

   STEP01 m_Step01;

   // 共通項目の作成
   void CreateCommon( ID3D11Device* pD3DDevice );

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

   // 作成
   void CreateResourceAndShaderCompile( ID3D11Device* pD3DDevice, IDXGISwapChain* pSwapChain
                                      , const TCHAR pSrcFile[] );
   void CreateResource( ID3D11Device* pD3DDevice
                      , IDXGISwapChain* pSwapChain
                      , const BYTE* pVSShaderStep01, size_t VSBytecodeLengthStep01
                      , const BYTE* pPSShaderStep01, size_t PSBytecodeLengthStep01
                      );
   // シェーダー開始
   void Step01_Begin( ID3D11DeviceContext* pD3DDeviceContext );
   // 定数バッファとシェーダーリソースビューをデバイスに設定
   void Step01_SetCBuffer( ID3D11DeviceContext* pD3DDeviceContext
                         , const D3DXMATRIX* p_matWVP
                         , const D3DXVECTOR4* p_vecLight, const D3DXVECTOR4* p_vecEyePos
                         , const D3DXVECTOR4* p_vecLiteColor
                         , const D3DXVECTOR4* p_vecDarkColor
                         , const D3DXVECTOR4* p_vecWarmColor
                         , const D3DXVECTOR4* p_vecCoolColor
                         , float SpecularPower
                         , ID3D11ShaderResourceView* pDecalMap
                         , ID3D11SamplerState* pSamplerState
                         );
   // シェーダー終了
   void Step01_End( ID3D11DeviceContext* );
};

#endif

---Gooch.cpp---  ↑

#include "DX11User.h"
#include "D3D11User.h"
#include "GraphicsPipeline.h"
#include "Exception.h"
#include "Gooch.h"

CGooch::CGooch()
{
   m_Step01.pConstantBuffers = nullptr;
}

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

void CGooch::Invalidate()
{
   SAFE_RELEASE( m_Step01.pConstantBuffers );
}

void CGooch::CreateCommon( ID3D11Device* )
{
}

void CGooch::CreateResourceAndShaderCompile( ID3D11Device* pD3DDevice, IDXGISwapChain* pSwapChain, const TCHAR pSrcFile[] )
{
   ID3D10Blob* pBlob[2] = { nullptr, nullptr };

   try
   {
      // 頂点シェーダーのコンパイル
      m_Step01.GraphicsPipline.ShaderCompileFromFile( pSrcFile, "Step01_VS_Main", "vs_4_0", &pBlob[0] );

      // ピクセルシェーダーのコンパイル
      m_Step01.GraphicsPipline.ShaderCompileFromFile( pSrcFile, "Step01_PS_Main", "ps_4_0", &pBlob[1] );

      CreateResource( pD3DDevice
                    , pSwapChain
                    , reinterpret_cast<LPBYTE>( pBlob[0]->GetBufferPointer() ), pBlob[0]->GetBufferSize()
                    , reinterpret_cast<LPBYTE>( pBlob[1]->GetBufferPointer() ), pBlob[1]->GetBufferSize()
                    );
   }
   catch( CException ex )
   {
      for( UINT i=0; i<_countof( pBlob ); i++ )
         SAFE_RELEASE( pBlob[i] );

      throw( ex );
   }
}

void CGooch::CreateResource( ID3D11Device* pD3DDevice
                          , IDXGISwapChain* pSwapChain
                          , const BYTE* pVSShaderStep01, size_t VSBytecodeLengthStep01
                          , const BYTE* pPSShaderStep01, size_t PSBytecodeLengthStep01
                          )
{
   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 },
   };

   m_Step01.GraphicsPipline.CreateVertexShader( pD3DDevice, pVSShaderStep01, VSBytecodeLengthStep01, layout, _countof( layout ) );

   m_Step01.GraphicsPipline.CreatePixelShader( pD3DDevice, pPSShaderStep01, PSBytecodeLengthStep01 );

   m_Step01.GraphicsPipline.CreateRasterizerState( pD3DDevice, pSwapChain, D3D11_CULL_MODE::D3D11_CULL_BACK );

   m_Step01.GraphicsPipline.CreateDepthStencilState( pD3DDevice, TRUE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL );

   // ブレンドステートを作成する
   CGraphicsPipline::BLENDSTATTYPE BlendStateType[1] = { CGraphicsPipline::BLENDSTATTYPE::BLEND_NONE };
   m_Step01.GraphicsPipline.CreateBlendState( pD3DDevice, BlendStateType, 1 );

   // 定数バッファを作成する
   D3D11_BUFFER_DESC BufferDesc;
   ::ZeroMemory( &BufferDesc, sizeof( BufferDesc ) );
   BufferDesc.ByteWidth             = sizeof( STEP01::CBUFFER ); // バッファサイズ
   BufferDesc.Usage                 = D3D11_USAGE_DYNAMIC;       // リソース使用法を特定する
   BufferDesc.BindFlags             = D3D11_BIND_CONSTANT_BUFFER;// バッファの種類
   BufferDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_WRITE;    // CPU アクセスする
   BufferDesc.MiscFlags             = 0;                         // その他のフラグも設定しない
   if( FAILED( pD3DDevice->CreateBuffer( &BufferDesc, nullptr, &m_Step01.pConstantBuffers ) ) )
   {
      throw( CException( _T("CGooch::CreateResource()でエラーが発生しました。"), _T("ID3D11Device::CreateBuffer()が失敗しました。"), _T("") ) );
   }

   //// 共通項目の作成
   //CreateCommon( pD3DDevice );
}

void CGooch::Step01_Begin( ID3D11DeviceContext* pD3DDeviceContext )
{
   m_Step01.GraphicsPipline.SetVertexShader( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetHullShader( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetDomainShader( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetGeometryShader( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetPixelShader( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetComputeShader( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetRasterizerState( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetDepthStencilState( pD3DDeviceContext );
   m_Step01.GraphicsPipline.SetBlendState( pD3DDeviceContext );
}

// 定数バッファとシェーダーリソースビューをデバイスに設定する
void CGooch::Step01_SetCBuffer( ID3D11DeviceContext* pD3DDeviceContext
                             , const D3DXMATRIX* p_matWVP
                             , const D3DXVECTOR4* p_vecLight, const D3DXVECTOR4* p_vecEyePos
                             , const D3DXVECTOR4* p_vecLiteColor
                             , const D3DXVECTOR4* p_vecDarkColor
                             , const D3DXVECTOR4* p_vecWarmColor
                             , const D3DXVECTOR4* p_vecCoolColor
                             , float SpecularPower
                             , ID3D11ShaderResourceView* pDecalMap
                             , ID3D11SamplerState* pSamplerState
                             )
{
   // 定数バッファを設定

   D3D11_MAPPED_SUBRESOURCE mappedResource;
   STEP01::CBUFFER* cbuffer;

   if( FAILED( pD3DDeviceContext->Map( m_Step01.pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) )
   {
      throw( CException( _T("CGooch::Step01_SetCBuffer()でエラーが発生しました。"), _T("ID3D11DeviceContext::Map()が失敗しました。"), _T("") ) );
   }
   cbuffer = reinterpret_cast<STEP01::CBUFFER*>(mappedResource.pData);

   ::CopyMemory( &cbuffer->matWVP, p_matWVP, sizeof( D3DXMATRIX ));
   ::CopyMemory( &cbuffer->vecLight, p_vecLight, sizeof( D3DXVECTOR4 ));
   ::CopyMemory( &cbuffer->vecEyePos, p_vecEyePos, sizeof( D3DXVECTOR4 ));
   ::CopyMemory( &cbuffer->vecLiteColor, p_vecLiteColor, sizeof( D3DXVECTOR4 ));
   ::CopyMemory( &cbuffer->vecDarkColor, p_vecDarkColor, sizeof( D3DXVECTOR4 ));
   ::CopyMemory( &cbuffer->vecWarmColor, p_vecWarmColor, sizeof( D3DXVECTOR4 ));
   ::CopyMemory( &cbuffer->vecCoolColor, p_vecCoolColor, sizeof( D3DXVECTOR4 ));
   cbuffer->SpecularPower = SpecularPower;
   pD3DDeviceContext->Unmap( m_Step01.pConstantBuffers, 0 );

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

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

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

   // サンプラーを設定する
   pD3DDeviceContext->PSSetSamplers( 0, 1, &pSamplerState );
}

void CGooch::Step01_End( ID3D11DeviceContext* )
{

}

---main.cpp---  ↑

#include "../../USER/DX11User.h"
#include "../../USER/D3D11User.h"
#include "../../USER/DebugFontUser.h"
#include "../../USER/Exception.h"
#include "../../USER/Gooch.h"

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

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

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

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

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

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

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

// Gooch クラス
CGooch* g_pGooch = nullptr;

// サンプラーステート
ID3D11SamplerState* g_pSamplerState = nullptr;

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

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

// ビュー行列
D3DXMATRIX g_matView;

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

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

// リソースを作成
HRESULT CreateResource()
{
   HRESULT hr = E_FAIL;

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

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

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

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

   // Goochクラスの初期化
   g_pGooch = NEW CGooch();

#ifndef UNCOMPILED_SHADER
   g_pGooch->CreateResource( g_pD3D11User->m_D3DDevice, g_pD3D11User->m_SwapChain, g_Step01_VS_Main, sizeof( g_Step01_VS_Main ), g_Step01_PS_Main, sizeof( g_Step01_PS_Main ) );
#else
   g_pGooch->CreateResourceAndShaderCompile( g_pD3D11User->m_D3DDevice, g_pD3D11User->m_SwapChain, _T("../../USER/HLSL/Gooch.hlsl") );
#endif

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

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

   hr = S_OK;

EXIT:
   return hr;
}

// メモリ開放
void Invalidate()
{
   SAFE_RELEASE( g_pSamplerState );
   SAFE_DELETE( g_pGooch );
   SAFE_DELETE( g_pMeshBall );
   SAFE_DELETE( g_pMeshPlane );
   SAFE_DELETE( g_pMeshLoader );
   SAFE_DELETE( g_pDebugFontUser );
   SAFE_DELETE( g_pD3D11User );
}

// メッシュ描画
void RenderMesh( D3DXMATRIX* pMatView, D3DXMATRIX* pMatProj )
{
   D3DXMATRIX matScaling, matTranslation, matWorld, matWVP, matInv, matWV;
   D3DXVECTOR4 vec4LightDir, vec4EyePos;
   ID3D11ShaderResourceView* pDecalMap = nullptr;

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

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

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

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

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

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

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

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

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

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

      // 定数バッファとシェーダーリソースビューを設定する
      g_pGooch->Step01_SetCBuffer( g_pD3D11User->m_D3DDeviceContext
                                 , &matWVP
                                 , &vec4LightDir, &vec4EyePos
                                 , &D3DXVECTOR4( 1, 1, 1, 1 )
                                 , &D3DXVECTOR4( 0, 0, 0, 0 )
                                 , &D3DXVECTOR4( 1, 1, 1, 0 )
                                 , &D3DXVECTOR4( 0, 0, 0, 0 )
                                 , 0.0f
                                 , pDecalMap, g_pSamplerState
                                 );

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

   // *****************************************************************************************************************
   // ボールの描画
   // *****************************************************************************************************************

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

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

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

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

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

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

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

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

      // 定数バッファとシェーダーリソースビューを設定する
      g_pGooch->Step01_SetCBuffer( g_pD3D11User->m_D3DDeviceContext
                                 , &matWVP
                                 , &vec4LightDir, &vec4EyePos
                                 , &D3DXVECTOR4( 1, 1, 1, 1 )     // 明度のうち明るい色
                                 , &D3DXVECTOR4( 0, 0, 0, 0 )     // 明度のうち暗い色
                                 , &D3DXVECTOR4( 1, 0.5, 0, 0 )   // 色相のうち暖色系の色
                                 , &D3DXVECTOR4( 0, 0, 1, 0 )     // 色相のうち寒色系の色
                                 , 2.0f
                                 , pDecalMap, g_pSamplerState
                                 );

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

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

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

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

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

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

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

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

   g_pGooch->Step01_Begin( g_pD3D11User->m_D3DDeviceContext );
   {
      // メッシュを描画
      RenderMesh( &g_matView, &matProj );
   }
   g_pGooch->Step01_End( g_pD3D11User->m_D3DDeviceContext );

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

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

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

   hr = S_OK;

EXIT:
   return hr;
}

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

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

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

   hr = S_OK;

EXIT:

   return hr;
}

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

   case WM_KEYUP:
      g_KeyBuffer[wParam] = 0;

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

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

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

   case WM_ACTIVATE:
      Activate = true;
      break;

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

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

   return 0L;
}

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

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

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

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

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

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

   // リソースを作成
   try
   {
      CreateResource();
   }
   catch( CException ex )
   {
      ::MessageBox( nullptr, ex.m_pErrorStr, _T("リソースの作成エラー"), MB_OK );
      goto EXIT;
   }

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

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

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

   ::UnregisterClass( AppName, hInstance );

   return msg.wParam;
}

サンプラーステートはテクスチャーとセットで使用するため、管理する場所もテクスチャーと同じところとすべきだと思いますが、 この辺は FBX のローダーを修正するときにでも対応しようかと思います。 今回はとりあえずmain.cpp内で作成を行いました。


web拍手 by FC2

Prev Top Next

inserted by FC2 system