varying vec2 		texcoord;
varying vec2 		texcoord1;

uniform sampler2D 			bmp,
							tex;
uniform samplerCube			ambientCube;
uniform samplerCube			ambientCubeDiffuse;
uniform sampler2D			brdfLUT;
uniform sampler2DShadow 	shadowmap;
uniform sampler2DShadow 	shadowmap2;
uniform sampler2DShadow 	shadowmap4;

#ifdef PSYSTEM
	uniform sampler2D 		depthBG;
#endif

#ifdef BUMP2
	uniform sampler2D 		bmp1;
	varying vec2 			texcoord2;
#endif

varying vec4		eyepos;
uniform vec2		density;
uniform vec3		refrColor;
uniform vec3		diffuseColor;
uniform vec3		ambientColor;
uniform vec3		specularColor;

uniform float		alphalevel;
uniform float		scatter;
uniform float 		backscatter;

//varying float 		fFex;
varying vec4 		fogScat;

float				Pi=3.14159265359;
vec4 				texColor;

uniform float invAmbientRange;
uniform vec3 ambientPos;
uniform float ambientScatter;

uniform float cubeLod;
uniform float cubeLod2;
uniform float maskDistance;

uniform vec3		lightDir;
uniform vec4		lightcolor;
uniform vec2 		spec;
uniform vec2		fresnel;

uniform vec3 		moonlightcolor;
	
varying vec4 		vpos;
uniform	float		reflSaturation;

#ifdef PSYSTEM

	varying float 	life;
	varying vec2	cosina;
	uniform vec4	data;
	uniform float	alphaMul;
	varying vec4 	posDir;
	uniform vec3 	sunpos;
	uniform vec4 	particleFade;
	varying vec4 	pos;
	
//#else
#endif

// SHADOWMAP PARAMS
uniform vec3 		lightrange;		//r=1, g=2, b=4
/*uniform float 		lightrange2;
uniform float 		lightrange4;
*/
uniform mat4		reprojTM2;
uniform mat4		reprojTM4;
		
uniform int 		split4;
uniform int 		split8;

uniform float		cOfs;

uniform vec4		LTM0,
					LTM1,
					LTM2,
					LTM3;

uniform vec4		LTM0b,
					LTM1b,
					LTM2b,
					LTM3b;

uniform vec4		LTM0c,
					LTM1c,
					LTM2c,
					LTM3c;

//////////////////////////////////////////

varying mat3		TBN;
varying vec3		viewDir;
uniform vec4 		reflColorMul;

///////// LIGHTS ////////////////////////
uniform vec4 		light0[4];			//x = flag, y = range, z=cos, w=fallof
uniform vec3 		lightpos0[4];
uniform vec3 		lightdir0[4];
uniform vec4 		lightColor0[4];

/*uniform vec4 		light1;			//x = flag, y = range, z=cos, w=fallof
uniform vec3 		lightpos1;
uniform vec3 		lightdir1;
uniform vec4 		lightColor1;

uniform vec4 		light2;			//x = flag, y = range, z=cos, w=fallof
uniform vec3 		lightpos2;
uniform vec3 		lightdir2;
uniform vec4 		lightColor2;

uniform vec4 		light3;			//x = flag, y = range, z=cos, w=fallof
uniform vec3 		lightpos3;
uniform vec3 		lightdir3;
uniform vec4 		lightColor3;*/

/*uniform float 		lightRange0[4];
uniform float 		lightCos0[4];
uniform float 		lightfallof0[4];
*/
/*uniform float 		light1;
uniform vec3 		lightpos1;
uniform vec3 		lightdir1;
uniform vec4		lightColor1;
uniform float 		lightRange1;
uniform float 		lightCos1;
uniform float 		lightfallof1;*/
///////////////////////////////////////////

// TAO /////////
//varying float TAO;

vec4 normalColor;


// ------------ ATMOSPHERE ------------------------------
uniform float 		length_unit;
uniform vec3 		earth_center;
uniform vec3 		sundirW;
uniform vec3		campos;
uniform vec3 		inScatterColor;
uniform vec3 		fogColor;
						
vec3 Wpos=(vpos.xyz*length_unit)-earth_center.xyz;

vec3 GetSunIrradiance(vec3 p, vec3 sun_direction);
vec3 GetSkyRadianceToPoint(vec3 camera, vec3 point, float shadow_length,
    vec3 sun_direction, out vec3 transmittance);
