// GameObject.fx

#define NUM_INSTANCES_PER_CALL 60

//*************************************************************************************************************************************
// Instancing data
float4 vInstanceMatrixCol1[NUM_INSTANCES_PER_CALL];
float4 vInstanceMatrixCol2[NUM_INSTANCES_PER_CALL];
float4 vInstanceMatrixCol3[NUM_INSTANCES_PER_CALL];
float  fInstanceAlpha[NUM_INSTANCES_PER_CALL];

//*************************************************************************************************************************************
// Material Color
float4 fMaterialColor = { 1.0f, 1.0f, 1.0f, 1.0f };

//*************************************************************************************************************************************
// Textures and Samplers
texture texDiffuse;
texture texClamped;

sampler g_samDiffuse =
sampler_state
{
    Texture = <texDiffuse>;
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
};

sampler g_samClamped =
sampler_state
{
    Texture = <texClamped>;
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = None;
    AddressU = Clamp;
    AddressV = Clamp;
};

bool bUseDiffuseTex = true;
bool bTexFlipped = false;

//*************************************************************************************************************************************
// Transform Data
float4x4 ViewProj    : VIEWPROJECTION;
float4x4 ViewInverse : VIEWINVERSE;

//*************************************************************************************************************************************
// Lighting Data
float4 LightPos0      = { 0.0f, 0.0f, 0.0f, 0.0f };   // Light 0 Position
float4 LightPos1      = { 0.0f, 0.0f, 0.0f, 0.0f };   // Light 1 Position
float4 LightDiffuse0  = { 0.0f, 1.0f, 0.0f, 1.0f };   // Light Diffuse
float4 LightDiffuse1  = { 1.0f, 0.0f, 0.0f, 1.0f };   // Light Diffuse
float4 LightAmbient   = { 0.3f, 0.3f, 0.3f, 1.0f };   // Light Ambient

float4 EyePos;

float SpecularExponent = 155.0f;
float Kd = 0.9f;
float Ks = 0.8f;
float LightIntensity = 1.0f;

float2 vTexScale = float2 (1.0f,1.0f);
float2 vTexOffset = float2 (0.0f,0.0f);

//*************************************************************************************************************************************
// Vertex Shaders
//*************************************************************************************************************************************

void VS_HWBatch_Plastic (    float4 vPos                            : POSITION, 
                                float3 vNormal                      : NORMAL,
                                float3 vTangent                     : TANGENT,
                                float2 vTex0                        : TEXCOORD0,
                                float4 vMatrixCol1                  : TEXCOORD1,
                                float4 vMatrixCol2                  : TEXCOORD2,
                                float4 vMatrixCol3                  : TEXCOORD3,
                                float  fAlpha                       : TEXCOORD7,
                                out float4 hPos                     : POSITION,
                                out float2 vTex0Out                 : TEXCOORD0,
                                out float3 LightVec0                : TEXCOORD1,
                                out float3 LightVec1                : TEXCOORD2,
                                out float3 WorldNormal              : TEXCOORD3,
                                out float3 WorldTangent             : TEXCOORD4,
                                out float3 WorldView                : TEXCOORD5,
                                out float  AlphaOut                 : TEXCOORD6
                               )
{
            
    float4 vMatrixRow1 = float4 ( vMatrixCol1.x, vMatrixCol2.x, vMatrixCol3.x, 0.0f );
    float4 vMatrixRow2 = float4 ( vMatrixCol1.y, vMatrixCol2.y, vMatrixCol3.y, 0.0f );
    float4 vMatrixRow3 = float4 ( vMatrixCol1.z, vMatrixCol2.z, vMatrixCol3.z, 0.0f );
    float4 vMatrixRow4 = float4 ( vMatrixCol1.w, vMatrixCol2.w, vMatrixCol3.w, 1.0f );

    float4x4 vInstanceMatrix = float4x4 ( vMatrixRow1, vMatrixRow2, vMatrixRow3, vMatrixRow4 );
  
    AlphaOut = fAlpha;
    
       
    float4 Po = float4( vPos.xyz, 1.0f); 
    float4 Pw = mul ( Po, vInstanceMatrix );

    float4 vLightWorldPos1 = mul ( LightPos1, ViewInverse );
    

    LightVec0 = normalize ( LightPos0.xyz - Pw.xyz );
    LightVec1 = normalize ( vLightWorldPos1.xyz - Po.xyz );

    vTex0Out = vTex0;
    
    WorldView = EyePos - Pw.xyz;    
    hPos = mul ( Pw, ViewProj );

    vInstanceMatrix._41 = vInstanceMatrix._42 = vInstanceMatrix._43 = 0.0f;
    WorldNormal = mul ( vNormal, vInstanceMatrix).xyz;
    WorldTangent = mul ( vTangent, vInstanceMatrix ).xyz;
  
               
}


