uniform sampler2D depthpacked;
uniform sampler2D normalmap;
uniform float brightness;
uniform float blur_range;

float unpackFloatFromVec3i(const vec3 value){
	const vec3 bitSh = vec3( 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0);
	return(dot(value, bitSh));
}
/*
vec3 packFloatToVec3i(const float value)
{
	const vec3 bitSh = vec3( 256.0 * 256.0, 256.0, 1.0);
	const vec3 bitMsk = vec3( 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
	vec3 res = fract(value * bitSh);
	res -= res.xxy * bitMsk;
	return res;
}*/

float getdepth(vec2 xy){
	float depth;
	vec3 col=texture2D(depthpacked,xy).xyz;
	if(col.x==0.0 && col.y==0.0 && col.z==0.0)
		depth=1000000000.0;
	else
		depth=unpackFloatFromVec3i(col);
	return depth;
}

float doDepth(vec2 xy, vec2 xy2, float d, float depth, vec3 n2, vec3 n1){
	if(depth == 1000000000.0|| d == 1000000000.0)
		return 2.0*brightness;
	float nd = distance(n1,n2);
	if(nd<0.000001 )
		return 1.0*brightness;
	float ret=0.0;
	float dd = 1.5*brightness;
	float m = brightness;

	vec3 a =vec3(xy*vec2(depth),depth);
	vec3 b =vec3(xy2*vec2(d),d);

	ret = -distance(a,b)*0.5*brightness;

	if(d<depth)
		dd = dot(n1,n2);

	return dd-ret*1000.0;
}
void main()
{
	vec2 xy = gl_TexCoord[0].xy;
	float depth = getdepth(xy);
	int i;
	int counter = 0;
	vec2 xy2 = vec2(0);

	vec2 bluRangeVec = vec2(2.1*blur_range*0.000001/depth);

	vec4 nor = texture2D(normalmap,xy)-vec4(0.5);
	vec3 normal2;

	float res2=0.0;
	xy2 = xy; // *vec2(depth);
	for(i = -8 ; i < 8 ; i++) {
		if(i != 0 ) {
			xy2.x = fract(dot(xy2*vec2(10.0)+vec2(float(i)*13.33),xy.xy*vec2(595.0)))-0.5;
			xy2.y = fract(dot(xy2*vec2(10.0),xy.yx*5500.0-vec2(float(i)+depth)))-0.5;
			xy2*=bluRangeVec;

			normal2 = texture2D(normalmap,xy+xy2*vec2(i)).xyz-vec3(0.5);
			res2 += doDepth(xy,xy+xy2*vec2(i),getdepth(xy+xy2*vec2(i)),depth,normal2     ,nor.xyz);

			counter++;
		}
	}
	res2 /= float(counter);

	vec4 ao = vec4(0.5+res2/2.0);
	gl_FragColor = ao;

}
