//
// Standard - X tree fragment with diffuse gradient (light direction) - basic version (no round normals)
// 27-12-2010: Created!
//

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

// Vertex to pixel shader structure
struct v2p
{
  float3 Position       : TEXCOORD4; //POSITION;
  float3 normal         : TEXCOORD5;
  float3 RayleighColor	: TEXCOORD2;
  float3 MieColor       : TEXCOORD3;
  float3 tc0            : TEXCOORD0;
  float3 Direction      : TEXCOORD1;
  float  extinction     : TEXCOORD6;
};

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 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     shininess,
#ifdef CSM
  // shadow mapping
	uniform sampler2D    shadowArray  : TEXUNIT7,
  uniform float4x4     smTexMatArray[SM_MAX_SPLITS],  
  uniform float smSplits, 
#endif
  uniform float     sunny,
  uniform float     exposure
)
{
  float3 skyColor;
  float3 normal; //=float3(0,1,0);        // Fixed normal to get even lighting
  
#ifdef CSM
  // Output shadowing info using original 3D model's normal (overrule?)
  // Use original normal to avoid funny shadowing!
  //float shadow=GetShadowFactor(IN.Position, normal,shadowArray, smTexMatArray, smSplits, lightDirection);
  //float shadow=GetShadowFactor(IN.Position, IN.normal,shadowArray, smTexMatArray, smSplits, lightDirection)*sunny;
  
  // Don't catch shadows
  float shadow=1;
  //outShadow.rgb = IN.normal;
#else
  const float shadow=1;
#endif

  // Tree matrix
  float3 up=float3(0,1,0);
  //float3 fwd=IN.normal;
  float3 fwd=normalize(IN.Direction);
  float3 side=cross(up,fwd);
  //float3 side=cross(fwd,up);
  float3x3 mat=float3x3(side,up,fwd);
  float3 lightDirTreeSpace;

  // Subtle light fall-through - not a complete cylinder. 1.0=full, 0=flat
  const float roundNess=0.5;
  // Make a normal that defines a sort of cylinder  
  float3 n;
  // Detect U direction along polygon
  float uDirection=ddx(IN.tc0.x);

  if(uDirection<0)n.x=roundNess*(1-2*IN.tc0.x);
  else            n.x=roundNess*(IN.tc0.x*2-1);
  
  //n.y=1-IN.tc0.y*2;
  n.y=roundNess*(IN.tc0.y*2-1);
  
  // Forward to the eye
  n.z=1;
  n=normalize(n);
  
  // Rotate into tree space
  normal=mul(n,mat);

  // 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);
//baseCol=float4(1,1,1,1);

  // Lighting
  float3 ambient,diffuse,specular;
  LightingSun(Ke,Ka,Kd,Ks,shininess,lightDirection,lightColor,lightAmbient,IN.Position,normal,eyePosW,
    ambient,diffuse,specular);
  float3 sdColor=baseCol*diffuse+specular;
  float3 ambientColor=baseCol*(ambient+Ke);
  //baseCol.rgb=baseCol*(ambient+Ke)+baseCol*diffuse+specular;

  // HDR toning of sky (for LDR shaders)
  //skyColor.rgb=1.0-exp(-exposure*skyColor.rgb);

#ifdef CSM_MRT
  // Mix sky with texture color based on atmospheric influence
  outColor.rgb=lerp(skyColor,ambientColor,IN.extinction);
  //outShadow.rgb=lerp(skyColor,sdColor,IN.extinction);
  outShadow.rgb=sdColor*IN.extinction;
  outShadow.a=shadow;
  
  // Blending
  outColor.a=baseCol.a;
  outShadow.a=1;
#else
  // Mix sky with texture color based on atmospheric influence
  outColor.rgb=lerp(skyColor,ambientColor+sdColor*shadow,IN.extinction);
//outColor.rgb=IN.normal;
//outColor.rgb=side;
//outColor.rgb=normal;
//outColor.rgb=n.y;
//outColor.rgb=lightDirection;
//outColor.rgb=gradColor;
//if(front)outColor.rgb=float3(0,10,0); else outColor.rgb=float3(10,0,0);
//outColor.rgb*=5;
//outColor.rgb=n.x;
//outColor.rgb=n.y*5;
//float v=ddx(IN.tc0.x); if(v>0)outColor.rgb=float3(0,10,0); else outColor.rgb=float3(10,0,0);
//outColor.rgb=IN.tc0.x*5;
//outColor.rgb=IN.tc0.y;
//outColor.rgb=float3(0,10,0);
  // Blending
  outColor.a=baseCol.a;
//outColor.a=1;
#endif
}
