#ifdef ENABLE_DARKNESS_EFFECT
	#if MC_VERSION >= 11900
		uniform float darknessFactor;
	#endif
#endif

#ifdef OVERWORLD
vec3 GetFogColor(vec3 viewPos) {
	vec3  nViewPos=normalize(viewPos);
	float lViewPos=length(viewPos) / 64.0;
	      lViewPos=1.0 - exp(-lViewPos * lViewPos);

    float VoU=clampInv11(dot(nViewPos,  upVec));
    float VoL=clampInv11(dot(nViewPos, sunVec));

	float density       =0.4;
	float nightDensity  =0.65;
	float weatherDensity=1.5;
	float groundDensity =0.08 * (4.0 - 3.0 * sunVisibility) * (10.0 * pow2(rainStrengthS) + 1.0);

    float exposure     =exp2(timeBrightness * 0.75 - 0.75);
    float nightExposure=exp2(-3.5);

	float baseGradient=exp(-(VoU * 0.5 + 0.5) * 0.5 / density);

    vec3 fog=fogCol * baseGradient / (SKY_I * SKY_I);
         fog=fog / sqrt(fog * fog + 1.0) * exposure * sunVisibility * (SKY_I * SKY_I);

	float sunMix=(VoL * 0.5 + 0.5) * pow(clamp01(1.0 - VoU), 2.0 - sunVisibility) *
                   pow(1.0 - exposure * 0.6, 3.0);
    float horizonMix=pow(1.0 - abs(VoU), 2.5) * 0.125 * (1.0 - exposure * 0.5);
    float lightMix  =(1.0 - (1.0 - sunMix) * (1.0 - horizonMix)) * lViewPos;

    vec3 lightFog=pow(lightSun, vec3(4.0 - sunVisibility)) * baseGradient;
         lightFog=lightFog / (1.0 + lightFog * rainStrengthS);

    fog = mix(
        sqrt(fog * (1.0 - lightMix)),
        sqrt(lightFog),
        lightMix
    );
    fog*=fog;

	float nightGradient =exp(-(VoU * 0.5 + 0.5) * 0.35 / nightDensity);
	vec3  nightFog      =lightNight * lightNight * nightGradient * nightExposure;
	      nightFog     *=mix(SKY_NIGHT, 1.0, sunVisibility);
	      fog           =mix(nightFog, fog, sunVisibility * sunVisibility);

    float rainGradient =exp(-(VoU * 0.5 + 0.5) * 0.125 / weatherDensity);
    vec3  weatherFog   =weatherCol.rgb * weatherCol.rgb;
          weatherFog  *=GetLuminance(ambientCol / (weatherFog)) * (0.2 * sunVisibility + 0.2);
          fog          =mix(fog, weatherFog * rainGradient, rainStrengthS);

		#ifdef UNDERGROUND_FOG
			fog =mix(minLightCol * 0.1, fog * eBS, eBS);
		#endif

	#if MC_VERSION >=11800
	    fog*=clamp01((cameraPosition.y + 70.0) / 8.0);
	#else
		fog*=clamp01((cameraPosition.y + 6.0) / 8.0);
	#endif

	return fog;
}
#endif