void VS_HWBatch_Plastic_Scaled (    float4 vPos                            : POSITION, 
                                    float3 vNormal                      : NORMAL,
                                    float3 vTangent                     : TANGENT,
                                    float2 vTex0                        : TEXCOORD0,
                                    float4 vMatrixCol1                  : TEXCOORD1,
                                    float4 vMatrixCol2                  : TEXCOORD2,
                                    float4 vMatrixCol3                  : TEXCOORD3,
                                    float  fAlpha                       : TEXCOORD7,
                                    out float4 hPos                     : POSITION,
                                    out float2 vTex0Out                 : TEXCOORD0,
                                    out float3 LightVec0                : TEXCOORD1,
                                    out float3 LightVec1                : TEXCOORD2,
                                    out float3 WorldNormal              : TEXCOORD3,
                                    out float3 WorldTangent             : TEXCOORD4,
                                    out float3 WorldView                : TEXCOORD5,
                                    out float  AlphaOut                 : TEXCOORD6
                               )
{
            
    float4 vMatrixRow1 = float4 ( vMatrixCol1.x, vMatrixCol2.x, vMatrixCol3.x, 0.0f );
    float4 vMatrixRow2 = float4 ( vMatrixCol1.y, vMatrixCol2.y, vMatrixCol3.y, 0.0f );
    float4 vMatrixRow3 = float4 ( vMatrixCol1.z, vMatrixCol2.z, vMatrixCol3.z, 0.0f );
    float4 vMatrixRow4 = float4 ( vMatrixCol1.w, vMatrixCol2.w, vMatrixCol3.w, 1.0f );

    float4x4 vInstanceMatrix = float4x4 ( vMatrixRow1, vMatrixRow2, vMatrixRow3, vMatrixRow4 );
  
    AlphaOut = fAlpha;
    
   
    float4 Po = float4( vPos.xyz, 1.0f); 
    float4 Pw = mul ( Po, vInstanceMatrix );
    

    float4 vLightWorldPos1 = mul ( LightPos1, ViewInverse );

   
    LightVec0 = normalize ( LightPos0.xyz - Po.xyz );
    LightVec1 = normalize ( vLightWorldPos1.xyz - Po.xyz );

    WorldView = EyePos - Pw.xyz;    
    hPos = mul ( Pw, ViewProj );

    // scale the tex coord
    float b = ( 0.5f * vTexScale.x ) - 0.5f;
    float s = ( 2.0f - vTexScale.x );
    
    vTex0Out.x = ( vTex0.x * s ) + b;
    if ( bTexFlipped )        
        vTex0Out.x = 1.0f - vTex0Out.x;
    
    b = ( 0.5f * vTexScale.y ) - 0.5f;
    s = ( 2.0f - vTexScale.y );

    vTex0Out.y = ( vTex0.y * s ) + b;

    vTex0Out.x += (vTexOffset.x * (1.0f - vTexScale.x) * 0.5f);
    vTex0Out.y += (vTexOffset.y * (1.0f - vTexScale.y) * 0.5f);

    vInstanceMatrix._41 = vInstanceMatrix._42 = vInstanceMatrix._43 = 0.0f;
    WorldNormal = mul ( vNormal, vInstanceMatrix).xyz;
    WorldTangent = mul ( vTangent, vInstanceMatrix ).xyz;

               
}


