/*
water wavering from Shadertoy "Seascape" by TDM ( https://www.shadertoy.com/view/Ms2SD1 )
License of this module: CC BY-NC-SA 3.0 ( https://creativecommons.org/licenses/by-nc-sa/3.0/ )
*/

#define ITER_FRAGMENT 5 // [1 2 3 4 5 6 7 8]
//#define SEA_HEIGHT 0.5  // [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.5]
#define SEA_HEIGHT 1.0  // [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.5]
#define SEA_CHOPPY 4.0  // [0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5]
#define SEA_FREQ 0.03   // [0.02 0.03 0.04 0.05 0.1] 
#define SEA_SPEED 1.6   // [0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0]
#define EPSILON_NRM (2.0 / viewSize.x)

float hash(vec2 p) {
    return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453123);
}

float noise(in vec2 p) {
    vec2 i = floor( p );
    vec2 f = fract( p );	
	f = f*f*(3.0-2.0*f);
    return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), 
                     hash( i + vec2(1.0,0.0) ), f.x),
                mix( hash( i + vec2(0.0,1.0) ), 
                     hash( i + vec2(1.0,1.0) ), f.x), f.y);
}

float sea_octave(vec2 uv, float choppy) {
    uv += noise(uv);        
    vec2 wv = 1.0-abs(sin(uv));
    vec2 swv = abs(cos(uv));    
    wv = mix(wv,swv,wv);
    return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
}

float mapWater(vec3 p, int steps) {
    float freq = SEA_FREQ;
    float amp = SEA_HEIGHT;
    float choppy = SEA_CHOPPY;
    vec2 uv = p.xz; uv.x *= 0.75;
    
    float d, h = 0.0;
    const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
    float seaTime = (1.0 + frameTimeCounter * SEA_SPEED);
    for(int i = 0; i < steps; i++)
    {        
    	d = sea_octave((uv+seaTime)*freq,choppy);
    	d += sea_octave((uv-seaTime)*freq,choppy);
        h += d * amp;        
    	uv *= octave_m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    
    return p.y - h;
}

vec3 getNormalWater(vec3 p, float eps) {   
    vec3 n;
    eps *= 60.0;
    n.y = mapWater(p, ITER_FRAGMENT);    
    n.x = mapWater(vec3(p.x+eps,p.y,p.z), ITER_FRAGMENT) - n.y;
    n.z = mapWater(vec3(p.x,p.y,p.z+eps), ITER_FRAGMENT) - n.y;
    n.y = eps;  
    return normalize(n);
}
