shader_type sky;

// --- COLORI BASE ---
uniform vec3 sky_top_color : source_color;
uniform vec3 sky_horizon_color : source_color;
uniform float night_intensity : hint_range(0.0, 1.0) = 0.0;

// --- NUVOLE (AGGIORNATE PER GRADIENTE, OPACITÀ E SOLE) ---
group_uniforms Nuvole;
uniform sampler2D cloud_noise : filter_linear_mipmap, repeat_enable;
// NUOVO: Colore del sole in tempo reale passato dallo script
uniform vec3 sun_color : source_color = vec3(1.0);
// Colore del "cuore" della nuvola
uniform vec4 cloud_center_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
// Colore del bordo esterno (es. un azzurrino o lilla)
uniform vec4 cloud_edge_color : source_color = vec4(0.8, 0.85, 0.9, 1.0);
uniform vec2 cloud_direction = vec2(0.5, 0.2);
uniform float cloud_speed : hint_range(0.0, 2.0) = 0.1;
uniform float cloud_scale = 0.5;
// Aumenta per avere meno nuvole, diminuisci per un cielo coperto
uniform float cloud_threshold : hint_range(0.0, 1.0) = 0.5;
// Distanza tra il centro e il bordo (controlla il gradiente del colore)
uniform float cloud_edge_thickness : hint_range(0.0, 0.5) = 0.1;
// Quanto è morbido e trasparente il bordo estremo della nuvola
uniform float cloud_edge_softness : hint_range(0.0, 0.5) = 0.05;

// --- STELLE FISSE ---
group_uniforms Stelle_Fisse;
uniform float star_density : hint_range(0.0, 2000.0) = 1500.0;
uniform float star_rarity : hint_range(100.0, 5000.0) = 2500.0;
uniform float star_scale_variation : hint_range(0.0, 1.0) = 0.5;

// --- STELLE CADENTI ---
group_uniforms Stelle_Cadenti;
uniform sampler2D shooting_star_texture : hint_default_black, filter_linear_mipmap;
uniform vec4 shooting_star_color : source_color = vec4(1.0, 0.9, 0.7, 1.0);
uniform float shooting_star_density : hint_range(0.0, 1.0) = 0.3;
uniform float shooting_star_speed : hint_range(0.1, 3.0) = 1.0;
uniform float shooting_star_scale : hint_range(0.1, 20.0) = 5.0;
uniform float shooting_star_lifetime : hint_range(0.1, 1.0) = 0.5;
uniform float shooting_star_travel_dist : hint_range(1.0, 30.0) = 15.0;


// --- UTILITY FUNCTIONS ---
float hash(vec3 p) {
	p = fract(p * 0.1031);
	p += dot(p, p.yzx + 33.33);
	return fract((p.x + p.y) * p.z);
}

vec2 hash2(vec3 p) {
	float h1 = hash(p);
	float h2 = hash(p + vec3(57.1, 13.7, 9.3));
	return vec2(h1, h2);
}

vec3 hash3(float seed) {
	vec3 p = fract(vec3(seed) * vec3(0.1031, 0.1030, 0.0973));
	p += dot(p, p.yzx + 33.33);
	return fract((p.xxy + p.yzz) * p.zyx);
}


