#version 330 core

// Ocean Water Frag Shader
//
// this version has foam and AOI-related opacity;
// plus depth-related greenish color
// plus wave-peak foam
//
// Opacity that was determined purely from LOS-slant-range
// thru the water looked bad during my flyover cutscene.
//
// I am now leaning toward more simplistic opacity
// algorithm based on AOI.
//
// Also, I was unhappy with formal fresnel formula.  A
// simplified version seems better to me.
//

in float depth; // depth>=0 (input from vert.shader)

in float wlev;

in vec2 waveDirection;
in vec3 position;
in vec3 waveNormal;

in vec4 aPos;



out vec4 color;


uniform int ibkgd; // 0=sunny, 1,2: foggy, 3:eve, 4:night

uniform vec3 eyePos; // virtual (pos wrt island sand)

uniform samplerCube envMap;


////////////// begin fizz insert /////////////////

uniform float mytime;


float fizz( vec2 p, vec2 t ) {

	float time = mytime*2.0;
	float phase = 2.0*t.x + 2.0*t.y; //definite improvement...phase-offset

	float col = 0.0;
	float c=0.0;
	c+=cos(p.x*80.0+time*3.0)*cos(p.y*60.0+cos(time*p.x*0.6+time*2.0)+time*3.0);
	c+=cos(p.y*70.0+time*1.2)*cos(p.x*70.0+cos(time*p.y*0.4+time*1.2)+time*1.5);
	c+=cos(p.y*90.0+time*2.0)*cos(p.y*50.0+cos(time*p.x*0.3+time*1.2)+time*2.5);
	col = cos(c+time+phase);

	col = 0.25*col + 0.75;

	return col;

} // end fizz


const float maxamp=0.04; //  0.03 ~= sum_ampl. of waterwaves

////////////// end fizz insert /////////////////








//////// insert 20dec17 begin /////////////////////////////////////
uniform int fogcolr=1; //  0=>noFog, 1=>white, 2=>brownish, 3=>purple, 4=>gray
uniform int foglevl=0; // 0=>noFog, 1=>Fog, 2=>heavy

const vec4 vFogColor=vec4(0.8,0.8,0.8,1.0); //normal white
const vec4 vDfogColor=vec4(0.3,0.3,0.3,1.0); //gray
const vec4 vSootColor=vec4(50.0/255,30.0/255,10.0/255,1.0); // brown
const vec4 vMystColor=vec4(0.7,0.5,0.7,1.0); // purple
//////// insert 20dec17 end /////////////////////////////////////





const float fStart=0.0;
const float fEnd=16.0; // normal fog
const float sEnd= 8.0; // heavy fog
const float xEnd= 4.0; // extreme fog


float getFogFactor(float rng)
{
	float fResult = 0.0;

	if(foglevl==3) // extreme fog
		fResult = (xEnd-rng)/(xEnd-fStart);

	else if(foglevl==2) // heavy fog
		fResult = (sEnd-rng)/(sEnd-fStart);

	else if(foglevl==1) // normal fog
		fResult = (fEnd-rng)/(fEnd-fStart);

	else // no fog
		fResult=1.0;
	
	fResult = 1.0-clamp(fResult, 0.0, 1.0);
	
	return sqrt(fResult);
}












