varying vec2 		texcoord;
uniform sampler2D 	tex;
varying vec4		diffuse;		// diffuse color * material color
uniform vec4		ambientColor;	// ambient  * material color
uniform vec4 		diffuseColor;	// material color 

// shadows data
uniform sampler2DShadow 	shadowmap;
uniform float 				lightrange;
varying vec4				eyepos;
uniform vec4				LTM0,
							LTM1,
							LTM2,
							LTM3;
							
varying float		alphaFade;
uniform float 		maxDist;

uniform vec3 		inScatterColor;

uniform mat4		reprojTM;

uniform vec3 		earth_center;
uniform float 		length_unit;

uniform vec3  		campos;
uniform vec3		sundir;
uniform vec3 		sunColor;	// sun color * sun power
uniform vec3 		moonlightcolor;
varying vec3 		Wpos;
varying vec4 		Wnormal;

#ifdef _HEIGHTMAP_

	uniform sampler2D	cmask;	
	varying vec2 		texcoord2;
#else
	#ifndef BSET
		uniform sampler2D 	noiseTex;
	#endif
#endif

//varying vec3 localLightsDiffuse;

uniform vec4 localLightsPos[8];
uniform vec3 localLightsColor[8];
uniform int numLights;

vec3 localLightsDiffuse;

vec3 GetSolarRadiance();
vec3 GetSkyRadiance(vec3 camera, vec3 view_ray, float shadow_length,
    vec3 sun_direction, out vec3 transmittance);
vec3 GetSkyRadianceToPoint(vec3 camera, vec3 point, float shadow_length,
    vec3 sun_direction, out vec3 transmittance);
vec3 GetSunAndSkyIrradiance(
    vec3 p, vec3 normal, vec3 sun_direction, out vec3 sky_irradiance);
vec3 GetTrasmittanceTexture(vec2 uv);
vec3 GetScatteringTexture(vec3 uv);
vec3 GetSunIrradiance(vec3 p, vec3 sun_direction);
vec3 GetIndirectIrradiance(vec3 p, vec3 sun_direction);

float ComputeShadowOcclusion()
{
	// SHADOW MAP CODE
	vec4	XYproj;	
	float 	shadowOcc=1.0;
	vec3 	projcoords;
			
	if( -eyepos.z/**/ <= lightrange )
	{
		// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
		vec4 reprojPos=reprojTM*eyepos;
		XYproj.x = dot(reprojPos,LTM0);
		XYproj.y = dot(reprojPos,LTM1);
		XYproj.z = dot(reprojPos,LTM2);
		XYproj.w = dot(reprojPos,LTM3);

		projcoords.xy=XYproj.xy;
		projcoords.z=XYproj.z-0.004;
		
		///////////////////////////////////
		shadowOcc=min(shadow2D(shadowmap,projcoords).r,1.0);
	//	shadowOcc=shadowOcc+clamp((-eyepos.z-(lightrange-500.0))/(lightrange-500.0),0.0,1.0);
	}
//	shadowOcc*=(1.0-clamp((-eyepos.z-(lightrange-1000.0))/1000.0,0.0,1.0));
	////////////////////////////////////////
	
	return shadowOcc;
}

void main()
{
	vec3 	Lin=vec3(0.0,0.0,0.0);
	vec3 	Fex=vec3(0.0,0.0,0.0);
	vec4 	color=vec4(0.0,0.0,0.0,1.0);
	vec3 	finalColor=vec3(0.0,0.0,0.0);
		
	if(-eyepos.z<=maxDist)
	{
		color=texture2D(tex,texcoord.st);
		color.rgb=pow(color.rgb,vec3(2.2))*diffuseColor.rgb;
		
		// convert normal to eye space
		float occlusion=1.0;
		localLightsDiffuse=vec3(0.0,0.0,0.0);
		#ifdef _SHADOWS_
			occlusion=ComputeShadowOcclusion();
			
			vec3 lightDir;
			float lightAtt;
			for(int i=0; i<numLights; i++)
			{
				// compute light dir
				lightDir=localLightsPos[i].xyz-Wpos.xyz;
				
				// compute light diffuse contribute
				lightAtt=1.0 - min(length(lightDir)/localLightsPos[i].w,1.0);
				lightAtt*=max(dot(normalize(lightDir),Wnormal.xyz),0.0);
				localLightsDiffuse+=localLightsColor[i]*vec3(lightAtt);//*lightMultiplier;
			}
		#endif
		
		#ifdef _HEIGHTMAP_
			
			vec3 one=vec3(1.0,1.0,1.0);
			vec4 maskColor=texture2D(cmask,texcoord2.st);
			maskColor.rgb=pow(maskColor.rgb,vec3(2.2));
			
			vec3 rmul=color.rgb*maskColor.rgb;
			vec3 rscr=one-((one-maskColor.rgb)*(one-color.rgb));
			color.rgb=(color.rgb*rscr+(one-color.rgb)*rmul)*maskColor.a;
			color.a=1.0;
		#else
			#ifdef BSET
				color.a*=alphaFade;
			#endif
		#endif
		
		vec3 WposFromEarth=(Wpos.xyz*length_unit)-earth_center.xyz;
		vec3 camposFromEarth=(campos.xyz*length_unit)-earth_center.xyz;
		camposFromEarth.y=max(camposFromEarth.y,-earth_center.y);
		
		vec3 skyAmbient=GetIndirectIrradiance(WposFromEarth, sundir);
		
		vec3 ambient=color.xyz*ambientColor.xyz*skyAmbient;
		vec3 sunlight=sunColor.xyz*GetSunIrradiance(WposFromEarth, sundir) + moonlightcolor;
		finalColor=(diffuse.xyz*sunlight*vec3(occlusion) + localLightsDiffuse)*color.xyz + ambient;
		
		Lin=GetSkyRadianceToPoint(camposFromEarth, WposFromEarth, 0.0, sundir, Fex)*inScatterColor;
	}
	
	gl_FragColor.xyz=Lin+(Fex*finalColor);/*Lin+(Fex*diffuse.xyz*color.xyz)*/;
	gl_FragColor.a=color.a+0.25;
}
