improve lighting - grass shader
This commit is contained in:
133
Shaders/grass_leaves.gdshader
Normal file
133
Shaders/grass_leaves.gdshader
Normal file
@@ -0,0 +1,133 @@
|
||||
shader_type spatial;
|
||||
|
||||
render_mode specular_disabled, cull_disabled, ambient_light_disabled;
|
||||
|
||||
// --- GLOBAL UNIFORMS (Vento e Neve) ---
|
||||
global uniform float wind_scale;
|
||||
global uniform float wind_speed;
|
||||
global uniform float wind_strength;
|
||||
global uniform vec3 wind_direction;
|
||||
global uniform sampler2D 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 * wind_speed;
|
||||
vec2 noise_uv = (instance_pos.xz * wind_scale) + (time * wind_direction.xz * 0.5);
|
||||
float noise_val = textureLod(wind_noise, noise_uv, 2.0).r;
|
||||
float sway = sin(time + (noise_val * 10.0));
|
||||
total_angle += (sway * 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;
|
||||
}
|
||||
1
Shaders/grass_leaves.gdshader.uid
Normal file
1
Shaders/grass_leaves.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cjratw2ndyu8x
|
||||
109
Shaders/stylized.gdshader
Normal file
109
Shaders/stylized.gdshader
Normal file
@@ -0,0 +1,109 @@
|
||||
shader_type spatial;
|
||||
|
||||
group_uniforms Shader.Albedo;
|
||||
uniform vec4 albedo_color : source_color = vec4(1.0);
|
||||
uniform sampler2D albedo_texture;
|
||||
uniform float albedo_affect : hint_range(0.0, 1.0, 0.05) = 0.0;
|
||||
|
||||
group_uniforms Shader.Light;
|
||||
uniform bool use_stepped = true;
|
||||
uniform float steps = 3.0;
|
||||
uniform float step_smoothness : hint_range(0.0, 1.0, 0.05) = 0.3;
|
||||
uniform vec4 shadow_tint : source_color;
|
||||
uniform float shadow_tint_amount : hint_range(0.0, 1.0, 0.1) = 0.4;
|
||||
|
||||
group_uniforms Shader.Specular;
|
||||
uniform float specular : hint_range(0.0, 1.0, 0.05) = 0.0;
|
||||
|
||||
group_uniforms Shader.Normal;
|
||||
uniform float normal_strength : hint_range(0.0, 1.0, 0.05) = 0.0;
|
||||
uniform sampler2D normal_texture;
|
||||
|
||||
group_uniforms Shader.Rim;
|
||||
uniform bool use_rim = true;
|
||||
uniform vec4 rim_color : source_color = vec4(1.0);
|
||||
uniform float rim_amount = 2.0;
|
||||
uniform float rim_smoothness = 0.2;
|
||||
uniform float rim_mask_shadow : hint_range(0.0, 1.0, 0.05) = 1.0;
|
||||
uniform float rim_blend : hint_range(0.0, 1.0, 0.05) = 1.0;
|
||||
|
||||
group_uniforms Shader.Pattern;
|
||||
uniform bool use_pattern = true;
|
||||
uniform sampler2D pattern_texture;
|
||||
uniform int pattern_uv_mode : hint_enum("UV", "Screen", "Local Screen") = 2;
|
||||
uniform float pattern_tiling = 32.0;
|
||||
uniform float pattern_amount : hint_range(0.0, 1.0, 0.05) = 0.5;
|
||||
uniform float pattern_smoothness : hint_range(0.0, 1.0, 0.05) = 0.5;
|
||||
uniform float pattern_blend : hint_range(0.0, 1.0, 0.05) = 0.2;
|
||||
|
||||
varying vec4 node_position;
|
||||
|
||||
float fresnel(float amount, vec3 normal, vec3 view)
|
||||
{
|
||||
return pow((1.0 - clamp(dot(normalize(normal), normalize(view)), 0.0, 1.0 )), amount);
|
||||
}
|
||||
|
||||
vec2 pattern_uv(vec2 uv, vec2 screen_uv){
|
||||
vec2 p_uv = uv;
|
||||
if(pattern_uv_mode == 1) { p_uv = screen_uv; }
|
||||
if(pattern_uv_mode == 2) { p_uv = (screen_uv * 2.0 - 1.0) * node_position.w - node_position.xy; }
|
||||
return p_uv;
|
||||
}
|
||||
|
||||
float shape_value(float value, vec2 uv, vec2 screen_size){
|
||||
float aspect = screen_size.y / screen_size.x;
|
||||
vec2 pattern_uv = uv * pattern_tiling * vec2(1.0, aspect);
|
||||
float shadow_pattern = texture(pattern_texture, pattern_uv).r;
|
||||
shadow_pattern = clamp(smoothstep(shadow_pattern - pattern_smoothness, shadow_pattern + pattern_smoothness, value + pattern_amount), 0.0, value + pattern_amount);
|
||||
return shadow_pattern;
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
node_position = (PROJECTION_MATRIX * vec4(NODE_POSITION_VIEW, 1.0));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec4 albedo = texture(albedo_texture, UV) * albedo_color;
|
||||
vec4 normal_map = texture(normal_texture, UV);
|
||||
|
||||
ALBEDO = albedo.rgb;
|
||||
|
||||
NORMAL_MAP = mix(vec3(0.5,0.5,1.0), normal_map.rgb, normal_strength);
|
||||
|
||||
SPECULAR = specular;
|
||||
}
|
||||
|
||||
void light () {
|
||||
float ndotl = clamp(dot(NORMAL,LIGHT),0.0,1.0) * ATTENUATION;
|
||||
|
||||
float light = ndotl;
|
||||
|
||||
if(use_stepped){
|
||||
float light_mult = light * steps;
|
||||
float step_base = floor(light_mult);
|
||||
float light_factor = light_mult - step_base;
|
||||
|
||||
light_factor = smoothstep(0.5 - step_smoothness, 0.5 + step_smoothness, light_factor);
|
||||
light = (step_base + light_factor) / steps;
|
||||
}
|
||||
|
||||
if(use_pattern){
|
||||
vec2 p_uv = pattern_uv(UV, SCREEN_UV);
|
||||
|
||||
light = mix(light, shape_value(light, p_uv, VIEWPORT_SIZE), pattern_blend);
|
||||
}
|
||||
|
||||
vec3 diffuse = vec3(light) * (LIGHT_COLOR / PI);
|
||||
diffuse = (shadow_tint.rgb * (1.0 - (light)) * shadow_tint_amount) + diffuse * light;
|
||||
|
||||
if(use_rim){
|
||||
float rim_value = fresnel(rim_amount, NORMAL, VIEW);
|
||||
rim_value = smoothstep(0.5 - (rim_smoothness / 2.0), 0.5 + (rim_smoothness / 2.0), rim_value);
|
||||
rim_value = mix(rim_value, rim_value * light, rim_mask_shadow);
|
||||
|
||||
diffuse += rim_color.rgb * rim_value * rim_blend;
|
||||
}
|
||||
|
||||
DIFFUSE_LIGHT += mix(diffuse, ALBEDO * diffuse, albedo_affect);
|
||||
SPECULAR_LIGHT += vec3(pow(light, 50.0)) * specular;
|
||||
}
|
||||
1
Shaders/stylized.gdshader.uid
Normal file
1
Shaders/stylized.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bkb1f7plk6r1j
|
||||
@@ -95,6 +95,7 @@ void vertex() {
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
|
||||
vec2 shifted_uv = UV + texture_offset;
|
||||
vec4 tex = texture(alpha_texture, shifted_uv);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user