// Authored Nether atmosphere for NOISE. The implementation is deliberately
// texture-free so it remains stable with both the fragment and compute paths.
#ifndef NOISE_NETHER_GLSL
#define NOISE_NETHER_GLSL

vec3 noiseNetherAtmosphereColor(vec3 baseFog) {
	vec3 vanillaFog = clamp(baseFog, vec3(0.0), vec3(0.72));
	vec3 infernalBase = vec3(0.150, 0.034, 0.018);
	vec3 biomeColor = vanillaFog * vec3(0.56, 0.58, 0.60);
	float biomePresence = smoothstep(0.015, 0.22, max(vanillaFog.r, max(vanillaFog.g, vanillaFog.b)));
	vec3 atmosphere = mix(infernalBase, max(biomeColor, vec3(0.016, 0.008, 0.006)), biomePresence * 0.52);
	return clamp(atmosphere + vec3(0.014, 0.005, 0.003), vec3(0.008), vec3(0.36, 0.25, 0.22));
}

float noiseNetherSmoke(vec3 worldPosition, float frameTimeCounter) {
	float broad = sin(worldPosition.x * 0.027 + worldPosition.z * 0.019
		+ frameTimeCounter * 0.075);
	float crossing = sin(worldPosition.x * 0.011 - worldPosition.z * 0.034
		- frameTimeCounter * 0.052);
	float vertical = sin(worldPosition.y * 0.083 + worldPosition.x * 0.014
		+ frameTimeCounter * 0.031);
	return clamp(0.58 + broad * 0.18 + crossing * 0.15 + vertical * 0.09, 0.16, 1.0);
}

float noiseNetherFogAmount(
	float distanceFraction,
	vec3 worldPosition,
	float frameTimeCounter
) {
	float smoke = noiseNetherSmoke(worldPosition, frameTimeCounter);
	float distanceOpticalDepth = pow(distanceFraction * 1.28, 1.55)
		* mix(0.74, 1.10, smoke);
	float lavaSeaHaze = 1.0 - smoothstep(31.0, 58.0, worldPosition.y);
	float ceilingHaze = smoothstep(88.0, 124.0, worldPosition.y);
	float layeredHaze = (lavaSeaHaze * 0.20 + ceilingHaze * 0.12)
		* smoothstep(0.055, 0.70, distanceFraction);
	return clamp(1.0 - exp(-(distanceOpticalDepth + layeredHaze)), 0.0, 0.94);
}

vec3 noiseNetherSkyColor(
	vec3 worldDirection,
	vec3 baseFog,
	float frameTimeCounter
) {
	vec3 direction = noiseSafeNormalize(worldDirection, vec3(0.0, 0.0, -1.0));
	vec3 atmosphere = noiseNetherAtmosphereColor(baseFog);
	float horizon = 1.0 - smoothstep(0.02, 0.72, abs(direction.y));
	float angularSmoke = sin(atan(direction.z, direction.x) * 3.0
		+ direction.y * 8.0 + frameTimeCounter * 0.018) * 0.5 + 0.5;
	float smokeBand = horizon * mix(0.58, 0.88, angularSmoke);
	vec3 voidColor = vec3(0.0080, 0.0030, 0.0024);
	vec3 sky = mix(voidColor, atmosphere * 0.76, smokeBand);
	sky += vec3(0.060, 0.009, 0.003) * pow(max(-direction.y, 0.0), 2.0);
	return sky;
}

vec3 noiseNetherGrade(vec3 color) {
	float luminance = dot(color, NOISE_LUMA);
	float heat = smoothstep(0.045, 0.95, luminance);
	vec3 shadowTint = vec3(0.86, 0.72, 0.66);
	vec3 lightTint = vec3(1.06, 0.91, 0.76);
	vec3 graded = color * mix(shadowTint, lightTint, heat);
	float emberEnergy = max(graded.r - max(graded.g, graded.b), 0.0);
	graded += vec3(0.045, 0.006, 0.002) * emberEnergy;
	return graded;
}

#endif