void VS_SHBatch_Plastic(    float4 vPos                         : POSITION, 
                            float3 vNormal                      : NORMAL,
                            float3 vTangent                     : TANGENT,
                            float2 vTex0                        : TEXCOORD0,
                            float  fInstanceIndex               : TEXCOORD1,
                            out float4 hPos                     : POSITION,
                            out float2 vTex0Out                 : TEXCOORD0,
                            out float3 LightVec0                : TEXCOORD1,
                            out float3 LightVec1                : TEXCOORD2,
                            out float3 WorldNormal              : TEXCOORD3,
                            out float3 WorldTangent             : TEXCOORD4,
                            out float3 WorldView                : TEXCOORD5,
                            out float AlphaOut                  : TEXCOORD6 )
{           
   

    float4 vMatrixRow1 = float4 ( vInstanceMatrixCol1[fInstanceIndex].x, vInstanceMatrixCol2[fInstanceIndex].x, vInstanceMatrixCol3[fInstanceIndex].x, 0.0f );
    float4 vMatrixRow2 = float4 ( vInstanceMatrixCol1[fInstanceIndex].y, vInstanceMatrixCol2[fInstanceIndex].y, vInstanceMatrixCol3[fInstanceIndex].y, 0.0f );
    float4 vMatrixRow3 = float4 ( vInstanceMatrixCol1[fInstanceIndex].z, vInstanceMatrixCol2[fInstanceIndex].z, vInstanceMatrixCol3[fInstanceIndex].z, 0.0f );
    float4 vMatrixRow4 = float4 ( vInstanceMatrixCol1[fInstanceIndex].w, vInstanceMatrixCol2[fInstanceIndex].w, vInstanceMatrixCol3[fInstanceIndex].w, 1.0f );

    float4x4 vInstanceMatrix = float4x4 ( vMatrixRow1, vMatrixRow2, vMatrixRow3, vMatrixRow4 );
  
    AlphaOut = fInstanceAlpha[fInstanceIndex];
     
  
    float4 Po = float4( vPos.xyz, 1.0f); 
    float4 Pw = mul ( Po, vInstanceMatrix );
    
    float4 vLightWorldPos1 = mul ( LightPos1, ViewInverse );
    

    LightVec0 = normalize ( LightPos0.xyz - Po.xyz );
    LightVec1 = normalize ( vLightWorldPos1.xyz - Po.xyz );

    vTex0Out = vTex0;
        

    WorldView = EyePos - Pw.xyz;    
    hPos = mul ( Pw, ViewProj );

         
    vInstanceMatrix._41 = vInstanceMatrix._42 = vInstanceMatrix._43 = 0.0f;
    WorldNormal = mul ( vNormal, vInstanceMatrix).xyz;
    WorldTangent = mul ( vTangent, vInstanceMatrix ).xyz;


}

