Interfaces e classes em efeitos

Há várias maneiras de usar classes e interfaces em Efeitos 11. Para obter a sintaxe de interface e classe, consulte Interfaces e classes.

As seções a seguir detalham como especificar instâncias de classe para um sombreador que usa interfaces. Usaremos a seguinte interface e classes nos exemplos:

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;

Observe que as instâncias de interface podem ser inicializadas para instâncias de classe. Matrizes de instâncias de classe e interface também têm suporte e podem ser inicializadas como no exemplo a seguir:

CRed pRedArray[2];
IColor pIColor3 = pRedArray[1];
IColor pIColorArray[2] = {pRed, pGreen};
IColor pIColorArray2[2] = pRedArray;

Parâmetros de interface uniforme

Assim como outros tipos de dados uniformes, os parâmetros de interface uniforme devem ser especificados na chamada CompileShader. Os parâmetros de interface podem ser atribuídos a instâncias de interface global ou instâncias de classe global. Quando atribuído a uma instância de interface global, o sombreador terá uma dependência na instância de interface, o que significa que ele deve ser definido como uma instância de classe. Quando atribuído a instâncias de classe globais, o compilador especializa o sombreador (como com outros tipos de dados uniformes) para usar essa classe. Isso é importante para dois cenários:

  1. Sombreadores com um destino 4_x poderão usar parâmetros de interface se esses parâmetros forem uniformes e atribuídos a instâncias de classe globais (portanto, nenhuma vinculação dinâmica será usada).
  2. Os usuários podem decidir ter muitos sombreadores compilados e especializados sem vinculação dinâmica ou poucos sombreadores compilados com vinculação dinâmica.
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) ) );
  }
}

Se pIColor2 permanecer inalterado por meio da API, as duas passagens anteriores serão funcionalmente equivalentes, mas a primeira usará um sombreador estático ps_4_0 enquanto o segundo usará um sombreador ps_5_0 com vinculação dinâmica. Se pIColor2 for alterado por meio da API de efeitos (consulte Configurando instâncias de classe abaixo), o comportamento do sombreador de pixel na segunda passagem poderá ser alterado.

Parâmetros de interface não uniformes

Parâmetros de interface não uniformes criam dependências de interface para os sombreadores. Ao aplicar um sombreador com parâmetros de interface, esses parâmetros devem ser atribuídos com a chamada BindInterfaces. Instâncias de interface global e instâncias de classe global podem ser especificadas na chamada 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 ) );
  }
}

Se pIColor2 permanecer inalterado por meio da API, as duas passagens anteriores serão funcionalmente equivalentes e ambas usarão a vinculação dinâmica. Se pIColor2 for alterado por meio da API de efeitos (consulte Configurando instâncias de classe abaixo), o comportamento do sombreador de pixel na segunda passagem poderá ser alterado.

Definindo instâncias de classe

Ao definir um sombreador com vinculação de sombreador dinâmico para o dispositivo Direct3D 11, as instâncias de classe também devem ser especificadas. É um erro definir esse sombreador com uma instância de classe NULL . Portanto, todas as instâncias de interface que um sombreador referencia devem ter uma instância de classe associada.

O exemplo a seguir mostra como obter uma variável de instância de classe de um efeito e defini-la como uma variável de interface:

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 );

Efeitos (Direct3D 11)