void sky() {
	float sky_v = clamp(EYEDIR.y, 0.0, 1.0);
	vec3 final_sky = mix(sky_horizon_color, sky_top_color, sky_v);

	if (night_intensity > 0.05) {
		
		// 1. LOGICA STELLE FISSE
		vec3 star_pos = EYEDIR * star_density;
		vec2 rnd = hash2(star_pos);
		float star_shape = pow(rnd.x, star_rarity);
		float scale_factor = mix(1.0, (rnd.y * 0.8 + 0.2), star_scale_variation);
		star_shape *= scale_factor;
		star_shape *= pow(sky_v, 4.0);
		float twinkle_speed = TIME * (1.0 + rnd.y * 5.0);
		float twinkle_phase = rnd.x * 100.0;
		float twinkle = sin(twinkle_speed + twinkle_phase) * 0.25 + 0.75;
		star_shape *= twinkle;
		final_sky += star_shape * night_intensity;

		// 2. LOGICA STELLE CADENTI
		if (shooting_star_density > 0.001) {
			float time_scaled = TIME * shooting_star_speed;
			float time_seed = floor(time_scaled);
			float time_progress = fract(time_scaled);
			vec3 shoot_rnd = hash3(time_seed);

			if (shoot_rnd.z < shooting_star_density * night_intensity) {
				vec3 center = normalize(vec3(shoot_rnd.x * 2.0 - 1.0, shoot_rnd.y * 0.6 + 0.4, shoot_rnd.z * 2.0 - 1.0));
				vec3 up = vec3(0.0, 1.0, 0.0);
				vec3 tangent = normalize(cross(up, center));
				vec3 bitangent = cross(center, tangent);

				float random_angle = hash(vec3(time_seed)) * 6.28318;
				float s = sin(random_angle);
				float c = cos(random_angle);

				vec3 flight_axis = tangent * c - bitangent * s;
				vec3 side_axis = tangent * s + bitangent * c;

				if (flight_axis.y > 0.0) {
					flight_axis = -flight_axis;
					side_axis = -side_axis;
				}

				float proj_x = dot(EYEDIR, side_axis);
				float proj_y = dot(EYEDIR, flight_axis);
				float proj_z = dot(EYEDIR, center);

				if (proj_z > 0.0) {
					vec2 uv = vec2(proj_x, -proj_y) * shooting_star_scale;
					uv.y += (time_progress - (shooting_star_lifetime * 0.5)) * shooting_star_travel_dist;
					uv.x += 0.5;
					
					float bounds = step(0.0, uv.x) * step(uv.x, 1.0) * step(0.0, uv.y) * step(uv.y, 1.0);

					if (bounds > 0.5) {
						float star_tex = texture(shooting_star_texture, uv).r;
						float fade_in = smoothstep(0.0, shooting_star_lifetime * 0.2, time_progress);
						float fade_out = 1.0 - smoothstep(shooting_star_lifetime * 0.7, shooting_star_lifetime, time_progress);
						float fade = fade_in * fade_out;
						final_sky += star_tex * shooting_star_color.rgb * night_intensity * fade;
					}
				}
			}
		}
	}

	// 3. LOGICA NUVOLE (MIGLIORATA)
	vec2 cloud_uv = EYEDIR.xz / (EYEDIR.y + 0.5); 
	cloud_uv = cloud_uv * cloud_scale + (TIME * cloud_direction * cloud_speed);
	float noise = texture(cloud_noise, cloud_uv).r;
	
	// A. Calcolo dell'opacità per il bordo estremo (Fade-out morbido verso il cielo trasparente)
	float cloud_alpha = smoothstep(cloud_threshold, cloud_threshold + cloud_edge_softness, noise);
	
	// B. Calcolo del gradiente di colore tra il bordo e il centro
	float color_gradient = smoothstep(cloud_threshold, cloud_threshold + cloud_edge_thickness, noise);
	
	// C. Creiamo il colore diurno mischiando il colore del bordo con quello centrale
	// MODIFICA: Moltiplichiamo il colore base delle nuvole per la tinta del sole/ambiente
	vec3 tinted_center = cloud_center_color.rgb * sun_color;
	vec3 tinted_edge = cloud_edge_color.rgb * sun_color;
	vec3 day_cloud_color = mix(tinted_edge, tinted_center, color_gradient);
	
	// D. Di notte le nuvole diventano scure (prendono il colore scuro della cima del cielo)
	vec3 night_cloud_color = sky_top_color * 0.4;
	vec3 current_cloud_color = mix(day_cloud_color, night_cloud_color, night_intensity);
	
	// E. Le nuvole si dissolvono dolcemente vicino all'orizzonte
	cloud_alpha *= smoothstep(0.1, 0.4, EYEDIR.y);
	
	// F. Applichiamo la nuvola al cielo basandoci sull'Alpha calcolato
	final_sky = mix(final_sky, current_cloud_color, cloud_alpha);

	COLOR = final_sky;
}