#version 300 es
precision mediump float;



flat in vec2 v_texMin;
flat in vec2 v_texMax;
flat in vec2 v_texSize;
flat in mat4 v_transform_inv;
flat in vec3 v_upDir;
flat in int v_climbDirection;
flat in float v_depth;

flat in int v_flags;

flat in vec2 v_texYRepeat;
flat in float v_destAmount;
flat in float v_brightness;
flat in float v_cutOff;
flat in vec4 v_mulColor;
flat in float v_hueShift;
flat in float v_sharpness;
flat in int v_stencilID;
flat in float v_mulLight;


in vec4 v_test;

in vec3 v_barycentric;
//ref, mask, func
flat in uvec3 v_stencilData;

#import "lib/stencil";
#import "lib/dithering";
#import "lib/sample-tex";
#import "lib/hsl";
#import "lib/flags";
#import "lib/compress";
#import "lib/gamma";
#import "lib/sun";
#import "lib/depth";
#import "lib/depth-fragment";
#import "lib/pi";
#import "lib/normal";


uniform bool u_useWireframes;


uniform sampler2D u_normalMesh;

uniform float u_sharpness; //{type: "SLIDER", min: 0, max: 1, default: 0.85, info: "How much much pixel sampling is sharpened"}
uniform float u_projectionTolerance; //{type: "SLIDER", min: 0, max: 1, default: 0.1}

uniform sampler2D u_sampler;
uniform vec2 u_samplerPixel;
uniform vec2 u_samplerSize;

uniform sampler2D u_data;
uniform vec2 u_dataPixel;
uniform vec2 u_dataRatio;

uniform sampler2D u_depth;
uniform vec2 u_depthRatio;
uniform vec2 u_depthPixel;
uniform vec2 u_depthSize;

uniform sampler2D u_light;
uniform vec2 u_lightPixel;
uniform vec2 u_lightRatio;

uniform mediump usampler2D u_normal;
uniform vec2 u_normalPixel;
uniform vec2 u_normalRatio;

uniform mat4 u_cameraProjInvM;

layout(location = 0) out vec4 outColor;

