設定 Direct3D 11 (效果狀態)
某些效果常數只需要初始化。 初始化之後,效果狀態會設定為整個轉譯迴圈的裝置。 每次呼叫轉譯迴圈時,都必須更新其他變數。 設定效果變數的基本程式碼如下所示,適用于每個變數類型。
效果會封裝執行轉譯階段所需的所有轉譯狀態。 就 API 而言,效果中封裝了三種類型的狀態。
常數狀態
首先,使用 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();
}
第三,使用更新方法來設定效果變數中應用程式中變數的值。
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 );
}
取得效果變數中狀態的兩種方式
有兩種方式可以取得包含在效果變數中的狀態。 假設已載入記憶體的效果。
其中一種方式是從已轉換成取樣器介面的 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 );
}
另一種方式是從 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 ) ) );
}
}
這就像您未使用效果一樣。 有三個呼叫,每種類型的著色器 (頂點、幾何和圖元) 。 第一個 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();
第二個步驟是指定用來存取紋理的檢視。 檢視會定義從紋理資源存取資料的一般方式。
OnD3D11FrameRender()
{
ID3D11ShaderResourceView* pDiffuseRV = NULL;
...
pDiffuseRV = g_Mesh11.GetMaterial(pSubset->MaterialID)->pDiffuseRV11;
g_ptxDiffuse->SetResource( pDiffuseRV );
...
}
從應用程式的觀點來看,未排序存取檢視的處理方式類似于著色器資源檢視。 不過,在效果圖元著色器和計算著色器函式中,未排序的存取檢視資料會從/寫入直接讀取/寫入。 您無法從未排序的存取檢視進行取樣。
如需檢視資源的詳細資訊,請參閱 資源。
相關主題