void main(){

	vec2 uv = vec2( position.x, position.z );
	float radius = length(uv); // r1=5, lagoonRad=3
	vec2 UV = fract( uv ); // now, both in [0..1)


	// set variable threshold for deep water foam:
	float dfoam = wlev + 2.0*maxamp; // deep water foam above this Ypos
	//float bfoam = wlev + maxamp/10.0; // breaker foam
	float bfoam = wlev;

	//vec3 wavdir = vec3( waveDirection.x, 0, waveDirection.y );
	vec3 wavdir = vec3( -position.x, 0, -position.z );
	float dprod = dot( waveNormal, normalize(wavdir) ); 
	// negative dprod => back of wave

   vec3 eyeraw = (position-eyePos);
   vec3 eye = normalize(eyeraw);
   vec3 r = reflect(eye, waveNormal);
  	vec4 precolor = texture(envMap, r);


///////// opacity below here /////////////////////////////////////////
// Note:  only for ocean (radius in [7..20]):
//
// @r=20 (max radius) Ysand=-1.43, depth=1.04
// @r=10              Ysand=-0.63, depth=0.24
// @r= 7              Ysand=-0.39, depth=0.00, MSL=-0.39
//

	// new Opacity strategy base upon AngleOfIncidence [AOI]
	const float halfpi = 2.0*atan(1.0,1.0);
	const float aoimax=halfpi;
	const float opmax=0.0; // minOpacity (@maxAOI)

	const float aoimin=aoimax*0.05; // 4.5 deg
	const float opmin = 0.99;  // maxOpacity (@minAOI)

	// AOI versus water normal vector
	float Naoi = halfpi - acos( dot(waveNormal, -eye) );
	float tto = (Naoi-aoimin)/(aoimax-aoimin);
	float opac = opmin + tto*(opmax-opmin);

	// finally, ensure transparent shallows
	//if( depth<0.02 ) opac *= 50.0*depth; //awesome...MUCH better
	if( depth<0.05 ) opac *= 20.0*depth; //13jan19 adj

	if ( (ibkgd==0) || (ibkgd==3) || (ibkgd==4) )
	{
		// increase opacity in lagoon to enhance apparent depth:
		float tt = max(0, (radius-4.8)/(6.8-4.8));
		if( radius<6.8 ) opac = (1-tt)*0.95 + tt*opac;
	}

	opac = clamp(opac, 0.0, 1.0);

///////// opacity above here /////////////////////////////////////////


////////// hue adjustment below ////////////////////////////////////////

	// fine hue adjustment to add green near shallows...

	// weight=1.0; => all blue  ...  weight=0.0; => all green
	float weight = 0.5 + radius/20; // all blue beyond rad=10
	if( weight<0.85 ) weight=0.85;
	if ( weight > 1.0 ) weight = 1.0;
	vec4 green=vec4(0.4, 0.9, 0.4, 1.0);
	vec4 watercolor = mix( green, precolor, weight ); // wt = amt of precolor

	color = watercolor;
	color.rgb *= 0.8; // subdue the somewhat oversaturated colors

	// finally, set opacity curve: //////////////////////////
  	color.a = opac;



// define foam below here ///////////////////////////////////////////////////

	if( depth <= 0.0002 ) // remember, depth might be negative
	{  
		// coarser shoreline foam
		float fuv = fizz(UV*2.0, uv); // 1.0 makes bigger bubbles
		float alpha=0.9;
		vec4 fcolor = vec4( vec3( fuv ), alpha );
		if( fuv>0.9 ) color = fcolor;
	}

	
	else

	if( 
		(radius>6) &&			// outside lagoon AND
		(
			//(position.y>2.0*dfoam)  // deep water foam
			//	||  					// or
			//((dprod>0.02) && (position.y>bfoam)) // breakers (dprod:.17/.02)
			dprod>0.11 // 13jan19 adjustment
		)
	)
	{  
		// finer wave foam
		float fuv = fizz(UV*4.0, uv); // 4.0 makes finer bubbles
		float alpha=0.9;
		vec4 fcolor = vec4( vec3(fuv), alpha ); // foam color
		if( fuv > 0.9 ) color = fcolor;
	}

// define foam above here ///////////////////////////////////////////////////



//////////////// begin insert /////////////////////////////////////////////
	if( foglevl>0 ) {
		const float yc=0.0;
		float dist = exp(-0.9*abs(aPos.y-yc)) * length( eyeraw );

		if( fogcolr==4 )
			color = mix(color,  vDfogColor, getFogFactor(dist)); //gray
		else if( fogcolr==3 )
			color = mix(color, vMystColor, getFogFactor(dist)); //purple
		else if( fogcolr==2 )
			color = mix(color, vSootColor, getFogFactor(dist)); //brown
		else if( fogcolr==1 )
			color = mix(color,  vFogColor, getFogFactor(dist)); //white

	}
//////////////// end insert /////////////////////////////////////////////



}


//--
//-- Copyright (C) 2019  <fastrgv@gmail.com>
//--
//-- This program is free software: you can redistribute it and/or modify
//-- it under the terms of the GNU General Public License as published by
//-- the Free Software Foundation, either version 3 of the License, or
//-- (at your option) any later version.
//--
//-- This program is distributed in the hope that it will be useful,
//-- but WITHOUT ANY WARRANTY; without even the implied warranty of
//-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//-- GNU General Public License for more details.
//--
//-- You may read the full text of the GNU General Public License
//-- at <http://www.gnu.org/licenses/>.
//--

