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

#ifdef PBR
varying vec3 lowresalbedo;
varying float shiny;
varying float smoothval;
uniform sampler2D texture;
#endif

varying vec4 lmtexcoord;
varying vec4 color;
flat varying float translucent;
flat varying float emissive;

attribute vec4 mc_Entity;
uniform vec3 cameraPosition;
uniform float frameTimeCounter;
uniform mat4 gbufferModelView;
uniform mat4 gbufferModelViewInverse;
attribute vec4 mc_midTexCoord;

#if defined NORMAL_MAPS
varying mat3 tbnMatrix;
attribute vec4 at_tangent;
#if defined POM
// POM
varying vec4 vtexcoordam; // .st for add, .pq for mul
varying vec4 vtexcoord;
varying vec4 tangent;
varying vec4 normalMat2;
#endif
#else
varying vec3 normalMat;

#endif

#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);
}

vec3 viewToWorld(vec3 viewPos)
{
    return (gbufferModelViewInverse * vec4(viewPos, 0.0)).xyz;
}

#include "/lib/vertex/main.glsl"

void main()
{
    // Define Transforms

    lmtexcoord.xyzw = vec4(gl_MultiTexCoord0.xy, gl_MultiTexCoord1.xy * recip);
    color = gl_Color;

    translucent = 0.0;
    emissive = 0.0;
    int entityCheck = int(mc_Entity.x);

    // Emissive Check
    emissive = (entityCheck == 1 || lmtexcoord.z > 0.942) ? 1.0 : 0.0;

#if defined NORMAL_MAPS
    tbnMatrix = computeTBNMatrix(gbufferModelViewInverse, gl_NormalMatrix, at_tangent, gl_Normal);

#if defined POM
    normalMat2 = vec4(normalize(gl_NormalMatrix * gl_Normal), 0);
    bool tangentValid = dot(at_tangent.xyz, at_tangent.xyz) > 1e-9;

    vec3 T = tangentValid ? normalize(mat3(gl_NormalMatrix) * at_tangent.xyz) : vec3(0.0);

    tangent = vec4(normalize(T), at_tangent.w);

    // POM
    vec2 midcoord = (gl_TextureMatrix[0] * mc_midTexCoord).st;
    vec2 texcoordminusmid = lmtexcoord.xy - midcoord;
    vtexcoordam.pq = abs(texcoordminusmid) * 2;
    vtexcoordam.st = min(lmtexcoord.xy, midcoord - texcoordminusmid);
    vtexcoord.xy = sign(texcoordminusmid) * 0.5 + 0.5;
#endif
#else
#ifdef COMPLEX_NORMALS
    normalMat = viewToWorld(normalize(gl_NormalMatrix * gl_Normal));
#else
    normalMat = gl_Normal;
#endif
#endif

#ifdef PBR
    lowresalbedo = texture(texture, lmtexcoord.xy).rgb;
#ifndef LEAVES
    vec3 entityData = computeShinyAndSmoothval(entityCheck);
    smoothval = entityData.x;
    shiny = entityData.y;
#else


#endif
#endif
    vec3 position = (mat3(gl_ModelViewMatrix) * gl_Vertex.xyz) + gl_ModelViewMatrix[3].xyz;

#ifdef LEAVES
    translucent = computeTranslucent(entityCheck);

    bool Flower = isFlower(entityCheck, (gl_MultiTexCoord0.t < mc_midTexCoord.t));
    bool Leaves = isLeaves(entityCheck, (abs(position.z) < 64.0 && gl_MultiTexCoord1.y > 100.0));
    vec4 temp = gl_Vertex;
    vec4 temp2 = gl_MultiTexCoord1;
    if (Flower || Leaves)
    {
        position = computeWaveOffset(position, cameraPosition, temp, temp2, gbufferModelView);
    }
#endif

#if defined ENTITY && defined NO_ENTITY_TAA
    gl_Position = toClipSpace3(position);

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