

#include "/lib/uniforms.glsl"
#define WATER_PROG
#define WAVY_STRENGTH 1.0 //[0.1 0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0]
#define WAVY_SPEED 0.0025 //[0.001 0.01 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 1.0 1.25 1.5 2.0 3.0 4.0]

varying mat3 tbnMatrix;
varying vec4 color;
varying float iswater;
varying vec4 lmtexcoord;
varying vec3 torch;
uniform int isEyeInWater;
varying vec3 viewVector;
varying vec3 normal0;
varying vec3 normal1;

attribute vec4 at_tangent;
uniform vec3 cameraPosition;
attribute vec4 mc_Entity;
uniform mat4 gbufferModelViewInverse;

#include "/lib/color_transforms.glsl"
#include "/lib/taa/res_params.glsl"

#include "/lib/sky_gradient.glsl"

//////////////////////////////VOID MAIN//////////////////////////////
//////////////////////////////VOID MAIN//////////////////////////////
//////////////////////////////VOID MAIN//////////////////////////////
//////////////////////////////VOID MAIN//////////////////////////////
//////////////////////////////VOID MAIN//////////////////////////////

const vec3 torchColor = vec3(3.000, 1.382, 0.408);

#define diagonal3(m) vec3((m)[0].x, (m)[1].y, m[2].z)
#define projMAD(m, v) (diagonal3(m) * (v) + (m)[3].xyz)
vec4 toClipSpace3(vec3 viewSpacePosition)
{
    return vec4(projMAD(gl_ProjectionMatrix, viewSpacePosition), -viewSpacePosition.z);
}

uniform float frameTimeCounter;
uniform mat4 gbufferModelView;
uniform sampler2D gaux4;

vec3 waterNormal(vec2 coord, vec3 normFragpos)
{
    coord = mod(coord / 64.0, 1.0);
    float strength = 0.75;

    float deltaPos = 0.0012;

    vec2 offsets[4] = vec2[](vec2(deltaPos, 0.0), vec2(-deltaPos, 0.0), vec2(0.0, deltaPos), vec2(0.0, -deltaPos));

    float heights[4];
    for (int i = 0; i < 4; i++)
    {
        heights[i] = texture(gaux4, coord + offsets[i]).x;
    }

    float dx = (heights[1] - heights[0]) * strength;
    float dy = (heights[3] - heights[2]) * strength;
    vec3 full = normalize(vec3(dx, dy, 0.5)) - vec3(0, 0, 1);

    return full;
}

vec3 computeWaveOffset(vec3 position, vec3 cameraPosition, vec4 vertex, vec4 MultiTexCoord, mat4 gbufferModelView,
                       vec3 posxz, vec3 viewVector)
{

    vec3 test = waterNormal(posxz.xz - posxz.y, normalize(viewVector));
    vec3 offsetWorldPos = vertex.xyz + cameraPosition;
    vec3 waveOffset = test;
    vec3 worldPos = offsetWorldPos + waveOffset - cameraPosition;
    return mat3(gbufferModelView) * worldPos + gbufferModelView[3].xyz;
}

void main()
{
    bool tangentValid = dot(at_tangent.xyz, at_tangent.xyz) > 1e-9; // TODO: Get at_tangent fixed so this isn't needed
    tbnMatrix[0] =
        mat3(gbufferModelViewInverse) * (tangentValid ? normalize(gl_NormalMatrix * at_tangent.xyz) : vec3(0.0));
    tbnMatrix[2] = mat3(gbufferModelViewInverse) * (normalize(gl_NormalMatrix * gl_Normal));
    tbnMatrix[1] = cross(tbnMatrix[0], tbnMatrix[2]) * (at_tangent.w < 0.0 ? -1.0 : 1.0);

    lmtexcoord.xy = (gl_TextureMatrix[0] * gl_MultiTexCoord0).st;
    float mat = 0.0;
    switch (int(mc_Entity.x))
    {
    case 8:
    case 9:
        mat = 1.0;
        gl_Position.z -= 1e-4;
        break;
    case 1:
        mat = 0.7;
        break;
    case 79:
        mat = 0.8;
        break;
    case 20002:
        mat = 0.01;
        break;
    default:
        break;
    }
    viewVector = (gl_ModelViewMatrix * gl_Vertex).xyz;
    color = gl_Color;

    normal0 = gl_NormalMatrix * gl_Normal;
    normal1 = gl_Normal;

    lmtexcoord.zw = (gl_MultiTexCoord1.xy / 255);
    iswater = mat;
    float lmx = gl_MultiTexCoord1.x * recip;
    // torch = vec3(3.000, 1.382, 0.408);
    torch = mix(vec3(1.0), vec3(3.000, 1.382, 0.408), 0.25);
    float lightmapX4 = lmx * lmx * lmx * lmx;
    torch *= lightmapX4 + lmx * 0.025;

    vec3 position = mat3(gl_ModelViewMatrix) * gl_Vertex.xyz + gl_ModelViewMatrix[3].xyz;
#ifdef VERTEX_WAVES
    if (iswater > 0.99)
    {
        vec3 p3 = (mat3(gbufferModelViewInverse) * viewVector) + gbufferModelViewInverse[3].xyz;
        vec3 posxz = p3 + cameraPosition;
        position = computeWaveOffset(position, cameraPosition, gl_Vertex, gl_MultiTexCoord1, gbufferModelView, posxz,
                                     viewVector);
    }

#endif
    gl_Position = taaFunc(toClipSpace3(position), frameCounter, viewResolution);

    // gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
