fix wind!

This commit is contained in:
2026-04-21 12:40:59 +02:00
parent 7a1ac3b698
commit 9a26a4114b
48 changed files with 2376 additions and 234 deletions

View File

@@ -1,11 +1,11 @@
shader_type canvas_item;
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
global uniform float global_wind_speed;
uniform vec4 dust_color : source_color = vec4(1.0, 0.456, 0.125, 0.6);
//Wind -> negative x = to the left. positive y = to the bottom
uniform vec2 wind_velocity = vec2(-0.2, 0.05);
uniform vec2 wind_speed = vec2(-0.2, 0.05);
uniform float wind_oscillation : hint_range(0.0, 1.0) = 0.3;
uniform float dust_speed : hint_range(0.01, 1.0) = 0.15;
@@ -28,12 +28,13 @@ vec3 hash33(vec3 p3) {
void fragment() {
vec4 scene_color = texture(screen_texture, SCREEN_UV);
float base_time = TIME * dust_speed;
vec2 osc = vec2(sin(TIME * 0.5), cos(TIME * 0.3)) * wind_oscillation;
vec2 final_wind = (wind_velocity + osc) * dust_speed;
float wind_active = step(0.0001, abs(global_wind_speed));
vec2 final_wind = ((wind_speed + osc) * dust_speed) * wind_active;
float final_particle_alpha = 0.0;
//Thresolds (near, medium, far)
vec3 layer_scales = vec3(20.0, 50.0, 100.0) / dust_density;
vec3 layer_thresholds = vec3(0.96, 0.98, 0.99);
@@ -70,4 +71,4 @@ void fragment() {
vec4 dust_colored_particle = dust_color * final_particle_alpha;
COLOR = scene_color + dust_colored_particle;
}
}

View File

@@ -5,7 +5,7 @@
[resource]
shader = ExtResource("1_80hx2")
shader_parameter/dust_color = Color(1, 0.9019608, 0.7019608, 0.6)
shader_parameter/wind_velocity = Vector2(-1, 0.5)
shader_parameter/wind_speed = Vector2(-0.2, 0.05)
shader_parameter/wind_oscillation = 0.0150000007125
shader_parameter/dust_speed = 0.15
shader_parameter/size_min = 0.010000000475

View File

@@ -14,19 +14,6 @@
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ruhh7"]
render_priority = 0
shader = ExtResource("2_i3hjl")
shader_parameter/cloud_scale = 0.05
shader_parameter/cloud_speed = 0.05
shader_parameter/direction = Vector2(0.5, 0.2)
shader_parameter/sun_angle = Vector2(0.5, 0.5)
shader_parameter/cloud_density = 0.4
shader_parameter/center_sharpness = 0.14
shader_parameter/shadow_color = Color(0, 0, 0, 1)
shader_parameter/opacity_center = 0.5
shader_parameter/opacity_edge = 0.2
shader_parameter/fade_start = 150.0
shader_parameter/fade_end = 300.0
shader_parameter/height_fade_start = 10.0
shader_parameter/height_fade_end = 50.0
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_r4tfj"]
transparency = 2

View File

@@ -70,9 +70,23 @@ func _ready() -> void:
func ApplyWindNoiseToMaterials():
var noise_tex = preload("res://core/daynight/noise.tres")
for node in get_tree().get_nodes_in_group("wind_node"):
if node is GeometryInstance3D and node.material_override != null:
node.material_override.set_shader_parameter("wind_noise", noise_tex)
_apply_wind_noise_to_node(node, noise_tex)
func _apply_wind_noise_to_node(node: Node, noise_tex: Texture2D) -> void:
if node is GeometryInstance3D:
var material_override := node.material_override as ShaderMaterial
if material_override:
material_override.set_shader_parameter("wind_noise", noise_tex)
if node is MeshInstance3D:
for surface_index in node.get_surface_override_material_count():
var surface_material := node.get_surface_override_material(surface_index) as ShaderMaterial
if surface_material:
surface_material.set_shader_parameter("wind_noise", noise_tex)
for child in node.get_children():
_apply_wind_noise_to_node(child, noise_tex)
func ApplyWeatherShaderToMaterials():
var weather_shader = preload("res://core/daynight/weather_overlay.tres")

View File

@@ -0,0 +1,134 @@
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;
}

