Microsoft Visual C++ 2010 Express
 Microsoft DirectX SDK (June 2010)
 Direct3D 11.0

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

無料レンタルサーバー
2010/07/08:
  1. ファイルの共有化のためにインクルードパスを変更
  2. 一部の環境でウィンドウモードに変更したとき何も表示されなくなる現象への対応
  3. エフェクトの初期化でエラーになったとき、アプリを終了しないバグ修正
2010/08/07:
  1. ポリゴンの表面の回転向きを反時計回りに変更( FBX SDK に対応するため )
2012/03/11:
  1. マルチレンダーターゲットに対応するためにブレンドステートを設定する関数を修正

今回は、ID3DX11Effectを使ってみようと思います。

これまでのサンプルでは頂点シェーダーに ID3D11VertexShader インターフェース、 ピクセルシェーダーに ID3D11PixelShader インターフェースを使用して シェーダーを個別に管理する方法で実装してきました。 今回は ID3DX11Effect インターフェイスを使用してシェーダーを一括管理する方法を紹介します。 この方法の場合、コーディングの量が圧倒的に少なくなるので楽になります。

Direct3D 9 では ID3DXEffect インターフェースは簡単に使用できたのですが、Direct3D 11 では( Direct3D 10 は知らない ) ソースによる提供となりました。したがって自分でコンパイルして、スタティックライブラリを作成する必要があります。 なんでこんなことしてるのか Microsoft の思惑は知りませんが、オープンソースのため自分で自由にカスタマイズすることができるようになりました。 それはいいのですが、ぶっちゃけバグってるので自分で修正するのはある意味必須かもね(笑)。

あと今回から Microsoft DirectX SDK (June 2010) にバージョンアップします。 バージョンアップするつもりはなかったのですが、 DirectX SDK (February 2010) に添付されているエフェクトのソースのプロジェクトファイルが 2005用 と 2008用 しかなかったため( 時期的に当然なんですが ) 2010 のプロジェクトファイルがある DirectX SDK (June 2010) にバージョンアップすることにしました。 とりあえず既存のソースは、修正なしで DirectX SDK (June 2010) で実行できました。でもインクルードとライブラリのディレクトリは変更しなきゃだめだよ。当然だけど。

1.DirectX SDK (June 2010)をダウンロードしてインストール
2010/7/3現在では日本語版のMSサイトで DirectX SDK (June 2010) は公開されていないようなので、英語版のMSサイトからダウンロードします。 DirectX Software Development Kit( 英語 )からダウンロードしてインストールしてください。

2.ソースをコンパイル
次にエフェクトのサンプルソースのコンパイルです。ソースは"DirectX SDK をインストールしたフォルダ\Samples\C++\Effects11" にあります。 コンパイルすると Effects11.lib が作成されます。

3.インクルードとスタティックライブラリをコピー
次にインクルードファイルとスタティックライブラリファイルをプロジェクトで設定している参照先のディレクトリにコピーします。
Effects11.lib
d3dx11effect.h
この2つのファイルです。

ここまでやれば( といってもたいしたことやってないですが )後は開発です。

---main.cpp---


#include "../../USER/DX11User.h"
#include "../../USER/D3D11User.h"
#include "../../USER/DebugFontUser.h"
// コンパイル済みエフェクト
#include "../../USER/HLSL/SimpleHLSL07_fx.h"

#include <d3dx11effect.h>                 // エフェクトのインクルードファイル
#pragma comment( lib, "Effects11.lib" )   // エフェクトのライブラリ
#pragma comment( lib, "d3dcompiler.lib" ) // Effects11.lib を使用するのに必要

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

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

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

// 頂点バッファ
ID3D11Buffer* g_pVertexBuffer = NULL;
// インデックスバッファ
ID3D11Buffer* g_pIndexBuffer = NULL;
// 入力レイアウト
ID3D11InputLayout* g_pLayout = NULL;
// 深度ステンシルステート
ID3D11DepthStencilState*  g_pDepthStencilState = NULL;

