エフェクト ステートの設定 (Direct3D 10)
一部のエフェクト定数は、初期化だけが必要です。一度初期化すると、レンダリング ループ全体についてエフェクト ステートがデバイスに設定されます。その他の変数は、レンダリング ループが呼び出されるたびに更新する必要があります。次に、エフェクト変数の設定の基本コードを変数型別に示します。
1 つのエフェクトによって、レンダリング パスの実行に必要なレンダリング ステートすべてがカプセル化されます。API に関しては、エフェクトでカプセル化されるステートは 3 種類あります。
- 定数ステート
- シェーダー ステート
- テクスチャー ステート
定数ステート
最初に、HLSL データ型を使用して、エフェクトで変数を宣言します。
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float4 g_MaterialAmbientColor; // Material's ambient color
float4 g_MaterialDiffuseColor; // Material's diffuse color
int g_nNumLights;
float3 g_LightDir[3]; // Light's direction in world space
float4 g_LightDiffuse[3]; // Light's diffuse color
float4 g_LightAmbient; // Light's ambient color
Texture2D g_MeshTexture; // Color texture for mesh
float g_fTime; // App's time in seconds
float4x4 g_mWorld; // World matrix for object
float4x4 g_mWorldViewProjection; // World * View * Projection matrix
2 番目に、アプリケーションによって設定できる変数をアプリケーションで宣言してから、エフェクト変数を更新します。
D3DXMATRIX mWorldViewProjection;
D3DXVECTOR3 vLightDir[MAX_LIGHTS];
D3DXVECTOR4 vLightDiffuse[MAX_LIGHTS];
D3DXMATRIX mWorld;
D3DXMATRIX mView;
D3DXMATRIX mProj;
// Get the projection and view matrix from the camera class
mWorld = g_mCenterMesh * *g_Camera.GetWorldMatrix();
mProj = *g_Camera.GetProjMatrix();
mView = *g_Camera.GetViewMatrix();
OnD3D10CreateDevice()
{
...
g_pLightDir = g_pEffect10->GetVariableByName( "g_LightDir" )->AsVector();
g_pLightDiffuse = g_pEffect10->GetVariableByName( "g_LightDiffuse" )->AsVector();
g_pmWorldViewProjection = g_pEffect10->GetVariableByName(
"g_mWorldViewProjection" )->AsMatrix();
g_pmWorld = g_pEffect10->GetVariableByName( "g_mWorld" )->AsMatrix();
g_pfTime = g_pEffect10->GetVariableByName( "g_fTime" )->AsScalar();
g_pMaterialAmbientColor = g_pEffect10->GetVariableByName("g_MaterialAmbientColor")->AsVector();
g_pMaterialDiffuseColor = g_pEffect10->GetVariableByName(
"g_MaterialDiffuseColor" )->AsVector();
g_pnNumLights = g_pEffect10->GetVariableByName( "g_nNumLights" )->AsScalar();
}
3 番目に、更新メソッドを使用して、エフェクト変数の変数値をアプリケーションで設定します。
OnD3D10FrameRender()
{
...
g_pLightDir->SetRawValue( vLightDir, 0, sizeof(D3DXVECTOR3)*MAX_LIGHTS );
g_pLightDiffuse->SetFloatVectorArray( (float*)vLightDiffuse, 0, MAX_LIGHTS );
g_pmWorldViewProjection->SetMatrix( (float*)&mWorldViewProjection );
g_pmWorld->SetMatrix( (float*)&mWorld );
g_pfTime->SetFloat( (float)fTime );
g_pnNumLights->SetInt( g_nNumActiveLights );
}
エフェクト変数のステートを取得する 2 つの方法
エフェクト変数に含まれるステートを取得するには 2 つの方法があります。エフェクトはメモリーにロードされていると仮定します。
1 つ目の方法では、サンプラー インターフェイスとしてキャストされている ID3D10EffectVariable インターフェイスからサンプラー ステートを取得します。
D3D10_SAMPLER_DESC sampler_desc;
ID3D10EffectVariable* l_pD3D10EffectVariable = NULL;
if( g_pEffect10 )
{
l_pD3D10EffectVariable = g_pEffect10->GetVariableByName( "MeshTextureSampler" );
if( l_pD3D10EffectVariable )
hr = (l_pD3D10EffectVariable->AsSampler())->GetBackingStore( 0,
&sampler_desc );
}
2 つ目の方法では、ID3D10SamplerState インターフェイスからサンプラー ステートを取得します。
ID3D10SamplerState* l_ppSamplerState = NULL;
D3D10_SAMPLER_DESC sampler_desc;
ID3D10EffectVariable* l_pD3D10EffectVariable = NULL;
if( g_pEffect10 )
{
l_pD3D10EffectVariable = g_pEffect10->GetVariableByName( "MeshTextureSampler" );
if( l_pD3D10EffectVariable )
{
hr = (l_pD3D10EffectVariable->AsSampler())->GetSampler( 0,
&l_ppSamplerState );
if( l_ppSamplerState )
l_ppSamplerState->GetDesc( &sampler_desc );
}
}
シェーダー ステート
シェーダー ステートは、パス内で、エフェクト テクニックで宣言され、割り当てられます。
technique10 RenderSceneWithTexture1Light
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, RenderSceneVS( 1, true, true ) ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, RenderScenePS( true ) ) );
}
}
この処理は、エフェクトを使用しない場合の処理と同様です。シェーダーのタイプ (頂点、ジオメトリ、およびピクセル) ごとに 1 回の計 3 回の呼び出しが実行されます。最初の呼び出しは、SetVertexShader で、ID3D10Device::VSSetShader が呼び出されます。CompileShader は、シェーダー プロファイル (vs_4_0) と頂点シェーダー関数 (RenderVS) の名前を取得する特殊なエフェクト関数です。つまり、これらの SetXXXShader 呼び出しそれぞれによって、関連付けられているシェーダー関数がコンパイルされ、コンパイルされたシェーダーへのポインターが返されます。
テクスチャー ステート
テクスチャー ステートは、変数の設定より少し複雑です。テクスチャー データは変数のように単に読み取られるのではなく、テクスチャーからサンプリングされるためです。このため、(テクスチャー タイプが使用されること以外は通常の変数と同様に) テクスチャー変数を定義して、サンプリング条件を定義する必要があります。次に、テクスチャー変数の宣言と、対応するサンプリング ステートの宣言の例を示します。
Texture2D g_MeshTexture; // Color texture for mesh
SamplerState MeshTextureSampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
次に、アプリケーションからテクスチャーを設定する例を示します。この例では、テクスチャーは、エフェクトの作成時にロードされたメッシュ データに格納されます。
最初の手順で、(メッシュの) エフェクトからテクスチャーへのポインターを取得します。
ID3D10EffectShaderResourceVariable* g_ptxDiffuse = NULL;
// Obtain variables
g_ptxDiffuse = g_pEffect10->GetVariableByName( "g_MeshTexture" )->AsShaderResource();
次の手順で、テクスチャーにアクセスするためのビューを指定します。このビューによって、テクスチャー リソースからデータにアクセスする一般的な方法が定義されます。
OnD3D10FrameRender()
{
ID3D10ShaderResourceView* pDiffuseRV = NULL;
...
pDiffuseRV = g_Mesh10.GetMaterial(pSubset->MaterialID)->pDiffuseRV10;
g_ptxDiffuse->SetResource( pDiffuseRV );
...
}
リソースの表示の詳細については、「テクスチャー ビュー (Direct3D 10)」を参照してください。