View File

@@ -0,0 +1 @@
uid://8l8glwvvs7fb

View File

@@ -43,7 +43,7 @@ void vertex() {
vec3 instance_pos = MODEL_MATRIX[3].xyz;
float total_angle = radians(rotation_degrees);
if (wind_enabled) {
if (wind_enabled && global_wind_speed > 0.0 && global_wind_strength > 0.0) {
float time = TIME * global_wind_speed;
vec2 noise_uv = (instance_pos.xz * global_wind_scale) + (time * global_wind_direction * 0.5);
float noise_val = textureLod(wind_noise, noise_uv, 2.0).r;

View File

@@ -0,0 +1,101 @@
shader_type spatial;
render_mode blend_mix, depth_draw_always;
// --- PARAMETRI COLORI ACQUA ---
uniform vec4 deep_water_color : source_color = vec4(0.0, 0.1, 0.2, 1.0);
uniform vec4 shallow_water_color : source_color = vec4(0.0, 0.4, 0.7, 1.0);
// Impostato a 5.0 come piace a te per un'acqua super profonda!
uniform float beer_law_factor : hint_range(0.0, 10.0) = 5.0;
// ---> PARAMETRI FAKE REFLECTION (SPECCHIATA) <---
group_uniforms Fake_Reflection_Proximity;
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
uniform float reflection_strength : hint_range(0.0, 1.0) = 0.6;
uniform float reflection_offset : hint_range(-0.5, 0.5) = 0.05; // Offset base
// LA MAGIA DELLO SPECCHIO: Valori positivi (es. 0.1 o 0.2) capovolgeranno l'immagine
uniform float reflection_stretch : hint_range(-1.0, 1.0) = 0.1;
uniform float max_reflection_distance : hint_range(0.1, 10.0) = 1.5;
// ---> PARAMETRI RIPPLES <---
group_uniforms Ripple_Settings;
uniform vec4 ripple_color : source_color = vec4(1.0, 1.0, 1.0, 0.7);
uniform float ripple_density : hint_range(0.0, 1.0) = 0.05;
uniform float ripple_scale : hint_range(0.5, 20.0) = 3.0;
uniform float ripple_speed : hint_range(0.1, 5.0) = 0.8;
uniform float ripple_thickness : hint_range(0.001, 0.1) = 0.02;
uniform sampler2D depth_texture : hint_depth_texture, filter_linear_mipmap;
varying vec2 world_pos_xz;
varying vec2 local_uv;
void vertex() {
// Salviamo la posizione XZ e la UV locale per l'effetto specchio
world_pos_xz = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xz;
local_uv = UV;
}
void fragment() {
// --- 1. LOGICA PROFONDITÀ (Beer's Law) ---
float depth = texture(depth_texture, SCREEN_UV).r;
vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth);
vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
view.xyz /= view.w;
float linear_depth = -view.z;
float depth_difference = linear_depth + VERTEX.z;
float water_depth_gradient = exp(-depth_difference * beer_law_factor);
vec4 base_water = mix(deep_water_color, shallow_water_color, water_depth_gradient);
// --- 2. LOGICA RIPPLES CASUALI ---
vec2 pos = world_pos_xz * ripple_scale;
vec2 cell = floor(pos);
vec2 local_pos = fract(pos) - 0.5;
float random_val = fract(sin(dot(cell, vec2(12.9898, 78.233))) * 43758.5453);
float is_active_cell = step(1.0 - ripple_density, random_val);
float ring = 0.0;
if (is_active_cell > 0.0) {
float local_time = fract(TIME * ripple_speed + random_val * 10.0);
float dist = length(local_pos);
ring = smoothstep(local_time - ripple_thickness, local_time, dist)
- smoothstep(local_time, local_time + ripple_thickness, dist);
ring *= (1.0 - local_time);
}
// --- 3. FAKE REFLECTION SPECCHIATA E A CORTO RAGGIO ---
vec2 ref_uv = SCREEN_UV;
// Il trucco per "capovolgere" il riflesso usando l'UV del piano dell'acqua
ref_uv.y -= reflection_offset + (local_uv.y * reflection_stretch);
// Distorciamo il riflesso dove ci sono i ripples
ref_uv += ring * 0.01;
vec3 screen_ref = textureLod(screen_texture, ref_uv, 0.0).rgb;
// Maschera di distanza (limita il riflesso solo alle cose vicine)
float ref_depth_raw = texture(depth_texture, ref_uv).r;
vec3 ref_ndc = vec3(ref_uv * 2.0 - 1.0, ref_depth_raw);
vec4 ref_view = INV_PROJECTION_MATRIX * vec4(ref_ndc, 1.0);
ref_view.xyz /= ref_view.w;
float ref_linear_depth = -ref_view.z;
float distance_from_water = abs(ref_linear_depth - (-VERTEX.z));
float reflection_mask = 1.0 - smoothstep(0.0, max_reflection_distance, distance_from_water);
float is_sky = step(ref_depth_raw, 0.00001); // Protezione anti-cielo
reflection_mask *= (1.0 - is_sky);
// --- 4. MIX FINALE ---
vec3 final_rgb = mix(base_water.rgb, screen_ref, reflection_strength * reflection_mask);
final_rgb = mix(final_rgb, ripple_color.rgb, ring * ripple_color.a);
ALBEDO = final_rgb;
// Alpha base dell'acqua + opacità dei ripples per farli sempre risaltare
ALPHA = mix(0.98, 0.4, water_depth_gradient);
ALPHA = clamp(ALPHA + (ring * ripple_color.a), 0.0, 1.0);
ROUGHNESS = 1.0;
SPECULAR = 0.0;
}

View File

@@ -0,0 +1 @@
uid://064bybt6le3h

View File

@@ -66,15 +66,15 @@ func _init(wind: GPUParticles3D, snow: GPUParticles3D,
thunder_sounds = thundersounds
rain_sounds = rainsounds
set_rain()
init_rain()
set_fireflies()
init_fireflies()
set_wind()
init_wind()
set_snow()
init_snow()
set_lightning()
init_lightning()
create_sound_players()
@@ -124,7 +124,7 @@ func _process(delta: float) -> void:
timer_next_lightning -= delta
if timer_next_lightning <= 0.0:
start_lightning()
set_lightning_timer()
init_lightning_timer()
else:
rain_intensity = move_toward(rain_intensity, 0.0, delta * 0.5)
@@ -281,7 +281,7 @@ func toggle_fireflies(value: bool):
particles_fireflies.emitting = thereare_fireflies and is_night
#disable fireflies and set default values and materials
func set_fireflies():
func init_fireflies():
if particles_fireflies:
particles_fireflies.visible = true
particles_fireflies.emitting = false
@@ -299,8 +299,10 @@ func toggle_wind(value: bool):
if particles_wind:
particles_wind.emitting = is_windy
_apply_wind_state()
#disable wind and set default values and materials
func set_wind():
func init_wind():
if particles_wind:
particles_wind.visible = true
particles_wind.emitting = false
@@ -312,26 +314,36 @@ func set_wind():
if environment_config:
_apply_cloud_config()
_apply_wind_config()
_apply_dust_config()
func _apply_wind_config() -> void:
RenderingServer.global_shader_parameter_set("global_wind_speed", environment_config.wind_speed)
RenderingServer.global_shader_parameter_set("global_wind_direction", environment_config.wind_direction)
RenderingServer.global_shader_parameter_set("global_wind_scale", environment_config.wind_scale)
RenderingServer.global_shader_parameter_set("global_wind_strength", environment_config.wind_strength)
if particles_wind:
var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial
if proc_mat_wind:
var wind_direction_3d := Vector3(environment_config.wind_direction.x, 0.0, environment_config.wind_direction.y)
if wind_direction_3d.length_squared() > 0.0:
var wind_axis := wind_direction_3d.normalized()
var wind_cross := wind_axis.cross(Vector3.UP)
if wind_cross.length_squared() == 0.0:
wind_cross = Vector3.FORWARD
else:
wind_cross = wind_cross.normalized()
var wind_up := wind_cross.cross(wind_axis).normalized()
proc_mat_wind.direction = wind_axis
particles_wind.global_transform = Transform3D(Basis(wind_cross, wind_axis, wind_up), particles_wind.global_position)
RenderingServer.global_shader_parameter_set("global_wind_direction", environment_config.wind_direction)
RenderingServer.global_shader_parameter_set("global_wind_scale", environment_config.wind_scale)
if particles_wind:
var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial
if proc_mat_wind:
var wind_direction_3d := Vector3(environment_config.wind_direction.x, 0.0, environment_config.wind_direction.y)
if wind_direction_3d.length_squared() > 0.0:
var wind_axis := wind_direction_3d.normalized()
var wind_cross := wind_axis.cross(Vector3.UP)
if wind_cross.length_squared() == 0.0:
wind_cross = Vector3.FORWARD
else:
wind_cross = wind_cross.normalized()
var wind_up := wind_cross.cross(wind_axis).normalized()
proc_mat_wind.direction = wind_axis
particles_wind.global_transform = Transform3D(Basis(wind_cross, wind_axis, wind_up), particles_wind.global_position)
_apply_wind_state()
func _apply_wind_state() -> void:
if environment_config == null:
return
var active_wind_speed := environment_config.wind_speed if is_windy else 0.0
var active_wind_strength := environment_config.wind_strength if is_windy else 0.0
RenderingServer.global_shader_parameter_set("global_wind_speed", active_wind_speed)
RenderingServer.global_shader_parameter_set("global_wind_strength", active_wind_strength)
func _apply_cloud_config() -> void:
var dir = environment_config.wind_direction
@@ -366,7 +378,7 @@ func toggle_storm(value: bool):
is_storm = value
#set lightning
func set_lightning():
func init_lightning():
lightning_light.name = "Lightning Light"
lightning_light.transform = Transform3D(
Vector3(-0.6238797, -0.342596, 0.7024259), # asse X
@@ -381,7 +393,7 @@ func set_lightning():
add_child(lightning_light)
create_lightning_sprite()
set_lightning_timer()
init_lightning_timer()
func create_lightning_sprite():
lightning_sprite = Sprite3D.new()
@@ -406,7 +418,7 @@ func create_lightning_sprite():
add_child(lightning_sprite)
#set next lightning timer
func set_lightning_timer():
func init_lightning_timer():
timer_next_lightning = randf_range(environment_config.lightning_min_time, environment_config.lightning_max_time)
func start_lightning():
@@ -460,7 +472,7 @@ func _play_thunder_delayed(delay: float):
#region Rain
#disable rain
func set_rain():
func init_rain():
if particles_rain:
particles_rain.visible = true
particles_rain.emitting = false
@@ -607,10 +619,10 @@ func toggle_snow(value: bool):
if snow_tween and snow_tween.is_valid():
snow_tween.kill()
snow_tween = create_tween()
snow_tween.tween_method(set_snow_amount, actual_snow_amount, target_snow_amount, environment_config.snow_transaction_time)
snow_tween.tween_method(init_snow_amount, actual_snow_amount, target_snow_amount, environment_config.snow_transaction_time)
#disable snow and set default values and shader
func set_snow(value: float = 0.0):
func init_snow(value: float = 0.0):
actual_snow_amount = value
RenderingServer.global_shader_parameter_set("global_snow_amount", value)
@@ -625,7 +637,7 @@ func set_snow(value: float = 0.0):
RenderingServer.global_shader_parameter_set("global_snow_start_time", -1.0)
RenderingServer.global_shader_parameter_set("global_snow_melt_time", -1.0)
func set_snow_amount(value: float):
func init_snow_amount(value: float):
actual_snow_amount = value
RenderingServer.global_shader_parameter_set("global_snow_amount", value)
@@ -663,4 +675,20 @@ func ApplyPostProcessBlurConfig() -> void:
if blur_material:
blur_material.set_shader_parameter("blur_amount", environment_config.blur_amount)
func _apply_dust_config() -> void:
var dust_color: Color = environment_config.dust_color
var dust_speed: float = environment_config.dust_speed
var dust_density: float = environment_config.dust_density
var dust_size_min: float = environment_config.dust_size_min
var dust_size_max: float = environment_config.dust_size_max
if environment_dust:
var dust_mat = environment_dust.material as ShaderMaterial
if dust_mat:
dust_mat.set_shader_parameter("dust_color", dust_color)
dust_mat.set_shader_parameter("dust_speed", dust_speed)
dust_mat.set_shader_parameter("dust_density", dust_density)
dust_mat.set_shader_parameter("dust_size_min", dust_size_min)
dust_mat.set_shader_parameter("dust_size_max", dust_size_max)
#endregion