Shader Model 5 Interfaces and Classes

In the pixel shader, we first define base interfaces for different light and material types:

//--------------------------------------------------------------------------------------
   // Interfaces
   //--------------------------------------------------------------------------------------
   interface iBaseLight
   {
   float3 IlluminateAmbient(float3 vNormal);

   float3 IlluminateDiffuse(float3 vNormal);

   float3 IlluminateSpecular(float3 vNormal, int specularPower );

   };
   
   // ...
   interface iBaseMaterial
   {
   float3 GetAmbientColor(float2 vTexcoord);

   float3 GetDiffuseColor(float2 vTexcoord);

   int GetSpecularPower();

   };

   // ...

Next we build specialized classes based on these interfaces, adding to the functionality where needed:

//--------------------------------------------------------------------------------------
   // Classes
   //--------------------------------------------------------------------------------------
   class cAmbientLight : iBaseLight
   {
   float3	m_vLightColor;
   bool     m_bEnable;

   float3 IlluminateAmbient(float3 vNormal);

   float3 IlluminateDiffuse(float3 vNormal);

   float3 IlluminateSpecular(float3 vNormal, int specularPower );
   };

   // ...
   class cBaseMaterial : iBaseMaterial
   {
   float3	m_vColor;
   int      m_iSpecPower;

   float3 GetAmbientColor(float2 vTexcoord);

   float3 GetDiffuseColor(float2 vTexcoord);
   
   int GetSpecularPower();

   };
   // ....

Abstract Instances and The Shaders Main Function

The pixel shaders main function uses abstract instances of the interfaces for computation. These interfaces instances are made concrete by the application code at shader bind time:

/--------------------------------------------------------------------------------------
              // Abstract Interface Instances for dyamic linkage / permutation
              //--------------------------------------------------------------------------------------
              iBaseLight     g_abstractAmbientLighting;
              iBaseLight     g_abstractDirectLighting;
              iBaseMaterial  g_abstractMaterial;

              //--------------------------------------------------------------------------------------
              // Pixel Shader
              //--------------------------------------------------------------------------------------
              float4 PSMain( PS_INPUT Input ) : SV_TARGET
              {
                 // Compute the Ambient term
                 float3   Ambient = (float3)0.0f;

                 Ambient = g_abstractMaterial.GetAmbientColor( Input.vTexcoord ) * g_abstractAmbientLighting.IlluminateAmbient( Input.vNormal );

                 // Accumulate the Diffuse contribution
                 float3   Diffuse = (float3)0.0f;

                 Diffuse += g_abstractMaterial.GetDiffuseColor( Input.vTexcoord ) * g_abstractDirectLighting.IlluminateDiffuse( Input.vNormal );

                 // Compute the Specular contribution
                 float3   Specular = (float3)0.0f;
                 Specular += g_abstractDirectLighting.IlluminateSpecular( Input.vNormal, g_abstractMaterial.GetSpecularPower() );

                 // Accumulate the lighting with saturation
                 float3 Lighting = saturate( Ambient + Diffuse + Specular );

                 return float4(Lighting,1.0f);
                 }

// use shader reflection to get data locations for the interface array
ID3D11ShaderReflection* pReflector = NULL;
//ID3D11shaderReflection是访问shader信息的一个interface; V_RETURN( D3DReflect( pPixelShaderBuffer->GetBufferPointer(), pPixelShaderBuffer->GetBufferSize(),
//D3Dreflect函数用以create一个id3d11shaderreflection的interface; IID_ID3D11ShaderReflection, (void**) &pReflector) ); g_iNumPSInterfaces = pReflector->GetNumInterfaceSlots(); g_dynamicLinkageArray = (ID3D11ClassInstance**) malloc( sizeof(ID3D11ClassInstance*) * g_iNumPSInterfaces ); if (g_dynamicLinkageArray == NULL) return E_FAIL; ID3D11ShaderReflectionVariable* pAmbientLightingVar = pReflector->GetVariableByName("g_abstractAmbientLighting"); g_iAmbientLightingOffset = pAmbientLightingVar->GetInterfaceSlot(0); ID3D11ShaderReflectionVariable* pDirectLightingVar = pReflector->GetVariableByName("g_abstractDirectLighting"); g_iDirectLightingOffset = pDirectLightingVar->GetInterfaceSlot(0); ID3D11ShaderReflectionVariable* pMaterialVar = pReflector->GetVariableByName("g_abstractMaterial"); g_iMaterialOffset = pMaterialVar->GetInterfaceSlot(0); // ...

