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;
#ifdef OMNISCALE
   float4 Omni   : COLOR1;
#endif
   float  Fog    : FOG;
   float4 TexCoord01    : TEXCOORD0;    // T0, Spec0
   float4 Normal        : TEXCOORD2;    // xyz - normal, w - omniSpec
   float3 EyeVec        : TEXCOORD4;    // xyz - eyeVec, w - fresnel power
};

struct PS_OUTPUT
{
   float4 Color : COLOR0;
};

sampler2D sTex0   : register (s0);
sampler2D sSpec0  : register (s1);
samplerCUBE sCube : register (s2);
sampler2D sShading : register (s3);

PS_OUTPUT MAINFUNCTION (PS_INPUT Input) 
{
  PS_OUTPUT Out;

  // Sample the textures
  float4 tex =  tex2D(sTex0, Input.TexCoord01.xy);
#ifdef ALPHATEST
  if (tex.a < ALPHATEST)
  {
    discard;
  }
#endif
  float4 spec = tex2D(sSpec0, Input.TexCoord01.zw);

  float3 normal = normalize(Input.Normal.xyz);

  float3 normEyeVec = normalize (Input.EyeVec.xyz);

  float3 reflectVec = reflect(normEyeVec, normal);

  float2 specular = tex2D(sShading, float2(saturate(dot (reflectVec, worldLight)), 0.0)).gb;
  specular.x = specular.x * 256.0 + specular.y;

  // Compute diffuse color
  float4 diffuse = saturate(dot (worldLight, normal)) * diffuseColor + ambientColor;
#ifdef OMNISCALE
  diffuse = diffuse + Input.Omni;
#endif

  // Compute cube map vector [E - 2(E dot N)N], then sample the cube map
  float4 cube = texCUBE (sCube, reflectVec);
  float dayTime = saturate(ambientColor.b * 2.0);
  cube.rgb *= 1.6;
  cube *= dayTime;

  // Calculate fresnel effect for better reflections
  float dotEyeVecNormal = abs(dot(normEyeVec, normal));

  // Use the specular alpha for reflection amount and add fresnel to that
  float2 fresnel = tex2D(sShading, float2(dotEyeVecNormal, 0.0)).ra;
  fresnel.x = fresnel.x / 256.0 + fresnel.y;

  //less reflection during night
  fresnel *= tex.a;

  specular = specular * cube.a;

  Out.Color = (tex * Input.Color * diffuse) +
                   ((cube + specularColor * specular.x + float4(1.0, 0.9, 0.8, 0.0) * Input.Normal.w) * spec) *
                   fresnel.x;
  Out.Color.a = 1.0;

  return (Out);
}
