uniform sampler2D depthTex;	// depth texture
uniform sampler2D normalTex; // normal tex
uniform sampler2D BGTex; // relected background

uniform int NUM_SAMPLES;

varying vec2 	texCoord;
varying vec2	VPOS;

uniform vec4	TM0,
				TM1,
				TM2,
				TM3;

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(void)
{	
	// compute eye space position
	vec4 pos = texture2D(depthTex,texCoord.st);
	pos.xy=VPOS.xy*-pos.z;
	pos.w=1.0;
	
	// get normal
	vec4 normal = decode(texture2D(normalTex,texCoord.st));
		
	// get eyedir
	vec3 eye=normalize(pos.xyz);
	
	// compute reflected vector
	vec3 reflected=reflect(eye,normal.xyz);

	// compute reflected color
	vec4 reflColor=vec4(0.0,0.0,0.0,0.0);
	float depthZ=0.0;
	float t=0.0;
	if(reflected.z<-0.2)
	{
		t=-reflected.z;
		t=(t-0.2)/0.1;
		t=clamp(t,0.0,1.0);
		
		vec4 sspos;
		vec2 expUV;
		
		vec4 prevOfs;
		prevOfs.x = dot(pos,TM0);
		prevOfs.y = dot(pos,TM1);
		prevOfs.w = dot(pos,TM3);
		prevOfs.xy=prevOfs.xy/prevOfs.w;
		prevOfs.xy=vec2(1.0-prevOfs.x,1.0-prevOfs.y);
		
		reflected*=20;
		
		// try to see if reflection vector if too small for reaching a surface
		for(int i=0; i < NUM_SAMPLES; i++)
		{
			pos.xyz+=reflected;
		
			// compute texture space beam pos
			sspos.x = dot(pos,TM0);
			sspos.y = dot(pos,TM1);
			sspos.w = dot(pos,TM3);
			sspos.xy=sspos.xy/sspos.w;
			sspos.xy=vec2(1.0-sspos.x,1.0-sspos.y);
			
			//compare z
			depthZ=texture2D( depthTex, sspos.xy ).x;
			if(pos.z<depthZ+10.0 && pos.z>depthZ-10.0)
			{
				expUV=abs((prevOfs.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(prevOfs.x>=1.0)
					break;
				if(prevOfs.x<=0.0)
					break;
				if(prevOfs.y>=1.0)
					break;
				if(prevOfs.y<=0.0)
					break;
					
				reflColor=texture2D( BGTex, prevOfs.xy );
				reflColor.a=1.0;
				break;
			}
			prevOfs.xy=sspos.xy;
		}
	}	
	gl_FragColor = reflColor*t;
}