uniform sampler2D 			posTex;
uniform sampler2DShadow 	shadowmap;
uniform sampler2DShadow 	shadowmap2;
uniform sampler2DShadow 	shadowmap4;
uniform sampler2DShadow 	shadowmap8;
uniform sampler2DShadow 	shadowmapGlobal;
uniform sampler2DShadow 	shadowmapTerrain;

uniform mat4		reprojTM2;
uniform mat4		reprojTM4;
uniform mat4		reprojTM8;

varying vec2 		texcoord;
uniform float 		lightrange;
uniform float 		lightrange2;
uniform float 		lightrange4;
uniform float 		lightrange8;
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;
					
uniform float		cOfs2;
uniform float 		shadowRes;

uniform vec4		LTM0e,
					LTM1e,
					LTM2e,
					LTM3e;		

uniform vec4		LTM0f,
					LTM1f,
					LTM2f,
					LTM3f;								

varying vec2		VPOS;

uniform float	wFar;

void main()
{
	vec2	Zproj;
	vec4	XYproj;
	vec4 	reprojPos;	

	vec4 pos;
	pos.z = texture2D(posTex,texcoord.st).r;
	pos.xy=VPOS.xy*-pos.z;
	pos.w=1.0;

	float shadowOcc=1.0;
	gl_FragColor.r=1.0;
	
	vec3 projcoords;
	vec3 shadowcoords;
	float dOfs = cOfs2;
	
	XYproj.x = dot(pos,LTM0f);
	XYproj.y = dot(pos,LTM1f);
	XYproj.z = dot(pos,LTM2f);
	XYproj.w = dot(pos,LTM3f);

	projcoords.xy=XYproj.xy;
	projcoords.z=XYproj.z-0.005;
	
	///////////////////////////////////
	if( (clamp(projcoords.x,0.0,1.0)==projcoords.x)&&(clamp(projcoords.y,0.0,1.0)==projcoords.y) )
	{	
		shadowcoords.z=projcoords.z;
		shadowcoords.xy=projcoords.xy+vec2(-dOfs,dOfs);
		shadowOcc=shadow2D(shadowmapTerrain,shadowcoords).r;
		shadowcoords.xy=projcoords.xy+vec2(dOfs,dOfs);
		shadowOcc+=shadow2D(shadowmapTerrain,shadowcoords).r;
		shadowcoords.xy=projcoords.xy+vec2(dOfs,-dOfs);
		shadowOcc+=shadow2D(shadowmapTerrain,shadowcoords).r;
		shadowcoords.xy=projcoords.xy+vec2(-dOfs,-dOfs);
		shadowOcc+=shadow2D(shadowmapTerrain,shadowcoords).r;
		shadowOcc *= 0.25;

		float lightrange32=lightrange8*12.0;
		float lrangeMin=lightrange32-5000.0;
		shadowOcc=mix(shadowOcc,1.0,( clamp( (-pos.z-lrangeMin)/(lightrange32-lrangeMin),0.0,1.0) ));
		gl_FragColor.r=shadowOcc;
			
		if(shadowOcc>0.0)
		{
			float shadowbias=floor(shadowRes)*0.0001;
		
			//////////////////////////////////////////////////////////////////////
			XYproj.x = dot(pos,LTM0e);
			XYproj.y = dot(pos,LTM1e);
			XYproj.z = dot(pos,LTM2e);
			XYproj.w = dot(pos,LTM3e);

			vec3 gProjcoords=vec3(XYproj.xy,XYproj.z-(0.0025+shadowbias/*+shadowRes*0.0025*/));
			//projcoords.xy=XYproj.xy;
			//projcoords.z=XYproj.z-(0.0025+shadowbias/*+shadowRes*0.0025*/);
			///////////////////////////////////

			if( (clamp(gProjcoords.x,0.0,1.0)==gProjcoords.x)&&(clamp(gProjcoords.y,0.0,1.0)==gProjcoords.y) )
			{	
				//if(shadowOcc>0.0)
				//{
					if( -pos.z/lightrange <= 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);

						projcoords.xy=XYproj.xy;
						projcoords.z=XYproj.z-(0.0002+shadowbias/*+shadowRes*0.0025*/);
						///////////////////////////////////

						dOfs = cOfs;
						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;
						gl_FragColor.r*=shadowOcc;
					}
					else
					{				
						if( -pos.z/lightrange2 <= 1.0 )
						{
							// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
							reprojPos=reprojTM2*pos;
							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+shadowbias/*+shadowRes*0.0025*/);
							///////////////////////////////////

							dOfs = cOfs;
							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;
							gl_FragColor.r*=shadowOcc;
						}
						else
						{
							if( -pos.z/lightrange4 <= 1.0 )
							{
								// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
								reprojPos=reprojTM4*pos;
								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+shadowbias/*+shadowRes*0.0025*/);
								///////////////////////////////////

								dOfs = cOfs;
								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;
								gl_FragColor.r*=shadowOcc;
							}
							else
							{
								if( -pos.z/lightrange8 <= 1.0 )
								{
									// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
									reprojPos=reprojTM8*pos;
									XYproj.x = dot(reprojPos,LTM0d);
									XYproj.y = dot(reprojPos,LTM1d);
									XYproj.z = dot(reprojPos,LTM2d);
									XYproj.w = dot(reprojPos,LTM3d);

									projcoords.xy=XYproj.xy;
									projcoords.z=XYproj.z-(0.002+shadowbias/*+shadowRes*0.0025*/);
									///////////////////////////////////

									dOfs = cOfs;
									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) ));*/
									gl_FragColor.r*=shadowOcc;
								}
								else
								{
									float lightrange16=lightrange8*3.0;
									if( -pos.z/lightrange16 <= 1.0 )
									{
										shadowOcc=0.0;
										shadowcoords.z=gProjcoords.z;

										shadowcoords.xy=gProjcoords.xy+vec2(-cOfs2,cOfs2);
										shadowOcc+=shadow2D(shadowmapGlobal,shadowcoords).r;
										shadowcoords.xy=gProjcoords.xy+vec2(cOfs2,cOfs2);
										shadowOcc+=shadow2D(shadowmapGlobal,shadowcoords).r;
										shadowcoords.xy=gProjcoords.xy+vec2(cOfs2,-cOfs2);
										shadowOcc+=shadow2D(shadowmapGlobal,shadowcoords).r;
										shadowcoords.xy=gProjcoords.xy+vec2(-cOfs2,-cOfs2);
										shadowOcc+=shadow2D(shadowmapGlobal,shadowcoords).r;

										shadowOcc *= 0.25;
										
										float lrangeMin=lightrange16-2000.0;
										shadowOcc=mix(shadowOcc,1.0,( clamp( (-pos.z-lrangeMin)/(lightrange16-lrangeMin),0.0,1.0) ));
										gl_FragColor.r*=shadowOcc;
									}
								}
							}
						}
					}
				//}
			}
		}
	}
	
	gl_FragColor.r=max(1.0-gl_FragColor.r,0.0);
	/*if(gl_FragColor.r>0.0 && gl_FragColor.r<1.0) 
		gl_FragColor.r=0.5;*/
}