Next we enumerate all possible permutations of material object that exist in the shader:

// Material Dynamic Permutation
enum E_MATERIAL_TYPES
{
   MATERIAL_PLASTIC,
   MATERIAL_PLASTIC_TEXTURED,
   MATERIAL_PLASTIC_LIGHTING_ONLY,

   MATERIAL_ROUGH,
   MATERIAL_ROUGH_TEXTURED,
   MATERIAL_ROUGH_LIGHTING_ONLY,

   MATERIAL_TYPE_COUNT
};
char*  g_pMaterialClassNames[ MATERIAL_TYPE_COUNT ] =
{
   "g_plasticMaterial",             // cPlasticMaterial
   "g_plasticTexturedMaterial",     // cPlasticTexturedMaterial
   "g_plasticLightingOnlyMaterial", // cPlasticLightingOnlyMaterial
   "g_roughMaterial",               // cRoughMaterial
   "g_roughTexturedMaterial",       // cRoughTexturedMaterial
   "g_roughLightingOnlyMaterial"    // cRoughLightingOnlyMaterial
};
E_MATERIAL_TYPES            g_iMaterial = MATERIAL_PLASTIC_TEXTURED;


// ...

// Acquire the material Class Instances for all possible material settings
for( UINT i=0; i < MATERIAL_TYPE_COUNT; i++)
{
   g_pPSClassLinkage->GetClassInstance( g_pMaterialClassNames[i], 0, &g_pMaterialClasses[i] );
}

shader中(如果显卡不支持DX11,则STATIC_PERMUTE为True):

#if !defined( STATIC_PERMUTE ) iBaseLight g_abstractAmbientLighting; ... iBaseMaterial g_abstractMaterial; #else ... #define g_abstractAmbientLighting g_ambientLight #define g_abstractDirectLighting g_directionalLight #define g_abstractEnvironmentLighting g_environmentLight #define g_abstractMaterial g_plasticMaterial #endif

App中(D3DX11CompileFromFile的第二个参数就是D3D10_SHADER_MACRO *pDefines,预定义列表。显然预定义改变,需重新编译):

  1.    // Compile the shader using optional defines and an include handler for header processing static const D3D_SHADER_MACRO Shader_Macros[] = { "STATIC_PERMUTE", "1", NULL, NULL }; ID3DBlob* pErrorBlob; hr = D3DX11CompileFromFile( szFileName, &Shader_Macros[0], pIncludeHandler, szEntryPoint, szShaderModel, flags, 0, NULL, ppBlobOut, &pErrorBlob, NULL ); ...

  2. // Expand compressed vectors
    tmpNormal = R10G10B10A2_UNORM_TO_R32G32B32_FLOAT( Input.vNormal );

    float3 R10G10B10A2_UNORM_TO_R32G32B32_FLOAT( in float3 vVec )
    {
    vVec *= 2.0f;
    return vVec >= 1.0f ? ( vVec - 2.0f ) : vVec;
    }

 3.场景渲染时,动态指定父类指针实际子类实例。

shader:

 //interface

interface iBaseMaterial

{

float3 GetAmbientColor(float2 vTexcoord);

float3 GetDiffuseColor(float2 vTexcoord);

int GetSpecularPower();

};

//class

class cBaseMaterial:iBaseMaterial

{

float3 m_color;

int m_specularPower;

float3 GetAmbientColor(float2 vTexcoord){return m_color}

float3 GetDiffuseColor(float2 vTexcoord){return m_color}

int GetSpecularPower(){return m_specularPower}

};

//PlasticMaterial/

class cPlasticMaterial:cBaseMaterial

{};

class cPlasticTextureMaterial:cPlasticMaterial

{

float3 GetAmbientColor(float2 vTexcoord);

float3 GetDiffuseColor(float2 vTexcoord);

}

class cPlasticLightingOnlyMaterial : cBaseMaterial

{
float3 GetAmbientColor(float2 vTexcoord)
{
return (float3)1.0f;
}

float3 GetDiffuseColor(float2 vTexcoord)
{
return (float3)1.0f;
}

};

//RoughMaterial//

class cRoughMaterial : cBaseMaterial
{
int GetSpecularPower()
{
return m_iSpecPower;
}
};

