add rain puddle

This commit is contained in:
2026-03-31 23:59:04 +02:00
parent b05abd395f
commit 0be4b503e2
6 changed files with 94 additions and 40 deletions

View File

@@ -230,7 +230,7 @@ blur = NodePath("Blur")
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)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
emitting = false
amount = 60
lifetime = 4.0

View File

@@ -25,6 +25,8 @@ var timer_next_lightning: float = 0.0
var is_raining: bool = false
var rain_intensity: float = 0.0
var rain_tween: Tween
var puddle_tween: Tween
var puddle_amount: float = 0.0
var snow_tween: Tween
var snow_particles_tween: Tween
@@ -81,6 +83,10 @@ func _ready() -> void:
func _process(delta: float) -> void:
_follow_camera()
var is_night = day_time >= 2.5
if particles_fireflies:
particles_fireflies.emitting = thereare_fireflies and is_night
var base_tint: Color
var base_sky_top: Color
@@ -228,8 +234,9 @@ func _follow_camera() -> void:
func toggle_fireflies(value: bool):
thereare_fireflies = value
var is_night = day_time >= 2.5
if particles_fireflies:
particles_fireflies.emitting = thereare_fireflies
particles_fireflies.emitting = thereare_fireflies and is_night
#disable fireflies and set default values and materials
func set_fireflies():
@@ -390,6 +397,11 @@ func set_rain():
if particles_rain:
particles_rain.visible = true
particles_rain.emitting = false
RenderingServer.global_shader_parameter_set("global_rain_puddle_amount", 0.0)
func set_puddle_amount(value: float):
puddle_amount = value
RenderingServer.global_shader_parameter_set("global_rain_puddle_amount", value)
func toggle_rain(value: bool):
is_raining = value
@@ -403,17 +415,24 @@ func toggle_rain(value: bool):
if rain_tween and rain_tween.is_valid():
rain_tween.kill()
if puddle_tween and puddle_tween.is_valid():
puddle_tween.kill()
if is_raining:
particles_rain.amount_ratio = 0.0
particles_rain.emitting = true
rain_tween = create_tween()
rain_tween.tween_property(particles_rain, "amount_ratio", 1.0, environment_config.rain_fade_time)
puddle_tween = create_tween()
puddle_tween.tween_method(set_puddle_amount, puddle_amount, 1.0, environment_config.puddle_form_time)
else:
rain_tween = create_tween()
rain_tween.tween_property(particles_rain, "amount_ratio", 0.0, environment_config.rain_fade_time)
rain_tween.tween_callback(func():
particles_rain.emitting = false
trigger_after_rain())
puddle_tween = create_tween()
puddle_tween.tween_method(set_puddle_amount, puddle_amount, 0.0, environment_config.puddle_dry_time)
func trigger_morning() -> void:
spawn_single_godray()

View File

