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

vec3 DistortShadow(inout vec3 worldPos,float distortFactor){
    worldPos.xy/=distortFactor;
    worldPos.z*=.2;
    return worldPos*.5+.5;
}
#endif

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_STRENGHT1;
		float jitter2 = 1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*3.0*speed)-sin(frameTimeCounter*4.5*speed))*JITTER_STRENGHT2;
        float jitter3 = 1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*1.5*speed)-sin(frameTimeCounter*2.5*speed))*JITTER_STRENGHT3;
	#endif
	
	decode = pow(decode, 2.0) * 5.0;
    #ifdef LIGHT_JITTER
    decode *= jitter1 * jitter2 * jitter3;
    #endif
    decode += pow(decode, 0.4) * 0.1;
	
	return decode;
}

void GetLighting(inout vec3 albedo,out vec3 shadow,vec3 viewPos,vec3 worldPos,
    vec2 lightmap,float smoothLighting,float NdotL,float quarterNdotU,
float parallaxShadow,float emissive,float foliage){
    
    #if defined OVERWORLD||defined END
    vec3 shadowPos=ToShadow(worldPos);
    
    float distb=sqrt(shadowPos.x*shadowPos.x+shadowPos.y*shadowPos.y);
    float distortFactor=distb*shadowMapBias+(1.-shadowMapBias);
    shadowPos=DistortShadow(shadowPos,distortFactor);
    
    float doShadow=float(
        shadowPos.x>0.&&shadowPos.x<1.&&
        shadowPos.y>0.&&shadowPos.y<1.
    );
    
    #ifdef OVERWORLD
    doShadow*=float(lightmap.y>.001);
    #endif
    
    if((NdotL>0.||foliage>.5)){
        if(doShadow>.5){
            float NdotLm=NdotL*.99+.01;
            
            float biasFactor=sqrt(1.-NdotLm*NdotLm)/NdotLm;
            float distortBias=distortFactor*shadowDistance/256.;
            distortBias*=8.*distortBias;
            
            float bias=(distortBias*biasFactor+.05)/shadowMapResolution;
            float offset=1./shadowMapResolution;
            
            if(foliage>.5){
                bias=.0002;
                offset=.0007;
            }
            
            shadow=GetShadow(shadowPos,bias,offset);
            
        }else shadow=vec3(lightmap.y);
    }
    shadow*=parallaxShadow;
    
    vec3 fullShadow=shadow*max(NdotL,foliage);
    
    #ifdef OVERWORLD
    float shadowMult=1.*(1.-.95*rainStrength);
    vec3 sceneLighting = mix(ambientCol, lightCol, fullShadow * shadowMult);
    sceneLighting *= lightmap.y * lightmap.y * lightmap.y;

    float shadowTime = worldTime;
	shadowTime -= floor(shadowTime / 24000) * 24000;
	if (shadowTime < 12800) {
		shadowTime = clamp((12800 - shadowTime) / 400, 0.0, 1.0);
	} else if (shadowTime < 23200) {
		if (shadowTime < 18000) shadowTime = clamp((shadowTime - 12800) / 400, 0.0, 1.0);
		if (shadowTime > 18000) shadowTime = clamp((23200 - shadowTime) / 400, 0.0, 1.0);
	} else {
		shadowTime = clamp((shadowTime - 23200) / 400, 0.0, 1.0);
	}
	fullShadow *= clamp(pow(shadowTime, 2), 0.0, 1.0);
	
    /*vec3 sceneLighting = mix(ambientCol, lightCol, fullShadow * shadowMult);
    sceneLighting *= lightmap.y * lightmap.y * lightmap.y;*/

    #endif
    
    #ifdef END
    vec3 sceneLighting=endCol*(.075*fullShadow+.05);
    #endif
    
    if(foliage>.5){
        float VdotL=clamp(dot(normalize(viewPos.xyz),lightVec),0.,1.);
        float subsurface=pow(VdotL,25.)*(1.-rainStrength);
        sceneLighting*=3.*fullShadow*subsurface+1.;
    }
    #else

    vec3 sceneLighting=netherColSqrt.rgb*.1;
    #endif
    
    #if defined GBUFFERS_WATER
	if (mat > 2.98 && mat < 3.02) sceneLighting *= 0.0;
	#endif
    
	#ifndef ADVANCED_MATERIALS
	if (lightmap.x > 0.5) lightmap.x = smoothstep(0.0, 1.0, lightmap.x);
    float newLightmap  = pow(lightmap.x, 10.0) * 1.5 + max(lightmap.x - 0.1, 0.0);
	#endif

    float torchDist = length(worldPos);
    float handTorchLightmap = 0.0;

    #ifdef DYNAMIC_HAND_LIGHT
    if(heldItemId == 12999 ||heldItemId2 == 12999 ){
        handTorchLightmap = clamp(1.0 - ((torchDist - DIST_MAX_LIGHT) / (DIST_DECLINE - DIST_MAX_LIGHT)),0.0,1.0) * MAX_LIGHT; // (torchDist,2.0 = puissance du declin de la distance)   (*0.1 = Reglage de la disctance je sais pas trop comment l'expliquer) (0.5 = c'est l'eclairage maximale entre 0 et 1)
        }
    #endif

    float newLightmap=pow(lightmap.x,10.)*(EMISSIVE_BRIGHTNESS+.5)+lightmap.x*.7;
          newLightmap=max(newLightmap,handTorchLightmap);
          newLightmap=CurveBlockLight(newLightmap);
    
    vec3 blockLighting=blocklightCol*sqrt(newLightmap);
    
    float minLighting=(.009*screenBrightness+.001)*(1.-eBS);
    
    vec3 emissiveLighting=albedo.rgb*(emissive*4./quarterNdotU);
    
    float nightVisionLighting=nightVision*.25;
    
    albedo*=sceneLighting+blockLighting+emissiveLighting+nightVisionLighting+minLighting;
    albedo *= pow(quarterNdotU, SHADING_STRENGTH) * smoothLighting * smoothLighting;
    
    #ifdef DESATURATION
    #ifdef OVERWORLD
    float desatAmount=sqrt(max(sqrt(length(fullShadow/3.))*lightmap.y,lightmap.y))*
    sunVisibility*(1.-rainStrength*.4)+sqrt(lightmap.x+emissive);
    
    vec3 desatNight=lightNight/LIGHT_NI;
    vec3 desatWeather=weatherCol.rgb/weatherCol.a*.5;
    
    desatNight*=desatNight;desatWeather*=desatWeather;
    
    float desatNWMix=(1.-sunVisibility)*(1.-rainStrength);
    
    vec3 desatColor=mix(desatWeather,desatNight,desatNWMix);
    desatColor=mix(vec3(.1),desatColor,sqrt(lightmap.y))*10.;
    #endif
    
    #ifdef NETHER
    float desatAmount=sqrt(lightmap.x+emissive);
    
    vec3 desatColor=netherColSqrt.rgb/netherColSqrt.a;
    #endif
    
    #ifdef END
    float desatAmount=sqrt(lightmap.x+emissive);
    
    vec3 desatColor=endCol*1.25;
    #endif
    
    desatAmount=clamp(desatAmount,DESATURATION_FACTOR*.4,1.);
    desatColor*=1.-desatAmount;
    
    albedo.rgb=mix(GetLuminance(albedo.rgb)*desatColor,albedo.rgb,desatAmount);
    #endif
}