varying vec3 position;
varying vec3 worldPos;
varying vec3 normal;
varying vec3 tangent;
varying vec3 binormal;
varying vec3 eye;
varying vec3 eyeTan;

uniform sampler2D reflectionMap;
uniform sampler2D refractionMap;

uniform sampler2D normalMap1;
uniform sampler2D normalMap2;

uniform vec2 viewSize;
uniform float scrollTime;

uniform mat4 invViewMatrix;

const vec3 waterColor = vec3(0.8, 0.8, 0.5); //vec3(0.7, 0.9, 0.6);

const float flowSpeed = 0.1;
const float textureScale = 0.25;
const float waveAmplitude = 1.5;

const float uvDistortion = 0.025;

const float dispersion = 0.5;
const vec3 eta = vec3(1.0 + dispersion * 0.9, 1.0 + dispersion * 0.6, 1.0 + dispersion * 0.3);

const float waterFogDepth = 2.0;

const float scatterAmount = 3.5; //amount of sunlight scattering of waves
const vec3 scatterColor = vec3(0.0, 1.0, 0.95); // color of the sunlight scattering

mat3 cotangentFrame(vec3 N, vec3 p, vec2 uv)
{
    vec3 dp1 = dFdx(p);
    vec3 dp2 = dFdy(p);
    vec2 duv1 = dFdx(uv);
    vec2 duv2 = dFdy(uv);
    vec3 dp2perp = cross(dp2, N);
    vec3 dp1perp = cross(N, dp1);
    vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
    vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
    float invmax = inversesqrt(max(dot(T, T), dot(B, B)));
    return mat3(T * invmax, B * invmax, N);
}

void main()
{
    vec2 reflectionCoordinates = gl_FragCoord.xy / viewSize;
    reflectionCoordinates = clamp(reflectionCoordinates, 0.001, 0.999);
    
    vec3 dirToLight = gl_LightSource[0].position.xyz;
    
    vec3 eyeN = normalize(normal);
    vec3 eyeT = normalize(tangent);
    vec3 eyeB = normalize(binormal);
    vec3 L = dirToLight; /*vec3(dot(dirToLight, eyeT),
                  dot(dirToLight, eyeB),
                  dot(dirToLight, eyeN)); */
    vec3 Ee = normalize(eye);
    vec3 E = normalize(eyeTan);
    vec3 H = normalize(L + Ee);
    
    vec2 uv = gl_TexCoord[0].st * textureScale;
    vec2 scrolluv1 = vec2(uv.s, uv.t - scrollTime * flowSpeed);
    vec2 scrolluv2 = vec2(uv.s - scrollTime * flowSpeed, uv.t);
    vec3 norm1 = normalize(texture2D(normalMap1, scrolluv1).rgb * 2.0 - 1.0);
    vec3 norm2 = normalize(texture2D(normalMap2, scrolluv2).rgb * 2.0 - 1.0);
    
    float fade = min(100.0, length(position)) / 100.0;
    vec3 N = mix(vec3(0.0, 0.0, 1.0), (norm1 + norm2) * 0.5, waveAmplitude);  
    N = mix(N, vec3(0.0, 0.0, 1.0), fade);
    
    mat3 TBN = cotangentFrame(eyeN, position, gl_TexCoord[0].st);
    N = normalize(TBN * N);
    
    vec2 noise = N.xy * uvDistortion;
    
    vec2 projCoord = reflectionCoordinates + noise;
    projCoord = clamp(projCoord, 0.0, 1.0);
    
    vec3 sunPos = vec3(gl_ModelViewMatrixInverse * gl_LightSource[0].position);
    vec3 sunext = vec3(0.45, 0.55, 0.68); //sunlight extinction
      
    vec3 reflection = texture2D(reflectionMap, vec2(projCoord.x, 1.0 - projCoord.y)).rgb;

    vec2 noiseR = noise * eta.r;
    vec2 noiseG = noise * eta.g;
    vec2 noiseB = noise * eta.b;

    //vec3 refraction = texture2D(refractionMap, reflectionCoordinates + noise).rgb;
    
    vec3 refraction;
    refraction.r = texture2D(refractionMap, clamp(reflectionCoordinates + noiseR, 0.0, 1.0)).r;
    refraction.g = texture2D(refractionMap, clamp(reflectionCoordinates + noiseG, 0.0, 1.0)).g;
    refraction.b = texture2D(refractionMap, clamp(reflectionCoordinates + noiseB, 0.0, 1.0)).b;
    
    float fresnel = clamp(0.04 + pow(1.0 - max(dot(eyeN, Ee), 0.0), 2.0), 0.0, 0.5);
    
    vec3 luminosity = vec3(0.30, 0.59, 0.11);
    float reflectivity = pow(dot(luminosity, reflection.rgb * 2.0), 3.0);
    
    vec3 specColor = mix(vec3(1.0, 0.5, 0.2), vec3(1.0, 1.0, 1.0), clamp(1.0 - exp(-(sunPos.z / 500.0) * sunext), 0.0, 1.0));
    
    float NH = dot(N, H);
    float specular = float(max(NH, 0.0) > 0.999);
    
    vec3 color = mix(refraction * waterColor, reflection, fresnel);

    gl_FragColor = vec4(color + specColor * specular, 1.0);
}