void VS_SHBatch_Plastic_Scaled (    float4 vPos                         : POSITION, 
                            float3 vNormal                      : NORMAL,
                            float3 vTangent                     : TANGENT,
                            float2 vTex0                        : TEXCOORD0,
                            float  fInstanceIndex               : TEXCOORD1,
                            out float4 hPos                     : POSITION,
                            out float2 vTex0Out                 : TEXCOORD0,
                            out float3 LightVec0                : TEXCOORD1,
                            out float3 LightVec1                : TEXCOORD2,
                            out float3 WorldNormal              : TEXCOORD3,
                            out float3 WorldTangent             : TEXCOORD4,
                            out float3 WorldView                : TEXCOORD5,
                            out float  AlphaOut                 : TEXCOORD6 )
{

    float4 vMatrixRow1 = float4 ( vInstanceMatrixCol1[fInstanceIndex].x, vInstanceMatrixCol2[fInstanceIndex].x, vInstanceMatrixCol3[fInstanceIndex].x, 0.0f );
    float4 vMatrixRow2 = float4 ( vInstanceMatrixCol1[fInstanceIndex].y, vInstanceMatrixCol2[fInstanceIndex].y, vInstanceMatrixCol3[fInstanceIndex].y, 0.0f );
    float4 vMatrixRow3 = float4 ( vInstanceMatrixCol1[fInstanceIndex].z, vInstanceMatrixCol2[fInstanceIndex].z, vInstanceMatrixCol3[fInstanceIndex].z, 0.0f );
    float4 vMatrixRow4 = float4 ( vInstanceMatrixCol1[fInstanceIndex].w, vInstanceMatrixCol2[fInstanceIndex].w, vInstanceMatrixCol3[fInstanceIndex].w, 1.0f );

    float4x4 vInstanceMatrix = float4x4 ( vMatrixRow1, vMatrixRow2, vMatrixRow3, vMatrixRow4 );
  
    AlphaOut = fInstanceAlpha[fInstanceIndex];
     
  
    float4 Po = float4( vPos.xyz, 1.0f); 
    float4 Pw = mul ( Po, vInstanceMatrix );
    
    float4 vLightWorldPos1 = mul ( LightPos1, ViewInverse );
    

    LightVec0 = normalize ( LightPos0.xyz - Po.xyz );
    LightVec1 = normalize ( vLightWorldPos1.xyz - Po.xyz );


    vTex0Out = vTex0;
    
    WorldView = EyePos - Pw.xyz;    
    hPos = mul ( Pw, ViewProj );
    
    // scale the tex coord
    float b = ( 0.5f * vTexScale.x ) - 0.5f;
    float s = ( 2.0f - vTexScale.x );
    
    vTex0Out.x = ( vTex0.x * s ) + b;
    if ( bTexFlipped )        
        vTex0Out.x = 1.0f - vTex0Out.x;
    
    b = ( 0.5f * vTexScale.y ) - 0.5f;
    s = ( 2.0f - vTexScale.y );

    vTex0Out.y = ( vTex0.y * s ) + b;

    vTex0Out.x += (vTexOffset.x * (1.0f - vTexScale.x) * 0.5f);
    vTex0Out.y += (vTexOffset.y * (1.0f - vTexScale.y) * 0.5f);


    vInstanceMatrix._41 = vInstanceMatrix._42 = vInstanceMatrix._43 = 0.0f;
    WorldNormal = mul ( vNormal, vInstanceMatrix).xyz;
    WorldTangent = mul ( vTangent, vInstanceMatrix ).xyz;


}


//*************************************************************************************************************************************
// Pixel Shaders
//*************************************************************************************************************************************
 

void PS_Plastic_Shared (                float4 hPos                         : POSITION,
                                        float2 vTex0                        : TEXCOORD0,
                                        float3 LightVec                    : TEXCOORD1,
                                        float3 WorldNormal                  : TEXCOORD2,
                                        float3 WorldTangent                 : TEXCOORD3,
                                        float3 WorldView                    : TEXCOORD4,
                                        float3 LightColor,
                                        out float3 DiffuseContrib,
                                        out float3 SpecularContrib                             ) 
{
    float3 Ln = normalize ( LightVec.xyz );
    float3 Nn = normalize ( WorldNormal ); 
    float3 Vn = normalize ( WorldView );
    float3 Hn = normalize ( Vn + Ln );
    float4 litV = lit(dot(Nn,Ln),dot(Nn,Hn),SpecularExponent);
    
    DiffuseContrib = litV.y * Kd * LightColor + LightAmbient;
    SpecularContrib = litV.z * Ks * LightColor;
           
}

