Bagikan melalui


Antarmuka dan Kelas dalam Efek

Ada banyak cara untuk menggunakan kelas dan antarmuka di Efek 11. Untuk sintaks antarmuka dan kelas, lihat Antarmuka dan Kelas.

Bagian berikut merinci cara menentukan instans kelas ke shader yang menggunakan antarmuka. Kami akan menggunakan antarmuka dan kelas berikut dalam contoh:

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;

Perhatikan bahwa instans antarmuka dapat diinisialisasi ke instans kelas. Array instans kelas dan antarmuka juga didukung dan dapat diinisialisasi seperti dalam contoh berikut:

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

Parameter Antarmuka Seragam

Sama seperti jenis data seragam lainnya, parameter antarmuka seragam harus ditentukan dalam panggilan CompileShader. Parameter antarmuka dapat ditetapkan ke instans antarmuka global atau instans kelas global. Saat ditetapkan ke instans antarmuka global, shader akan memiliki dependensi pada instans antarmuka, yang berarti harus diatur ke instans kelas. Saat ditetapkan ke instans kelas global, pengkompilasi mengkhususkan shader (seperti halnya jenis data seragam lainnya) untuk menggunakan kelas tersebut. Ini penting untuk dua skenario:

  1. Shader dengan target 4_x dapat menggunakan parameter antarmuka jika parameter ini seragam dan ditetapkan ke instans kelas global (sehingga tidak ada tautan dinamis yang digunakan).
  2. Pengguna dapat memutuskan untuk memiliki banyak shader khusus yang dikompilasi tanpa tautan dinamis atau beberapa shader yang dikompilasi dengan tautan dinamis.
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) ) );
  }
}

Jika pIColor2 tetap tidak berubah melalui API, maka dua pass sebelumnya setara secara fungsional, tetapi yang pertama menggunakan shader statis ps_4_0 sementara yang kedua menggunakan shader ps_5_0 dengan tautan dinamis. Jika pIColor2 diubah melalui API efek (lihat Mengatur Instans Kelas di bawah), perilaku shader piksel di pass kedua dapat berubah.

Parameter Antarmuka Non-Seragam

Parameter antarmuka non-seragam membuat dependensi antarmuka untuk shader. Saat menerapkan shader dengan parameter antarmuka, parameter ini harus ditetapkan dengan panggilan BindInterfaces. Instans antarmuka global dan instans kelas global dapat ditentukan dalam panggilan 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 ) );
  }
}

Jika pIColor2 tetap tidak berubah melalui API, maka dua pass sebelumnya setara secara fungsional dan keduanya menggunakan linkage dinamis. Jika pIColor2 diubah melalui API efek (lihat Mengatur Instans Kelas di bawah), perilaku shader piksel di pass kedua dapat berubah.

Mengatur Instans Kelas

Saat mengatur shader dengan tautan shader dinamis ke perangkat Direct3D 11, instans kelas juga harus ditentukan. Ini adalah kesalahan untuk mengatur shader seperti itu dengan instans kelas NULL . Oleh karena itu, semua instans antarmuka yang referensi shader harus memiliki instans kelas terkait.

Contoh berikut menunjukkan cara mendapatkan variabel instans kelas dari efek dan mengaturnya ke variabel antarmuka:

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

Efek (Direct3D 11)