varying vec2 		texcoord;
varying vec2 		texcoord1;

uniform sampler2D 	bmp,
					tex;
uniform samplerCube	ambientCube;

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

uniform float		alphaLevel;
uniform float		scatter;

varying vec3 		Fex;
varying vec3 		Lin;
float				Pi=3.14159265359;
vec4 				texColor;

#ifdef BUMP2

	varying vec2 		texcoord2;
	uniform sampler2D 	bmp1;

#endif

	uniform vec3		lightDir;
	uniform vec4		lightcolor;
	uniform vec2 		spec;
	uniform vec2		fresnel;
	
#ifdef PSYSTEM

	varying float 	life;
	varying vec2	cosina;
	uniform vec4	data;
//	varying mat3	vtm;
	uniform float	alphaMul;
	varying vec4 	posDir;
	uniform vec3 	sunpos;
	/*uniform vec3	horizonColor;
	uniform vec3	zenithColor;
	uniform float  	inScatter;*/
	//varying float	h;
	
#else
	
	// SHADOWMAP PARAMS
	uniform sampler2DShadow 	shadowmap;
	uniform sampler2DShadow 	shadowmap2;
	uniform sampler2DShadow 	shadowmap4;
	uniform sampler2DShadow 	shadowmap8;

	uniform float 		lightrange;
	uniform float 		lightrange2;
	uniform float 		lightrange4;
	uniform float 		lightrange8;
			
	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;

	uniform vec4		LTM0d,
						LTM1d,
						LTM2d,
						LTM3d;
	//////////////////////////////////////////

	/*varying vec3		w0,
						w1,
						w2;*/
	varying mat3		TBN;
	varying vec3		viewDir;
	varying vec4 		vpos;
		
//	#ifdef CUBEREFL
	
	//	uniform samplerCube	reflCube;
	//	uniform float		reflScale;
	//	uniform float		reflPow;
		uniform vec4 		reflColorMul;

//	#endif
	
#endif

///////// LIGHTS ////////////////////////
uniform float 		light0;
uniform vec3 		lightpos0;
uniform vec3 		lightdir0;
uniform vec3 		lightColor0;
uniform float 		lightRange0;
uniform float 		lightCos0;
uniform float 		lightfallof0;

uniform float 		light1;
uniform vec3 		lightpos1;
uniform vec3 		lightdir1;
uniform vec3 		lightColor1;
uniform float 		lightRange1;
uniform float 		lightCos1;
uniform float 		lightfallof1;
///////////////////////////////////////////

vec4 normalColor;

