uniform sampler2D 	colorTex,
			normalTex,
			matTex,
			posTex;

#ifdef ALPHABLEND

	uniform sampler2D 	bgTex;

#endif

#ifdef SPOT

uniform sampler2D 	lightTex;

#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,
					cOfs;

uniform vec4		LTM0,
			LTM1,
			LTM2,
			LTM3;

varying vec2		VPOS;
uniform float 		bias;


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

	vec4 color = texture2D(colorTex,texcoord.st);
	vec4 normal = texture2D(normalTex,texcoord.st);
	vec4 pos = texture2D(posTex,texcoord.st);
	vec4 mat = texture2D(matTex,texcoord.st);
	
	float scatter=floor(pos.a)/256.0;	//1/256.0;
	float scatterRed=pos.a-floor(pos.a);
	normal.xyz=normalize(normal.xyz);	
	
	// 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;

#ifdef SPOT

	projcoords.xyz=XYproj.xyz/XYproj.w;
	float att=clamp(1.0 - XYproj.z/lightrange,0.0,1.0);
	projcolor=texture2D(lightTex,projcoords.xy).xyz*att;

#endif

#ifdef OMNI

	float vDist=length(lightpos-pos.xyz)/lightrange;
	projcolor= vec3(clamp(1.0 - vDist,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 )
		{	
			vec3 ldir=lightpos-pos.xyz;
			ldir=normalize(ldir);
					
			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 scatterWidth*/0.5, NLwrap) * smoothstep(/*1.0 ScatterWidth*2.0 */1.0, /*scatterWidth*/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);
				}
			}
		}
		
		#ifdef ALPHABLEND
			vec4 dest=texture2D(bgTex,texcoord.st);
			finalcolor.xyz = dest.xyz + (finalcolor.xyz*lightcolor.xyz*projcolor)*lightscale*shadowOcc*color.a;
			gl_FragColor.xyz=max(finalcolor.xyz,0.0);
		#else	
			gl_FragColor.xyz=max((finalcolor.xyz*lightcolor.xyz*projcolor)*lightscale*shadowOcc,0.0);
		#endif
	}
	else
	{
		#ifdef ALPHABLEND
			vec4 dest=texture2D(bgTex,texcoord.st);
			gl_FragColor.xyz=max(dest.xyz,0.0);
		#else	
			discard; //gl_FragColor.xyz=vec3(0.0,0.0,0.0);
		#endif
	}
	gl_FragColor.a=0.0;
}
