shader_type spatial; // Aggiunto 'ambient_light_disabled' per proteggere i colori piatti // Mantenuto 'diffuse_toon' per ottimizzare i calcoli della luce interna di Godot render_mode diffuse_toon, specular_disabled, ambient_light_disabled; group_uniforms Albedo_Settings; uniform vec4 albedo_color : source_color = vec4(1.0); uniform sampler2D albedo_texture : source_color, filter_nearest; uniform bool use_texture = true; uniform vec2 uv_scale = vec2(1.0, 1.0); uniform float palette_shift_y : hint_range(0.0, 1.0) = 0.0; // --- PARAMETRI GRADIENTE GLOBALE --- group_uniforms Height_Gradient; global uniform vec4 global_gradient_color_top; global uniform vec4 global_gradient_color_bot; global uniform float global_gradient_intensity; uniform float gradient_start_y = 0.0; // Altezza MONDO dove il gradiente è 100% Bottom uniform float gradient_end_y = 10.0; // Altezza MONDO dove il gradiente è 100% Top group_uniforms Toon_Lighting; uniform float light_steps : hint_range(1.0, 10.0, 1.0) = 3.0; uniform float step_softness : hint_range(0.01, 1.0) = 0.1; uniform vec4 shadow_color : source_color = vec4(0.4, 0.4, 0.6, 1.0); uniform float shadow_offset : hint_range(-1.0, 1.0) = 0.0; uniform float cast_shadow_strength : hint_range(0.0, 1.0) = 0.6; // ---> NUOVI PARAMETRI TOON SPECULAR <--- uniform float specular_size : hint_range(10.0, 200.0) = 60.0; // Più è alto, più il punto luce è piccolo uniform float specular_softness : hint_range(0.0, 0.1) = 0.01; // Morbidezza del bordo del punto luce uniform float specular_intensity_multiplier : hint_range(0.0, 2.0) = 0.5; // Forza del riflesso group_uniforms Emission_Settings; uniform vec4 emission_color : source_color = vec4(0.0, 0.0, 0.0, 1.0); uniform float emission_energy : hint_range(0.0, 16.0) = 0.0; varying float world_y; void vertex() { world_y = (MODEL_MATRIX * vec4(VERTEX, 1.0)).y; } void fragment() { vec2 final_uv = (UV * uv_scale) + vec2(0.0, palette_shift_y); vec4 tex = texture(albedo_texture, final_uv); vec3 base_color = albedo_color.rgb; if (use_texture) base_color *= tex.rgb; // --- APPLICAZIONE GRADIENTE B我們 --- // Calcoliamo il mix tra l'altezza minima e massima (0.0 = Bottom, 1.0 = Top) float grad_factor = smoothstep(gradient_start_y, gradient_end_y, world_y); // Ricaviamo il colore attuale del gradiente per questa specifica altezza vec3 current_gradient_color = mix(global_gradient_color_bot.rgb, global_gradient_color_top.rgb, grad_factor); // Miscela il colore base con il gradiente ottenuto, usando l'intensità globale base_color = mix(base_color, current_gradient_color, global_gradient_intensity); ALBEDO = base_color; EMISSION = emission_color.rgb * emission_energy; } void light() { float shadow_factor = mix(1.0 - cast_shadow_strength, 1.0, ATTENUATION); float n_dot_l = dot(NORMAL, LIGHT); float intensity = clamp((n_dot_l * shadow_factor) + shadow_offset, 0.0, 1.0); float raw_step = intensity * light_steps; float lower_step = floor(raw_step); float fract_step = fract(raw_step); float lerp_step = smoothstep(0.5 - step_softness, 0.5 + step_softness, fract_step); float stepped_intensity = (lower_step + lerp_step) / light_steps; vec3 light_part = vec3(1.2); vec3 shaded_part = shadow_color.rgb; vec3 final_toon_light = mix(shaded_part, light_part, clamp(stepped_intensity, 0.0, 1.0)); float cutoff_mask = smoothstep(0.0, 0.05, ATTENUATION); DIFFUSE_LIGHT += (final_toon_light * LIGHT_COLOR) * cutoff_mask; // ---> AGGIUNTA TOON SPECULAR (Metodo 1) <--- // Calcoliamo la direzione a metà strada tra la vista e la luce vec3 half_direction = normalize(VIEW + LIGHT); float n_dot_h = max(0.0, dot(NORMAL, half_direction)); // Applichiamo la potenza (shininess) per definire la dimensione del punto luce float spec_power = pow(n_dot_h, specular_size); // Creiamo un gradino netto (Toon) invece della sfumatura classica PBR float toon_specular = smoothstep(0.5 - specular_softness, 0.5 + specular_softness, spec_power); // Moltiplichiamo il riflesso per il colore della luce (Sole o Luna) vec3 specular_highlight = LIGHT_COLOR * toon_specular * specular_intensity_multiplier; // Sommiamo il punto luce finale alla diffusione, mascherandolo con "cutoff_mask" // per evitare che il riflesso brilli anche nelle zone in ombra profonda. DIFFUSE_LIGHT += (specular_highlight * cutoff_mask); }