improve lighting - grass shader

This commit is contained in:
Matteo Sonaglioni
2026-03-18 15:23:50 +01:00
parent 89a08abfb9
commit d86a9bfb10
18 changed files with 419 additions and 96 deletions

View File

@@ -1,7 +1,5 @@
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;
@@ -11,14 +9,13 @@ 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
uniform float gradient_start_y = 0.0;
uniform float gradient_end_y = 10.0;
group_uniforms Toon_Lighting;
uniform float light_steps : hint_range(1.0, 10.0, 1.0) = 3.0;
@@ -27,10 +24,15 @@ 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
// ---> NUOVO SISTEMA: GHIBLI DIRECTIONAL GLINT <---
group_uniforms Ghibli_Directional_Glint;
uniform bool use_ghibli_glint = true;
// Colore del bagliore (consigliato: panna caldo o albicocca desaturato)
uniform vec4 glint_color : source_color = vec4(1.0, 0.95, 0.85, 1.0);
// Quanta luce extra vogliamo (es: 1.0 = colora, >1.0 = fa brillare, ideale per Bloom)
uniform float glint_intensity : hint_range(0.0, 10.0) = 1.0;
// DEFINIZIONE DELL'ANGOLO: Più è alto, più la fascia di luce è stretta e netta (HArd Step)
uniform float glint_sharpness : hint_range(1.0, 128.0) = 32.0;
group_uniforms Emission_Settings;
uniform vec4 emission_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
@@ -49,14 +51,8 @@ void fragment() {
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;
@@ -64,41 +60,44 @@ void fragment() {
}
void light() {
// GESTIONE ATTENUAZIONE E OMBRE (Anti-frittura con dither)
float shadow_factor = mix(1.0 - cast_shadow_strength, 1.0, ATTENUATION);
float cutoff_mask = smoothstep(0.0, 0.1, ATTENUATION);
float n_dot_l = dot(NORMAL, LIGHT);
float intensity = clamp((n_dot_l * shadow_factor) + shadow_offset, 0.0, 1.0);
// Anti-frittura dither
float dither = fract(sin(dot(FRAGCOORD.xy, vec2(12.9898, 78.233))) * 43758.5453);
float intensity = (clamp(n_dot_l, 0.0, 1.0) * shadow_factor) + (dither - 0.5) * 0.02;
float raw_step = intensity * light_steps;
float raw_step = (intensity + shadow_offset) * 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;
float soft_lerp = smoothstep(0.5 - step_softness, 0.5 + step_softness, fract_step);
float stepped_intensity = (lower_step + soft_lerp) / light_steps;
vec3 light_part = vec3(1.2);
vec3 shaded_part = shadow_color.rgb;
// Colori finali Toon
vec3 light_color_final = mix(shadow_color.rgb, vec3(1.1), clamp(stepped_intensity, 0.0, 1.0));
DIFFUSE_LIGHT += (light_color_final * LIGHT_COLOR) * cutoff_mask;
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);
// ---> GHIBLI DIRECTIONAL GLINT (Il segreto dei tetti) <---
// Sfrutta solo la direzione del sole e la normale dell'oggetto, NON la telecamera.
if (use_ghibli_glint) {
// Calcoliamo un'area di "massima luce" molto aggressiva rivolta perpendicolarmente al sole
// Più 'glint_sharpness' è alto, più la fascia si stringe e diventa selettiva
float glint_raw = pow(max(0.0, n_dot_l), glint_sharpness);
// Toon-ifichiamo l'area con un taglio netto ma pulito
float glint_mask = smoothstep(0.5 - step_softness*0.5, 0.5 + step_softness*0.5, glint_raw);
// Mascheriamo per evitare che appaia nelle ombre proiettate dagli alberi (ATTENUATION)
// e puliamo i bordi laterali (cutoff a 0.0)
glint_mask *= smoothstep(0.0, 0.1, n_dot_l);
// Calcoliamo la luce extra finale
vec3 extra_sun_glint = glint_mask * glint_color.rgb * LIGHT_COLOR * glint_intensity * ATTENUATION;
// Aggiungiamo questa "botta" di luce extra direzionale
DIFFUSE_LIGHT += extra_sun_glint;
}
}