效果中的接口和类

可通过多种方式使用效果 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 调用中指定统一接口参数。 可以将接口参数分配给全局接口实例或全局类实例。 当分配给全局接口实例时,着色器将依赖于接口实例,这意味着它必须设置为类实例。 当分配给全局类实例时,编译器将着色器 (专用于其他统一数据类型,) 使用该类。 这在两种方案中非常重要:

  1. 如果具有4_x目标的着色器是统一的,并且分配给全局类实例 (因此) 不使用动态链接,则可以使用这些接口参数。
  2. 用户可以决定使用许多没有动态链接的已编译的专用着色器,或者将几个具有动态链接的已编译着色器。
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着色器。 如果通过效果 API 更改 pIColor2 (请参阅下面的设置类实例) ,则第二次传递中的像素着色器的行为可能会更改。

非统一接口参数

非统一接口参数为着色器创建接口依赖项。 使用接口参数应用着色器时,必须使用 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 保持不变,则前两个传递在功能上是等效的,并且都使用动态链接。 如果通过效果 API 更改 pIColor2 (请参阅下面的设置类实例) ,则第二次传递中的像素着色器的行为可能会更改。

设置类实例

使用动态着色器链接设置到 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 );

Direct3D 11) (效果