vec3 GetSkyRadiance(vec3 camera, vec3 view_ray, float shadow_length,
    vec3 sun_direction, out vec3 transmittance);	
vec3 GetSkyRadianceWithoutPhase(vec3 camera, vec3 view_ray, float shadow_length,
    vec3 sun_direction, out vec3 transmittance);

// ------------------------------------------------

vec4 RGBMDecode( vec4 rgbm ) {
  return vec4(6.0 * rgbm.rgb * rgbm.a,1.0);
}

vec3 cubeLookup(vec3 v, float lod) {
   float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
   float scale = 1.0 - exp2(lod) / 128.0;
   if (abs(v.x) != M) v.x *= scale;
   if (abs(v.y) != M) v.y *= scale;
   if (abs(v.z) != M) v.z *= scale;
   return v;
}

float phong_diffuse()
{
	return (1.0 / Pi);
}

vec3 fresnel_factor_F90(vec3 f0, float f90, float product)
{
	return f0+(vec3(f90)-f0)*pow(1.0-product,5.0);
}

vec3 fresnel_factor(vec3 f0, float product)
{
	return mix(f0, vec3(1.0), pow(1.01 - product, 5.0));
}

float D_GGX(float a2, float NdH)
{
	//float m = roughness * roughness;
	float d = (NdH * a2 - NdH) * NdH + 1.0;
	return a2 / (Pi*d*d);
}

float G_schlick(float roughness, float NdV, float NdL)
{
	float r=(roughness+1.0)/2.0;
	float k=r*r*0.5;//0.125;
	float V = NdV * (1.0 - k) + k;
	float L = NdL * (1.0 - k) + k;
	return /*1.0/*/0.25/(V*L);
}

float G_Smith( float a2, float NdV, float NdL )
{
	float V = NdV + sqrt( NdV * (NdV - NdV * a2) + a2 );
	float L = NdL + sqrt( NdL * (NdL - NdL * a2) + a2 );
	return 1.0/( V*L );
}

float G_SmithJointApprox( float a, float NdV, float NdL )
{
	float V = NdL * ( NdV * ( 1 - a ) + a );
	float L = NdV * ( NdL * ( 1 - a ) + a );
	return 0.5 /( V+L );
}

