#define FOG_DENSITY 1.0 // [0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.5 3.0 4.0 5.0 7.5 10.0]
#define FOG_SEA_LEVEL 60.0 // [-150.0 -100.0 -75.0 -50.0 -40.0 -30.0 -20.0 -10.0 0.0 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0 120.0 140.0 160.0 180.0 200.0 256.0]
#define FOG_LAYER_HEIGHT 45.0 // [0.0 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0 120.0 140.0 160.0 180.0 200.0 256.0]
#define FOG_TOP (FOG_SEA_LEVEL + FOG_LAYER_HEIGHT)
#define FOG_ABSORP vec3(8e-5)
#define FOG_SCATTER_DAY vec3(255, 250, 232)/255.0
#define FOG_SCATTER_NIGHT vec3(209, 230, 255)/255.0
#define FOG_MAX_DIST 300
#define FOG_STEPS 4 // [4 8 12 14 16 18 20 22 24 28 32 40 46 52]
#define FOG_VARIATION // Makes the fog density have variation. Is slower but looks nicer.

#define GROUND_ATMOSPHERE_DENSITY 1.0 // Strength of the "blue haze" in the distance [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.5 3.0]
//#define TINTED_FOG_SHADOWS // Makes stained glass tint the volumetric shadows

vec3 FOG_SCATTER = vec3(8e-3);//mix(FOG_SCATTER_DAY, FOG_SCATTER_NIGHT, night)*8e-3;

mat2x3 SCATTER_AIR_MAT = mat2x3(atmosphere_coefficientRayleigh, atmosphere_coefficientMie);
mat3x3 SCATTER_MAT = mat3x3(atmosphere_coefficientRayleigh, atmosphere_coefficientMie, atmosphere_coefficientMie);
mat3x3 EXTINCTION_MAT = mat3x3(atmosphere_coefficientRayleigh, atmosphere_coefficientMie*1.1, atmosphere_coefficientMie*1.1);

float sinuousFunction(float x) {
    return clamp01((sin(x) + sin(1.3*x)*0.7 + sin(PI*x)*0.2)*0.33 + 0.5);
}

vec2 grayNoiseRes = textureSize(colortex14, 0);
vec2 grayNoiseResInv = rcp(grayNoiseRes);

// vec4 noiseSmooth(vec2 coord) {
//     coord = coord * grayNoiseRes + 0.5;

// 	vec2 whole = floor(coord);
// 	vec2 part  = cubeSmooth(fract(coord));

// 	coord = (whole + part - 0.5) * grayNoiseResInv;

// 	return texture2D(colortex14, coord);
// }

// float fbm(vec3 pos) {
// 	float p = floor(pos.z);
// 	float f = pos.z - p;
	
    
// 	const float zStretch = 17.0 * grayNoiseResInv.x;
	
// 	vec2 coord = pos.xy * grayNoiseResInv + (p * zStretch);
	
// 	vec2 noise = noiseSmooth(coord).xy;
	
// 	return mix(noise.x, noise.y, f);
// }

float fbm(vec3 pos) {
    vec3 p = floor(pos);
    vec3 f = fract(pos);
    // float zStretch = 10.0 * invNoisTexRes;
    
    vec2 sampleCoord = (p.xy-vec2(97.0)*p.z) + f.xy;//pos.xy*invNoisTexRes + p * 17.0 * invNoisTexRes;
    
    vec2 noise = texture(noisetex, sampleCoord*noiseResInv).ba;//vec2(texture(tex, sampleCoord)[channel], texture(tex, sampleCoord + 17.0 * invNoisTexRes)[channel]);
    
    return smoothstep(0.3, 0.7, cube_smooth(mix(noise.x, noise.y, f.z)));
}

float fogNoise(vec3 pos) {
    pos *= 0.10;
    vec3 windOffset = vec3(frameTimeCounter, frameTimeCounter * 0.5, frameTimeCounter * 0.5);
    #ifndef FOG_VARIATION
    return 0.8;
    #else
    float noise = fbm(pos*2.5 + windOffset) + clamp(fbm(pos*9.0 - windOffset*3.0)*0.75, 0.3, 1.0);// + fbm(pos*5.0 + windOffset);// - fbm(pos*4.0 + windOffset) * 0.25;
    return (noise);
    // return 0.4;
    #endif
}

float sunriseMultiplier = 30.0*isMorn;//pow(isMorn, 0.9);
float sunsetMultiplier = 12.0*isSunset;//pow(isSunset, 0.7);
float nightMultiplier = night*10.4;
float rainMultiplier = 1.0;//wetness*30.0;

float calcFogDensity(vec3 pos, float doFBM) {
    float isMorn = max(float(worldTime > 22000  || worldTime < 2000), 0.06);
    float noise = mix(1.0, fogNoise(pos), doFBM);
    // float x = clamp01(map(max(pos.y, 70), FOG_SEA_LEVEL, FOG_SEA_LEVEL+FOG_LAYER_HEIGHT, 0.0, 1.0));
    float density = noise * (1.0 - smoothstep(FOG_TOP - 18.0, FOG_TOP, pos.y));//noise;//expf(-2.0 * x)
    return FOG_DENSITY * 20.0 * density * max(max(max(max(sunriseMultiplier, rainMultiplier), sunsetMultiplier), nightMultiplier), 3.0);// * float(pos.y < 100.0);
}

float calcAtmosFogDensity(float height) {
    return GROUND_ATMOSPHERE_DENSITY * 10.0;
}