@@ -1,27 +1,21 @@
shader_type spatial;
render_mode blend_mix, depth_draw_never;
// --- Snow globals ---
//Snow globals
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);
// --- Rain globals ---
global uniform float global_rain_intensity;
// --- Shared ---
uniform sampler2D noise_texture : filter_linear_mipmap, repeat_enable;
// --- Snow params ---
uniform float snow_noise_scale : hint_range(0.01, 1.0) = 0.15;
uniform float snow_edge_softness : hint_range(0.01, 0.5) = 0.2;
uniform float snow_roughness_variation : hint_range(0.0, 0.3) = 0.15;
uniform float snow_color_variation : hint_range(0.0, 0.15) = 0.05;
// --- Rain params ---
//Rain globals
global uniform float global_rain_intensity;
global uniform float global_rain_puddle_amount;
uniform float ripple_scale : hint_range(0.1, 5.0) = 1.5;
uniform float ripple_speed : hint_range(0.5, 5.0) = 2.0;
uniform float ripple_layers : hint_range(1.0, 4.0) = 3.0;
@@ -30,6 +24,10 @@ uniform float streak_speed : hint_range(0.1, 3.0) = 0.8;
uniform float wetness_darkening : hint_range(0.0, 0.5) = 0.25;
uniform float wet_roughness : hint_range(0.0, 0.3) = 0.05;
uniform float rain_normal_strength : hint_range(0.0, 1.0) = 0.4;
uniform float puddle_noise_scale : hint_range(0.01, 0.5) = 0.08;
uniform float puddle_threshold : hint_range(0.0, 0.8) = 0.45;
uniform sampler2D noise_texture : filter_linear_mipmap, repeat_enable;
float ripple_ring(vec2 uv, float time_offset) {
float d = length(uv);
@@ -44,7 +42,7 @@ void fragment() {
float facing_up = clamp(world_normal.y, 0.0, 1.0);
float noise_val = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
// ===================== SNOW =====================
//Snow
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);
@@ -66,7 +64,7 @@ void fragment() {
vec3 snow_albedo = clamp(global_snow_color.rgb + vec3(shade), 0.0, 1.0);
float snow_rough = mix(0.15 - snow_roughness_variation, 0.15 + snow_roughness_variation, noise_val);
// ===================== RAIN =====================
//Rain
float rain_int = clamp(global_rain_intensity, 0.0, 1.0);
float rain_factor = 0.0;
vec3 rain_albedo = vec3(0.0);
@@ -77,11 +75,11 @@ void fragment() {
if (rain_int > 0.01 && facing_up > 0.3) {
float surface_mask = smoothstep(0.3, 0.6, facing_up);
// Slope detection: 0 = flat, 1 = peak at ~30-45 degrees
//Slope detection: 0 = flat, 1 = peak at ~30-45 degrees
float slope_angle = 1.0 - facing_up;
float slope_mask = smoothstep(0.1, 0.25, slope_angle) * smoothstep(0.75, 0.5, slope_angle);
// Ripples on horizontal surfaces
//Ripples on horizontal surfaces
float ripple = 0.0;
for (float i = 0.0; i < ripple_layers; i += 1.0) {
float phase = i * 2.17;
@@ -94,11 +92,11 @@ void fragment() {
}
ripple /= ripple_layers;
// Flowing water on inclined surfaces (30-45 degrees)
//Flowing water on inclined surfaces (30-45 degrees)
vec3 down_dir = normalize(world_normal - vec3(0.0, 1.0, 0.0) * facing_up);
float flow_speed = streak_speed * (1.0 + slope_angle * 2.0);
// Main flow rivulets
//Main flow rivulets
float flow_coord = dot(world_pos, down_dir);
float lateral_coord = dot(world_pos.xz, vec2(-down_dir.z, down_dir.x)) * streak_scale;
vec2 flow_uv = vec2(lateral_coord, flow_coord * streak_scale - TIME * flow_speed);
@@ -106,26 +104,71 @@ void fragment() {
float flow2 = texture(noise_texture, flow_uv * 0.7 + vec2(0.3, TIME * flow_speed * 0.3)).r;
float rivulets = smoothstep(0.3, 0.7, flow_noise) * smoothstep(0.25, 0.6, flow2);
// Accumulation at bottom (lower world_pos.y gets more water)
//Accumulation at bottom (lower world_pos.y gets more water)
float height_factor = texture(noise_texture, world_pos.xz * 0.05).r;
float accumulation = smoothstep(0.6, 0.2, fract(world_pos.y * 0.3 + height_factor * 0.5));
rivulets = mix(rivulets, rivulets + accumulation * 0.3, slope_mask);
float streak = rivulets * slope_mask;
// Blend ripples (flat) and streaks (inclined)
//Blend ripples (flat) and streaks (inclined)
float flat_weight = smoothstep(0.3, 0.15, slope_angle);
float effect = mix(streak, ripple, flat_weight) * rain_int * surface_mask;
float darkness = wetness_darkening * rain_int * surface_mask;
vec2 normal_offset = vec2(dFdx(effect), dFdy(effect)) * rain_normal_strength;
rain_normal = vec3(normal_offset.x + 0.5, normal_offset.y + 0.5, 1.0);
rain_albedo = vec3(0.02, 0.02, 0.03);
rain_metallic = 0.3 * rain_int;
rain_factor = effect * 0.8 + darkness;
rain_albedo = vec3(0.05, 0.05, 0.06);
rain_metallic = 0.15 * rain_int;
rain_factor = darkness + effect * 0.15;
}
//Puddles
float puddle_factor = 0.0;
float puddle_amt = clamp(global_rain_puddle_amount, 0.0, 1.0);
if (puddle_amt > 0.01 && facing_up > 0.85) {
float puddle_mask = smoothstep(0.85, 0.95, facing_up);
// Large-scale distribution: sparse zones where puddles can form
float distribution = texture(noise_texture, world_pos.xz * puddle_noise_scale * 0.15 + vec2(13.7, 7.3)).r;
float sparse_mask = smoothstep(0.55 - puddle_amt * 0.3, 0.35 - puddle_amt * 0.2, distribution);
// Multi-scale noise for organic puddle shapes
float n1 = texture(noise_texture, world_pos.xz * puddle_noise_scale).r;
float n2 = texture(noise_texture, world_pos.xz * puddle_noise_scale * 2.7 + vec2(5.7, 3.1)).r;
float n3 = texture(noise_texture, world_pos.xz * puddle_noise_scale * 5.3 + vec2(11.2, 8.9)).r;
float puddle_noise = n1 * 0.5 + n2 * 0.3 + n3 * 0.2;
// Puddles expand as puddle_amount increases
float threshold = puddle_threshold + (1.0 - puddle_amt) * 0.35;
float puddle_shape = smoothstep(threshold, threshold - 0.08, puddle_noise);
puddle_factor = puddle_shape * sparse_mask * puddle_mask * puddle_amt;
// Ripples inside puddles
if (puddle_factor > 0.1 && rain_int > 0.01) {
float puddle_ripple = 0.0;
for (float i = 0.0; i < 2.0; i += 1.0) {
float phase = i * 3.14;
vec2 r_uv = fract(world_pos.xz * ripple_scale * 0.8 + vec2(phase * 0.7)) - 0.5;
puddle_ripple += ripple_ring(r_uv, phase * 2.3);
}
puddle_ripple *= 0.5 * rain_int;
vec2 p_normal_offset = vec2(dFdx(puddle_ripple), dFdy(puddle_ripple)) * 0.6;
rain_normal = vec3(p_normal_offset.x + 0.5, p_normal_offset.y + 0.5, 1.0);
}
}
//Combine
//Puddles override rain when stronger
if (puddle_factor > rain_factor) {
rain_albedo = vec3(0.01, 0.01, 0.02);
rain_rough = 0.02;
rain_metallic = 0.5 * puddle_amt;
rain_factor = puddle_factor;
}
// ===================== COMBINE =====================
if (snow_factor > rain_factor) {
ALBEDO = snow_albedo;
ROUGHNESS = snow_rough;

View File

@@ -1,21 +1,7 @@
[gd_resource type="ShaderMaterial" format=3]
[gd_resource type="ShaderMaterial" format=3 uid="uid://cn5vw7unbqgve"]
[ext_resource type="Shader" path="res://core/daynight/weather_overlay.gdshader" id="1_weather"]
[ext_resource type="NoiseTexture2D" uid="uid://bpswbjh4jj1ou" path="res://core/daynight/noise.tres" id="2_noise"]
[ext_resource type="Shader" uid="uid://dh3j2jp6defuk" path="res://core/daynight/weather_overlay.gdshader" id="1_weather"]
[resource]
render_priority = 0
shader = ExtResource("1_weather")
shader_parameter/noise_texture = ExtResource("2_noise")
shader_parameter/snow_noise_scale = 0.15
shader_parameter/snow_edge_softness = 0.2
shader_parameter/snow_roughness_variation = 0.15
shader_parameter/snow_color_variation = 0.05
shader_parameter/ripple_scale = 1.5
shader_parameter/ripple_speed = 2.0
shader_parameter/ripple_layers = 3.0
shader_parameter/streak_scale = 2.0
shader_parameter/streak_speed = 0.8
shader_parameter/wetness_darkening = 0.25
shader_parameter/wet_roughness = 0.05
shader_parameter/rain_normal_strength = 0.4

View File

@@ -73,6 +73,8 @@ extends Resource
@export_group("Rain")
@export var rain_mode_color: Color = Color(0.5, 0.6, 0.7, 1.0)
@export var rain_fade_time: float = 5.0
@export var puddle_form_time: float = 15.0
@export var puddle_dry_time: float = 20.0
@export_group("Lightning and Thunders")
@export var lightning_min_time: float = 5.0

View File

@@ -103,3 +103,7 @@ global_rain_intensity={
"type": "float",
"value": 0.0
}
global_rain_puddle_amount={
"type": "float",
"value": 0.0
}