#ifdef GL_ES
precision mediump int;
precision highp float;
#endif

#define USE_OGRE_FROM_FUTURE
#include <OgreUnifiedShader.h>

SAMPLER2D(shadowMap0, 0);
SAMPLER2D(shadowMap1, 1);
SAMPLER2D(shadowMap2, 2);
SAMPLER2D(alphaTexture, 3);

OGRE_UNIFORMS(
uniform vec4 materialColor;
uniform vec4 invShadowMapSize0;
uniform vec4 invShadowMapSize1;
uniform vec4 invShadowMapSize2;
uniform vec4 lightPosition[6];
uniform vec4 spotlight[6];
uniform vec4 spotDir[6];
uniform vec4 lightAtt[6];
uniform vec4 lightDiff[6];
uniform vec4 fogParams;
uniform vec4 slicePlane;
uniform vec4 pssmSplitPoints;
)

vec2 lightAttribution(vec3 wp, vec3 normal, int id)
{
  if ((lightAtt[id].x == 0.0) && (lightAtt[id].y == 1.0) && (lightAtt[id].z == 0.0) && (lightAtt[id].w == 0.0))
    return vec2(0.0, 0.0);
  
  vec3 ld = normalize(lightPosition[id].xyz - (vec3_splat(lightPosition[id].w) * wp.xyz));
  
  float diffFactor = (lightDiff[id].x + lightDiff[id].y + lightDiff[id].z) * 0.333333333;
  
  // attenuation
  if(lightAtt[id].w > 0.0)
  {
    float lightDist = length(lightPosition[id].xyz - wp.xyz);
    if (lightDist > lightAtt[id].x)
      return vec2(0.0, 0.0);
    
    float la = 1.0 / (lightAtt[id].y + lightAtt[id].z * lightDist + lightAtt[id].w * lightDist * lightDist);
    float spot = (spotlight[id].w == 0.0) ? 1.0 : saturate((dot(-normalize(spotDir[id].xyz - (vec3_splat(spotDir[id].w) * wp.xyz)), ld) - spotlight[id].y) / (spotlight[id].x - spotlight[id].y));
    float cb = saturate(saturate(dot(normal, ld)) * spot * la * diffFactor);
    return vec2(cb, cb);
  }
  else
  {
    return vec2(saturate(dot(normal, ld) * diffFactor), 0.0);
  }
}

float shadowFiltering(sampler2D shadowMap, vec4 shadowUV, vec2 invShadowMapSize)
{
  shadowUV = shadowUV / shadowUV.w;  
  vec2 centerdepth = texture2D(shadowMap, shadowUV.xy).xy;

  // gradient calculation
  vec2 s1 = texture2D(shadowMap, shadowUV.xy + vec2(-invShadowMapSize.x, 0.0)).xy;
  vec2 s2 = texture2D(shadowMap, shadowUV.xy + vec2(+invShadowMapSize.x, 0.0)).xy;
  vec2 s3 = texture2D(shadowMap, shadowUV.xy + vec2(0.0, -invShadowMapSize.y)).xy;
  vec2 s4 = texture2D(shadowMap, shadowUV.xy + vec2(0.0, +invShadowMapSize.y)).xy;

  float final = (centerdepth.x > shadowUV.z) ? 0.0 : centerdepth.y;
  final += (s1.x > shadowUV.z) ? 0.0 : s1.y;
  final += (s2.x > shadowUV.z) ? 0.0 : s2.y;
  final += (s3.x > shadowUV.z) ? 0.0 : s3.y;
  final += (s4.x > shadowUV.z) ? 0.0 : s4.y;
  final *= 0.2;
  
  return final;
}

MAIN_PARAMETERS
IN(vec3 oUv, TEXCOORD0)
IN(vec3 oNormal, TEXCOORD1)
IN(vec3 oWp, TEXCOORD2)
IN(vec4 oLightPosition0, TEXCOORD3)
IN(vec4 oLightPosition1, TEXCOORD4)
IN(vec4 oLightPosition2, TEXCOORD5)
MAIN_DECLARATION
{
  if(((slicePlane.x + slicePlane.y + slicePlane.z) != 0.0) && (slicePlane.x * oWp.x + slicePlane.y * oWp.y + slicePlane.z * oWp.z + slicePlane.w > 0.0))
    discard;
  
  // get alpha
  float alpha = texture2D(alphaTexture, oUv.xy).a;
  //if(alpha < 0.05)
  //  discard;
	
  alpha *= materialColor.a;
  vec2 ld0 = lightAttribution(oWp, oNormal, 0);
  vec2 ld1 = lightAttribution(oWp, oNormal, 1);
  vec2 ld2 = lightAttribution(oWp, oNormal, 2);
  vec2 ld3 = lightAttribution(oWp, oNormal, 3);
  vec2 ld4 = lightAttribution(oWp, oNormal, 4);
  vec2 ld5 = lightAttribution(oWp, oNormal, 5);
  float ld = saturate(ld0.x - saturate(ld1.y + ld2.y + ld3.y + ld4.y + ld5.y));
  
  // calculate shadow
  float shadow = 0.0;
  //vec4 splitColour;
  if (oUv.z <= pssmSplitPoints.y)
  {
  	//splitColour = vec4(1.0, 0.0, 0.0, 1.0);
  	shadow = shadowFiltering(shadowMap0, oLightPosition0, invShadowMapSize0.xy);
  }
  else if (oUv.z <= pssmSplitPoints.z)
  {
  	//splitColour = vec4(0, 1.0, 0.0, 1.0);
  	shadow = shadowFiltering(shadowMap1, oLightPosition1, invShadowMapSize1.xy);
  }
  else
  {
  	//splitColour = vec4(1.0, 1.0, 0.0, 1.0);
  	shadow = shadowFiltering(shadowMap2, oLightPosition2, invShadowMapSize2.xy);
  }
	
  float fog = saturate((fogParams.z - oUv.z) * fogParams.w);
  shadow *= fog * ld;
  
  // Calculate total pixel brightness
  vec3 brightness = vec3_splat(1.0 - (shadow * alpha));
  gl_FragColor = vec4(brightness, 1.0);
}