vec3 CookTorrance(float NdL, float NdV, float NdH, vec3 F, float rough, float a)
{
	float a2=a*a;
	float D = D_GGX(a2, NdH);
	float G = G_schlick(rough, NdV, NdL);
	//float G = G_SmithJointApprox(a,NdV, NdL);//G_schlick(rough, NdV, NdL);
	//float G = G_Smith(a2,NdV, NdL);//G_schlick(rough, NdV, NdL);
	return max(D*G,0.0)*F;// (D*F*G) / mix(1.0-(roughness*0.9),1.0,4*NdL*NdV); 
} 

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

			projcoords.xy=XYproj.xy;
			projcoords.z=XYproj.z-0.00005;
			///////////////////////////////////

			float dOfs = cOfs*0.5;
			shadowOcc=0.0;

			vec3 shadowcoords;
			shadowcoords.z=projcoords.z;

			shadowcoords.xy=projcoords.xy+vec2(-dOfs,dOfs);
			shadowOcc+=shadow2D(shadowmap,shadowcoords).r;

			shadowcoords.xy=projcoords.xy+vec2(dOfs,dOfs);
			shadowOcc+=shadow2D(shadowmap,shadowcoords).r;

			shadowcoords.xy=projcoords.xy+vec2(dOfs,-dOfs);
			shadowOcc+=shadow2D(shadowmap,shadowcoords).r;

			shadowcoords.xy=projcoords.xy+vec2(-dOfs,-dOfs);
			shadowOcc+=shadow2D(shadowmap,shadowcoords).r;
			
			shadowOcc *= 0.25;
		}
		else
		{	
			if( -eyepos.z/lightrange.g <= 1.0 )
			{
				// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
				reprojPos=reprojTM2*eyepos;
				XYproj.x = dot(reprojPos,LTM0b);
				XYproj.y = dot(reprojPos,LTM1b);
				XYproj.z = dot(reprojPos,LTM2b);
				XYproj.w = dot(reprojPos,LTM3b);

				projcoords.xy=XYproj.xy;
				projcoords.z=XYproj.z-0.0004;
				///////////////////////////////////

				float dOfs = cOfs*0.5;
				shadowOcc=0.0;

				vec3 shadowcoords;
				shadowcoords.z=projcoords.z;

				shadowcoords.xy=projcoords.xy+vec2(-dOfs,dOfs);
				shadowOcc+=shadow2D(shadowmap2,shadowcoords).r;

				shadowcoords.xy=projcoords.xy+vec2(dOfs,dOfs);
				shadowOcc+=shadow2D(shadowmap2,shadowcoords).r;

				shadowcoords.xy=projcoords.xy+vec2(dOfs,-dOfs);
				shadowOcc+=shadow2D(shadowmap2,shadowcoords).r;

				shadowcoords.xy=projcoords.xy+vec2(-dOfs,-dOfs);
				shadowOcc+=shadow2D(shadowmap2,shadowcoords).r;
				
				shadowOcc *= 0.25;
			}
			else
			{
				if( -eyepos.z/lightrange.b <= 1.0 )
				{
					// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
					reprojPos=reprojTM4*eyepos;
					XYproj.x = dot(reprojPos,LTM0c);
					XYproj.y = dot(reprojPos,LTM1c);
					XYproj.z = dot(reprojPos,LTM2c);
					XYproj.w = dot(reprojPos,LTM3c);

					projcoords.xy=XYproj.xy;
					projcoords.z=XYproj.z-0.0006;
					///////////////////////////////////

					float dOfs = cOfs*0.5;
					shadowOcc=0.0;

					vec3 shadowcoords;
					shadowcoords.z=projcoords.z;

					shadowcoords.xy=projcoords.xy+vec2(-dOfs,dOfs);
					shadowOcc+=shadow2D(shadowmap4,shadowcoords).r;

					shadowcoords.xy=projcoords.xy+vec2(dOfs,dOfs);
					shadowOcc+=shadow2D(shadowmap4,shadowcoords).r;

					shadowcoords.xy=projcoords.xy+vec2(dOfs,-dOfs);
					shadowOcc+=shadow2D(shadowmap4,shadowcoords).r;

					shadowcoords.xy=projcoords.xy+vec2(-dOfs,-dOfs);
					shadowOcc+=shadow2D(shadowmap4,shadowcoords).r;
				
					shadowOcc *= 0.25;
					float lrangeMin=lightrange.b-300.0;
					shadowOcc=mix(shadowOcc,1.0,( clamp( (-eyepos.z-lrangeMin)/(lightrange.b-lrangeMin),0.0,1.0) ));
				}
			}
		}
		////////////////////////////////////////

	#ifdef PSYSTEM
		
		//float specular = 0;
		if(shadowOcc>0.0)
		{
			// atmosphere ////////////
			vec3 sunColor = GetSunIrradiance(Wpos, sundirW);
			//////////////////////////
		
			vec3 diffuse;
			diffuse=(dot(ldir,posDir.xyz)*(1.0-scatter)+scatter/*0.5+0.5*/)*diffuseColor;
			
			vec3 LT=ldir-posDir.xyz;
			float backlight=pow(clamp(dot(-LT,vdir),0.0,1.0),2.0)*backscatter*(1.0-texColor.a);
			return texColor.rgb*(diffuse+backlight)*(lightcolor.rgb*sunColor + moonlightcolor)*shadowOcc;
		}
		return vec3(0.0,0.0,0.0);
		
	#else
		
		vec3 diffuse = vec3(0.0,0.0,0.0);
		vec3 specular=vec3(0.0,0.0,0.0);
				
		// atmosphere ////////////
		vec3 sunColor = GetSunIrradiance(Wpos, sundirW);
		//////////////////////////
		
		if(shadowOcc>0.0)
		{
			vec3 REFL=specularColor.rgb;//*fresnel.x;
			float rough=clamp(sqrt(fresnel.y*normalColor.b),0.05,1.0);
			
			// compute all vectors
			vec3 H = normalize(ldir+vdir);
			float NdotH = (dot(H,N.xyz));
			float EdotH = clamp(dot(vdir,H),0.0,1.0);
			float NdotE = clamp(dot(N.xyz,vdir),0.0,1.0);
			float NdotL = clamp(dot(ldir,N.xyz),0.0,1.0);
		
			// fresnel
			vec3 specfresnel=fresnel_factor(REFL, EdotH)*fresnel.x;
			
			// diffuse
			diffuse = ((vec3(1.0) - specfresnel) * phong_diffuse() * NdotL);
			
			// specular
			specular = CookTorrance(NdotL, NdotE, NdotH, specfresnel, rough, rough*rough) * NdotL;
		}
		
		// result
		return (texColor.rgb*diffuseColor.rgb*diffuse + specular)*(lightcolor.rgb*sunColor.rgb + moonlightcolor)*shadowOcc;
		
	#endif
}