float4 PS_Plastic_Textured ( float4 hPos                         : POSITION,
                             float2 vTex0                        : TEXCOORD0,
                             float3 LightVec0                    : TEXCOORD1,
                             float3 LightVec1                    : TEXCOORD2,
                             float3 WorldNormal                  : TEXCOORD3,
                             float3 WorldTangent                 : TEXCOORD4,
                             float3 WorldView                    : TEXCOORD5,
                             float  Alpha                        : TEXCOORD6 ) : COLOR0
{
   
    float3 diffContrib0, diffContrib1;
    float3 specContrib0, specContrib1;
    
    float3 Col0 = ( LightIntensity / dot ( LightVec0.xyz, LightVec0.xyz ) ) * LightDiffuse0;
   
    PS_Plastic_Shared ( hPos, vTex0, LightVec0, WorldNormal, WorldTangent, WorldView, Col0, diffContrib0, specContrib0 );

    float3 Col1 = ( LightIntensity / dot ( LightVec1.xyz, LightVec1.xyz ) ) * LightDiffuse1;
    
    PS_Plastic_Shared ( hPos, vTex0, LightVec1, WorldNormal, WorldTangent, WorldView, Col1, diffContrib1, specContrib1 );
    
    float4 map = tex2D ( g_samDiffuse, vTex0 );
    float3 result;
    if ( bUseDiffuseTex )
    {
		map = ( (fMaterialColor * ( 1 - map.a )) + (map * map.a) ); // Decal blending
		result = saturate ( specContrib0 + ( map.rgb * diffContrib0 ) +
				 specContrib1 + ( map.rgb * diffContrib1 ) );
	}
    else
        result = saturate ( specContrib0 + ( fMaterialColor * diffContrib0 ) +
                 specContrib1 + ( fMaterialColor * diffContrib1 ) );

    return float4 ( result, 1.0f );
}


float4 PS_Plastic_Textured_Scaled ( float4 hPos                         : POSITION,
                                              float2 vTex0                        : TEXCOORD0,
                                              float3 LightVec0                    : TEXCOORD1,
                                              float3 LightVec1                    : TEXCOORD2,
                                              float3 WorldNormal                  : TEXCOORD3,
                                              float3 WorldTangent                 : TEXCOORD4,
                                              float3 WorldView                    : TEXCOORD5,
                                              float Alpha                        : TEXCOORD6 ) : COLOR0
{
    

    float3 diffContrib0, diffContrib1;
    float3 specContrib0, specContrib1;
    
    float3 Col0 = ( LightIntensity / dot ( LightVec0.xyz, LightVec0.xyz ) ) * LightDiffuse0;
   
    PS_Plastic_Shared ( hPos, vTex0, LightVec0, WorldNormal, WorldTangent, WorldView, Col0, diffContrib0, specContrib0 );

    float3 Col1 = ( LightIntensity / dot ( LightVec1.xyz, LightVec1.xyz ) ) * LightDiffuse1;
    
    PS_Plastic_Shared ( hPos, vTex0, LightVec1, WorldNormal, WorldTangent, WorldView, Col1, diffContrib1, specContrib1 );
    
    float4 map = tex2D ( g_samClamped, vTex0 );
    float4 result;
    if ( bUseDiffuseTex )
        result = float4 ( saturate ( specContrib0 + ( map * diffContrib0 ) +
                 specContrib1 + ( map * diffContrib1 ) ), map.a );
    else
        result = float4 ( saturate ( specContrib0 + ( fMaterialColor * diffContrib0 ) +
                 specContrib1 + ( fMaterialColor * diffContrib1 ) ), fMaterialColor.a );

    return result;
}

