效果中的介面和類別
在 Effects 11 中使用類別和介面的方法有很多種。 如需介面和類別語法,請參閱 介面和類別。
下列各節將詳細說明如何將類別實例指定給使用介面的著色器。 我們將在範例中使用下列介面和類別:
interface IColor
{
float4 GetColor();
};
class CRed : IColor
{
float4 GetColor() { return float4(1,0,0,1); }
};
class CGreen : IColor
{
float4 GetColor() { return float4(0,1,0,1); }
};
CRed pRed;
CGreen pGreen;
IColor pIColor;
IColor pIColor2 = pRed;
請注意,介面實例可以初始化為類別實例。 類別和介面實例的陣列也受到支援,而且可以如下列範例所示進行初始化:
CRed pRedArray[2];
IColor pIColor3 = pRedArray[1];
IColor pIColorArray[2] = {pRed, pGreen};
IColor pIColorArray2[2] = pRedArray;
統一介面參數
就像其他統一數據類型一樣,必須在 CompileShader 呼叫中指定統一介面參數。 介面參數可以指派給全域介面實例或全域類別實例。 指派給全域介面實例時,著色器會相依於介面實例,這表示它必須設定為類別實例。 指派給全域類別實例時,編譯程式會特製化著色器(如同其他統一數據類型),以使用該類別。 這在兩個案例中很重要:
- 如果這些參數是統一且指派給全域類別實例,則具有4_x目標的著色器可以使用介面參數(因此不會使用動態連結)。
- 用戶可以決定有許多經過編譯的特製化著色器,且沒有動態連結,或少數具有動態連結的已編譯著色器。
float4 PSUniform( uniform IColor color ) : SV_Target
{
return color;
}
technique11
{
pass
{
SetPixelShader( CompileShader( ps_4_0, PSUniform(pRed) ) );
}
pass
{
SetPixelShader( CompileShader( ps_5_0, PSUniform(pIColor2) ) );
}
}
如果 pIColor2 透過 API 維持不變,則前兩個階段的功能相等,但第一個階段會使用ps_4_0靜態著色器,而第二個階段則使用具有動態連結的ps_5_0著色器。 如果 pIColor2 透過效果 API 變更(請參閱下面的設定類別實例),則第二階段圖元著色器的行為可能會變更。
非統一介面參數
非統一介面參數會建立著色器的介面相依性。 使用介面參數套用著色器時,必須使用 BindInterfaces 呼叫來指派這些參數。 您可以在 BindInterfaces 呼叫中指定全域介面實例和全域類別實例。
float4 PSAbstract( IColor color ) : SV_Target
{
return color;
}
PixelShader pPSAbstract = CompileShader( ps_5_0, PSAbstract(pRed) );
technique11
{
pass
{
SetPixelShader( BindInterfaces( pPSAbstract, pRed ) );
}
pass
{
SetPixelShader( BindInterfaces( pPSAbstract, pIColor2 ) );
}
}
如果 pIColor2 透過 API 維持不變,則前兩個階段的功能相等,且兩者都使用動態連結。 如果 pIColor2 透過效果 API 變更(請參閱下面的設定類別實例),則第二階段圖元著色器的行為可能會變更。
設定類別實例
使用 Direct3D 11 裝置的動態著色器連結來設定著色器時,也必須指定類別實例。 使用 NULL 類別實例來設定這類著色器是錯誤的。 因此,著色器參考的所有介面實例都必須有相關聯的類別實例。
下列範例示範如何從效果取得類別實例變數,並將其設定為介面變數:
ID3DX11EffectPass* pPass = pEffect->GetTechniqueByIndex(0)->GetPassByIndex(1);
ID3DX11EffectInterfaceVariable* pIface = pEffect->GetVariableByName( "pIColor2" )->AsInterface();
ID3DX11EffectClassInstanceVariable* pCI = pEffect->GetVariableByName( "pGreen" )->AsClassInstance();
pIface->SetClassInstance( pCI );
pPass->Apply( 0, pDeviceContext );
// Apply the same pass with a different class instance
pCI = pEffect->GetVariableByName( "pRedArray" )->GetElement(1)->AsClassInstance();
pIface->SetClassInstance( pCI );
pPass->Apply( 0, pDeviceContext );
相關主題