shader_type spatial;

render_mode specular_disabled, cull_disabled, ambient_light_disabled;

// --- GLOBAL UNIFORMS (Vento e Neve) ---
global uniform float global_wind_scale;
global uniform float global_wind_speed;
global uniform float global_wind_strength;
global uniform vec2 global_wind_direction;
//global uniform sampler2D global_wind_noise : filter_linear_mipmap;
global uniform float global_snow_amount;

// --- PARAMETRI ESTETICI ---
uniform bool billboard_enabled = true; 
uniform bool wind_enabled = true;      
uniform vec4 base_color : source_color = vec4(0.2, 0.6, 0.3, 1.0);
uniform sampler2D alpha_texture : source_color, filter_nearest;
uniform float leaves_scale = 1.0;
uniform float rotation_degrees = 0.0;
uniform vec2 texture_offset = vec2(0.0, 0.0);
uniform float opacity : hint_range(0.0, 1.0) = 1.0; 

// ---> NUOVI PARAMETRI PER VARIAZIONE ERBA <---
group_uniforms Grass_Variance;
uniform sampler2D color_variance_noise : filter_linear_mipmap; // Trascina qui un FastNoiseLite
uniform float variance_scale = 0.1; // Grandezza delle chiazze (più basso = chiazze più grandi)
uniform vec4 variance_color : source_color = vec4(0.3, 0.5, 0.2, 1.0); // Colore delle chiazze (es: verde più scuro o giallastro)
uniform float variance_intensity : hint_range(0.0, 1.0) = 0.4; // Quanto si vedono le chiazze

uniform vec4 snow_color : source_color = vec4(0.85, 0.9, 0.95, 1.0);

// --- CONTROLLO GRADIENTE E RANDOM ---
uniform float height_min = 0.0;
uniform float height_max = 5.0;
uniform float shadow_intensity : hint_range(0.0, 1.0) = 0.5;
uniform float highlight_intensity : hint_range(0.0, 1.0) = 0.3;
uniform float light_steps : hint_range(1.0, 10.0) = 4.0;
uniform float random_mix : hint_range(0.0, 1.0) = 0.3;

uniform float cast_shadow_strength : hint_range(0.0, 1.0) = 0.6;

varying vec3 v_final_color;
varying float v_shade_factor; 
varying vec3 v_world_pos; // Passiamo la posizione mondo per il rumore

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

void vertex() {
	vec3 instance_pos = MODEL_MATRIX[3].xyz;
	v_world_pos = instance_pos; // Salviamo la posizione dell'istanza
	
	// --- LOGICA VENTO ---
	float total_angle = radians(rotation_degrees);
	if (wind_enabled) {
		float time = TIME * global_wind_speed;
		vec2 noise_uv = (instance_pos.xz * global_wind_scale) + (time * global_wind_direction.xy * 0.5);
		//float noise_val = textureLod(wind_noise, noise_uv, 2.0).r;
		//float sway = sin(time + (noise_val * 10.0));
		float sway = sin(time + (0.1 * 10.0));
		total_angle += (sway * global_wind_strength);
	}

	// --- CALCOLO COLORE ---
	float h_factor = clamp((instance_pos.y - height_min) / (height_max - height_min), 0.0, 1.0);
	float leaf_rand = hash(instance_pos);
	float combined_factor = mix(h_factor, leaf_rand, random_mix);
	combined_factor = ceil(combined_factor * light_steps) / light_steps;
	
	v_shade_factor = combined_factor; 
	
	vec3 dark_color = base_color.rgb * (1.0 - shadow_intensity);
	vec3 light_color = base_color.rgb + (vec3(1.0) - base_color.rgb) * highlight_intensity;
	v_final_color = mix(dark_color, light_color, combined_factor);

	// --- LOGICA TRASFORMAZIONE ---
	if (billboard_enabled) {
		vec3 view_pos_origin = (VIEW_MATRIX * vec4(instance_pos, 1.0)).xyz;
		vec2 offset = (UV - 0.5) * leaves_scale;

		float c = cos(total_angle);
		float s = sin(total_angle);
		vec2 rotated_offset = vec2(offset.x * c - offset.y * s, offset.x * s + offset.y * c);
		
		vec3 final_pos = view_pos_origin + vec3(rotated_offset.x, rotated_offset.y, 0.0);

		MODELVIEW_MATRIX = mat4(1.0);
		MODELVIEW_MATRIX[3].xyz = final_pos;
		VERTEX = vec3(0.0);
	} else {
		float c = cos(total_angle);
		float s = sin(total_angle);
		
		vec2 local_v = (VERTEX.xy) * leaves_scale;
		VERTEX.x = local_v.x * c - local_v.y * s;
		VERTEX.y = local_v.x * s + local_v.y * c;
	}
}

void fragment() {
	vec2 shifted_uv = UV + texture_offset;
	vec4 tex = texture(alpha_texture, shifted_uv);
	
	// ---> LOGICA VARIAZIONE COLORE MONDO <---
	// Usiamo la posizione XZ del mondo per campionare il rumore
	float noise_sample = texture(color_variance_noise, v_world_pos.xz * variance_scale).r;
	// Applichiamo la variazione al colore finale dell'erba
	vec3 varied_grass_color = mix(v_final_color, variance_color.rgb, noise_sample * variance_intensity);
	
	float top_mask = 1.0 - shifted_uv.y; 
	float snow_mask = smoothstep(1.0 - global_snow_amount, 1.2 - global_snow_amount, top_mask);
	snow_mask *= step(0.01, global_snow_amount);
	
	vec3 dark_snow = snow_color.rgb * (1.0 - shadow_intensity);
	vec3 shaded_snow = mix(dark_snow, snow_color.rgb, v_shade_factor);
	
	// Mescoliamo il colore variato con la neve
	vec3 final_albedo = mix(varied_grass_color, shaded_snow, snow_mask);

	ALBEDO = final_albedo;
	ALPHA = tex.r * opacity; 
	ALPHA_SCISSOR_THRESHOLD = 0.5;
	
	ROUGHNESS = 0.02; 
}

void light() {
	float shadow_factor = mix(1.0 - cast_shadow_strength, 1.0, ATTENUATION);
	float cutoff_mask = smoothstep(0.0, 0.05, ATTENUATION);
	DIFFUSE_LIGHT += (shadow_factor * LIGHT_COLOR) * cutoff_mask;
}