uniform sampler2D 	colorTex,
					normalTex,
					matTex,
					posTex;
uniform sampler2D	brdfLUT;			
uniform sampler2D 	normalsSampler2D;

uniform samplerCube	envCube;
varying vec2 		texcoord;
uniform vec4		ambientColor;		
varying vec2		VPOS;
uniform mat4		eyeToWorld;
uniform vec3		campos;
uniform	float		reflMul;
uniform	float		saturation;

uniform vec3 		lightpos;
uniform float		lightrange;
uniform float 		invLightrange;
uniform float		mapSize;

uniform vec3 		boxMax;
uniform vec3 		boxMin;
uniform float		cubeLod;

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 RGBMDecode( vec4 rgbm ) {
  return vec4(6.0 * rgbm.rgb * rgbm.a,1.0);
}

vec3 cubeLookup(vec3 v, float lod) {
   float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
   float scale = 1- exp2(lod) / mapSize;
   if (abs(v.x) != M) v.x *= scale;
   if (abs(v.y) != M) v.y *= scale;
   if (abs(v.z) != M) v.z *= scale;
   return v;
}

vec3 cubeTapOfs(vec3 v, vec2 ofs)
{
	float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
	if (abs(v.x) == M)
		return normalize(v+vec3(0.0,ofs.x,ofs.y));
	if (abs(v.y) == M)
		return normalize(v+vec3(ofs.x,0.0,ofs.y));
	if (abs(v.z) == M)
		return normalize(v+vec3(ofs.x,ofs.y,0.0));
	return vec3(0.0);
}

void main()
{
	vec4 finalcolor=vec4(0.0,0.0,0.0,0.0);
	
	if(reflMul>0.0)
	{
		vec4 encoded=texture2D(normalTex,texcoord.st);
		float reflPow=encoded.z;//*16.0;
		vec3 specular=vec3(0.0,0.0,0.0);
			
		vec4 mat = texture2D(matTex,texcoord.st);
				
		/*if(reflPow>0.5 || mat.x>0.0)
		{*/
			vec4 pos;
			pos.z = texture2D(posTex,texcoord.st).r;
			pos.xy=VPOS.xy*-pos.z;
			pos.w=1.0;
			
			if(-pos.z<lightrange)
			{
				vec4 normal = decode(encoded);
				vec4 metalColor=texture2D(colorTex,texcoord.st);
				float metal=mat.x*step(metalColor.a,0.0);	// if(scatter=metalColor.a > 0) metal = 0
		
				//mat.y=sqrt(mat.y);
				float lrangeMin=lightrange-1000.0;
				float att=1.0-( clamp( (-pos.z-lrangeMin)/(lightrange-lrangeMin),0.0,1.0) );
				if(att>0.0)
				{
					// IBL specular
					float rough=sqrt(mat.y);

					pos=eyeToWorld*pos;
					vec4 N=eyeToWorld*vec4(normal.xyz,0.0);
					vec3 vdir=normalize(campos-pos.xyz);
					
					vec3 reflection = reflect(vdir.xyz,N.xyz);
					reflection= ((lightpos-pos.xyz)*invLightrange) + reflection;

					float NdotV=max(dot(vdir,N.xyz),0.0);
					vec3 REFL=mix(vec3(0.04)*reflPow*reflPow/*max((reflPow-0.5),0.0)*2.0*/,metalColor.xyz/*reflPow*/,metal);
					float rmax = max(max(REFL.r, REFL.g), REFL.b);
					float REFL90 = clamp(rmax*25.0,0.0,1.0);	
					float glossLod=rough*cubeLod;
					vec4 IBLspecular = RGBMDecode(textureCubeLod(envCube,reflection.xyz,glossLod));
					
					vec2 brdf = texture2D(brdfLUT, vec2(NdotV, rough)).xy;
					vec3 IBL=REFL*brdf.x+brdf.y*REFL90;
					//IBL=mix(IBL,IBL,metal);
					
					vec3 specular=IBL*IBLspecular.xyz;
		
					finalcolor.rgb = specular.rgb*att*reflMul;//*ambientColor.rgb;
					
					// DESATURATE
					//=0.5;
					float lum=dot(finalcolor.rgb,vec3(0.3,0.59,0.11));
					finalcolor.rgb=mix(vec3(lum),finalcolor.rgb,saturation);
				}
			}
		//}
	}
	
	gl_FragColor=max(finalcolor,0.0);
}