class cRoughTexturedMaterial : cRoughMaterial
{
float3 GetAmbientColor(float2 vTexcoord);

float3 GetDiffuseColor(float2 vTexcoord);

};

class cRoughLightingOnlyMaterial : cRoughMaterial
{
float3 GetAmbientColor(float2 vTexcoord)
{
return (float3)1.0f;
}

float3 GetDiffuseColor(float2 vTexcoord)
{
return (float3)1.0f;
}

};

float4 PSMain( PS_INPUT Input ) : SV_TARGET
{
float3 Ambient = (float3)0.0f;
Ambient = g_abstractMaterial.GetAmbientColor( Input.vTexcoord ) * g_abstractAmbientLighting.IlluminateAmbient( Input.vNormal );

float3 Diffuse = (float3)0.0f;

Diffuse += g_abstractMaterial.GetDiffuseColor( Input.vTexcoord ) * g_abstractDirectLighting.IlluminateDiffuse( Input.vNormal );

float3 Specular = (float3)0.0f;
Specular += g_abstractDirectLighting.IlluminateSpecular( Input.vNormal, g_abstractMaterial.GetSpecularPower() );
Specular += g_abstractEnvironmentLighting.IlluminateSpecular( Input.vNormal, g_abstractMaterial.GetSpecularPower() );

float3 Lighting = saturate( Ambient + Diffuse + Specular );

return float4(Lighting,1.0f);
}

App中:
设置shader中声明的Interface的具体子类实例。

// 初始化阶段, 相当于初始化shader中各interface子类实例

ID3D11ClassLinkage* g_pPSClassLinkage= NULL;

truct CB_PS_PER_PRIMITIVE
{ D3DXVECTOR4 m_vObjectColorPlastic; // Plastic -.w is Specular Power

D3DXVECTOR4 m_vObjectColorPlasticTextured; // Plastic -.w is Specular Power 

D3DXVECTOR4 m_vObjectColorPlasticLightingOnly; // Plastic - Lighting Only

D3DXVECTOR4 m_vObjectColorRough; // Rough Material -.w is Specular Power
D3DXVECTOR4 m_vObjectColorRoughTextured; // Rough Material -.w is Specular Power
D3DXVECTOR4 m_vObjectColorRoughLightingOnly; // Rough Material -.w is Specular Power

};

enum E_MATERIAL_TYPES
{
MATERIAL_PLASTIC,
MATERIAL_PLASTIC_TEXTURED,
MATERIAL_PLASTIC_LIGHTING_ONLY,

MATERIAL_ROUGH,
MATERIAL_ROUGH_TEXTURED,
MATERIAL_ROUGH_LIGHTING_ONLY,

MATERIAL_TYPE_COUNT
};

char* g_pMaterialClassNames[ MATERIAL_TYPE_COUNT ] =
{
"g_plasticMaterial", // cPlasticMaterial
"g_plasticTexturedMaterial", // cPlasticTexturedMaterial
"g_plasticLightingOnlyMaterial", // cPlasticLightingOnlyMaterial
"g_roughMaterial", // cRoughMaterial
"g_roughTexturedMaterial", // cRoughTexturedMaterial
"g_roughLightingOnlyMaterial" // cRoughLightingOnlyMaterial
};

// use shader reflection to get data locations for the interface array

//shader中的metadata可以被reflection调用
ID3D11ShaderReflection* pReflector = NULL;
V_RETURN( D3DReflect( pPixelShaderBuffer->GetBufferPointer(), pPixelShaderBuffer-> GetBufferSize(), IID_ID3D11ShaderReflection, ( void**) & pReflector) );
g_iNumPSInterfaces = pReflector-> GetNumInterfaceSlots();
// shader中所有的interface指针构成的列表
g_dynamicLinkageArray = (ID3D11ClassInstance**) malloc( sizeof(ID3D11ClassInstance*) * g_iNumPSInterfaces );
ID3D11ShaderReflectionVariable* pMaterialVar = pReflector->GetVariableByName( " g_abstractMaterial " );
int g_iMaterialOffset = pMaterialVar->GetInterfaceSlot( 0 );
for( UINT i=0; i < MATERIAL_TYPE_COUNT; i++) { g_pPSClassLinkage->GetClassInstance( g_pMaterialClassNames[i], 0, &g_pMaterialClasses[i] ); //声明shader中各ClassInstance 


转载于:https://www.cnblogs.com/RenderLife/archive/2012/10/15/2720334.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值