uniform sampler2D depthTex;	// depth texture
uniform sampler2D normalTex; // normal tex
uniform sampler2D BGTex; // relected background
//uniform sampler2D rotMap;	// rotation normal map
uniform float reflScale;

uniform int 		NUM_SAMPLES;

varying vec2 	texCoord;
varying vec2	VPOS;

/*uniform vec4	TM0,
				TM1,
				TM2,
				TM3;*/
				
uniform mat4 reprojTM;
uniform mat4 projTM;

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;
}

vec4 getSSpos(vec4 pos)
{
	vec4 sspos;
		
	// compute texture space beam pos
	/*sspos.x = dot(pos,TM0);
	sspos.y = dot(pos,TM1);
	sspos.w = dot(pos,TM3);*/
	sspos=projTM*pos;
	sspos.xy=sspos.xy/sspos.w;
	sspos.xy=vec2(1.0)-sspos.xy;
	return sspos;
}

/*vec4 getFinalColor(vec2 coords)
{
	float 	totalContribution=1.0;
	vec4  	acc=texture2D( BGTex, coords );
	
	if(gMat.y<=0.99)
	{
		vec4 	tapBlur;
		vec2 	tccoords;
		for(int i=0; i<12; i++)
		{
			tccoords=coords+filterTaps[i]*((1.0-gMat.y)*50.0);
			tapBlur=texture2D(BGTex,tccoords);
			acc += tapBlur;
			totalContribution++;
		}
	}
	return acc.rgba/totalContribution;
}*/

/*vec4 Reproject(vec2 coords)
{
	vec2 newcoords=prevTM
	vec4  	acc=texture2D( BGTex, coords );
}*/

void main(void)
{	
	// compute eye space position
	vec4 pos = texture2D(depthTex,texCoord.st);
	pos.xy=VPOS.xy*-pos.z;
	pos.w=1.0;
	
	float t=0.0;
	float t1;
	vec4 reflColor=vec4(0.0,0.0,0.0,0.0);	
			
	if(-pos.z<NUM_SAMPLES*5.0)
	{
		vec3 reflected;
		vec4 curpos;
		vec4 sspos;
		vec2 expUV;
	
		float rangeMax=NUM_SAMPLES*5.0;
		float rangeMin=rangeMax-200.0;
		t1=1.0-clamp((-pos.z-rangeMin)/(rangeMax-rangeMin),0.0,1.0);
	
		// get normal
		vec4 encoded=texture2D(normalTex,texCoord.st);
		vec4 normal = decode(encoded);
		//reflPow=encoded.z*16.0;
		
		// get eyedir
		vec3 eye=normalize(pos.xyz);
		
		// compute reflected vector
		reflected=reflect(eye,normal.xyz);

		// compute reflected color
		if(reflected.z<0.5)
		{
			t=-reflected.z;
			t=(t-0.2)/0.1;
			t=clamp(t,0.0,1.0);
			
			//float jitter=(texture2D(rotMap,texCoord.st).x*2.0-1.0);
			reflected*=2.5;//+jitter;
						
			vec4 oldpos;
			curpos=pos;
			int i=0;
			int stepsize=NUM_SAMPLES/30;
			int count=30;
			vec3 reflStep=reflected*stepsize;
			int refine=0;
			
			while(stepsize>1 && i<count)
			{
				oldpos=curpos;
				curpos.xyz+=reflStep;
				sspos=getSSpos(curpos);
				sspos.z=texture2D( depthTex, sspos.xy ).x;
				if(curpos.z<sspos.z+2.5)
				{
					stepsize/=2;
					count*=2;
					i=-1;
					reflStep=reflected*stepsize;
					if(stepsize<=1)
					{
						if(curpos.z>sspos.z-12.5)
						{
							refine=1;
							break;
						}
					}
					curpos=oldpos;
				}
				i++;
			}
			curpos=oldpos;
			if(refine==1)
			{
				reflected*0.25;
				for(int i=0; i<20; i++)
				{
					curpos.xyz+=reflected;
					sspos=getSSpos(curpos);
					sspos.z=texture2D( depthTex, sspos.xy ).x;
					if(curpos.z<=sspos.z+2.5 && curpos.z>=sspos.z-2.5)
					{
						expUV=abs((sspos.xy-vec2(0.5))*vec2(2.0));	
						t*= 1.0-clamp((expUV.x-0.8)*5.0,0.0,1.0);
						t*=	1.0-clamp((expUV.y-0.8)*5.0,0.0,1.0);
						if(sspos.x>=1.0)
							break;
						if(sspos.x<=0.0)
							break;
						if(sspos.y>=1.0)
							break;
						if(sspos.y<=0.0)
							break;
							
						// reproject the point
						curpos=reprojTM*curpos;
						sspos=getSSpos(curpos);
						
						reflColor=texture2D( BGTex, sspos.xy );//getFinalColor( sspos.xy );
						reflColor.a=1.0;
						break;
					}
				}
			}
		}	
	}
	float reflmul=t*t1;// reflPow;
	gl_FragColor.xyz = reflColor.xyz;
	gl_FragColor.a=reflmul*reflColor.a*reflScale;
}