vec3 ComputeSunLight(vec3 N, vec3 vdir, vec3 ldir, float specAlpha)
{
	#ifdef PSYSTEM
		
		//float specular = 0;
		vec3 diffuse;
		
		/*if( scatter>0.0 )
		{
			diffuse=(dot(N,ldir)*0.5+0.5)*diffuseColor;
				
			vec3 LTLight=ldir+N.xyz;
			float LTdot=pow(clamp(dot(vdir,-LTLight),0.0,1.0),2.0)*scatter;
			diffuse += LTdot*diffuseColor;
		}
		else
			diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;
*/
		diffuse=/*clamp*/(dot(ldir,posDir.xyz)*0.5+0.5/*,0.0,1.0*/)*diffuseColor;
		
		//vec3 E=sunpos-eyepos;
		//E=normalize(E);
		//float backlight=pow(clamp(dot(E,ldir),0.0,1.0),13.0);//*(1.0-texColor.a);
		vec3 LT=ldir+posDir.xyz;
		float backlight=pow(clamp(dot(-LT,vdir),0.0,1.0),10.0)*scatter*(1.0-texColor.a);
		return texColor.rgb*lightcolor.rgb*(diffuse+backlight);
		
		
	#else
	
		vec3 diffuse = diffuseColor;

		// SHADOW MAP CODE
		vec4	XYproj;	
		float shadowOcc=1.0;
		vec3 projcoords;
				
		if( -eyepos.z/lightrange <= 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/lightrange2 <= 1.0 )
			{
				// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
				XYproj.x = dot(eyepos,LTM0b);
				XYproj.y = dot(eyepos,LTM1b);
				XYproj.z = dot(eyepos,LTM2b);
				XYproj.w = dot(eyepos,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;
				
				/*float lrangeMin=lightrange2-200.0;
				shadowOcc=mix(shadowOcc,1.0,( clamp( (-eyepos.z-lrangeMin)/(lightrange2-lrangeMin),0.0,1.0) ));*/
			}
			else
			{
				if( -eyepos.z/lightrange4 <= 1.0 )
				{
					// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
					XYproj.x = dot(eyepos,LTM0c);
					XYproj.y = dot(eyepos,LTM1c);
					XYproj.z = dot(eyepos,LTM2c);
					XYproj.w = dot(eyepos,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=lightrange4-300.0;
					shadowOcc=mix(shadowOcc,1.0,( clamp( (-eyepos.z-lrangeMin)/(lightrange4-lrangeMin),0.0,1.0) ));
				}
				/*else
				{
					if( -eyepos.z/lightrange8 <= 1.0 )
					{
						if(split8==1)
						{
							// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
							XYproj.x = dot(eyepos,LTM0d);
							XYproj.y = dot(eyepos,LTM1d);
							XYproj.z = dot(eyepos,LTM2d);
							XYproj.w = dot(eyepos,LTM3d);

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

							float dOfs = cOfs*0.5;
							shadowOcc=0.0;

							vec3 shadowcoords;
							shadowcoords.z=projcoords.z;

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

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

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

							shadowcoords.xy=projcoords.xy+vec2(-dOfs,-dOfs);
							shadowOcc+=shadow2D(shadowmap8,shadowcoords).r;
					
							shadowOcc *= 0.25;
								
							float lrangeMin=lightrange8-1000.0;
							shadowOcc=mix(shadowOcc,1.0,( clamp( (-pos.z-lrangeMin)/(lightrange8-lrangeMin),0.0,1.0) ));
						}
					}
				}*/
			}
		}
		////////////////////////////////////////
		
		float specular=0.0;
			
	/*	if( -eyepos.z < 4000.0 )	
		{
			if( -eyepos.z < 2000.0 )
			{*/
				if(shadowOcc>0.0)
				{
					float S=fresnel.y*normalColor.a;
					diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;	
					diffuse/=Pi;
					diffuse*=0.9;
		
					if(S>0.0)	// specular reflectance (fresnel)
					{
						vec3 H = normalize(ldir+vdir);
						float NdotH = (dot(H,N.xyz));
						float EdotH = dot(vdir,H);
						float NdotE = dot(N.xyz,vdir);
						float NdotL = dot(ldir,N.xyz);
						float F=0.1+0.9*pow((1.0-EdotH),5.0);
						specular=max((0.0397436*S+0.0856832)*(F*pow(NdotH,S)/max(NdotL,NdotE)),0.0);
					}					
				}
		/*	}
			else
				diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;
		}	*/						
		return (diffuse*texColor.rgb+specular)*lightcolor.rgb*shadowOcc;
		
	#endif
}

vec3 ComputeLight(vec3 N, vec3 vdir, vec3 lpos, vec3 lcolor, float lrange, float light, vec3 lightdir, float lcos, float fallof, float specAlpha)
{
	vec3 diffuse = diffuseColor;
	
	#ifdef PSYSTEM
		
		if(light>1.0)
		{
			vec3 ldir=lpos-eyepos.xyz;
			float dist=length(ldir)/lrange;
			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 linAtt=clamp(1.0 - dist,0.0,1.0);
				float att=min(1.0,linAtt*angAtt*fallof);
				/*if( scatter>0.0 )
				{
					diffuse=(dot(N,ldir)*0.5+0.5)*diffuseColor;
						
					vec3 LTLight=ldir+N.xyz;
					float LTdot=pow(clamp(dot(vdir,-LTLight),0.0,1.0),2.0)*scatter;// + vec3(0.15, 0.15, 0.15);
					diffuse += LTdot*diffuseColor;
				}
				else
					diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;*/
				diffuse=clamp(dot(ldir,posDir.xyz),0.0,1.0)*diffuseColor;
				vec3 LT=ldir+posDir.xyz;
				float backlight=pow(clamp(dot(-LT,vdir),0.0,1.0),10.0)*scatter*(1.0-texColor.a);
				return (diffuse+backlight)*lcolor*texColor.rgb*att;
			}
		}
		else
		{
			vec3 ldir=lpos-eyepos.xyz;
			float dist=length(ldir)/lrange;
			if(dist<=1.0)
			{
				ldir=normalize(ldir);
				float att= clamp((1.0 - dist)*fallof,0.0,1.0);
				/*if( scatter>0.0 )
				{
					float NLwrap=(dot(ldir,N)+scatter)/(1.0+scatter);
					diffuse = vec3(max(NLwrap,0.0));
					float fScatter = smoothstep(0.0, 0.5, NLwrap) * smoothstep(1.0, 0.5,NLwrap);
					diffuse = diffuseColor*((fScatter*vec3(0.15, 0.15, 0.15))+diffuse); 
				}
				else
					diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;*/
				if( scatter>0.0 )
				{
					diffuse=(dot(N,ldir)*0.5+0.5)*diffuseColor;
						
					vec3 LTLight=ldir+N.xyz;
					float LTdot=pow(clamp(dot(vdir,-LTLight),0.0,1.0),2.0)*scatter;// + vec3(0.15, 0.15, 0.15);
					diffuse += LTdot*diffuseColor;//*diffuseColor;*/
				}
				else
					diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;
				return (diffuse)*lcolor*texColor.rgb*att;
			}
		}
	
	#else
	
		if(light>1.0)
		{
			float specular = 0.0;
			vec3 ldir=lpos-vpos.xyz;
			float dist=length(ldir)/lrange;
			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 linAtt=clamp(1.0 - dist,0.0,1.0);
				float att=min(1.0,linAtt*angAtt*fallof);
				/*if( -eyepos.z < 4000.0 )
				{
					diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;
					if( -eyepos.z < 2000.0 )
					{
						vec3 halfv = normalize(ldir+vdir);
						specular = clamp(dot(halfv, N.xyz),0.0,1.0);
						specular = pow(specular,spec.x)*spec.y;
					}
				}*/
				diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;	
				diffuse/=Pi;
				diffuse*=0.9;
		
				float S=fresnel.y*normalColor.a;
				if(S>0.0)	// specular reflectance (fresnel)
				{
					vec3 H = normalize(ldir+vdir);
					float NdotH = (dot(H,N.xyz));
					float EdotH = dot(vdir,H);
					float NdotE = dot(N.xyz,vdir);
					float NdotL = dot(ldir,N.xyz);
					float F=0.1+0.9*pow((1.0-EdotH),5.0);
					specular=max((0.0397436*S+0.0856832)*(F*pow(NdotH,S)/max(NdotL,NdotE)),0.0);
				}					
					
				return (diffuse*texColor.rgb+specular)*lcolor*att;
			}
		}
		else
		{
			float specular = 0.0;
			vec3 ldir=lpos-vpos.xyz;
			float dist=length(ldir)/lrange;
			if(dist<=1.0)
			{
				ldir=normalize(ldir);
				float att= clamp((1.0 - dist)*fallof,0.0,1.0);
				/*if( -eyepos.z < 4000.0 )
				{
					diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;
					if( -eyepos.z < 2000.0 )
					{
						vec3 halfv = normalize(ldir+vdir);
						specular = clamp(dot(halfv, N.xyz),0.0,1.0);
						specular = pow(specular,spec.x)*spec.y*specAlpha;
					}
				}*/
				
				diffuse = clamp(dot(N,ldir),0.0,1.0)*diffuseColor;	
				diffuse/=Pi;
				diffuse*=0.9;
		
				float S=fresnel.y*normalColor.a;
				if(S>0.0)	// specular reflectance (fresnel)
				{
					vec3 H = normalize(ldir+vdir);
					float NdotH = (dot(H,N.xyz));
					float EdotH = dot(vdir,H);
					float NdotE = dot(N.xyz,vdir);
					float NdotL = dot(ldir,N.xyz);
					float F=0.1+0.9*pow((1.0-EdotH),5.0);
					specular=max((0.0397436*S+0.0856832)*(F*pow(NdotH,S)/max(NdotL,NdotE)),0.0);
				}					
				
				return (diffuse*texColor.rgb+specular)*lcolor*att;
			}
		}
		
	#endif

	return vec3(0.0,0.0,0.0);
}

