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 in view space
	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);
		
		reflected*=20.0;
		
		// compute pos in screen space
		/*vec4 sspPos;
		sspPos.x = dot(pos,TM0);
		sspPos.y = dot(pos,TM1);
		sspPos.z = pos.z;//dot(pos,TM2);
		sspPos.w = dot(pos,TM3);
		sspPos.xy=sspPos.xy/sspPos.w;
		sspPos.xy=vec2(1.0-sspPos.x,1.0-sspPos.y);*/
		
		// compute reflect pos in view space
		vec4 vspPosReflect = vec4(pos.xyz + reflected,1.0);
		
		// compute reflect pos in screen space
		vec4 sspPosReflect;
		sspPosReflect.x = dot(vspPosReflect,TM0);
		sspPosReflect.y = dot(vspPosReflect,TM1);
		sspPosReflect.z = vspPosReflect.z;//dot(vspPosReflect,TM2);
		sspPosReflect.w = dot(vspPosReflect,TM3);
		sspPosReflect.xy=sspPosReflect.xy/sspPosReflect.w;
		sspPosReflect.xy=vec2(1.0-sspPosReflect.x,1.0-sspPosReflect.y);
		
		// compute reflect in screen space	
		vec3 sspReflect = sspPosReflect.xyz - vec3(texCoord.st,pos.z);
		
		//vec4 sspos;
		vec2 expUV;
		vec4 prevOfs=vec4(texCoord.st,pos.z,1.0);

		// try to see if reflection vector if too small for reaching a surface
		for(int i=0; i < NUM_SAMPLES; i++)
		{
			//compare z
			depthZ=texture2D( depthTex, sspPosReflect.xy ).x;
			if(sspPosReflect.z<depthZ+10.0 && sspPosReflect.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;
					
				//prevOfs.xy=prevOfs.xy + (depthZ-prevOfs.z)*sspReflect;
				reflColor=texture2D( BGTex, prevOfs.xy/*+sspReflect.xy*(sspPosReflect.z-depthZ)/*prevOfs.xy + (depthZ-prevOfs.z)*sspReflect.xy*/ );
				reflColor.a=1.0;
				break;
			}
			prevOfs=sspPosReflect;
			sspPosReflect.xyz += sspReflect;
		}
	}	
	gl_FragColor = reflColor*t;
}