float4 ambientColor  : register (c0);
float4 diffuseColor  : register (c1);
float4 worldLight    : register (c2);
float4 specularColor : register (c3); //power in c3.a

struct PS_INPUT
{
   float4 Color  : COLOR0;
   float4 Omni   : COLOR1;
   float  Fog    : FOG;
#if NUMTEX > 3
   float4 Tex0    : TEXCOORD0; // base0 + base1
   float4 Tex1    : TEXCOORD1; // base2 + base3
   float2 Spec    : TEXCOORD2; // specular map
   float3 Normal  : TEXCOORD3; // world space vertex normal
   float3 EyeVec  : TEXCOORD4; // world space eye vec
#elif NUMTEX > 2
   float4 Tex0    : TEXCOORD0; // base0 + base1
   float4 Tex1    : TEXCOORD1; // base2 + spec map
   float3 Normal  : TEXCOORD2; // world space vertex normal
   float3 EyeVec  : TEXCOORD3; // world space eye vec
#elif NUMTEX > 1   
   float4 Tex0    : TEXCOORD0; // base0 + base1
   float2 Spec    : TEXCOORD1; // specular map
   float3 Normal  : TEXCOORD2; // world space vertex normal
   float3 EyeVec  : TEXCOORD3; // world space eye vec
#else   
   float4 Tex0    : TEXCOORD0; // base0 + specular map
   float3 Normal  : TEXCOORD1; // world space vertex normal
   float3 EyeVec  : TEXCOORD2; // world space eye vec
#endif   
};

struct PS_OUTPUT
{
   float4 Color : COLOR0;
};

sampler2D sTex0: register (s0);

#if NUMTEX > 3 // only doing a limited number of 4-stage + spec map for now

 sampler2D sTex1: register (s1);
 sampler2D sTex2: register (s2);
 sampler2D sTex3: register (s3);
 sampler2D sSpec: register (s4);

 #if MULTEX == 0
  PS_OUTPUT ps20_blinnSpecMapT0T1T2T3 (PS_INPUT Input)
 #elif MULTEX == 1 
  PS_OUTPUT ps20_blinnSpecMapT0xT1T2T3 (PS_INPUT Input)
 #endif 

#elif NUMTEX > 2

 sampler2D sTex1: register (s1);
 sampler2D sTex2: register (s2);
 sampler2D sSpec: register (s3);

 #if MULTEX == 0
  PS_OUTPUT ps20_blinnSpecMapT0T1T2 (PS_INPUT Input)
 #elif MULTEX == 1 
  PS_OUTPUT ps20_blinnSpecMapT0xT1T2 (PS_INPUT Input)
 #elif MULTEX == 2 
  PS_OUTPUT ps20_blinnSpecMapT0T1xT2 (PS_INPUT Input)
 #elif MULTEX == 3 
  PS_OUTPUT ps20_blinnSpecMapT0xT1xT2 (PS_INPUT Input)
 #endif 

#elif NUMTEX > 1

 sampler2D sTex1: register (s1);
 sampler2D sSpec: register (s2);

 #if   LERPALPHA == 1
  PS_OUTPUT ps20_blinnSpecMapT0lerpT1VertexAlpha (PS_INPUT Input)
 #elif MULTEX == 0
  PS_OUTPUT ps20_blinnSpecMapT0T1 (PS_INPUT Input)
 #elif MULTEX == 1 
  PS_OUTPUT ps20_blinnSpecMapT0xT1 (PS_INPUT Input)
 #endif 

#else
 
 sampler2D sSpec: register (s1);
 
 PS_OUTPUT ps20_blinnSpecMapT0Custom (PS_INPUT Input)

#endif
{
  PS_OUTPUT Out;
  
  float4 tex = tex2D (sTex0, Input.Tex0.xy);        // sample base tex
  
#if NUMTEX > 3

  float4 tex1 = tex2D (sTex1, Input.Tex0.zw);  // sample base tex
  float4 tex2 = tex2D (sTex2, Input.Tex1.xy);  // sample base tex
  float4 tex3 = tex2D (sTex3, Input.Tex1.zw);  // sample base tex
  float4 spec = tex2D (sSpec, Input.Spec.xy);  // sample spec tex (gloss)

 #if MULTEX == 0
   tex = saturate (tex + tex1 + tex2 + tex3);
 #elif MULTEX == 1 
   tex = saturate (tex * tex1 + tex2 + tex3);
 #endif

#elif NUMTEX > 2

  float4 tex1 = tex2D (sTex1, Input.Tex0.zw);  // sample base tex
  float4 tex2 = tex2D (sTex2, Input.Tex1.xy);  // sample base tex
  float4 spec = tex2D (sSpec, Input.Tex1.zw);  // sample spec tex (gloss)

 #if MULTEX == 0
   tex = saturate (tex + tex1 + tex2);
 #elif MULTEX == 1 
   tex = saturate (tex * tex1 + tex2);
 #elif MULTEX == 2 
   tex = saturate (tex + tex1 * tex2);
 #elif MULTEX == 3 
   tex = saturate (tex * tex1 * tex2);
 #endif

#elif NUMTEX > 1

  float4 tex1 = tex2D (sTex1, Input.Tex0.zw);  // sample base tex
  float4 spec = tex2D (sSpec, Input.Spec.xy);  // sample spec tex (gloss)

 #if   LERPALPHA == 1
   tex = lerp (tex1, tex, Input.Color.a);
 #elif MULTEX == 0
   tex = saturate (tex + tex1);
 #elif MULTEX == 1 
   tex = (tex * tex1);
 #endif

#else

  float4 spec = tex2D (sSpec, Input.Tex0.zw);  // sample spec tex (gloss)

#endif

  float3 normal = normalize (Input.Normal);
  
  // compute specular color
  float3 halfway = normalize (worldLight - normalize(Input.EyeVec)); 
  half4 specular;
  specular.rgb = saturate ((pow (dot (halfway, normal), specularColor.a) * specularColor)) * spec;
  //specular.rgb = saturate ((pow (dot (halfway, normal), specularColor.a) * specularColor) + Input.Omni) * spec;
  specular.a = 0;

  // compute diffuse color
  half4 diffuse = saturate ((saturate (dot (worldLight, normal))) * diffuseColor + ambientColor + Input.Omni) * tex;
  
  Out.Color = (diffuse + specular) * Input.Color;
  return (Out);
}
