#if defined OVERWORLD|| defined END
#include "/lib/lighting/shadows.glsl"
#endif

    vec3 toLinear(vec3 color) {
	return mix(color / 12.92, pow((color + 0.055) / 1.055, vec3(2.4)), vec3(greaterThan(color, vec3(0.04045))));
}

vec3 BlackBody(float Temperature)
{
    float t = pow(Temperature, -1.5);
    float lt = log(Temperature);

    vec3 col = vec3(0.0);
         col.x = 220000.0 * t + 0.58039215686;
         col.y = 0.39231372549 * lt - 2.44549019608;
         col.y = Temperature > 6500. ? 138039.215686 * t + 0.72156862745 : col.y;
         col.z = 0.76078431372 * lt - 5.68078431373;
         col = clamp01(col);
         col = Temperature < 1000. ? col * Temperature * 0.001 : col;

    return toLinear(col);
}

float CurveBlockLight(float blockLight)
{
    float decode=pow(blockLight,1.0/0.25);
    #ifdef LIGHT_JITTER
    const float speed=JITTER_SPEED;
        float jitter1=1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*6.9*speed)-sin(frameTimeCounter*9.5*speed))*JITTER_STRENGTH1;
        float jitter2=1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*3.0*speed)-sin(frameTimeCounter*4.5*speed))*JITTER_STRENGTH2;
        float jitter3=1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*1.5*speed)-sin(frameTimeCounter*2.5*speed))*JITTER_STRENGTH3;
    #endif

    #ifdef LIGHT_JITTER
        decode*=jitter1*jitter2*jitter3;
    #endif

    return decode;
}

