struct VS_INPUT
{
	float4 Position	: POSITION;
	float3 Normal	: NORMAL;
	float2 UV	: TEXCOORD0;
};

struct VS_OUTPUT
{
	float4 Position	: POSITION;
	float3 Pos	: TEXCOORD0;
	float3 Normal	: TEXCOORD1;
	float2 UV	: TEXCOORD2;
	float2 Scaled	: TEXCOORD3;
	float2 Clouds	: TEXCOORD4;
};

VS_OUTPUT main_vp
(
	VS_INPUT i,
	uniform float4x4   worldViewProj,
	uniform float4x4   world,
	uniform float      cloudtime
)
{

	VS_OUTPUT o;
	//Calculate output position
	o.Position = mul(worldViewProj, i.Position);
	//hand over uvs to pixel shader
	o.UV = i.UV;
	o.Scaled = i.UV * 512;
	//hand over input position and normal to pixel shader
	o.Pos = i.Position;
	o.Normal = i.Normal;
	//Calculate new uvs for fake scattering
	float4 tmp = mul(world, i.Position);
	o.Clouds.x = (tmp.x+10000)/5000 + (cloudtime/320.0f);
	o.Clouds.y = (tmp.z+10000)/5000 + (cloudtime/160.0f);

	return o;
}


float4 main_fp
(
	VS_OUTPUT i,
	//get the 3 nearest lights
	uniform float3		lightDiffuse,
	uniform float4		lightAtt,
	uniform float4		LightPos,
	uniform float3		lightDiffuse2,
	uniform float4		lightAtt2,
	uniform float4		LightPos2,
	uniform float3		lightDiffuse3,
	uniform float4		lightAtt3,
	uniform float4		LightPos3,
	//ambientlight color
	uniform float4		ambient,
	//input textures
	uniform sampler2D	ground		 : register(s0),
	uniform sampler2D	splat1		 : register(s1),
	uniform sampler2D	splat2		 : register(s2),
	uniform sampler2D	splat3		 : register(s3),
	uniform sampler2D	splat4		 : register(s4),
	uniform sampler2D	coverage	 : register(s5),
	uniform sampler2D	colerage	 : register(s6),
	uniform sampler2D	cloudTex	 : register(s7)
): COLOR0
{
	//We love ogre workaround (normaly the paramters should go directly into an array)
	float3 alightDiffuse[3] = {lightDiffuse,lightDiffuse2,lightDiffuse3};
	float4 alightAtt[3] = {lightAtt,lightAtt2,lightAtt3};
	float4 aLightPos[3] = {LightPos,LightPos2,LightPos3};

	//Read in textures for splatintensity and color modulation
	float4 coveragemap = tex2D(coverage, i.UV);
	float4 coleragemap = tex2D(colerage, i.UV);

	float4 wolken = tex2D(cloudTex, i.Clouds);
	//Splat textures TEX1 is the ground texture which is splatted all over the ground
	float4 TEX1 = tex2D(ground, i.Scaled);
	float4 TEX2 = tex2D(splat1, i.Scaled);
	float4 TEX3 = tex2D(splat2, i.Scaled);
	float4 TEX4 = tex2D(splat3, i.Scaled);
	float4 TEX5 = tex2D(splat4, i.Scaled);

	float3 normal = normalize(i.Normal);

	//Blend textures with intensity and alpha channel
	float4 diffColor = lerp(lerp(lerp(lerp(TEX1,TEX2,coveragemap.r*TEX2.a),TEX3,coveragemap.g*TEX3.a),TEX4,coveragemap.b*TEX4.a),TEX5,coveragemap.a*TEX5.a);

	//add ambient light and color blending
	float4 oColor = diffColor * ambient * coleragemap;

	//for every light calculate diffuse lighting
	for (int j = 0; j < 3; j++)
	{
		if (any(alightDiffuse[j]))
		{
			//Ogre stores type of light in the .w component 0 = directional Lights (POS=DIRECTION), 1 = point lights 
			float3 lightDir = aLightPos[j].xyz -  (i.Pos * aLightPos[j].w);

			float dist = length(lightDir);

			lightDir = normalize(lightDir);

			float iD = saturate(dot(normal, lightDir));
			//calculate pointlight attenuation 				
			float att = 1 / (alightAtt[j].y + alightAtt[j].z * dist + alightAtt[j].w * dist * dist);
			//add light
			oColor.rgb += att * (diffColor.rgb * alightDiffuse[j] * iD);
		}
	}
	//modulate clouds shadows
	oColor *= wolken;
	return saturate(oColor);
}