在 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 );
相关主题