Sdílet prostřednictvím


Rozhraní a třídy v efektech

Třídy a rozhraní v efektech 11 lze použít mnoha způsoby. Informace o syntaxi rozhraní a tříd naleznete v tématu Rozhraní a třídy.

Následující části podrobně popisuje, jak určit instance třídy do shaderu, který používá rozhraní. V příkladech použijeme následující rozhraní a třídy:

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;

Všimněte si, že instance rozhraní lze inicializovat na instance třídy. Pole instancí třídy a rozhraní jsou také podporována a lze je inicializovat jako v následujícím příkladu:

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

Parametry jednotného rozhraní

Stejně jako jiné jednotné datové typy musí být parametry jednotného rozhraní zadány ve volání CompileShader. Parametry rozhraní lze přiřadit k instancím globálního rozhraní nebo instancím globální třídy. Při přiřazení k instanci globálního rozhraní bude shader mít závislost na instanci rozhraní, což znamená, že musí být nastavena na instanci třídy. Při přiřazení k instancím globální třídy se kompilátor specializuje na použití této třídy shader (stejně jako u jiných jednotných datových typů). To je důležité pro dva scénáře:

  1. Shadery s cílem 4_x můžou používat parametry rozhraní, pokud jsou tyto parametry jednotné a přiřazené k instancím globální třídy (takže se nepoužívá dynamické propojení).
  2. Uživatelé se můžou rozhodnout mít mnoho kompilovaných specializovaných shaderů bez dynamického propojení nebo několika zkompilovaných shaderů s dynamickým propojením.
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) ) );
  }
}

Pokud pIColor2 zůstane beze změny prostřednictvím rozhraní API, jsou předchozí dva průchody funkčně ekvivalentní, ale první používá ps_4_0 statický shader, zatímco druhý používá ps_5_0 shader s dynamickým propojením. Pokud se pIColor2 změní prostřednictvím rozhraní API efektů (viz nastavení instancí tříd níže), může se změnit chování shaderu pixelů v druhém průchodu.

Parametry rozhraní, které nejsou jednotné

Ne uniformní parametry rozhraní vytvářejí závislosti rozhraní pro shadery. Při použití shaderu s parametry rozhraní musí být tyto parametry přiřazeny volání BindInterfaces. Instance globálního rozhraní a instance globální třídy lze zadat ve volání 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 ) );
  }
}

Pokud pIColor2 zůstane beze změny prostřednictvím rozhraní API, jsou předchozí dva průchody funkčně ekvivalentní a oba používají dynamické propojení. Pokud se pIColor2 změní prostřednictvím rozhraní API efektů (viz nastavení instancí tříd níže), může se změnit chování shaderu pixelů v druhém průchodu.

Nastavení instancí třídy

Při nastavování shaderu s dynamickým propojením shaderu se zařízením Direct3D 11 musí být také zadány instance tříd. Jedná se o chybu nastavení takového shaderu s NULL instance třídy. Proto všechny instance rozhraní, na které odkazuje shader, musí mít přidruženou instanci třídy.

Následující příklad ukazuje, jak získat proměnnou instance třídy z efektu a nastavit ji na proměnnou rozhraní:

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

efekty (Direct3D 11)