uniform sampler2D 	wavesNormal,
					wavesPos;
varying vec2 		texcoord;
uniform vec3		sundir;
uniform vec3  		SUN; 	// = colore del sole
uniform sampler2D 	bg,
					depthBG,
					reflBG;
uniform mat4		eyeToWorld;

uniform vec3		horizonColor;
uniform vec3		zenithColor;
uniform vec3 		fogColor; 
uniform vec3		ambientColor;
uniform vec3		waterColor;

uniform float 		inScatter;
uniform float       extintion;
uniform vec3		campos;

uniform float		fogMultiplier;
uniform float		reflMul;
uniform float		reflLevel;
uniform float		specPow;
uniform float		specMul;
uniform float		fresnelPow;

uniform float		density;
uniform float		refrbump;
uniform float		reflbump;

varying vec2		VPOS;

// costanti passate allo shader
uniform vec3  cBr; 	// = RayLeigh
uniform vec3  cBm; 	// = Mie	
uniform	vec3  C0; 	// = cBr+cBm;	
uniform vec3  C1; 	// = 1.0/(cBr+cBm);
uniform float C2;	// = log(e)
uniform float C4;	// = (1-g)^2
uniform float C5;	// = 1+g^2
uniform float C6;	// = 2*g
uniform float C7;	// = 3/2

uniform float wFar;

uniform float cHeightFallof;//=0.0005;
float cVolFogHeightDensityAtViewer=exp( cHeightFallof * -campos.y);
float Pi=3.14159265359;

float ComputeVolumetricFog( vec3 cameraToWorldPos )
{
	float fogInt = length( cameraToWorldPos )* cVolFogHeightDensityAtViewer;
	
	if( abs( cameraToWorldPos.y) > 0.01)
	{
		float t = cHeightFallof * cameraToWorldPos.y;
		fogInt*= ( 1.0-exp( -t ) ) / t;
		
	}
	return fogInt; //exp( -extintion/*0.001*/ * fogInt);
}

float ComputeScatter( vec3 cameraToWorldPos, float L, float ext )
{
	vec3 dir=normalize(cameraToWorldPos);
	return ( ( exp((dir.y-1.0)*ext*L) - 1.0 ) / ((dir.y-1.0) * ext))*0.01;
}

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*g;
    n.z = 1.0-f/2.0;
	n.w=enc.w;
    return n;
}

////////////////////////////
void main()
{
	vec4 encWavNormal=texture2D(wavesNormal,texcoord.st);
	vec4 wavNormal=decode(encWavNormal);//decode(texture2D(wavesNormal,texcoord.st));
	float wavDepth=texture2D(wavesPos,texcoord.st).r;
	vec4 wavPos;
	wavPos.z=wavDepth;
	//float spumeDensity=wavPos.a;
	//wavPos.z*=wFar;
	
	// compute position in eye space
	vec2 UV=texcoord.xy;
	wavPos.xy=VPOS*-wavPos.z;
	wavPos.w=1.0;
	//float distance=length(wavPos.xyz);
	
	// compute normals
	vec3 normal=wavNormal.xyz;
	vec3 UVnormal;
	UVnormal.z=normal.y;
	UVnormal.x=-normal.z;
	UVnormal.y=-normal.x;
	UVnormal=normalize(UVnormal);
	
	// transform pos into world space
	vec4 Wpos=eyeToWorld*wavPos;
	
	// copmpute attenuation
	vec3 Cam2WorldPos=Wpos.xyz-campos.xyz;
	float delta=/*1.0-*/ComputeVolumetricFog(Cam2WorldPos);
	//delta *= distance;
	
	vec3 tvdir=normalize(-Cam2WorldPos.xyz);
	float cos=dot(sundir,tvdir.xyz);
	float F1=(1.0 + cos*cos*0.5);
	float F2=(C4/pow(C5-C6*cos*0.5,C7));
	vec3 Br = cBr*F1;
	vec3 Bm = cBm*F2;

	// PROVA DIFFUSO ////////////
	float NdotL=clamp(dot(sundir,normal),0.0,1.0);
	
	vec3 H = sundir+tvdir;
	H=normalize(H);
	//float spec = clamp(dot(halfv,normal),0.0,1.0);
	//spec = pow(spec,specPow)*specMul;
	
	float NdotH = (dot(H,normal));
	float EdotH = dot(tvdir,H);
	float NdotE = dot(normal,tvdir);
	float F=specMul+(1.0-specMul)*pow((1.0-EdotH),5.0);
	float spec=max((0.0397436*specPow+0.0856832)*(F*pow(NdotH,specPow)/max(NdotL,NdotE)),0.0)*0.25;
	
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	vec2 reflectOffset=UV+UVnormal.xy*reflbump;
	UV+=UVnormal.xy*refrbump*(1.0-clamp(-wavPos.z*0.00025,0.0,1.0));
	float depth=texture2D(depthBG,UV).z;
	float d=abs(depth-wavPos.z);
	float att=(clamp(exp(-d*density),0.0,1.0));
		
	// WATER COLOR //////////////////////////////////
	float wScatter=ComputeScatter(Cam2WorldPos,d,density);
	/////////////////////////////////////////////////
	
	float fresnelres=(specMul+(1.0-specMul)*pow((1.0-NdotE),fresnelPow))*reflLevel;/*min(pow(1.0-dot(normal,tvdir),fresnelPow)*reflLevel,1.0);*/
	vec3 reflcolor=texture2D(reflBG,reflectOffset).xyz;
	
	////////////////////////////////
	///////////////////////////// FOG ////////////////////////////////
	/*vec3 LinMul;
	LinMul=C1*(1.0-exp(-C0*min(distance,10000.0)));
	vec3 fogLin = (Br+Bm*0.1)*LinMul;
	vec3 scatterFogColor=fogLin*inScatter + fogColor*fogMultiplier;*/
	vec3 Fex=exp(-C0*extintion*delta);
	vec3 Lin=(Br+Bm)*C1*(1.0-Fex)*inScatter*fogColor;
	//////////////////////////////////
	
	float foamDensity=0.0;
	vec3 foamColor=vec3(0.25,0.25,0.25);
	vec3 waterFinalColor=waterColor;
	waterFinalColor= texture2D(bg,UV*0.25).rgb*att + waterFinalColor*wScatter;
	
	float depth2=texture2D(depthBG,texcoord.xy).z;
	float d2=exp(-abs(depth2-wavPos.z)*0.005);
	float fdist=1.0-(clamp(d2,0.0,1.0));
	if(-wavPos.z<50000.0)
	{
		foamDensity=/*spumeDensity**/encWavNormal.a*clamp(pow(d2,5.0),0.0,1.0)*clamp(fdist*10.0,0.0,1.0);
		foamDensity=clamp(foamDensity,0.0,1.0);
		foamColor=ambientColor*foamColor+NdotL*SUN;
		foamColor=foamColor*Fex + Lin;

		// spume
		//float spumeDensity=clamp(mix(0.0,encWavNormal.z,fdist),0.0,1.0);
		waterFinalColor=mix(waterFinalColor,foamColor,encWavNormal.z);
	}
	
	waterFinalColor=mix(waterFinalColor,reflcolor*reflMul,clamp(fresnelres,0.0,1.0)) + spec*SUN;
	waterFinalColor=mix(waterFinalColor, foamColor, foamDensity);
	waterFinalColor=waterFinalColor*Fex+Lin;//mix(scatterFogColor, waterFinalColor, fogdist);
	gl_FragColor.xyz=max(waterFinalColor,0.0);
	gl_FragColor.w=clamp(fdist*10.0,0.0,1.0);
}