void main()
{	
	texColor=texture2D(tex,texcoord.st);
	
	#ifdef PSYSTEM
		
		if(life>0.0)
		{
			vec4 refl=vec4(0.0,0.0,0.0,0.0);
			vec3 litColor=vec3(0.0,0.0,0.0);
			vec3 ambient=texColor.rgb*diffuseColor*ambientColor;//*vec3(0.5,0.5,0.5);
			
			float alpha=( clamp( (life-0.2) * 5.0,0.0,1.0) );
				
			texColor.a*=alpha;
			vec3 N;
			vec3 vdir;
			
			vdir=normalize(-eyepos.xyz);
			litColor += ComputeSunLight(N,vdir,lightDir,1.0);
			
			if(light0>0.0)
			{
				litColor += ComputeLight(N, vdir, lightpos0, lightColor0, lightRange0, light0, lightdir0, lightCos0, lightfallof0, 1.0);
				if(light1>0.0)
				{
					litColor += ComputeLight(N, vdir, lightpos1, lightColor1, lightRange1, light1, lightdir1, lightCos1, lightfallof1, 1.0);
				}
			}
			
			vec3 finalColor=litColor + ambient; 

			finalColor=Fex*finalColor + Lin;//mix(fog.rgb,finalColor,fog.a);
	
			gl_FragColor.rgb=max(finalColor,0.0);
			gl_FragColor.a=max(texColor.a*alphaLevel*alphaMul,0.0);			
		}
		else
		{
			discard;
		}
		
	#else

		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);
		vec3 normal=normalize((normalColor.xyz*2.0)-1.0);
		vec3 ambient;
	
		#ifdef BUMP2

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

		#endif

		vec3 N;	
		vec3 vdir;
		
	/*	if( -eyepos.z < 4000.0 )	
		{*/
			/*N.x=dot(w0,normal);
			N.y=dot(w1,normal);
			N.z=dot(w2,normal);*/
			N=TBN*normal;			
			N=normalize(N);
			
		/*	if( -eyepos.z < 2000.0 )
			{*/
				vdir=normalize(viewDir);
					
				//#ifdef CUBEREFL
				
					float E=fresnel.y*0.00390625*normalColor.a;
					vec3 reflection = reflect(vdir,N);
					vec4 specular = textureCubeLod(ambientCube,reflection.xyz,(1.0-E)*7.0);
				/*	reflInt=max(pow(1.0-abs(dot(N,vdir)),fresnel.x)*normalColor.a,0.0)*reflPow;
					refl=textureCube(reflCube,reflection.xyz)*reflColorMul*reflScale;*/
					
			//	#endif
				
				vec4 diffuse=textureCubeLod(ambientCube,N.xyz,6.0);	
				ambient=ambientColor.rgb*mix(texColor.rgb*diffuseColor.rgb*diffuse.rgb, specular.rgb*reflColorMul.rgb, E);
			/*}*/
	//	}
		litColor += ComputeSunLight(N,vdir,lightDir,normalColor.a);
		if(light0>0.0)
		{
			litColor += ComputeLight(N, vdir, lightpos0, lightColor0, lightRange0, light0, lightdir0, lightCos0, lightfallof0, normalColor.a);
			if(light1>0.0)
			{
				litColor += ComputeLight(N, vdir, lightpos1, lightColor1, lightRange1, light1, lightdir1, lightCos1, lightfallof1, normalColor.a);
			}
		}
		
		vec3 finalColor= litColor+ambient;
		finalColor=Fex*finalColor + Lin;
	
		gl_FragColor.rgb=max(finalColor,0.0);
		gl_FragColor.a=max(texColor.a*alphaLevel,0.0);
	
	#endif
}
