uniform sampler2D 	colorTex,
					normalTex,
					matTex,
					posTex,
					lightTex;

#ifdef SHADOW

uniform sampler2D 	shadowmap;

#endif

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

uniform vec4		LTM0,
			LTM1,
			LTM2,
			LTM3;


float getBilinearFilteredShadow(sampler2D tex, vec2 coords, float dist) 
{
   /*	vec2 uv = coords*512.0;
   	vec2 ratio = uv-floor(uv);
   	vec2 opposite = vec2(1.0,1.0) - ratio;
*/
	vec4 shadowSample;

   	shadowSample.r=texture2D(tex,coords).x;
/* 	shadowSample.g=texture2D(tex,coords + vec2(cOfs,0.0) ).x;
	shadowSample.b=texture2D(tex,coords + vec2(0.0,cOfs) ).x;
	shadowSample.a=texture2D(tex,coords + vec2(cOfs,cOfs) ).x;
*/
	shadowSample.r=(dist - (shadowSample.r) < 0.0) ? 1.0 : 0.0;
/*	shadowSample.g=(dist - (shadowSample.g) < 0.0) ? 1.0 : 0.0;
	shadowSample.b=(dist - (shadowSample.b) < 0.0) ? 1.0 : 0.0;
	shadowSample.a=(dist - (shadowSample.a) < 0.0) ? 1.0 : 0.0;

   	float result = (shadowSample.r * opposite.x + shadowSample.g * ratio.x) * opposite.y + 
                   	(shadowSample.b * opposite.x + shadowSample.a * ratio.x) * ratio.y;*/
   return shadowSample.r; //result;
}

void main()
{
	vec2	Zproj;
	vec4	XYproj;	

	vec4 color = texture2D(colorTex,texcoord.st);
	vec4 normal = texture2D(normalTex,texcoord.st);
	vec4 pos = texture2D(posTex,texcoord.st);
	vec4 mat = texture2D(matTex,texcoord.st);
	
	// COMPUTE LIGHT TEXTURE PROJECTION + ATTENUATION
	pos.w=1.0;
	XYproj.x = dot(pos,LTM0);
	XYproj.y = dot(pos,LTM1);
	XYproj.w = dot(pos,LTM2);

	float shadowOcc=1.0;
	float dist=XYproj.w;
	float att=1.0 - dist/lightrange;

	vec2 projcoords=XYproj.xy/XYproj.w;
	vec3 projcolor=texture2D(lightTex,projcoords).xyz*att;
	///////////////////////////////////

#ifdef SHADOW

	vec4 shadowDist;
	dist=dist-16.0;
	float dOfs = cOfs*0.5;//*pow(dist,1.1)*0.001;
	shadowOcc=0.0;

	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(-dOfs,dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(dOfs,dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(-dOfs,-dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(dOfs,-dOfs), dist); 

	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(-dOfs,0), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(0,dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(0,-dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(dOfs,0), dist); 

	dOfs*=2.0;
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(-dOfs,dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(dOfs,dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(-dOfs,-dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(dOfs,-dOfs), dist); 

	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(-dOfs,0), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(0,dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(0,-dOfs), dist); 
	shadowOcc+=getBilinearFilteredShadow(shadowmap, projcoords+vec2(dOfs,0), dist); 

	shadowOcc *= 0.0625;

#endif

	vec3 vdir=-pos;
	vdir=normalize(vdir);

	vec3 ldir=lightpos-pos;
	ldir=normalize(ldir);
	
	float diffuse = clamp(dot(ldir,normal.xyz),0.0,1.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;

	vec4 finalcolor=(color*diffuse) + spec;

	float fresnelres=pow(1.0-clamp(dot(normal,vdir),0.0,1.0),mat.z);
	finalcolor += (fresnelres * mat.w * mat.y);

	gl_FragColor.xyz=(finalcolor.xyz*lightcolor.xyz*projcolor)*lightscale*shadowOcc;
	gl_FragColor.a=0.0;
}