void GetLighting(inout vec3 albedo, out vec3 shadow, vec3 viewPos, vec3 worldPos,
                 vec2 lightmap, float smoothLighting, float NoL, float vanillaDiffuse,
                 float parallaxShadow, float emission, float subsurface, float leaves, float dither) {

        lightmap.x = max(lightmap.x * 1.15 - 0.15, 0.0);
        float shadowMult = 1.0;
        float shadowTime = 1.0;
        float ambientColMult = 0.0;
        float lightingColMult = 0.0;

        #if defined OVERWORLD || defined END
            if (NoL > 0.0 || subsurface > 0.0) shadow = GetShadow(worldPos, NoL, subsurface, lightmap.y);
            shadow *= parallaxShadow;
            NoL = clamp01(NoL * 1.01 - 0.01);

            float scattering = 0.0;
            #ifdef SHADOW_SUBSURFACE
            if (subsurface > 0.0){
                float VoL = clamp01(dot(normalize(viewPos.xyz), lightVec) * 0.5 + 0.5);
                scattering = pow(VoL, 16.0) * (1.0 - rainStrengthS) * (1.0 - sunVisibility +0.5) * (1.0 - moonVisibility + 2.0) * subsurface;
                NoL = mix(NoL, 1.0, sqrt(subsurface) * 0.7);
                NoL = mix(NoL, 1.0, scattering);
            }
            #endif

            vec3 fullShadow = shadow * max(NoL, subsurface * (1.0 - max(rainStrengthS, (1.0 - sunVisibility)) * 0.50));

                #ifdef OVERWORLD

                        shadowMult = 1.0 * (1.0 - 0.95 * rainStrengthS) * shadowFade;
                        shadowTime = abs(sunVisibility - 0.5) * 2.0;
                        shadowTime *= shadowTime;
                        shadowMult *= shadowTime * shadowTime;

                    if (isEyeInWater == 1) ambientCol *= pow(lightmap.y, 2.5);

                    vec3 lightingCol = pow(lightCol, vec3(1.0 + sunVisibility * 2.0 - timeBrightness));
                         lightingCol *= (1.0 + 0.4 * leaves);

                    vec3 shadowDecider = fullShadow * shadowMult;
                    if (isEyeInWater == 1) shadowDecider *= pow(min(lightmap.y * 1.03, 1.0), 200.0);
                        if (moonVisibility > 0){
                            ambientColMult = AMBIENT_MULT_NIGHT;
                            lightingColMult = LIGHT_MULT_NIGHT;
                        }
                        else {
                            ambientColMult = AMBIENT_GROUND_DAY;
                            lightingColMult = LIGHT_GROUND_DAY;
                        }

                    vec3 sceneLighting = mix(ambientCol * ambientColMult , lightingCol * lightingColMult, shadowDecider);

                    if (isEyeInWater == 0) sceneLighting *= pow(lightmap.y, 2.5);

                #endif

                #ifdef END
                    #if BRIGHTNESS_END == 1
                        float brightnessEnd = AMBIANT_END;
                    #elif BRIGHTNESS_END == 2
                        float brightnessEnd = (AMBIANT_END * 100);
                    #endif

                    vec3 ambientEnd = endCol.rgb * 0.17 * brightnessEnd;
                    vec3 lightEnd   = endCol.rgb * 0.37 * brightnessEnd;
                    vec3 shadowDecider = fullShadow * 3.0;
                    vec3 sceneLighting = mix(ambientEnd, lightEnd, shadowDecider);
                    sceneLighting *= 0.20 * (0.7 + 0.3 * screenBrightness2);
                #endif

            #else
                vec3 sceneLighting = netherColSqrt.rgb * 0.1;
            #endif

            float torchDist=length(viewPos);
            float handTorchLightmap=0.0;
            vec3 handLightCol=vec3(0.1);

            #ifdef DYNAMIC_HAND_LIGHT
                float handLight = max(float(heldBlockLightValue), float(heldBlockLightValue2));
                float handLightFactor = clamp((handLight - 2.0 * length(viewPos)) / 15.0, 0.0, 0.9333);
                lightmap.x = max(lightmap.x, handLightFactor);
            #endif

            #ifdef DYNAMIC_HAND_LIGHT
            	if (heldItemId==13001||heldItemId2==13001|| //Glowstone, Torch, Jack'o Lantern, Lantern, Campfire, Shroomlight, Lava Bucket, Blaze Rod
					heldItemId==13002||heldItemId2==13002|| //Beacon
					heldItemId==13003||heldItemId2==13003|| //Redstone Torch
					heldItemId==13004||heldItemId2==13004|| //Soul Lantern, Soul Campfire, Soul Torch
					heldItemId==13005||heldItemId2==13005|| //Sea Lantern
					heldItemId==13006||heldItemId2==13006|| //End Rod, Crying Obsidian, End Crystal, Nether Star
					heldItemId==13007||heldItemId2==13007|| //Sea Pickle
                    heldItemId==13008||heldItemId2==13008){ //Conduit

                handTorchLightmap=clamp01(1.-((torchDist-DIST_MAX_LIGHT)/(DIST_DECLINE-DIST_MAX_LIGHT)))*MAX_LIGHT;

                #ifdef COLORED_DYNAMIC_HAND_LIGHT

                if(heldItemId==13002||heldItemId2==13002)
                {
                    handLightCol=vec3(.4863,.7686,.9882);
                }
                else if(heldItemId==13003||heldItemId2==13003)
                {
                    handLightCol=vec3(0.8863, 0.0235, 0.0235);
                }
                else if(heldItemId==13004||heldItemId2==13004)
                {
                    handLightCol=vec3(0.0, 0.1843, 1.0);
                }
                else if(heldItemId==13005||heldItemId2==13005)
                {
                    handLightCol=vec3(0.0, 0.8549, 0.6667);
                }
                else if(heldItemId==13006||heldItemId2==13006)
                {
                    handLightCol=vec3(0.9765, 0.3412, 1.0);
                }
                else if(heldItemId==13007||heldItemId2==13007)
                {
                    handLightCol=vec3(0.8275, 0.8314, 0.4118);
                }
                else if(heldItemId==13008||heldItemId2==13008)
                {
                    handLightCol=vec3(0.9922, 0.9255, 0.7059);
                }
                else if(heldItemId==13001||heldItemId2==13001)
                {
                    handLightCol=vec3(1.,.3686,0.);
                }
                #endif
            }
            #endif

        float LightPower=LIGHTING_POWER_DAY * sunVisibility + LIGHTING_POWER_NIGHT * moonVisibility;

        if(isEyeInWater==0) LightPower = mix(LIGHTING_POWER_INSIDE,LightPower,eBS);
        if(isEyeInWater==1) LightPower = mix(LIGHTING_POWER_UNDERWATER,LightPower,eBS);

        #if CONCENTRATE_BLOCK_LIGHT == 1
            float newLightmap  = pow(lightmap.x, 120.0 / LightPower) * BLOCKLIGHT_LUMA + max((lightmap.x - 0.05) * 0.925, 0.0) * (screenBrightness2*0.25 + 0.9);
        #endif

        #if CONCENTRATE_BLOCK_LIGHT == 2
            float newLightmap  = sqrt(pow(lightmap.x, 120.0 / LightPower) * BLOCKLIGHT_I + max((lightmap.x - 0.05) * 0.925, 0.0) * (screenBrightness2*0.25 + 0.9));
        #endif

        #ifndef HAND
            #ifdef BLOCKLIGHT_BY_TEMP
                blocklightCol=BlackBody(BLOCKLIGHT_TEMP) * 2.0 * BLOCKLIGHT_LUMA;
            #endif
        #endif

        handTorchLightmap=CurveBlockLight(handTorchLightmap);
        newLightmap=CurveBlockLight(newLightmap);

        #ifdef OVERWORLD

            #if SHINE_BLOCKLIGHTINGLIMITER == 0
                float newLightMap = newLightmap;
            #endif

            #if SHINE_BLOCKLIGHTINGLIMITER == 1
                float newLightMap = newLightmap * newLightmap;
            #endif

                #ifdef COLORED_LIGHTING
                    float CLr = texture(noisetex, 0.00006 * (worldPos.xz + cameraPosition.xz)).r;
                    float CLg = texture(noisetex, 0.00009 * (worldPos.xz + cameraPosition.xz)).r;
                    float CLb = texture(noisetex, 0.00014 * (worldPos.xz + cameraPosition.xz)).r;
                    blocklightCol = vec3(CLr, CLg, CLb);
                    blocklightCol *= blocklightCol * BLOCKLIGHT_I * 2.22;
                #endif

            vec3 blockLighting=max(blocklightCol*(newLightMap),handLightCol * (handTorchLightmap));
        #else
            vec3 blockLighting=max(blocklightCol*(newLightmap),handLightCol * (handTorchLightmap));
        #endif

        float shade = pow(vanillaDiffuse, SHADING_STRENGTH);
        vec3 emissiveLighting = albedo * vec3(emission * 7.0 / shade) * EMISSIVE_MULTIPLIER;

        float lightFlatten = clamp01(1.0 - pow(1.0 - emission, 128.0));
        vanillaDiffuse = mix(vanillaDiffuse, 1.0, lightFlatten);
        smoothLighting = mix(smoothLighting, 1.0, lightFlatten);

        float nightVisionLighting=nightVision * 0.25;

        vec3 minLighting = minLightCol * (1.0 - eBS);
        minLighting *= ((isEyeInWater == 1) ? MINLIGHT_U_I : MINLIGHT_I);

        albedo *= sceneLighting + blockLighting + emissiveLighting + nightVisionLighting + minLighting;
        albedo *= shade * smoothLighting * smoothLighting;

        #if defined GBUFFERS_HAND && defined HAND_BLOOM_REDUCTION
            float strenghtAlbedo = (albedo.r + albedo.g + albedo.b) / HAND_BLOOM_REDUCTION_STRENGTH;
            if (strenghtAlbedo > 1.0) albedo.rgb = albedo.rgb * max(2.0 - strenghtAlbedo, 0.34);
	    #endif

}

