uniform sampler2D 	colorTex,
			normalTex,
			matTex,
			posTex;
float		Pi=3.14159265359;

#ifdef SPOT

	uniform vec3 		lightdir;
	uniform float 		lightCos;

	#ifdef PROJECTION

		uniform sampler2D 	lightTex;

	#endif

#endif

#ifdef OMNI

uniform vec2		prj;

	#ifdef PROJECTION

		uniform samplerCube 	projTex;

	#endif

#endif


#ifdef SHADOW

uniform sampler2DShadow	shadowmap;

	#ifdef OMNI

	uniform samplerCube	indCube;

	#endif

#endif

varying vec2 		texcoord;
uniform vec3 		lightpos;
uniform vec3		lightcolor;
uniform float		lightscale;
uniform float		lightrange,
					lightfallof,
					cOfs;

uniform vec4		LTM0,
					LTM1,
					LTM2,
					LTM3;

varying vec2		VPOS;
uniform float 		bias;

vec4 decode(vec4 enc)
{
    vec2 fenc = enc.xy*4.0-2.0;
    float f = dot(fenc,fenc);
    float g = sqrt(1.0-f/4.0);
    vec4 n;
    n.xy = fenc.xy*g;
    n.z = 1.0-f/2.0;
	n.w=enc.w;
    return n;
}

void main()
{
	vec4	XYproj;	
	vec3 	projcoords;
	vec3 	projcolor;

	vec4 color = texture2D(colorTex,texcoord.st);
	vec4 normal = decode(texture2D(normalTex,texcoord.st));
	vec4 pos = texture2D(posTex,texcoord.st);
	vec4 mat = texture2D(matTex,texcoord.st);
	
	mat.y*=256.0;
	
	//pos.z*=wFar;
	float scatter=mat.x;/*floor(pos.a)/256.0;	//1/256.0;
	float scatterRed=pos.a-floor(pos.a);*/
	//normal.xyz=normalize(normal.xyz);	// normal.a = scatter level
	
	// compute position
	pos.xy=VPOS.xy*-pos.z;
	pos.w=1.0;

	// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
	XYproj.x = dot(pos,LTM0);
	XYproj.y = dot(pos,LTM1);
	XYproj.z = dot(pos,LTM2);
	XYproj.w = dot(pos,LTM3);

	float shadowOcc=1.0;
	
	vec3 ldir=lightpos-pos.xyz;
	float vDist=length(ldir)/lightrange;
	ldir=normalize(ldir);
	
#ifdef SPOT

	float linAtt=clamp(1.0 - vDist,0.0,1.0);
	float cos=dot(lightdir,ldir);
	float angAtt=clamp(1.0 - ((1.0-cos)/(1.0-lightCos)),0.0,1.0);
	float att=min(1.0,linAtt*angAtt*lightfallof);
	projcolor= vec3(att);			
	projcoords.xyz=XYproj.xyz/XYproj.w;
	
	#ifdef PROJECTION
	
		projcolor=texture2D(lightTex,projcoords.xy).xyz*projcolor;
			
	#endif

#endif

#ifdef OMNI

	projcolor= vec3(clamp((1.0 - vDist)*lightfallof,0.0,1.0));
	
	#ifdef PROJECTION
	
		projcolor=textureCube(projTex,XYproj.xyz).xyz*projcolor;
		
	#endif

#endif

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


#ifdef SHADOW

	#ifdef OMNI

		float MA;
	
		MA=max(abs(XYproj.x),abs(XYproj.y));
		MA=max(MA,abs(XYproj.z));

		projcoords.xy=textureCube(indCube, XYproj.xyz).xy;
		projcoords.z=-(prj.y/-MA)-prj.x;
		projcoords.z=projcoords.z*0.5+0.5;
	
	#endif

	projcoords.z=projcoords.z-bias;
	float dOfsX = cOfs*0.5;
	float dOfsY = dOfsX;
	
	#ifdef OMNI
		dOfsX*=0.5;
	#endif

	shadowOcc=0.0;

	vec3 shadowcoords;
	shadowcoords.z=projcoords.z;

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

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

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

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

	shadowOcc *= 0.25;

#endif
	
	vec4 finalcolor=color;

	if(shadowOcc>0.0)
	{
		/*if( -pos.z < 8000.0 )
		{	
			if(scatter>0.0)
			{
				// scatter width=0.3
				float NLwrap=(dot(ldir,normal.xyz)+scatter)/(1.0+scatter);
				float diffuse = max(NLwrap,0.0);
				float fScatter = smoothstep(0.0, 0.5, NLwrap) * smoothstep(1.0, 0.5,NLwrap);
				finalcolor *= ((fScatter*vec4(scatterRed, 0.0, 0.0, 1.0))+diffuse); 
			}
			else
			{
				float diffuse = max(dot(ldir,normal.xyz),0.0);
				finalcolor *= diffuse;
			}
		
			if( -pos.z < 4000.0 )
			{
				vec3 vdir=-pos.xyz;
				vdir=normalize(vdir);
				
				if(mat.y>0.0)
				{
					vec3 halfv = ldir+vdir;
					halfv=normalize(halfv);
					float spec = clamp(dot(halfv, normal.xyz),0.0,1.0);
					spec = pow(spec,mat.x)*mat.y;
					finalcolor += spec;
				}
				
				if( -pos.z < 2000.0 )
				{
					float fresnelres=pow(1.0-clamp(dot(normal.xyz,vdir),0.0,1.0),mat.w);
					finalcolor += vec4(fresnelres * mat.z);
				}
			}
		}*/
		
		//vec3 ldir=lightdir;
		vec3 E=-pos.xyz;
		E=normalize(E);
		
		float diffuse = dot(ldir,normal.xyz);
		/*if(diffuse<=0.0) 
			discard;*/
		diffuse/=Pi;
		diffuse*=(0.9/*1.0-0.1/*mat.x*/);
		finalcolor *= diffuse;
		
		if(scatter>0.0)
		{
			vec3 LTLight=ldir+normal.xyz;
			float LTdot=pow(clamp(dot(E,-LTLight),0.0,1.0),3.0)*scatter;
			finalcolor += LTdot*color;
		}
		
		if(mat.y>0.0)	// specular reflectance (fresnel)
		{
			vec3 H = ldir+E;
			H=normalize(H);
			float NdotH = (dot(H,normal.xyz));
			float EdotH = dot(E,H);
			float NdotE = dot(normal.xyz,E);
			float NdotL = dot(ldir,normal.xyz);
			float F=/*mat.x*/0.1+(0.9/*1.0-0.1/*mat.x*/)*pow((1.0-EdotH),5.0);
			finalcolor+=max((0.0397436*mat.y+0.0856832)*(F*pow(NdotH,mat.y)/max(NdotL,NdotE)),0.0);
		}
		
		gl_FragColor.xyz=max((finalcolor.xyz*lightcolor.xyz)*lightscale*projcolor*shadowOcc,0.0);
	}
	else
		discard;
	gl_FragColor.a=0.0;
}