void main() {

    vec2 uv = gl_FragCoord.xy * u_depthPixel * u_depthRatio;//v_screenCoord * 0.5 + 0.5;
    vec2 normalUV = gl_FragCoord.xy * u_normalPixel * u_normalRatio;

    vec2 screenUV = gl_FragCoord.xy * u_dataPixel * u_dataRatio;
    vec4 data = texture(u_data, screenUV);

    int stencil = int(data.b * 255.0);
    bool stencilFunc = getFlag(v_flags, FLAG_STENCIL_FUNC);
    if(v_stencilID > 0) {
        if((v_stencilID == stencil) != stencilFunc) discard;
    }
    int flags = int(data.g * 255.0);
    bool ignoreDepth = getFlag(v_flags, IGNORE_DEPTH_TEST);
    if(!ignoreDepth && getFlag(flags, FLAG_DARKEST_COLOR)) discard;
    bool hasActorFlag = getFlag(v_flags, FLAG_ACTOR);
    if(!hasActorFlag && getFlag(flags, FLAG_ACTOR)) discard;

    int subStencil = flags >> 5;
    int checkSubStencil = v_flags >> 5;
    if(checkSubStencil > 0){
        if((checkSubStencil == subStencil) != stencilFunc) discard;
    }

    vec3 pos = sampleDepthToWorld(u_depth, u_depthRatio, gl_FragCoord.xy * u_depthPixel, u_cameraProjInvM);

    //albedo.rg = abs(uv - (v_screenCoord * 0.5 + 0.5)) * 100.0;
    //albedo.rgb = pos * 0.04;

    vec4 objPos = v_transform_inv * vec4(pos, 1.0);

    vec3 snapFactor = vec3(24.0, 16.0, 16.0) * vec3(v_texSize, v_depth);

    vec3 objPosSnap = trunc(objPos.xyz * snapFactor) / snapFactor;

    vec3 check = abs(objPosSnap.xyz + vec3(0.0, 0.0, 0.5)) - 0.5;

    if(any(greaterThan(check, vec3(0.0)))) discard;

    vec2 depthUV = gl_FragCoord.xy * u_depthPixel * u_depthRatio;

    uint packedNormal = texture(u_normal, uv).r;
    vec3 normal = unpackNormal(packedNormal);

    //vec3 normal = getNormalFromDepth(u_depth, u_depthSize, depthUV, u_cameraProjInvM);


    if(v_climbDirection == 0 && abs(dot(normal, v_upDir)) < u_projectionTolerance) discard;

    vec3 projectionCoord = objPos.xyz + vec3(0.5, 0.5, 1.0);
    projectionCoord.z = 1.0 - projectionCoord.z;


    vec2 zCoord = projectionCoord.xy;
    vec2 yCoord = projectionCoord.xz;
    vec2 xCoord = projectionCoord.yz;


    vec3 normalFactor = round(abs(normal));

    vec2 texCoord = mix(mix(xCoord, yCoord, normalFactor.y), zCoord, normalFactor.z);
    texCoord = zCoord;
    //project down walls

    if(v_climbDirection == 1)
    texCoord.y += projectionCoord.z;
    else if(v_climbDirection == 2)
    texCoord.x += projectionCoord.z;
    else if(v_climbDirection == 3)
    texCoord.y -= projectionCoord.z;
    else if(v_climbDirection == 4)
    texCoord.x -= projectionCoord.z;


    if(any(greaterThan(abs(texCoord - 0.5), vec2(0.5, 0.5)))) discard;

    //float visible = 1.0;
    //if(any(greaterThan(abs(texCoord - 0.5), vec2(0.5, 0.5)))) visible == 0.0;

    //albedo = vec4(texCoord, 0.2, 1.0);
    //texCoord.x = mix(v_texMin.x + 0.5, v_texMax.x - 0.5, texCoord.x);
    //texCoord.y = mix(v_texMin.y + 0.5, v_texMax.y - 0.5, texCoord.y);

    vec2 newTexCoord = (v_texMin * u_samplerSize - 0.5 + texCoord * v_texSize) * u_samplerPixel;

    SampleTexResult result = sampleTexSimple(newTexCoord, v_texMin, v_texMax,
    u_sampler, u_samplerPixel, u_samplerSize,
    v_sharpness, vec2(0.0), true);

    vec4 color = result.albedo;
    float hueShiftVal = v_hueShift;

    if(v_cutOff > 0.0){
        float revAlpha = 1.0 - v_mulColor.a;
        if(color.a <= revAlpha)
        discard;

        float v_cutInverse = 1.0 - v_cutOff;
        float hueFactor = max(0.0, min(1.0, (color.a - revAlpha) / (1.0 - v_cutOff*0.5)));
        hueShiftVal *= 1.0 - hueFactor;
        float newAlpha = min(1.0, (color.a - revAlpha) / v_cutInverse);
        color.a = newAlpha;
    }
    else{
        float luminince = linearLuminance(color.xyz);
        color.a *= v_mulColor.a;
        hueShiftVal *= 1.0 - luminince;
    }

    //if (color.a == 0.0)
      //  discard;
    color.rgb *= v_mulColor.rgb;
    color.rgb = hueShift3( color.rgb, hueShiftVal);
    color.rgb = sRGBToLinear(color.rgb);


    vec4 light = texture(u_light, screenUV);
    float lightFactor = 1.0 - (1.0 - min(light.a,1.0)) * v_mulLight;
    color.rgb *= finalLightColor(light.rgb, lightFactor);

    color.rgb *= mix(1.0, v_brightness, color.a * color.a);

    color = vec4(color.rgb, 1.0 - v_destAmount) * color.a;

    outColor = color;
    //color = texture(u_sampler, texCoord);
    //outColor = vec4(color.rgb, 1.0);

}