// シェーダーリソースビュー
ID3D11ShaderResourceView* g_pSRView = NULL;

// レンダリング エフェクト
// ID3DX11Effect
ID3DX11Effect* g_pEffect = NULL;
// パスの集合
// ID3DX11EffectTechnique
ID3DX11EffectTechnique* g_pEffectTechnique = NULL;
// パス
// ID3DX11EffectPass
ID3DX11EffectPass* g_pEffectPass = NULL;
// 定数バッファ
// ID3DX11EffectMatrixVariable
ID3DX11EffectMatrixVariable* g_pMatWVP = NULL;
// シェーダーリソース
// ID3DX11EffectShaderResourceVariable
ID3DX11EffectShaderResourceVariable* g_pTex = NULL;
// サンプラーステート
// ID3DX11EffectSamplerVariable
ID3DX11EffectSamplerVariable* g_pSampler = NULL;

// 頂点定義
struct VERTEX
{
   // 頂点座標
   D3DXVECTOR3   pos;
   // 頂点カラー
   D3DXCOLOR   color;
   // テクセル
   D3DXVECTOR2 texel;
};

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

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

// リソースの初期化
HRESULT Init()
{
   HRESULT hr = E_FAIL;
   ID3D10Blob* pBlob = NULL;
   D3DX11_IMAGE_LOAD_INFO info;
   // 頂点の実データを設定
   VERTEX v[] = {
                  D3DXVECTOR3(  50.0f,  50.0f, 0.0f ), 0xFFFFFFFF, D3DXVECTOR2( 1.0f, 0.0f ),
                  D3DXVECTOR3( -50.0f,  50.0f, 0.0f ), 0xFFFFFFFF, D3DXVECTOR2( 0.0f, 0.0f ),
                  D3DXVECTOR3(  50.0f, -50.0f, 0.0f ), 0xFFFFFFFF, D3DXVECTOR2( 1.0f, 1.0f ),
                  D3DXVECTOR3( -50.0f, -50.0f, 0.0f ), 0xFFFFFFFF, D3DXVECTOR2( 0.0f, 1.0f ),
               };

   ID3D11SamplerState* pSamplerState = NULL;

   // 頂点バッファを作成する
   hr = g_pD3D11User->CreateVertexBuffer( &g_pVertexBuffer, v, sizeof( v ), 0 );
   if( FAILED( hr ) ) goto EXIT;

   // インデックスバッファを作成する。
   UINT Index[] = { 0, 1, 2, 3};
   hr = g_pD3D11User->CreateIndexBuffer( &g_pIndexBuffer, Index, sizeof( Index ), 0 );
   if( FAILED( hr ) ) goto EXIT;

   // ファイルからシェーダーリソースビューを作成する
   ::ZeroMemory( &info, sizeof( D3DX11_IMAGE_LOAD_INFO ) );
   info.Width = D3DX11_DEFAULT; 
   info.Height = D3DX11_DEFAULT; 
   info.Depth = D3DX11_DEFAULT; 
   info.FirstMipLevel = D3DX11_DEFAULT;          // テクスチャーの最高解像度のミップマップ レベル。実際の使用方法不明
   info.MipLevels = 0;                           // ミップマップ数。0 または D3DX11_DEFAULT を使用するとすべてのミップマップ チェーンを作成する
   info.Usage = D3D11_USAGE_DEFAULT; 
   info.BindFlags = D3D11_BIND_SHADER_RESOURCE;
   info.CpuAccessFlags = 0;
   info.MiscFlags = 0;
   info.Format = DXGI_FORMAT_FROM_FILE;
   info.Filter = D3DX11_FILTER_POINT;            // テクスチャー読み込み時に使用するフィルター
   info.MipFilter = D3DX11_FILTER_POINT;         // ミップマップ作成時に使用するフィルター
   info.pSrcInfo = NULL;
   hr = D3DX11CreateShaderResourceViewFromFile( g_pD3D11User->m_D3DDevice, _T("res\\01.jpg"), &info, NULL, &g_pSRView, NULL );
   if( FAILED( hr ) ) goto EXIT;

   // バイナリ エフェクトまたはバイナリ ファイルからエフェクトを作成
   // D3DX11CreateEffectFromMemory
   hr = D3DX11CreateEffectFromMemory( (void*)g_main, sizeof( g_main ), 0, g_pD3D11User->m_D3DDevice, &g_pEffect );
   if( FAILED( hr ) ) goto EXIT;

   // 深度ステンシルステートを作成する
   D3D11_DEPTH_STENCIL_DESC ddsDesc;
   ::ZeroMemory( &ddsDesc, sizeof( ddsDesc ) );
   ddsDesc.DepthEnable = TRUE;                                     // 深度テストを使用する
   ddsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
   ddsDesc.DepthFunc = D3D11_COMPARISON_LESS;
   ddsDesc.StencilEnable = FALSE;
   hr = g_pD3D11User->m_D3DDevice->CreateDepthStencilState( &ddsDesc, &g_pDepthStencilState );
   if( FAILED( hr ) ) goto EXIT;

   // 名前によってテクニックを取得
   // ID3DX11Effect::GetTechniqueByName
   g_pEffectTechnique = g_pEffect->GetTechniqueByName( "TShader" );
   if( g_pEffectTechnique->IsValid() == FALSE ){ hr = E_FAIL; goto EXIT; }

   // 取得したテクニックから名前によってパスを取得
   // ID3DX11EffectTechnique::GetPassByName
   g_pEffectPass = g_pEffectTechnique->GetPassByName( "P0" );
   if( g_pEffectPass->IsValid() == FALSE ){ hr = E_FAIL; goto EXIT; }
   // D3DX11_PASS_DESC
   D3DX11_PASS_DESC passDesc;
   g_pEffectPass->GetDesc( &passDesc );
   D3D11_INPUT_ELEMENT_DESC layout[] = {
         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
         { "COLOR"   , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,       0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
   };
   // 入力レイアウトを作成する
   hr = g_pD3D11User->m_D3DDevice->CreateInputLayout( layout, _countof( layout ), passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &g_pLayout );
   if( FAILED( hr ) ) goto EXIT;

   // ID3DX11EffectVariable
   ID3DX11EffectVariable* pVariable = NULL;

   // 名前によって定数バッファを取得
   // ID3DX11Effect::GetVariableByName
   pVariable = g_pEffect->GetVariableByName( "g_matWVP" );
   if( pVariable->IsValid() == FALSE ){ hr = E_FAIL; goto EXIT; }
   // ID3DX11EffectVariable::AsMatrix
   g_pMatWVP = pVariable->AsMatrix();

   // 名前によってシェーダーリソースを取得
   pVariable = g_pEffect->GetVariableByName( "g_Tex" );
   if( pVariable->IsValid() == FALSE ){ hr = E_FAIL; goto EXIT; }
   // ID3DX11EffectVariable::AsShaderResource
   g_pTex = pVariable->AsShaderResource();

   // 名前によってサンプラーステートを取得
   pVariable = g_pEffect->GetVariableByName( "g_Sampler" );
   if( pVariable->IsValid() == FALSE ){ hr = E_FAIL; goto EXIT; }
   // ID3DX11EffectVariable::AsSampler
   g_pSampler = pVariable->AsSampler();
   // サンプラーステートの作成
   D3D11_SAMPLER_DESC samplerDesc;
   samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;         // サンプリング時に使用するフィルタ。ここでは異方性フィルターを使用する。
   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 = 16;                        // サンプリングに異方性補間を使用している場合の限界値。有効な値は 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, &pSamplerState );
   if( FAILED( hr ) ) goto EXIT;
   // サンプラーステートは同一のエフェクト内で変更する必要することはあまりないと思うのでここで設定する。
   g_pSampler->SetSampler( 0, pSamplerState );

   hr = S_OK;

EXIT:
   SAFE_RELEASE( pSamplerState );
   SAFE_RELEASE( pBlob );
   return hr;
}

// メモリ開放
void Invalidate()
{
   SAFE_RELEASE( g_pEffect );
   SAFE_RELEASE( g_pDepthStencilState );
   SAFE_RELEASE( g_pLayout );
   SAFE_RELEASE( g_pIndexBuffer );
   SAFE_RELEASE( g_pVertexBuffer );
   SAFE_RELEASE( g_pSRView );

   SAFE_DELETE( g_pDebugFontUser );
   SAFE_DELETE( g_pD3D11User );
}

// 描画処理
HRESULT Render()
{
   HRESULT hr = E_FAIL;
   D3DXMATRIX matWorld, matView, matProj, matWVP;

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

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

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

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

   // インデックスバッファ設定
   g_pD3D11User->m_D3DDeviceContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );

   // レイアウト設定
   g_pD3D11User->m_D3DDeviceContext->IASetInputLayout( g_pLayout );

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

   // 深度テストを有効にする
   g_pD3D11User->m_D3DDeviceContext->OMSetDepthStencilState( g_pDepthStencilState, 0 );

   // アルファブレンディングを無効
   D3D11_RENDER_TARGET_BLEND_DESC BlendDesc;
   BlendDesc = g_pD3D11User->GetDefaultBlendDesc();
   g_pD3D11User->SetBlendState( &BlendDesc, 1, FALSE );

   // 射影行列
   D3DXMatrixPerspectiveFovLH( &matProj, 3.1415926f / 2.0f, 4.0f / 3.0f, 1.0f, 250.0f );
   // ビュー行列
   D3DXMatrixLookAtLH( &matView,
                       &D3DXVECTOR3( 0.0f, 0.0f, -60.0f ),
                       &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
                       &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
   // ワールド行列
   D3DXMatrixTranslation( &matWorld, 0.0f, 0.0f, 20.0f );
   matWVP = matWorld * matView * matProj;

   // 行列をエフェクトに設定
   // ID3DX11EffectMatrixVariable::SetMatrixTranspose
   g_pMatWVP->SetMatrixTranspose( (float*)( matWVP.m ) );

   // シェーダーリソースをエフェクトに設定
   // ID3DX11EffectShaderResourceVariable::SetResource
   g_pTex->SetResource( g_pSRView );

   // パスに含まれているステートをデバイスに設定
   // ID3DX11EffectPass::Apply
   g_pEffectPass->Apply( 0, g_pD3D11User->m_D3DDeviceContext );
   
   // 描画
   g_pD3D11User->m_D3DDeviceContext->DrawIndexed( 4, 0, 0 );

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

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

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

   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_KEYUP:
      // アプリ終了
      if( wParam == VK_ESCAPE )
         ::DestroyWindow( hWnd );

      // F2キーを押すと、ウィンドウモードを切り替える。
      // 自動的にウィンドウモードを切り替える機能もあるが、ウィンドウスタイルを自由に変更するために自分で実装することにした。
      if( wParam == VK_F2 )
      {
         g_pD3D11User->ChangeWindowMode();
      }
      // スクリーンショットを作成する
      if( wParam == VK_SNAPSHOT )
         ScreenShot = true;
      break;

   case WM_ACTIVATE:
      Activate = true;
      break;

// フルスクリーンからウィンドウモードに切り替えるとき WM_SIZE イベントが発生せず、結果的に IDXGISwapChain::ResizeBuffers がコールされない。
// 環境にもよるようだが、画面上に何も表示されない現象が発生する可能性があるので
// D3D11USER::ChangeWindowModeOptimization() は D3D11USER::ChangeWindowMode() 内でコールするように修正し、ここでの処理は無効にする
//   case WM_SIZE:
//      g_pD3D11User->ChangeWindowModeOptimization();
//      break;

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

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

   return 0L;
}

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

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

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

   // ディスプレイモード一覧を取得する。
   // 取得した値はクラス内部に保持される。
   hr = g_pD3D11User->GetDisplayMode();
   if( FAILED( hr ) )
   {
      ::MessageBox( NULL, _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, TRUE, TRUE );
   if( FAILED( hr ) )
   {
      ::MessageBox( NULL, _T("Direct3D 11.0 初期化エラー"), _T("初期化エラー"), MB_OK );
      goto EXIT;
   }

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

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

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

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

   ::UnregisterClass( AppName, hInstance );

   return msg.wParam;
}

エフェクト用のインクルードとライブラリのリンクは DX11User.h ではなく main.cpp に記述します。というのはエフェクトは今回限りの使い捨てにするつもりだからです(笑)。

---SimpleHLSL07.hlsl---


// ワールド行列 × ビュー × 射影行列
cbuffer cbMatrixWVP : register( b0 )
{
   // 列優先
   column_major  float4x4 g_matWVP : packoffset( c0 );
};

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

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

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

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

// 頂点シェーダー
VS_OUT VS_Main( VS_IN In )
{
   VS_OUT Out;

   Out.pos = mul( float4( In.pos, 1 ), g_matWVP );

   Out.color = In.color;

   Out.texel = In.texel;

   return Out;
}

// ピクセルシェーダ
float4 PS_Main( VS_OUT In ) : SV_TARGET
{
   // サンプラーを使用してサンプリング
   return g_Tex.Sample( g_Sampler, In.texel );
}

// エントリーポイントとバージョンを指定する
technique11 TShader
{
   pass P0
   {
      SetVertexShader( CompileShader( vs_5_0, VS_Main() ) );
      SetGeometryShader( NULL );
      SetHullShader( NULL );
      SetDomainShader( NULL );
      SetPixelShader(  CompileShader( ps_5_0, PS_Main() ) );
      SetComputeShader( NULL );
   }
}

でもってシェーダーソース。今回はエフェクトを使用するのでエントリーポイントとコンパイルするシェーダーのバージョンを指定する必要があります。 それが technique11 キーワードです。これは Direct3D 9 でも同じなので大丈夫でしょう。各種ステートの設定もここで行います。
で DirectX SDK (February 2010) ではバグってて、 technique11 キーワード内を上のように記述すると実行時エラーになりました。 Direct3D 10 から Direct3D 11 にレベルアップするとき、修正対象から漏れちゃったって感じのバグです。 DirectX SDK (June 2010) では修正されています。

ただこれとは別に fx_4_0 でコンパイルすると実行時エラーになるのは仕様なのだろうか? EffectBinaryFormat.h に↓


// versions must be listed in ascending order
static CONST EVersionTag g_EffectVersions[] = 
{
    { "fx_4_0", D3D10_FXL_VERSION(4,0),   0xFEFF1001 },
    { "fx_4_1", D3D10_FXL_VERSION(4,1),   0xFEFF1011 },
    { "fx_5_0", D3D10_FXL_VERSION(5,0),   0xFEFF2001 },
};

という記述があるので少なくとも fx_4_0 まではサポートしてるきがするが、どうもこの辺があやしい。 ただ少なくとも Direct3D 9 モードは対象外と考えたほうがいいようです。 実際シェーダーモデル 5 に対応していないビデオカードの環境で実行したところ、エラーになりました。 ただ不思議なのは D3DX11CreateEffectFromMemory の戻り値が S_OK のくせにデバックウィンドウにエラーが出力されます。意味わからん。
とりあえずこのサンプルでは fxc.exe を使用して SimpleHLSL07.hlsl をコンパイルしてますが、バージョンには必ず fx_5_0 を使用してください。

さて、そんな訳でエフェクトはそのまま使用するのはちょっと不安があるので、当サイトでは使用しないことにします。 ロジックを追っていくきも、修正する気もないので。


web拍手 by FC2

Prev Top Next

inserted by FC2 system