vec3 ComputeLight(vec3 N, vec3 vdir, vec3 lpos, vec4 lcolor, float lrange, float light, vec3 lightdir, float lcos, float fallof)
{
	vec3 diffuse = diffuseColor;
	
	#ifdef PSYSTEM
		
		if(light>1.0)
		{
			vec3 ldir=(gl_ModelViewMatrix*vec4(lpos,1.0)).xyz-eyepos.xyz;
			float lightDistance=length(ldir);
			float dist=lightDistance/lrange;
			
			float decay=pow(clamp(1.0 - pow(dist,4.0),0.0,1.0),2.0)/(pow(lightDistance,2.0)+1.0);
			
			if(dist<=1.0)
			{
				ldir=normalize(ldir);
				/*float cos=dot(lightdir,ldir);
				float angAtt=clamp(1.0 - (1.0-cos)/(1.0-lcos),0.0,1.0);
				*/
				float maxConeAng=(1.0-lcos);
				float minConeAng=(1.0-fallof);
				float angRange=maxConeAng-minConeAng;
				float cos=1.0-dot((gl_ModelViewMatrix*vec4(lightdir,0.0)).xyz,ldir);
				cos=max(cos-minConeAng,0.0);
				float angAtt=clamp(1.0 - (cos/angRange/*(1.0-lightCos)*/),0.0,1.0);
	
				float att=decay*angAtt;//*fallof;
				
				if( scatter>0.0 )
				{
					diffuse=(dot(ldir,posDir.xyz)*(1.0-scatter)+scatter) * diffuseColor;
					vec3 LT=ldir-posDir.xyz;
					float backlight=pow(clamp(dot(-LT,vdir),0.0,1.0),2.0)*backscatter*(1.0-texColor.a);
					diffuse += backlight;
				}
				else
					diffuse = clamp(dot(posDir.xyz,ldir),0.0,1.0)*diffuseColor;
				return diffuse*lcolor.rgb*texColor.rgb*att;
			}
		}
		else
		{
			vec3 ldir=(gl_ModelViewMatrix*vec4(lpos,1.0)).xyz-eyepos.xyz;
			float lightDistance=length(ldir);
			float dist=lightDistance/lrange;
			
			float decay=pow(clamp(1.0 - pow(dist,4.0),0.0,1.0),2.0)/(pow(lightDistance,2.0)+1.0);
			
			if(dist<=1.0)
			{
				ldir=normalize(ldir);
				float att= decay;//*fallof;//clamp((1.0 - dist)*fallof,0.0,1.0);
				
				if( scatter>0.0 )
				{
					diffuse=(dot(ldir,posDir.xyz)*(1.0-scatter)+scatter/*0.5+0.5*/)*diffuseColor;		//=(dot(N,ldir)*0.5+0.5)*diffuseColor;		
					vec3 LTLight=ldir-posDir.xyz;
					float backlight=pow(clamp(dot(-LTLight,vdir),0.0,1.0),2.0)*backscatter*(1.0-texColor.a);// + vec3(0.15, 0.15, 0.15);
					diffuse += backlight;//*diffuseColor;
				}
				else
					diffuse = clamp(dot(posDir.xyz,ldir),0.0,1.0)*diffuseColor;
				return diffuse*lcolor.rgb*texColor.rgb*att;
			}
		}
	
	#else
	
		vec3 ldir=lpos-vpos.xyz;
		float lightDistance=length(ldir);
		float dist=lightDistance/lrange;
				
		float decay=pow(clamp(1.0 - pow(dist,4.0),0.0,1.0),2.0)/(pow(lightDistance,2.0)+1.0);
		
		if(dist<=1.0)
		{
			ldir=normalize(ldir);
			float att= decay;//*fallof;
			
			if(light>1.0)
			{
				/*float cos=dot(lightdir,ldir);
				float angAtt=clamp(1.0 - (1.0-cos)/(1.0-lcos),0.0,1.0);
				*/
				float maxConeAng=(1.0-lcos);
				float minConeAng=(1.0-fallof);
				float angRange=maxConeAng-minConeAng;
				float cos=1.0-dot(lightdir,ldir);
				cos=max(cos-minConeAng,0.0);
				float angAtt=clamp(1.0 - (cos/angRange/*(1.0-lightCos)*/),0.0,1.0);
				att*=angAtt;
			}
			
			vec3 REFL=specularColor.rgb;
			float rough=clamp(sqrt(fresnel.y*normalColor.b),0.05,1.0);
			
			// compute all vectors
			vec3 H = normalize(ldir+vdir);
			float NdotH = (dot(H,N.xyz));
			float EdotH = clamp(dot(vdir,H),0.0,1.0);
			float NdotE = clamp(dot(N.xyz,vdir),0.0,1.0);
			float NdotL = abs(dot(ldir,N.xyz));
		
			// fresnel
			vec3 specfresnel=vec3(0.0,0.0,0.0);
			
			// specular
			vec3 specular = vec3(0.0,0.0,0.0);
			
			if(lcolor.a>0.0)
			{
				specfresnel=fresnel_factor(REFL, EdotH)*fresnel.x;
				specular = CookTorrance(NdotL, NdotE, NdotH, specfresnel, rough, rough*rough) * NdotL * lcolor.a;
			}
			
			// diffuse
			vec3 diffuse = ((vec3(1.0) - specfresnel) * phong_diffuse() * NdotL);
			
			return (texColor.rgb*diffuseColor.rgb*diffuse + specular)*lcolor.rgb*att;
		}
		
	#endif

	return vec3(0.0,0.0,0.0);
}

