Condividi tramite


Interfacce e classi negli effetti

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

Le sezioni seguenti illustrano in dettaglio come specificare le istanze della classe in un shader che usa interfacce. Verranno usate le interfacce e le classi seguenti negli esempi:

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 in istanze di classe. Anche le matrici di istanze di classe e interfaccia sono supportate 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, è necessario specificare parametri di interfaccia uniformi nella chiamata CompileShader. I parametri dell'interfaccia possono essere assegnati alle istanze dell'interfaccia globale o alle istanze della classe globale. 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 collegamenti dinamici o 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 un 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 delle istanze della classe di seguito), il comportamento del pixel shader nel secondo passaggio potrebbe cambiare.

Parametri di interfaccia non uniformi

I parametri dell'interfaccia non uniformi creano dipendenze dell'interfaccia per gli shader. Quando si applica uno shader con parametri di interfaccia, questi parametri devono essere assegnati 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 funzionalmente equivalenti e entrambi usano il collegamento dinamico. Se pIColor2 viene modificato tramite l'API degli effetti (vedere Impostazione delle istanze della classe di seguito), il comportamento del pixel shader nel secondo passaggio potrebbe cambiare.

Impostazione delle istanze della classe

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

Nell'esempio seguente viene illustrato 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)