// Perlin Fog
void fog( in Ray ray, inout vec3 i, float scale ) {
	if ( ubo.settings.fog.stepScale <= 0 || ubo.settings.fog.range.x == 0 || ubo.settings.fog.range.y == 0 ) return;
#if FOG_RAY_MARCH
	if ( ubo.settings.fog.stepScale <= 0 || ubo.settings.fog.range.y <= 0 ) return;

	const float range = ubo.settings.fog.range.y;
	const vec3 boundsMin = ray.origin - vec3(range);
	const vec3 boundsMax = ray.origin + vec3(range);

	const vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, ray );
	const float dstToBox = rayBoxInfo.x;
	const float dstInsideBox = rayBoxInfo.y;
	const float depth = surface.position.eye.z;

	if ( dstInsideBox < 0 || dstToBox > depth ) return;

	const float marchLimit = min( depth - dstToBox, dstInsideBox );
	const int MAX_STEPS = 32;

	const float stepSize = marchLimit / float(MAX_STEPS);
	const vec3 stepVec = ray.direction * stepSize;
	const float jitter = rand2(gl_GlobalInvocationID.xy);

	const float densityScale = ubo.settings.fog.densityScale * 0.001;
	const vec3 densityOffset = ubo.settings.fog.offset * 0.01;
	const float densityThreshold = ubo.settings.fog.densityThreshold;
	const float densityMult = ubo.settings.fog.densityMultiplier;
	const float absorption = ubo.settings.fog.absorbtion;
	
	vec3 currentPos = ray.origin + (ray.direction * (dstToBox + stepSize * jitter));
	float transmittance = 1.0;

	for ( uint j = 0; j < MAX_STEPS; ++j ) {
		vec3 uvw = currentPos * densityScale + densityOffset;
		float noiseVal = textureLod(samplerNoise, uvw, 0.0).r;
		float density = max(0.0, noiseVal - densityThreshold) * densityMult;
		if ( density > 0.0 ) {
			float beer = exp(-density * stepSize * absorption);
			transmittance *= beer;
			if ( transmittance < 0.01 ) break;
		}
		currentPos += stepVec;
	}

	i.rgb = mix(ubo.settings.fog.color.rgb, i.rgb, transmittance );
#endif
#if FOG_BASIC
	const vec3 color = ubo.settings.fog.color.rgb;
	const float inner = ubo.settings.fog.range.x;
	const float outer = ubo.settings.fog.range.y * scale;
	const float distance = length(-surface.position.eye);
	const float factor = clamp( (distance - inner) / (outer - inner), 0.0, 1.0 );

	i.rgb = mix(i.rgb, color, factor);
#endif
}