float4 PS_Plastic_Textured_Transparency ( float4 hPos                         : POSITION,
                                          float2 vTex0                        : TEXCOORD0,
                                          float3 LightVec0                    : TEXCOORD1,
                                          float3 LightVec1                    : TEXCOORD2,
                                          float3 WorldNormal                  : TEXCOORD3,
                                          float3 WorldTangent                 : TEXCOORD4,
                                          float3 WorldView                    : TEXCOORD5,
                                          float3 Alpha                        : TEXCOORD6 ) : COLOR0
{
   
    float3 diffContrib0, diffContrib1;
    float3 specContrib0, specContrib1;
    
    float3 Col0 = ( LightIntensity / dot ( LightVec0.xyz, LightVec0.xyz ) ) * LightDiffuse0;
   
    PS_Plastic_Shared ( hPos, vTex0, LightVec0, WorldNormal, WorldTangent, WorldView, Col0, diffContrib0, specContrib0 );

    float3 Col1 = ( LightIntensity / dot ( LightVec1.xyz, LightVec1.xyz ) ) * LightDiffuse1;
    
    PS_Plastic_Shared ( hPos, vTex0, LightVec1, WorldNormal, WorldTangent, WorldView, Col1, diffContrib1, specContrib1 );
    
    float4 map = tex2D ( g_samDiffuse, vTex0 );
    float3 result = saturate ( specContrib0 + ( fMaterialColor * map * diffContrib0 ) +
                 specContrib1 + ( fMaterialColor * map * diffContrib1 ) );

    return float4 ( result, map.a );
}




//*************************************************************************************************************************************
// Techniques
//*************************************************************************************************************************************

technique HWBatching20
{
    pass P0
    {
        AlphaBlendEnable = false;
        CullMode = None; 
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_HWBatch_Plastic();
        PixelShader  = compile ps_2_0 PS_Plastic_Textured();        
    }      

    pass P1
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
       // AlphaTestEnable = true;
       // AlphaFunc = greaterequal;
       // AlphaRef = 255;
        VertexShader = compile vs_2_0 VS_HWBatch_Plastic ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Transparency();
    }

    pass P2
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_HWBatch_Plastic_Scaled ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Scaled ();
    }

}

technique HWBatching_Diffuse20
{
    pass P0
    {
        AlphaBlendEnable = false;
        CullMode = None; 
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_HWBatch_Plastic();
        PixelShader  = compile ps_2_0 PS_Plastic_Textured();        
    }      

    pass P1
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
        //AlphaTestEnable = true;
        //AlphaFunc = greaterequal;
        //AlphaRef = 255;
        VertexShader = compile vs_2_0 VS_HWBatch_Plastic ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Transparency();
    }

    pass P2
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_HWBatch_Plastic_Scaled ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Scaled ();
    }

}

technique SHBatching20
{
    pass P0
    {
        AlphaBlendEnable = false;
        CullMode = None; 
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_SHBatch_Plastic();
        PixelShader  = compile ps_2_0 PS_Plastic_Textured();        
    }      

    pass P1
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
        //AlphaTestEnable = true;
       // AlphaFunc = greaterequal;
       // AlphaRef = 255;
        VertexShader = compile vs_2_0 VS_SHBatch_Plastic ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Transparency();
    }

    pass P2
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_SHBatch_Plastic_Scaled ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Scaled ();
    }

}


technique SHBatching_Diffuse20
{
    pass P0
    {
        AlphaBlendEnable = false;
        CullMode = None; 
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_SHBatch_Plastic();
        PixelShader  = compile ps_2_0 PS_Plastic_Textured();        
    }      

    pass P1
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
        //AlphaTestEnable = true;
        //AlphaFunc = greaterequal;
        //AlphaRef = 255;
        VertexShader = compile vs_2_0 VS_SHBatch_Plastic ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Transparency();
    }

    pass P2
    {
        AlphaBlendEnable = true;
        CullMode = None;
        ZEnable = true;
        ZWriteEnable = true;
        VertexShader = compile vs_2_0 VS_SHBatch_Plastic_Scaled ();
        PixelShader = compile ps_2_0 PS_Plastic_Textured_Scaled ();
    }

}

