add snow management for materials

This commit is contained in:
2026-03-31 14:28:10 +02:00
parent 2f4fd27dfd
commit ade67a3b90
26 changed files with 693 additions and 97 deletions

View File

@@ -23,8 +23,8 @@ uniform float fade_start : hint_range(10.0, 1000.0) = 150.0;
uniform float fade_end : hint_range(50.0, 2000.0) = 300.0;
group_uniforms Fade_Height;
uniform float height_fade_start : hint_range(0.0, 500.0) = 10.0; // Inizia a svanire sopra i 10 metri
uniform float height_fade_end : hint_range(0.0, 1000.0) = 50.0; // Scompare del tutto a 50 metri di altezza
uniform float height_fade_start : hint_range(0.0, 500.0) = 10.0; // Start fade over 10m
uniform float height_fade_end : hint_range(0.0, 1000.0) = 50.0; // Disappear over 50m
void vertex() {
POSITION = vec4(VERTEX.xy, 1.0, 1.0);

View File

@@ -6,7 +6,6 @@
[ext_resource type="Shader" uid="uid://cq4vlcj8cuvge" path="res://core/daynight/fog.gdshader" id="2_r4tfj"]
[ext_resource type="PackedScene" uid="uid://dyxvcf2l8ba5x" path="res://core/daynight/god_ray.tscn" id="5_411rw"]
[ext_resource type="Shader" uid="uid://bb1jjwe31fl7o" path="res://core/daynight/wind.gdshader" id="5_djqkg"]
[ext_resource type="Shader" uid="uid://bwf4wjp802x8j" path="res://core/daynight/environment_dust.gdshader" id="7_ik86e"]
[ext_resource type="Material" uid="uid://codq5gx71rj4o" path="res://core/daynight/environment_dust_material.tres" id="8_amaf0"]
[ext_resource type="Shader" uid="uid://bkn6eqgbn37jx" path="res://core/daynight/blur.gdshader" id="9_amaf0"]
[ext_resource type="Shader" uid="uid://b5wa82soyhsqm" path="res://core/daynight/environment_shadows.gdshader" id="10_tuauy"]
@@ -113,6 +112,10 @@ point_count = 3
[sub_resource type="ShaderMaterial" id="ShaderMaterial_cer0u"]
render_priority = 0
shader = ExtResource("5_djqkg")
shader_parameter/wave_frequency = 1.0
shader_parameter/base_amplitude = 0.5
shader_parameter/secondary_ratio = 0.6
shader_parameter/time_scale_base = 3.0
[sub_resource type="TubeTrailMesh" id="TubeTrailMesh_vo82p"]
material = SubResource("ShaderMaterial_cer0u")
@@ -123,8 +126,8 @@ section_length = 2.0
curve = SubResource("Curve_b5atu")
[sub_resource type="Gradient" id="Gradient_b5atu"]
offsets = PackedFloat32Array(0, 0.49019608, 1)
colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0)
offsets = PackedFloat32Array(0, 0.1, 0.9, 1)
colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_ruhh7"]
gradient = SubResource("Gradient_b5atu")
@@ -182,17 +185,6 @@ particles_anim_loop = false
material = SubResource("StandardMaterial3D_ruhh7")
size = Vector2(0.05, 0.8)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ik86e"]
shader = ExtResource("7_ik86e")
shader_parameter/dust_color = Color(1, 0.9, 0.7, 0.6)
shader_parameter/wind_velocity = Vector2(-0.2, 0.05)
shader_parameter/wind_oscillation = 0.3
shader_parameter/dust_speed = 0.15
shader_parameter/size_min = 0.02
shader_parameter/size_max = 0.2
shader_parameter/dust_density = 1.0
shader_parameter/solid_core = 0.1
[sub_resource type="ShaderMaterial" id="ShaderMaterial_kavln"]
shader = ExtResource("9_amaf0")
shader_parameter/blur_amount = 0.70000003325
@@ -227,15 +219,15 @@ shader_parameter/height_fade_end = 50.0
[node name="EnvironmentManager" type="Node3D" unique_id=1611939731 node_paths=PackedStringArray("particles_wind", "particles_snow", "particles_fireflies", "particles_rain", "fog_overlay", "environment_dust", "blur", "environment_shadows")]
script = ExtResource("1_wecen")
environment_config = SubResource("Resource_r4tfj")
godray = ExtResource("5_411rw")
particles_wind = NodePath("Particles_Wind")
particles_snow = NodePath("Particles_Snow")
particles_fireflies = NodePath("Particles_Fireflies")
particles_rain = NodePath("Particles_Rain")
fog_overlay = NodePath("FogOverlay")
godray = ExtResource("5_411rw")
fog_overlay = NodePath("")
environment_dust = NodePath("EnvironmentDust")
blur = NodePath("Blur")
environment_shadows = NodePath("EnvironmentShadows")
environment_shadows = NodePath("EnvironmentCloudsShadows")
[node name="Particles_Fireflies" type="GPUParticles3D" parent="." unique_id=947538133]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 0)
@@ -256,6 +248,7 @@ draw_pass_1 = SubResource("TubeTrailMesh_vo82p")
[node name="Particles_Snow" type="GPUParticles3D" parent="." unique_id=1877039876]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 30, 0)
extra_cull_margin = 16384.0
emitting = false
amount = 2000
lifetime = 4.0
@@ -272,15 +265,6 @@ lifetime = 1.5
process_material = SubResource("ParticleProcessMaterial_b5atu")
draw_pass_1 = SubResource("QuadMesh_cer0u")
[node name="FogOverlay" type="ColorRect" parent="." unique_id=1694754918]
material = SubResource("ShaderMaterial_ik86e")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[node name="EnvironmentDust" type="ColorRect" parent="." unique_id=1245348005]
material = ExtResource("8_amaf0")
anchors_preset = 15
@@ -299,7 +283,7 @@ grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
[node name="EnvironmentShadows" type="MeshInstance3D" parent="." unique_id=159549433]
[node name="EnvironmentCloudsShadows" type="MeshInstance3D" parent="." unique_id=159549433]
extra_cull_margin = 16384.0
mesh = SubResource("QuadMesh_sxgg7")
surface_material_override/0 = SubResource("ShaderMaterial_oqt1s")

