//
// Standard
//

#include "atmosphere.cg"
#include "lighting.cg"
#include "fresnel.cg"
#include "shadowmapping.cg"

// Vertex to pixel shader structure
struct v2p
{
  float2 tc0            : TEXCOORD0;
  float3 Direction      : TEXCOORD1;
  float4 RayleighColor  : TEXCOORD2;
  float4 MieColor       : TEXCOORD3;
  float4 Position       : TEXCOORD4;    // For fragment shader
  float3 normal         : TEXCOORD5;
  float3 I              : TEXCOORD6;
  //float  fresnel        : TEXCOORD6;
  float3 R              : TEXCOORD7;    // Reflection vector
  float  extinction     : COLOR;
};

void main(
  // In
  in v2p IN,

  // Out
  out float4 outColor : COLOR0,
#ifdef CSM_MRT
  out float4 outShadow : COLOR1,
#endif
  
  // Constants
  uniform sampler2D   baseMap : TEXUNIT0,
  uniform samplerCUBE envMap  : TEXUNIT1,
  uniform float3    lightDirection,
  uniform float3    lightColor,
  uniform float3    lightAmbient,
  uniform float3    eyePosW,
  uniform float     atmosRayleigh,
  uniform float     atmosMie,
  uniform float3    Ke,
  uniform float3    Ka,
  uniform float3    Kd,
  uniform float3    Ks,
  uniform float     Kr,
  uniform float     shininess,
  uniform float     mipmap,         // >0=blurry envmap
  uniform float     sunny,
  uniform float     exposure,
#ifdef CSM
  // shadow mapping
	uniform sampler2D    shadowArray  : TEXUNIT7,
  uniform float4x4     smTexMatArray[SM_MAX_SPLITS],  
  uniform float smSplits, 
#endif
  uniform float    fresnelBias,
  uniform float    fresnelScale,
  uniform float    fresnelPower
)
{
  float3 skyColor;
  
#ifdef CSM
  float  shadow;
  
  // Output shadowing and normals
  shadow=GetShadowFactor(IN.Position, IN.normal,shadowArray, smTexMatArray, smSplits, lightDirection)*sunny;
  //outShadow.rgb = IN.normal;  
#else
  const float shadow=1;
#endif

  // Get sky gradient color
  skyColor.rgb=GetSkyColor(lightDirection,IN.Direction,IN.RayleighColor,IN.MieColor,atmosRayleigh,atmosMie,lightColor,lightAmbient);

  // Get base texture color
  float4 baseCol=tex2D(baseMap,IN.tc0);
  float  reflectiveNess=1-baseCol.a;

  // Reflection
  //const float Kr=0.5f;
  float4 envColor=texCUBElod(envMap,float4(IN.R,mipmap));
//envColor*=3.0f;
  
  // Lighting
  float3 ambient,diffuse,specular;
  LightingSun(Ke,Ka,Kd,Ks,shininess,lightDirection,lightColor,lightAmbient,IN.Position,IN.normal,eyePosW,
    ambient,diffuse,specular);
  float3 litColor=baseCol*diffuse+specular*reflectiveNess;
  //float3 litColor=baseCol*diffuse+specular;
  float3 shadowColor=baseCol*(ambient+Ke);
  //baseCol.rgb=baseCol*(ambient+Ke)+baseCol*diffuse+(specular*((int)outShadow.a));

  // Add reflection
  float fresnel=Fresnel(fresnelBias,fresnelScale,fresnelPower,normalize(IN.I),normalize(IN.normal));
  shadowColor=FresnelMix(shadowColor,envColor.rgb,Kr*reflectiveNess,fresnel);
  // Reflection influences opaque-ness?
  //baseCol.a=max(baseCol.a,envColor.g);

#ifdef CSM_MRT
  // Mix sky with texture color based on atmospheric influence
  outColor.rgb=lerp(skyColor,shadowColor,IN.extinction);
  //outShadow.rgb=lerp(skyColor,litColor,IN.extinction);
  outShadow.rgb=litColor*IN.extinction;
//outColor.rgb=fresnel;

  // Blending
  outColor.a=baseCol.a;
//outColor.a=1;
  // CSM
  outShadow.a=shadow;
#else
  outColor.rgb=lerp(skyColor,shadowColor+litColor*shadow,IN.extinction);
  outColor.a=baseCol.a;
#endif
}
