Delen via


Interfaces en klassen in effecten

Er zijn veel manieren om klassen en interfaces te gebruiken in Effecten 11. Zie Interfaces en klassenvoor interface- en klassesyntaxis.

In de volgende secties wordt beschreven hoe u klasse-exemplaren opgeeft aan een shader die gebruikmaakt van interfaces. In de voorbeelden gebruiken we de volgende interface en klassen:

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;

Let op: interface-exemplaren kunnen worden geïnitialiseerd naar klasse-exemplaren. Matrices van klasse- en interface-exemplaren worden ook ondersteund en kunnen worden geïnitialiseerd, zoals in het volgende voorbeeld:

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

Parameters voor uniforme interface

Net als bij andere uniforme gegevenstypen moeten uniforme interfaceparameters worden opgegeven in de CompileShader-aanroep. Interfaceparameters kunnen worden toegewezen aan globale interface-exemplaren of globale klasse-exemplaren. Wanneer deze is toegewezen aan een instantie van een globale interface, heeft de shader een afhankelijkheid van het interface-exemplaar. Dit betekent dat deze moet worden ingesteld op een klasse-exemplaar. Wanneer deze is toegewezen aan globale klasse-exemplaren, is de compiler gespecialiseerd in de shader (net als bij andere uniforme gegevenstypen) om die klasse te gebruiken. Dit is belangrijk voor twee scenario's:

  1. Shaders met een 4_x doel kunnen interfaceparameters gebruiken als deze parameters uniform zijn en worden toegewezen aan globale klasse-exemplaren (dus er wordt geen dynamische koppeling gebruikt).
  2. Gebruikers kunnen besluiten om veel gecompileerde, gespecialiseerde shaders zonder dynamische koppeling of weinig gecompileerde shaders met dynamische koppeling te hebben.
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) ) );
  }
}

Als pIColor2 ongewijzigd blijft via de API, zijn de vorige twee passen functioneel gelijkwaardig, maar de eerste gebruikt een ps_4_0 statische shader terwijl de tweede een ps_5_0 shader met dynamische koppeling gebruikt. Als pIColor2 wordt gewijzigd via de EFFECTEN-API (zie Instellingen van klasse-exemplaren hieronder), kan het gedrag van de pixel-shader in de tweede pas veranderen.

Niet-uniforme interfaceparameters

Niet-uniforme interfaceparameters maken interfaceafhankelijkheden voor de shaders. Wanneer u een shader met interfaceparameters toepast, moeten deze parameters worden toegewezen met de aanroep BindInterfaces. Globale interface-exemplaren en globale klasse-exemplaren kunnen worden opgegeven in de aanroep 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 ) );
  }
}

Als pIColor2 ongewijzigd blijft via de API, zijn de vorige twee passen functioneel gelijkwaardig en gebruiken beide dynamische koppeling. Als pIColor2 wordt gewijzigd via de EFFECTEN-API (zie Instellingen van klasse-exemplaren hieronder), kan het gedrag van de pixel-shader in de tweede pas veranderen.

Klasse-exemplaren instellen

Wanneer u een shader met dynamische shaderkoppeling instelt op het Direct3D 11-apparaat, moeten ook klasse-exemplaren worden opgegeven. Het is een fout om een dergelijke shader in te stellen met een NULL- klasse-exemplaar. Daarom moeten alle interface-exemplaren waarnaar een shader verwijst een gekoppeld klasse-exemplaar hebben.

In het volgende voorbeeld ziet u hoe u een klasse-exemplaarvariabele kunt ophalen uit een effect en deze instelt op een interfacevariabele:

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

effecten (Direct3D 11)