View File

@@ -29,6 +29,11 @@ var day_time: float = 0.0
func _ready() -> void:
#set noise texture 2d to materials in special group
ApplyWindNoiseToMaterials()
#set snow shader to materials in special group
ApplySnowShaderToMaterials()
if day_night_controller == null:
day_night_controller = DayNightController.new(
environment_config
@@ -56,6 +61,24 @@ func _ready() -> void:
weather_controller.name = "WeatherController"
add_child(weather_controller)
func ApplyWindNoiseToMaterials():
var noise_tex = preload("res://core/daynight/noise.tres")
for node in get_tree().get_nodes_in_group("wind_materials"):
if node is GeometryInstance3D:
node.material_override.set_shader_parameter("wind_noise", noise_tex)
func ApplySnowShaderToMaterials():
var snow_shader = preload("res://core/daynight/snow_overlay.tres")
#apply to node and childs
for node in get_tree().get_nodes_in_group("snow_materials"):
if node is GeometryInstance3D:
node.material_overlay = snow_shader
else:
for child in node.get_children():
if child is GeometryInstance3D:
child.material_overlay = snow_shader
func select_day_time(normalized_time: float) -> void:
# 0.0→0.25 = alba: day_time 1.0→2.0 (night colors → morning colors)
# 0.25→0.5 = giorno: day_time 2.0→2.0 (stays morning/afternoon)

11
core/daynight/noise.tres Normal file
View File

@@ -0,0 +1,11 @@
[gd_resource type="NoiseTexture2D" format=3 uid="uid://bpswbjh4jj1ou"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_xa3jw"]
noise_type = 3
seed = 1
frequency = 0.0158
metadata/_preview_in_3d_space_ = true
[resource]
noise = SubResource("FastNoiseLite_xa3jw")
seamless = true

View File

@@ -1,19 +1,30 @@
shader_type spatial;
render_mode blend_mix, depth_draw_opaque;
render_mode blend_mix, depth_draw_never;
global uniform float global_snow_amount;
uniform vec4 snow_color : source_color = vec4(0.95, 0.98, 1.0, 1.0);
global uniform float global_snow_start_time = -1.0;
global uniform float global_snow_accumulation_speed = 0.1;
global uniform float global_snow_melt_time = -1.0;
global uniform float global_snow_melt_speed = 0.1;
global uniform float global_snow_threshold = 0.5;
global uniform vec4 global_snow_color = vec4(0.92, 0.96, 1.0, 1.0);
void fragment() {
vec3 world_normal = (INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz;
float up_dot = dot(world_normal, vec3(0.0, 1.0, 0.0));
float snow_mask = smoothstep(1.0 - global_snow_amount, 1.1 - global_snow_amount, up_dot);
snow_mask *= step(0.01, global_snow_amount);
float snow_amount = 0.0;
if (global_snow_start_time >= 0.0) {
snow_amount = clamp((TIME - global_snow_start_time) * global_snow_accumulation_speed, 0.0, 1.0);
}
ALBEDO = snow_color.rgb;
ALPHA = snow_mask;
ROUGHNESS = 0.3;
SPECULAR = 0.5;
}
if (global_snow_melt_time >= 0.0) {
float melt = clamp((TIME - global_snow_melt_time) * global_snow_melt_speed, 0.0, 1.0);
snow_amount = snow_amount * (1.0 - melt);
}
vec3 world_normal = (INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz;
float facing_up = clamp(world_normal.y, 0.0, 1.0);
float snow_factor = smoothstep(global_snow_threshold, 1.0, facing_up) * snow_amount;
ALBEDO = global_snow_color.rgb;
ROUGHNESS = 0.15;
METALLIC = 0.0;
ALPHA = snow_factor;
}

View File

@@ -0,0 +1,7 @@
[gd_resource type="ShaderMaterial" format=3 uid="uid://bn4onuaqif5q3"]
[ext_resource type="Shader" uid="uid://cjd72g8cgjear" path="res://core/daynight/snow.gdshader" id="1_vwtmf"]
[resource]
render_priority = 0
shader = ExtResource("1_vwtmf")

View File

@@ -136,6 +136,11 @@ func _process(delta: float) -> void:
var final_sky_horizon = base_sky_horizon.lerp(base_sky_horizon * environment_config.rain_mode_color, rain_intensity)
var final_fog_color = base_fog_color.lerp(base_fog_color * environment_config.rain_mode_color, rain_intensity)
var final_fog_density = lerp(base_fog_density, base_fog_density * 4.0, rain_intensity)
final_tint = final_tint.lerp(final_tint * environment_config.snow_mode_color, actual_snow_amount)
final_sky_top = final_sky_top.lerp(final_sky_top * environment_config.snow_mode_color, actual_snow_amount)
final_sky_horizon = final_sky_horizon.lerp(final_sky_horizon * environment_config.snow_mode_color, actual_snow_amount)
final_fog_color = final_fog_color.lerp(final_fog_color * environment_config.snow_mode_color, actual_snow_amount)
#Shader parameters for global trunk_shader
var final_grad_top = base_grad_top.lerp(base_grad_top * environment_config.rain_mode_color, rain_intensity)
@@ -257,6 +262,13 @@ func set_wind():
if environment_config:
_apply_cloud_config()
_apply_wind_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)
func _apply_cloud_config() -> void:
var dir = environment_config.wind_direction
@@ -272,10 +284,16 @@ func _apply_cloud_config() -> void:
sky_mat.set_shader_parameter("cloud_scale", cloud_scale)
sky_mat.set_shader_parameter("cloud_speed", cloud_speed)
if environment_shadows and environment_shadows.material_override:
environment_shadows.material_override.set_shader_parameter("direction", dir)
environment_shadows.material_override.set_shader_parameter("cloud_scale", cloud_scale * envshadows_scale_rate)
environment_shadows.material_override.set_shader_parameter("cloud_speed", cloud_speed * envshadows_speed_rate)
var env_shadow_mat = environment_shadows.get_surface_override_material(0) if environment_shadows else null
if env_shadow_mat:
env_shadow_mat.set_shader_parameter("direction", dir)
env_shadow_mat.set_shader_parameter("cloud_scale", cloud_scale * envshadows_scale_rate)
env_shadow_mat.set_shader_parameter("cloud_speed", cloud_speed * envshadows_speed_rate)
if environment_config.material_clouds:
environment_config.material_clouds.set_shader_parameter("direction", dir)
environment_config.material_clouds.set_shader_parameter("cloud_scale", cloud_scale * envshadows_scale_rate)
environment_config.material_clouds.set_shader_parameter("cloud_speed", cloud_speed * envshadows_speed_rate)
#endregion
@@ -444,51 +462,55 @@ func toggle_snow(value: bool):
particles_snow.emitting = true
snow_particles_tween = create_tween()
snow_particles_tween.tween_property(particles_snow, "amount_ratio", 1.0, environment_config.snow_fade_time)
start_snow_accumulation()
else:
snow_particles_tween = create_tween()
snow_particles_tween.tween_property(particles_snow, "amount_ratio", 0.0, environment_config.snow_fade_time)
snow_particles_tween.tween_callback(func():
particles_snow.emitting = false)
# Accumulo neve sulle superfici
var target_snow: float = 1.0 if is_snowing else 0.0
start_snow_melt()
var target_snow_amount: float = 1.0 if is_snowing else 0.0
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, environment_config.snow_transaction_time)
if fog_overlay and fog_overlay.material:
var target_opacity: float = 0.5 if is_snowing else 0.1
var target_radius: float = 0.350 if is_snowing else 0.465
if cold_tween and cold_tween.is_valid():
cold_tween.kill()
cold_tween = create_tween()
cold_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
cold_tween.set_parallel(true)
cold_tween.tween_property(fog_overlay.material, "shader_parameter/max_opacity", target_opacity, 4.0)
cold_tween.tween_property(fog_overlay.material, "shader_parameter/clear_center_radius", target_radius, 4.0)
snow_tween.tween_method(set_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):
actual_snow_amount = value
actual_snow_amount = value
RenderingServer.global_shader_parameter_set("global_snow_amount", value)
if particles_snow:
particles_snow.emitting = false
particles_snow.amount = environment_config.snow_amount
if environment_config:
RenderingServer.global_shader_parameter_set("global_snow_threshold", environment_config.snow_threshold)
RenderingServer.global_shader_parameter_set("global_snow_color", environment_config.snow_color)
RenderingServer.global_shader_parameter_set("global_snow_accumulation_speed", environment_config.snow_accumulation_speed)
RenderingServer.global_shader_parameter_set("global_snow_melt_speed", environment_config.snow_melt_speed)
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):
actual_snow_amount = value
actual_snow_amount = value
RenderingServer.global_shader_parameter_set("global_snow_amount", value)
func start_snow_accumulation() -> void:
RenderingServer.global_shader_parameter_set("global_snow_melt_time", -1.0)
RenderingServer.global_shader_parameter_set("global_snow_start_time", Time.get_ticks_msec() / 1000.0)
func start_snow_melt() -> void:
RenderingServer.global_shader_parameter_set("global_snow_melt_time", Time.get_ticks_msec() / 1000.0)
RenderingServer.global_shader_parameter_set("global_snow_melt_speed", environment_config.snow_melt_speed)
#endregion
#region Post-Process
func toggle_fog_overlay(value: bool) -> void:
if fog_overlay:
fog_overlay.visible = value
pass
func toggle_dust(value: bool) -> void:
if environment_dust:

