uniform vec4 lightningBoltPosition;

float lightningFlashEffect(vec3 worldPos, vec3 lightningBoltPosition, float lightDistance){ //Thanks to Xonk!
    vec3 lightningPos = worldPos - vec3(lightningBoltPosition.x, max(worldPos.y, lightningBoltPosition.y), lightningBoltPosition.z);

    float lightningLight = max(1.0 - length(lightningPos) / lightDistance, 0.0);
          lightningLight = exp(-24.0 * (1.0 - lightningLight));

    return lightningLight;
}

void computeLPVFog(inout vec3 fog, in vec3 translucent, in float dither) {
    vec3 finalFog = vec3(0.0);

	//Depths
	float z0 = texture2D(depthtex0, texCoord).r;
	float z1 = texture2D(depthtex1, texCoord).r;

	//Positions
	vec3 viewPos = ToView(vec3(texCoord.xy, z0));

	//Total LPV Fog Visibility
	float density = 0.3;
	#ifdef OVERWORLD
		  density = mix(density, 0.5, wetness);
	#endif
	#ifdef NETHER
		  density = 0.5;
	#endif

    float fogVisibility = int(z0 > 0.56);

	#ifdef OVERWORLD
	fogVisibility *= 1.0 - timeBrightness * 0.5;
	#endif

	#if MC_VERSION >= 11900
	fogVisibility *= 1.0 - darknessFactor;
	#endif

	fogVisibility *= 1.0 - blindFactor;

	if (fogVisibility > 0.0) {
		//Linear Depths
		float linearDepth0 = getLinearDepth(z0);
		float linearDepth1 = getLinearDepth(z1);

		//Variables
        int sampleCount = 8;

		float fovFactor = gbufferProjection[1][1] / 1.37;
		float x = abs(texCoord.x - 0.5);
				x = 1.0 - x * x;
				x = pow(x, max(3.0 - fovFactor, 0.0));
		float maxDist = 128.0 * x;
		float minDist = (maxDist / sampleCount);

		float maxCurrentDist = min(linearDepth1, maxDist);

		//Ray Marching
		for (int i = 0; i < sampleCount; i++) {
			float currentDist = (i + dither) * minDist * 0.4;

			if (currentDist > maxCurrentDist || linearDepth1 < currentDist || (linearDepth0 < currentDist && translucent.rgb == vec3(0.0))) {
				break;
			}

            vec3 worldPos = ToWorld(ToView(vec3(texCoord, getLogarithmicDepth(currentDist))));

			if (length(worldPos.xz) < voxelVolumeSize) {
                float lightning = min(lightningFlashEffect(worldPos, lightningBoltPosition.xyz, 256.0) * lightningBoltPosition.w * 4.0, 1.0);

                float floodfillFade = maxOf(abs(worldPos));
                      floodfillFade /= voxelVolumeSize * 0.5;
                      floodfillFade = clamp(floodfillFade, 0.0, 1.0);

                vec3 voxelPos = ToVoxel(worldPos);

                vec3 voxelSamplePos = voxelPos;
                     voxelSamplePos /= voxelVolumeSize;
                     voxelSamplePos = clamp(voxelSamplePos, 0.0, 1.0);

                vec3 floodfillData = texture3D(floodfillSampler, voxelSamplePos).rgb;
                vec3 lighting = pow(floodfillData.rgb, vec3(0.75));
					 lighting = lighting * density + lighting * pow(length(lighting), LPV_FOG_THRESHOLD) * (1.0 - density);
				vec3 lpvFog = mix(lighting * 8.0 * LPV_FOG_STRENGTH, vec3(0.0), pow3(floodfillFade));

				//Translucency Blending
				if (linearDepth0 < currentDist) {
					lpvFog *= translucent.rgb;
				}

                float currentSampleIntensity = (currentDist / maxDist) / sampleCount;

				finalFog += lpvFog * currentSampleIntensity;
			}
		}
		finalFog *= fogVisibility;
	}

    fog += finalFog;
}