Condividi tramite


Interfacce e classi negli effetti

Esistono molti modi per usare classi e interfacce in Effects 11. Per la sintassi dell'interfaccia e della classe, vedere Interfacce e classi.

Le sezioni seguenti illustrano in dettaglio come specificare istanze di classe per uno shader che usa interfacce. Negli esempi si useranno l'interfaccia e le classi seguenti:

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;

Si noti che le istanze dell'interfaccia possono essere inizializzate nelle istanze della classe. Sono supportate anche matrici di istanze di classe e di interfaccia e possono essere inizializzate come nell'esempio seguente:

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

Parametri dell'interfaccia uniforme

Analogamente ad altri tipi di dati uniformi, i parametri di interfaccia uniformi devono essere specificati nella chiamata CompileShader. I parametri di interfaccia possono essere assegnati a istanze di interfaccia globali o a istanze di classi globali. Quando assegnato a un'istanza di interfaccia globale, lo shader avrà una dipendenza dall'istanza dell'interfaccia, il che significa che deve essere impostato su un'istanza di classe. Quando assegnato alle istanze della classe globale, il compilatore è specializzato nello shader (come con altri tipi di dati uniformi) per l'uso di tale classe. Questo è importante per due scenari:

  1. Gli shader con una destinazione 4_x possono usare parametri di interfaccia se questi parametri sono uniformi e assegnati alle istanze della classe globale (pertanto non viene usato alcun collegamento dinamico).
  2. Gli utenti possono decidere di avere molti shader compilati e specializzati senza collegamento dinamico o con pochi shader compilati con collegamento dinamico.
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 rimane invariato tramite l'API, i due passaggi precedenti sono funzionalmente equivalenti, ma il primo usa uno shader statico ps_4_0 mentre il secondo usa un ps_5_0 shader con collegamento dinamico. Se pIColor2 viene modificato tramite l'API degli effetti (vedere Impostazione di istanze di classe di seguito), il comportamento del pixel shader nel secondo passaggio può cambiare.

Parametri di interfaccia non uniformi

I parametri di interfaccia non uniformi creano dipendenze dell'interfaccia per gli shader. Quando si applica uno shader con parametri di interfaccia, questi parametri devono essere assegnati in con la chiamata BindInterfaces. Le istanze dell'interfaccia globale e le istanze della classe globale possono essere specificate nella chiamata 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 rimane invariato tramite l'API, i due passaggi precedenti sono equivalenti a livello funzionale e entrambi usano il collegamento dinamico. Se pIColor2 viene modificato tramite l'API degli effetti (vedere Impostazione di istanze di classe di seguito), il comportamento del pixel shader nel secondo passaggio può cambiare.

Impostazione di istanze di classe

Quando si imposta uno shader con collegamento dello shader dinamico al dispositivo Direct3D 11, è necessario specificare anche le istanze di classe. Si tratta di un errore durante l'impostazione di tale shader con un'istanza di classe NULL. Pertanto, tutte le istanze dell'interfaccia a cui fa riferimento un shader devono avere un'istanza di classe associata.

L'esempio seguente illustra come ottenere una variabile di istanza di classe da un effetto e impostarla su una variabile di interfaccia:

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

effetti (Direct3D 11)