View File

@@ -1,18 +1,31 @@
shader_type spatial;
render_mode unshaded;
/*
uniform float time_scale = 3.0;
uniform float wave_amplitude = 0.5;
uniform float wave_frequency = 1.0;
global uniform float global_wind_speed = 1.0; //0.0 = calm, 1.0 = normal, 2.0+ = strong
global uniform vec2 global_wind_direction = vec2(1.0, 0.0);
uniform float wave_frequency = 1.0;
uniform float base_amplitude = 0.5;
uniform float secondary_ratio = 0.6;
uniform float time_scale_base = 3.0;
void vertex() {
float random_seed_offset = INSTANCE_CUSTOM.x * 100.0;
float scaled_time = (TIME + random_seed_offset) * time_scale;
VERTEX.x += sin(VERTEX.y * wave_frequency + scaled_time) * wave_amplitude;
float random_seed_offset = INSTANCE_CUSTOM.x * 100.0;
float scaled_time = (TIME + random_seed_offset) * (time_scale_base * global_wind_speed);
float amplitude = base_amplitude * global_wind_speed;
vec2 wind_dir = normalize(global_wind_direction);
vec2 wind_perp = vec2(-wind_dir.y, wind_dir.x); //90° perpendicular
float primary_sway = sin(VERTEX.y * wave_frequency + scaled_time) * amplitude;
float secondary_sway = sin(VERTEX.y * wave_frequency * 1.3 + scaled_time * 0.7 + 1.57)
* (amplitude * secondary_ratio);
VERTEX.x += primary_sway * wind_dir.x + secondary_sway * wind_perp.x;
VERTEX.z += primary_sway * wind_dir.y + secondary_sway * wind_perp.y;
}
void fragment() {
ALBEDO = COLOR.rgb;
ALPHA = COLOR.a;
}*/
}