#ifdef FRAGMENT_SHADER
    #define DAY_R 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define DAY_G 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define DAY_B 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define DAY_I 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]

    #define NIGHT_R 0.9f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define NIGHT_G 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define NIGHT_B 1.1f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define NIGHT_I 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]

    #define SUNSET_R 1.1f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define SUNSET_G 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define SUNSET_B 0.8f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define SUNSET_I 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]

    #define SE_R 0.7f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define SE_G 0.4f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define SE_B 0.8f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]
    #define SE_I 1.0f // [0.5f 0.6f 0.7f 0.8f 0.9f 1.0f 1.1f 1.2f 1.3f 1.4f 1.5f]

    varying vec2 TexCoords;
    varying vec3 Normal;
    varying vec4 Color;

    varying vec2 LightmapCoords;

    uniform sampler2D texture;
    uniform sampler2D depthtex0;

    uniform vec3 cameraPosition;

    uniform bool isBiomeEnd;

    vec3 dayColor = vec3(DAY_R,DAY_G,DAY_B);
    vec3 nightColor = vec3(NIGHT_R,NIGHT_G,NIGHT_B);
    vec3 transitionColor = vec3(SUNSET_R,SUNSET_G,SUNSET_B);

    uniform int worldTime;

    vec3 currentColor;

    vec3 Diffuse;

    vec3 baseColor;
    vec3 baseDiffuse;

    vec3 baseDiffuseModifier;

    vec3 baseFog;

    vec3 fogAlbedo;

    float baseFogDistMin;
    float baseFogDistMax;
    float fogMin;
    float fogMax;

    uniform float near;
    uniform float far;

    uniform int viewWidth;
    uniform int viewHeight;

    uniform int currentRenderedItemId;
    uniform int entityId;

    #include "/lib/data/settings.glsl"

    #include "/lib/includes2.glsl"
    #include "/lib/optimizationFunctions.glsl"

    #include "/lib/colorFunctions.glsl"

    mediump float AdjustLightmapTorch(in float torch) {
        const mediump float K = 2.0f;
        const mediump float P = 5.06f;
        return K * pow2(torch, P);
    }

    mediump float AdjustLightmapSky(in float sky){
        mediump float sky_2 = sky * sky;
        return sky_2 * sky_2;
    }

    vec2 AdjustLightmap(in vec2 Lightmap){
        vec2 NewLightMap;
        NewLightMap.x = AdjustLightmapTorch(Lightmap.x);
        NewLightMap.y = AdjustLightmapSky(Lightmap.y);
        return NewLightMap;
    }

    vec4 vanillaLight(in vec2 Lightmap) {
        const vec3 TorchColor = vec3(1.0f, 1.0f, 1.0f);
        vec4 lightColor = vec4(TorchColor * Lightmap.x,1.0);
        return lightColor;
    }

    /* RENDERTARGETS:0,1,2,15,5,13,6,12 */

    void noonFunc(float time, float timeFactor) {
        if(isBiomeEnd) {
            fogMin = FOG_SE_DIST_MIN;
            fogMax = FOG_SE_DIST_MAX;
        } else {
            mediump float dayNightLerp = clamp((time+250f)/timeFactor,0,1);
            fogMin = FOG_DAY_DIST_MIN; //mix2(baseFogDistMin, FOG_DAY_DIST_MIN, dayNightLerp);
            fogMax = FOG_DAY_DIST_MAX; //mix2(baseFogDistMax, FOG_DAY_DIST_MAX, dayNightLerp);
            baseDiffuseModifier = vec3(DAY_I);
            currentColor = dayColor; //mix2(baseColor,dayColor,dayNightLerp);
            Diffuse = pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier; //mix2(baseDiffuse, pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier, mod(worldTime/6000f,2f));
            fogAlbedo = vec3(FOG_DAY_R, FOG_DAY_G, FOG_DAY_B); //mix2(baseFog, vec3(FOG_DAY_R, FOG_DAY_G, FOG_DAY_B), dayNightLerp);
        }
    }

    void sunsetFunc(float time, float timeFactor) {
        if(isBiomeEnd) {
            fogMin = FOG_SE_DIST_MIN;
            fogMax = FOG_SE_DIST_MAX;
        } else {
            mediump float sunsetLerp = clamp((time)/timeFactor,0,1);
            fogMin = mix3(FOG_DAY_DIST_MIN,FOG_SUNSET_DIST_MIN,FOG_NIGHT_DIST_MIN, sunsetLerp, 0.5); //mix2(baseFogDistMin, FOG_DAY_DIST_MIN, dayNightLerp);
            fogMax = mix3(FOG_DAY_DIST_MAX,FOG_SUNSET_DIST_MAX,FOG_NIGHT_DIST_MAX, sunsetLerp, 0.5); //mix2(baseFogDistMax, FOG_DAY_DIST_MAX, dayNightLerp);
            baseDiffuseModifier = mix3(vec3(DAY_I), vec3(SUNSET_I), vec3(NIGHT_I), sunsetLerp, 0.5);
            currentColor = mix3(dayColor, transitionColor, nightColor, sunsetLerp, 0.5); //mix2(dayColor, transitionColor, sunsetLerp);
            Diffuse = pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier; //mix2(baseDiffuse, pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier, mod(worldTime/6000f,2f));
            fogAlbedo = mix3(vec3(FOG_DAY_R, FOG_DAY_G, FOG_DAY_B), vec3(FOG_SUNSET_R, FOG_SUNSET_G, FOG_SUNSET_B), vec3(FOG_NIGHT_R, FOG_NIGHT_G, FOG_NIGHT_B), sunsetLerp, 0.5); //mix2(baseFog, vec3(FOG_SUNSET_R, FOG_SUNSET_G, FOG_SUNSET_B), sunsetLerp);
        }
    }

    void nightFunc(float time, float timeFactor) {
        if(isBiomeEnd) {
            fogMin = FOG_SE_DIST_MIN;
            fogMax = FOG_SE_DIST_MAX;
        } else {
            mediump float dayNightLerp = clamp((time+250f)/timeFactor,0,1);
            fogMin = FOG_NIGHT_DIST_MIN; //mix2(baseFogDistMin, FOG_NIGHT_DIST_MIN, dayNightLerp);
            fogMax = FOG_NIGHT_DIST_MAX; //mix2(baseFogDistMax, FOG_NIGHT_DIST_MAX, dayNightLerp);
            baseDiffuseModifier = vec3(NIGHT_I * 0.4f);
            currentColor = nightColor; //mix2(baseColor, nightColor, dayNightLerp);
            Diffuse = pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier; //mix2(baseDiffuse, pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier,mod(worldTime/6000f,2f));
            fogAlbedo = vec3(FOG_NIGHT_R, FOG_NIGHT_G, FOG_NIGHT_B); //mix2(baseFog, vec3(FOG_NIGHT_R, FOG_NIGHT_G, FOG_NIGHT_B), dayNightLerp);
        }
    }

    void dawnFunc(float time, float timeFactor) {
        if(isBiomeEnd) {
            fogMin = FOG_SE_DIST_MIN;
            fogMax = FOG_SE_DIST_MAX;
        } else {
            mediump float sunsetLerp = clamp((time)/timeFactor,0,1);
            fogMin = mix3(FOG_NIGHT_DIST_MIN,FOG_SUNSET_DIST_MIN,FOG_DAY_DIST_MIN, sunsetLerp, 0.5); //mix2(baseFogDistMin, FOG_DAY_DIST_MIN, dayNightLerp);
            fogMax = mix3(FOG_NIGHT_DIST_MAX,FOG_SUNSET_DIST_MAX,FOG_DAY_DIST_MAX, sunsetLerp, 0.5); //mix2(baseFogDistMax, FOG_DAY_DIST_MAX, dayNightLerp);
            baseDiffuseModifier = mix3(vec3(NIGHT_I), vec3(SUNSET_I), vec3(DAY_I), sunsetLerp, 0.5);
            currentColor = mix3(nightColor, transitionColor, dayColor, sunsetLerp, 0.5); //mix2(dayColor, transitionColor, sunsetLerp);
            Diffuse = pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier; //mix2(baseDiffuse, pow2(Diffuse.rgb,vec3(GAMMA)) * baseDiffuseModifier, mod(worldTime/6000f,2f));
            fogAlbedo = mix3(vec3(FOG_NIGHT_R, FOG_NIGHT_G, FOG_NIGHT_B), vec3(FOG_SUNSET_R, FOG_SUNSET_G, FOG_SUNSET_B), vec3(FOG_DAY_R, FOG_DAY_G, FOG_DAY_B), sunsetLerp, 0.5); //mix2(baseFog, vec3(FOG_SUNSET_R, FOG_SUNSET_G, FOG_SUNSET_B), sunsetLerp);
        }
    }

    #include "/lib/world/timeCycle.glsl"

    #ifdef DISTANT_HORIZONS
        uniform float dhFarPlane;
        uniform float dhRenderDistance;
    #else
        float dhFarPlane = far;
        float dhRenderDistance = far/16;
    #endif

    void main() {
        vec4 albedo = texture2D(texture, TexCoords) * Color;
        mediump float depth = texture2D(depthtex0, TexCoords).r;

        mediump float a;

        if(albedo.a > 0) {
            a = 1;
        } else {
            a = 0;
        }

        mediump float distanceFromCamera = distance(vec3(0), viewSpaceFragPosition);

        fogMin = FOG_DAY_DIST_MIN;
        fogMax = FOG_DAY_DIST_MAX;

        baseFogDistMin = fogMin;
        baseFogDistMax = fogMax;

        if(worldTime/(timePhase + 1) < 500f) {
            baseFogDistMin = fogMin;
            baseFogDistMax = fogMax;
        }

        timeFunctionFrag();

        mediump float fogStart = fogMin;
        mediump float fogEnd = fogMax;

        mediump float fogAmount = (length(viewSpaceFragPosition)*(far/dhRenderDistance * 0.75) - fogStart)/(fogEnd - fogStart);

        vec3 newNormal = (gbufferModelViewInverse * vec4(Normal,1.0)).xyz;

        vec4 hsv = CalcHSV(albedo.xyz);
        float glintMask = smoothstep(0.6, 0.8, hsv.y) * smoothstep(0.0, 0.4, hsv.w);
        if(hsv.x < 0.3 || hsv.x > 0.4) {
            glintMask = 0.0;
        }
        vec3 fallbackGlint = vec3(0.95, 0.8, 0.15);
        vec3 glintColor = texture2D(texture, TexCoords).xyz * fallbackGlint;
        vec3 glintHSV = rgb2hsv(glintColor);
        glintHSV.x += 0.8;
        glintHSV.z -= 0.1;
        glintHSV.z = pow2(glintHSV.z, 2);
        glintColor = mix2(glintColor, vec3(length(glintColor)), -glintHSV.y);
        glintColor = hsv2rgb(glintHSV);
        
        if(currentRenderedItemId > 0 && entityId == 10007) {
            albedo.xyz = mix2(albedo.xyz, (glintColor), glintMask);
        }

        gl_FragData[6] = vec4(0.0, encodeDist(distanceFromCamera,dhFarPlane), depth, 1.0);

        gl_FragData[0] = albedo;
        gl_FragData[1] = vec4(newNormal * 0.5 + 0.5f, 1.0f);

        float isCave = LightmapCoords.g;
        vec2 LightmapCoords2 = LightmapCoords;
        if(isBiomeEnd) LightmapCoords2 *= 0.25;
        gl_FragData[5] = vec4(LightmapCoords2, 0.0, 1.0);
        #ifdef ENTITY
            gl_FragData[7] = vec4(isCave, 1.0, 0.0, 1.0);
        #else
            gl_FragData[7] = vec4(isCave, 0.0, 0.0, 1.0);
        #endif

        #if LIGHTING_MODE > 0
            vec4 vanilla = vanillaLight(vec2(AdjustLightmap(LightmapCoords)));
            vec4 lighting = mix2(pow2(vanilla * 0.5f,vec4(0.25f)),vec4(vec3(0.0),1.0),1 - clamp(length(max(vanilla.xyz,vec3(0.0))),0,0.5));
            if(isBiomeEnd) lighting.xyz = max(lighting.xyz, vec3(SE_MIN_LIGHT * 0.1)); else lighting.xyz = max(lighting.xyz, vec3(MIN_LIGHT * 0.1));
            if(currentRenderedItemId > 0 && entityId == 10007) {
                lighting.xyz = mix2(lighting.xyz, 1 - texture2D(texture, TexCoords).xyz, glintMask);
            }
            gl_FragData[2] = encodeLight(vanilla,MAX_LIGHT);
        #else
            gl_FragData[2] = vec4(LightmapCoords, 0.0f, 1.0f);
        #endif
        gl_FragData[5] = vec4(LightmapCoords, 0.0f, 1.0f);
        gl_FragData[3] = vec4(distanceFromCamera, depth, 0.0, 1.0);
        gl_FragData[4] = vec4(0.0,0.0,0.0,1.0);
    }
#endif

#ifdef VERTEX_SHADER
    varying vec2 TexCoords;
    varying vec3 Normal;
    varying vec4 Color;

    varying vec2 LightmapCoords;

    out vec3 viewSpaceFragPosition;

    void main() {
        gl_Position = ftransform();

        LightmapCoords = mat2(gl_TextureMatrix[1]) * gl_MultiTexCoord1.st;

        viewSpaceFragPosition = (gl_ModelViewMatrix * gl_Vertex).xyz;

        TexCoords = gl_MultiTexCoord0.st;
        Normal = gl_NormalMatrix * gl_Normal;
        Color = gl_Color;
    }
#endif