void main()
{	
	#ifdef PSYSTEM
	
		if(life<=0.0)
			discard;
	
		texColor=texture2D(tex,texcoord.st);
		texColor.rgb=pow(texColor.rgb,vec3(2.2));
	
		vec2 UV=(pos.xy/pos.w)*0.5+0.5;
		float sceneDepth=texture2D(depthBG,UV.st).r;
		float alphaDepth=min((eyepos.z-sceneDepth)*0.0125,1.0);
		if(alphaDepth<=0.0)
			discard;
		
		// -------- ATMOSPHERE ---------------------------------		
		vec3 		Fex;
		vec3 		Lin;
		
		vec3 camposFromEarth=(campos.xyz*length_unit)-earth_center.xyz;
		camposFromEarth.y=max(camposFromEarth.y,-earth_center.y);
		Lin=GetSkyRadianceToPoint(camposFromEarth, Wpos, 0.0, sundirW, Fex)*inScatterColor;
		
		vec3 sundir2d=normalize(vec3(sundirW.x,0.0,sundirW.z));		
		vec3 viewdir2d_flat=normalize(cross(sundir2d,vec3(0.0,1.0,0.0)));
		vec3 tempFex=vec3(0.0);
		vec3 atmoColor_flat=GetSkyRadianceWithoutPhase(camposFromEarth, viewdir2d_flat, 0.0, sundirW, tempFex);
		// -----------------------------------------------------
		
		vec3 IBLdiffuse = vec3(dot(RGBMDecode(textureCubeLod(ambientCubeDiffuse,-posDir.xyz,cubeLod)).xyz,vec3(0.3,0.59,0.11)));
		vec4 refl=vec4(0.0,0.0,0.0,0.0);
		vec3 litColor=vec3(0.0,0.0,0.0);
		vec3 ambient=IBLdiffuse*ambientColor*(texColor.rgb*diffuseColor+(scatter*(1.0-texColor.a)));
		
		float pl=1.0-life;
		float fin=min(pl/particleFade.x,1.0);      
		float fout=1.0-min(max(pl-(1.0-particleFade.y),0.0)/particleFade.y,1.0);
		texColor.a*=(fin*fout);
		vec3 N;
		vec3 vdir;
		
		vdir=normalize(-eyepos.xyz);
		litColor += ComputeSunLight(N,vdir,lightDir);
		
		for(int i=0; i<4; i++)
		{
			if(light0[i].x>0.0)
				litColor += ComputeLight(N, vdir, lightpos0[i], lightColor0[i], light0[i].y, light0[i].x, lightdir0[i], light0[i].z, light0[i].w);
		}
	
		vec3 finalColor=(litColor + ambient); 
		
		finalColor=Fex*finalColor + Lin;
		gl_FragColor.rgb=max(finalColor*fogScat.a + (fogScat.rgb*atmoColor_flat),0.0);	
		gl_FragColor.a=clamp(texColor.a*alphalevel*alphaMul*alphaDepth,0.0,1.0);	
			
	#else

		texColor=texture2D(tex,texcoord.st);
		texColor.rgb=pow(texColor.rgb,vec3(2.2));
		
		vec4 refl=vec4(0.0,0.0,0.0,0.0);
		float reflInt=0.0;
		vec3 litColor=vec3(0.0,0.0,0.0);
		normalColor=texture2D(bmp,texcoord1.st);
		normalColor.xy=(normalColor.xy*2.0-1.0);
		vec3 normal=vec3(normalColor.xy,sqrt(1.0-normalColor.x*normalColor.x-normalColor.y*normalColor.y));
		normal=normalize(normal);
		
		vec3 ambient;
	
		#ifdef BUMP2

			vec4 normalColor1=texture2D(bmp1,texcoord2.st);
			normalColor1.xy=(normalColor1.xyz*2.0)-1.0;
			vec3 normal1=vec3(normalColor1.xy,sqrt(1.0-normalColor1.x*normalColor1.x-normalColor1.y*normalColor1.y));
			vec3 normal2=normal;
			normal=(normal2+normal1)*0.5;
			normal=normalize(normal);

		#endif

		vec3 N;	
		vec3 vdir;
		
		N=TBN*normal;			
		N=normalize(N);
		vdir=normalize(viewDir);
		
		if(-eyepos.z<maskDistance)
		{
			litColor += ComputeSunLight(N,vdir,lightDir);
			
			for(int i=0; i<4; i++)
			{
				if(light0[i].x>0.0)
					litColor += ComputeLight(N, vdir, lightpos0[i], lightColor0[i], light0[i].y, light0[i].x, lightdir0[i], light0[i].z, light0[i].w);
			}
		
			litColor = mix(litColor,vec3(0.0,0.0,0.0),clamp((-eyepos.z-(maskDistance-1000.0))/1000.0,0.0,1.0));
		}
		
		float NdotE = clamp(dot(N.xyz,vdir),0.0,1.0);
		
		vec3 REFL=specularColor.rgb*fresnel.x;
		float rough=sqrt(fresnel.y*normalColor.b);
		
		// IBL diffuse
		vec4 IBLdiffuse = RGBMDecode(textureCubeLod(ambientCubeDiffuse,-N.xyz,cubeLod));
		IBLdiffuse = IBLdiffuse*(phong_diffuse()+vec4(ambientScatter))/vec4(1+ambientScatter);
		vec3 diffuse =  IBLdiffuse.xyz * texColor.rgb * diffuseColor.rgb;
	
		// IBL specular
		vec3 reflection = reflect(vdir.xyz,N.xyz);
		float glossLod = rough*cubeLod2;
		
		vec4 IBLspecular = RGBMDecode(textureCubeLod(ambientCube,reflection.xyz,glossLod));
		vec2 brdf = texture2D(brdfLUT, vec2(NdotE, rough)).xy;
		vec3 IBL=REFL*brdf.x+brdf.y;
		vec3 specular = IBL*IBLspecular.xyz*fresnel.x;
		
		// DESATURATE SPEC
		float lum=dot(specular.rgb,vec3(0.3,0.59,0.11));
		specular.rgb=mix(vec3(lum),specular.rgb,reflSaturation);
			
		// final composition 
		ambient=(diffuse.rgb+specular.rgb);
		vec3 finalColor= (litColor+ambient);//*vec3(TAO); */
		
// -------- ATMOSPHERE ---------------------------------		
		vec3 		Fex;
		vec3 		Lin;
		
		vec3 camposFromEarth=(campos.xyz*length_unit)-earth_center.xyz;
		camposFromEarth.y=max(camposFromEarth.y,-earth_center.y);
		Lin=GetSkyRadianceToPoint(camposFromEarth, Wpos, 0.0, sundirW, Fex)*inScatterColor;
		vec3 fogFinalColor=Fex*finalColor + Lin;
		
		vec3 sundir2d=normalize(vec3(sundirW.x,0.0,sundirW.z));		
		vec3 viewdir2d_flat=normalize(cross(sundir2d,vec3(0.0,1.0,0.0)));
		Lin=GetSkyRadianceWithoutPhase(camposFromEarth, viewdir2d_flat, 0.0, sundirW, Fex);
		fogFinalColor=fogFinalColor*fogScat.a + (fogScat.rgb*Lin);
// -----------------------------------------------------

		float density=texColor.a*alphalevel;
		finalColor=mix(finalColor,fogFinalColor,density);
		
		gl_FragColor.rgb=max(finalColor,0.0);
		gl_FragColor.a=clamp(density,0.0,1.0);
	
	#endif
}
