効果の状態の設定 (Direct3D 11)
一部の効果定数は初期化するだけで済みます。 初期化されると、効果の状態は、レンダー ループ全体のデバイスに設定されます。 レンダー ループが呼び出されるたびに、他の変数を更新する必要があります。 効果変数を設定するための基本的なコードを、変数の種類ごとに次に示します。
効果は、レンダリング パスを実行するために必要なすべてのレンダリング状態をカプセル化します。 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
次に、アプリケーションで設定できる変数をアプリケーションで宣言し、効果変数を更新します。
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();
OnD3D11CreateDevice()
{
...
g_pLightDir = g_pEffect11->GetVariableByName( "g_LightDir" )->AsVector();
g_pLightDiffuse = g_pEffect11->GetVariableByName( "g_LightDiffuse" )->AsVector();
g_pmWorldViewProjection = g_pEffect11->GetVariableByName(
"g_mWorldViewProjection" )->AsMatrix();
g_pmWorld = g_pEffect11->GetVariableByName( "g_mWorld" )->AsMatrix();
g_pfTime = g_pEffect11->GetVariableByName( "g_fTime" )->AsScalar();
g_pMaterialAmbientColor = g_pEffect11->GetVariableByName("g_MaterialAmbientColor")->AsVector();
g_pMaterialDiffuseColor = g_pEffect11->GetVariableByName(
"g_MaterialDiffuseColor" )->AsVector();
g_pnNumLights = g_pEffect11->GetVariableByName( "g_nNumLights" )->AsScalar();
}
3 つ目は、update メソッドを使用して、エフェクト変数内のアプリケーション内の変数の値を設定することです。
OnD3D11FrameRender()
{
...
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 つの方法は、サンプラー インターフェイスとしてキャストされた ID3DX11EffectVariable からサンプラーの状態を取得することです。
D3D11_SAMPLER_DESC sampler_desc;
ID3D11EffectSamplerVariable* l_pD3D11EffectVariable = NULL;
if( g_pEffect11 )
{
l_pD3D11EffectVariable = g_pEffect11->GetVariableByName( "MeshTextureSampler" )->AsSampler();
if( l_pD3D11EffectVariable->IsValid() )
hr = (l_pD3D11EffectVariable->GetBackingStore( 0,
&sampler_desc );
}
もう 1 つの方法は、 ID3D11SamplerState からサンプラーの状態を取得することです。
ID3D11SamplerState* l_ppSamplerState = NULL;
D3D11_SAMPLER_DESC sampler_desc;
ID3D11EffectSamplerVariable* l_pD3D11EffectVariable = NULL;
if( g_pEffect11 )
{
l_pD3D11EffectVariable = g_pEffect11->GetVariableByName( "MeshTextureSampler" )->AsSampler();
if( l_pD3D11EffectVariable->IsValid )
{
hr = l_pD3D11EffectVariable->GetSampler( 0,
&l_ppSamplerState );
if( l_ppSamplerState )
l_ppSamplerState->GetDesc( &sampler_desc );
}
}
シェーダーの状態
シェーダーの状態は、パス内でエフェクト手法で宣言され、割り当てられます。
VertexShader vsRenderScene = CompileShader( vs_4_0, RenderSceneVS( 1, true, true );
technique10 RenderSceneWithTexture1Light
{
pass P0
{
SetVertexShader( vsRenderScene );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, RenderScenePS( true ) ) );
}
}
これは、効果を使用していない場合と同じように機能します。 シェーダーの種類 (頂点、ジオメトリ、ピクセル) ごとに 1 つずつ、3 つの呼び出しがあります。 最初の SetVertexShader は ID3D11DeviceContext::VSSetShader を呼び出します。 CompileShader は、シェーダー プロファイル (vs_4_0) と頂点シェーダー関数 (RenderVS) の名前を受け取る特殊効果関数です。 つまり、これらの各 CompileShader 呼び出しは、関連付けられたシェーダー関数をコンパイルし、コンパイルされたシェーダーへのポインターを返します。
すべてのシェーダーの状態を設定する必要があることに注意してください。 このパスには、SetHullShader または SetDomainShader 呼び出しは含まれません。つまり、現在バインドされているハル シェーダーとドメイン シェーダーは変更されません。
テクスチャの状態
テクスチャの状態は変数を設定するよりも少し複雑です。テクスチャ データは単に変数のように読み取られないため、テクスチャからサンプリングされます。 したがって、テクスチャ変数 (テクスチャ型を使用する以外は通常の変数と同様) を定義し、サンプリング条件を定義する必要があります。 テクスチャ変数宣言と、対応するサンプリング状態宣言の例を次に示します。
Texture2D g_MeshTexture; // Color texture for mesh
SamplerState MeshTextureSampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
アプリケーションからテクスチャを設定する例を次に示します。 この例では、テクスチャは、効果の作成時に読み込まれたメッシュ データに格納されます。
最初の手順では、(メッシュから) 効果からテクスチャへのポインターを取得します。
ID3D11EffectShaderResourceVariable* g_ptxDiffuse = NULL;
// Obtain variables
g_ptxDiffuse = g_pEffect11->GetVariableByName( "g_MeshTexture" )->AsShaderResource();
2 番目の手順では、テクスチャにアクセスするためのビューを指定します。 ビューは、テクスチャ リソースからデータにアクセスするための一般的な方法を定義します。
OnD3D11FrameRender()
{
ID3D11ShaderResourceView* pDiffuseRV = NULL;
...
pDiffuseRV = g_Mesh11.GetMaterial(pSubset->MaterialID)->pDiffuseRV11;
g_ptxDiffuse->SetResource( pDiffuseRV );
...
}
アプリケーションの観点からは、順序付けられていないアクセス ビューはシェーダー リソース ビューと同様に処理されます。 ただし、エフェクト ピクセル シェーダーとコンピューティング シェーダー関数では、順序付けられていないアクセス ビュー データの読み取り/書き込みが直接行われます。 順序付けられていないアクセス ビューからサンプリングすることはできません。
リソースの表示の詳細については、「 リソース」を参照してください。
関連トピック