vec3 NormalFog(inout vec3 color,vec3 viewPos){
	#if DISTANT_FADE > 0
		#if DISTANT_FADE_STYLE == 0
			float fogFactor = length(viewPos);
		#else
			vec4 worldPos = gbufferModelViewInverse * vec4(viewPos, 1.0);
			worldPos.xyz /= worldPos.w;
			float fogFactor = length(worldPos.xz);
		#endif
	#endif

#ifdef OVERWORLD
	float fogDensity=OVERWORLD_FOG_DENSITY;

		#if SUNVISIBILITY_FOG==0
			#endif

			#if SUNVISIBILITY_FOG==1
				fogDensity*=3-sunVisibility*2;
			#endif
			#if SUNVISIBILITY_FOG==2
				fogDensity*=4-sunVisibility*3;
			#endif

			#if SUNVISIBILITY_FOG==3
				fogDensity*=5-sunVisibility*4;
			#endif

			#if SUNVISIBILITY_FOG==4
				fogDensity*=6-sunVisibility*5;
		#endif

	float fog=length(viewPos) * fogDensity / 256.0;
	float clearDay=sunVisibility * (1.0 - rainStrengthS);
	vec3 fogColor=vec3(1.0);

	if(isEyeInWater==0){
		#ifdef UNDERGROUND_FOG
			fog *= mix(1.0, (RAIN_FOG_DENSITY * rainStrengthS + 1.0) / (4.0 * clearDay + 1.0) * eBS, eBS);
			fog = 1.0 - exp(-2.0 * pow(fog, 0.15 * clearDay * eBS + 1.25));
		#else
			fog *=(RAIN_FOG_DENSITY * rainStrengthS + 1.0) / (4.0 * clearDay + 1.0);
			fog = 1.0 - exp(-2.0 * pow(fog, 0.15 * clearDay + 1.25) * eBS);
		#endif

		fogColor *= GetFogColor(viewPos);
	}
	if(isEyeInWater>0){
		fog*=(0.5 * rainStrengthS + 1.0) / (4.0 * clearDay + 3.0);
		fog = 1.0 - exp(-2.0 * pow(fog, 0.15 * clearDay + 8.0) * eBS);
		fogColor *= GetFogColor(viewPos);
	}

	#if DISTANT_FADE == 1 || DISTANT_FADE == 3
		if(isEyeInWater == 0.0){
			#if MC_VERSION >= 11800
				float fogOffset = 0.0;
			#else
				float fogOffset = 12.0;
			#endif
			float vanillaFog = 1.0 - (far - (fogFactor + fogOffset)) * 5.0 / (OVERWORLD_FOG_DENSITY * far);

			vanillaFog = clamp01(vanillaFog);

			if(vanillaFog > 0.0){
				vec3 vanillaFogColor = GetSkyColor(viewPos, false);
				vanillaFogColor *= (4.0 - 3.0 * eBS) * (1.0 + nightVision);

				fogColor *= fog;

				fog = mix(fog, 1.0, vanillaFog);
				if(fog > 0.0) fogColor = mix(fogColor, vanillaFogColor, vanillaFog) / fog;
			}
		}
	#endif

#endif


#ifdef NETHER
	float viewLength=length(viewPos);
	float fog = 2.0 * pow(viewLength * NETHER_FOG_DENSITY / 256.0, 1.5);

	#if DISTANT_FADE == 2 || DISTANT_FADE == 3
		fog += 6.0 * pow(fogFactor * 1.0 / far, 6.0);
	#endif

	fog=1.-exp(-fog);
	vec3 fogColor=netherCol.rgb*0.04;
#endif

#ifdef END
	float fog = length(viewPos) * END_FOG_DENSITY / 128.0;
	#if DISTANT_FADE == 2 || DISTANT_FADE == 3
		fog += 6.0 * pow(fogFactor * 1 / far, 6.0);
	#endif
		fog = 1.0 - exp(-0.8 * fog * fog);
		vec3 fogColor = endCol.rgb * 0.007;
	#ifndef LIGHT_SHAFT
		fogColor *= 2.5;
	#endif
#endif

	color.rgb=mix(color.rgb,fogColor,fog);

	return vec3(color.rgb);
}

void WaterFog(vec3 color, vec3 viewPos, float fogrange) {
    float fog   =length(viewPos) / fogrange;
          fog   =1.0 - exp(-3.0 * fog * fog);
          color*=pow(max(rawWaterColor.rgb, vec3(0.1)), vec3(0.5)) * 3.0;
          color =mix(color, 0.8 * pow(rawWaterColor.rgb * (1.0 - blindFactor), vec3(2.0)), fog);

}

void BlindFog(inout vec3 color, vec3 viewPos) {
	float fog      =length(viewPos) * (blindFactor * 0.2);
	      fog      =(1.0 - exp(-6.0 * fog * fog * fog)) * blindFactor;
	      color.rgb=mix(color.rgb, vec3(0.0), fog);

}

#ifdef ENABLE_DARKNESS_EFFECT
	#if MC_VERSION >= 11900
		void DarknessFog(inout vec3 color, vec3 viewPos) {
			float viewLength=length(viewPos);
			#if DARKNESS_HARD_FOG == 0
				float fog = 2.0 * pow(viewLength * DARKNESS_FOG_DISTANCE / 256.0, 1.0);
			#else
				float fog = length(viewPos) * 0.01 * DARKNESS_FOG_DISTANCE;
			#endif
			fog = (1.0 - exp(-6.0 * fog * fog * fog)) * darknessFactor;
			color.rgb = mix(color.rgb, darknessColor, fog);
		}
	#endif
#endif

void LavaFog(inout vec3 color, vec3 viewPos) {
	float fog=length(viewPos) * LAVA_FOG_STRENGTH;
	      fog=(1.0 - exp(-4.0 * fog * fog * fog));

		#if MC_VERSION >=11700
		if  (gl_Fog.start / far < 0.0) fog=min(length(viewPos) * 0.01, 1.0);
		#endif

	color.rgb=mix(color.rgb, vec3(1.0, 0.3, 0.01), fog);

}

void SnowFog(inout vec3 color, vec3 viewPos) {
	float fog = length(viewPos) * POWDER_SNOW_FOG_STRENGTH;
	fog = (1.0 - exp(-1.0 * fog * fog * fog));
	color.rgb = mix(color.rgb, vec3(0.1, 0.15, 0.2), fog);
}

void Fog(inout vec3 color,vec3 viewPos){

	NormalFog(color,viewPos);

	if (isEyeInWater == 1)WaterFog(color.rgb, viewPos, waterFogRange * (1.0 + eBS));
	if (isEyeInWater == 2)LavaFog(color.rgb, viewPos);
	if (blindFactor  > 0.0)BlindFog(color.rgb, viewPos);

	#if MC_VERSION >= 11701
		if (isEyeInWater == 3)SnowFog(color.rgb, viewPos);
	#endif

	#ifdef ENABLE_DARKNESS_EFFECT
		#if MC_VERSION >= 11900
			if (darknessFactor > 0.001)DarknessFog(color.rgb, viewPos);
		#endif
	#endif
}