improve snow
This commit is contained in:
@@ -50,7 +50,7 @@ const RIVER_NEIGHBOUR_OFFSETS: Dictionary = {
|
||||
#aumentare generazione a 3000 o 4000
|
||||
#Se ci sono micro-scatti:
|
||||
#abbassare generazione a 1000 o 1500
|
||||
#Se i fili appaiono in ritardo:
|
||||
"res://tgcc/chunk/railway/scene/chunk_railway_curve_2.tscn"#Se i fili appaiono in ritardo:
|
||||
#aumentare wire a 1500 o 2000
|
||||
#Se il cleanup causa scatti:
|
||||
#abbassare cleanup a 500
|
||||
|
||||
@@ -3,7 +3,7 @@ extends Node3D
|
||||
|
||||
const NOISE_TEXTURE: Texture2D = preload("res://core/daynight/noise.tres")
|
||||
const WEATHER_SHADER: Material = preload("res://core/daynight/weather_overlay.tres")
|
||||
const DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME: int = 2 #how many update of the environment (apply materials) will be done per frame
|
||||
const DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME: int = 32 #how many update of the environment (apply materials) will be done per frame
|
||||
|
||||
@export var environment_config: EnvironmentConfig
|
||||
|
||||
@@ -80,6 +80,9 @@ func _ready() -> void:
|
||||
func _process(_delta: float) -> void:
|
||||
_process_pending_environment_nodes()
|
||||
|
||||
func flush_pending_environment_nodes() -> void:
|
||||
_process_pending_environment_nodes(-1)
|
||||
|
||||
func _on_tree_node_added(node: Node) -> void:
|
||||
if node.is_in_group("wind_node") or node.is_in_group("weather_node") or node.is_in_group("weather_vegetables_node"):
|
||||
_queue_dynamic_environment_node(node)
|
||||
@@ -108,10 +111,10 @@ func _queue_dynamic_environment_node(node: Node) -> void:
|
||||
|
||||
pending_environment_nodes[node.get_instance_id()] = node
|
||||
|
||||
func _process_pending_environment_nodes() -> void:
|
||||
func _process_pending_environment_nodes(max_nodes: int = DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME) -> void:
|
||||
var processed = 0
|
||||
for node_id in pending_environment_nodes.keys():
|
||||
if processed >= DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME:
|
||||
if max_nodes >= 0 and processed >= max_nodes:
|
||||
break
|
||||
|
||||
var node = pending_environment_nodes[node_id]
|
||||
|
||||
@@ -7,6 +7,7 @@ global uniform float global_snow_melt_time = -1.0;
|
||||
global uniform float global_snow_melt_speed = 0.1;
|
||||
global uniform float global_snow_amount = 0.0;
|
||||
global uniform vec4 global_snow_color = vec4(0.92, 0.96, 1.0, 1.0);
|
||||
const float SNOW_VISUAL_RESPONSE = 0.55;
|
||||
|
||||
uniform float max_height : hint_range(0.02, 1.0) = 0.2;
|
||||
uniform float half_width : hint_range(0.01, 20.0) = 1.0;
|
||||
@@ -68,10 +69,14 @@ float get_snow_amount() {
|
||||
return snow_amount;
|
||||
}
|
||||
|
||||
float get_visual_snow_amount(float snow_amount) {
|
||||
return pow(clamp(snow_amount, 0.0, 1.0), SNOW_VISUAL_RESPONSE);
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
vec3 base_vertex = VERTEX;
|
||||
vec3 world_pos = (MODEL_MATRIX * vec4(base_vertex, 1.0)).xyz;
|
||||
float snow_amount = get_snow_amount();
|
||||
float snow_amount = get_visual_snow_amount(get_snow_amount());
|
||||
float noise_val = fbm(world_pos.xz * noise_scale);
|
||||
float thickness = max_height * snow_amount * mix(
|
||||
1.0 - noise_strength,
|
||||
|
||||
@@ -3,6 +3,9 @@ extends Node
|
||||
|
||||
signal wind_parameters_changed(speed: float, strength: float, fade: float, direction: Vector2)
|
||||
|
||||
const SNOW_ACCUMULATION_DELAY: float = 4.0
|
||||
const SNOW_ACCUMULATION_DELAY_THRESHOLD: float = 0.01
|
||||
|
||||
var thunder_audio_player: AudioStreamPlayer
|
||||
var thunder_sounds: Array[AudioStream]
|
||||
var rain_sounds: Array[AudioStream]
|
||||
@@ -836,6 +839,8 @@ func toggle_snow(value: bool):
|
||||
|
||||
if is_snowing and is_raining:
|
||||
toggle_rain(false)
|
||||
|
||||
var snow_accumulation_delay: float = _get_snow_accumulation_delay() if is_snowing else 0.0
|
||||
|
||||
# Fade particelle neve
|
||||
if particles_snow:
|
||||
@@ -849,7 +854,7 @@ func toggle_snow(value: bool):
|
||||
snow_particles_tween = create_tween()
|
||||
snow_particles_tween.tween_property(particles_snow, "amount_ratio", 1.0, environment_config.snow_fade_time)
|
||||
|
||||
start_snow_accumulation()
|
||||
start_snow_accumulation(snow_accumulation_delay)
|
||||
else:
|
||||
snow_particles_tween = create_tween()
|
||||
snow_particles_tween.tween_property(particles_snow, "amount_ratio", 0.0, environment_config.snow_fade_time)
|
||||
@@ -864,6 +869,8 @@ func toggle_snow(value: bool):
|
||||
snow_weather_tween.kill()
|
||||
var snow_amount_transition_duration: float = _get_snow_amount_transition_duration(is_snowing)
|
||||
snow_tween = create_tween()
|
||||
if is_snowing and snow_accumulation_delay > 0.0:
|
||||
snow_tween.tween_interval(snow_accumulation_delay)
|
||||
snow_tween.tween_method(
|
||||
init_snow_amount,
|
||||
actual_snow_amount,
|
||||
@@ -928,14 +935,26 @@ func init_snow_amount(value: float):
|
||||
func init_snow_weather_amount(value: float):
|
||||
snow_weather_amount = value
|
||||
|
||||
func start_snow_accumulation() -> void:
|
||||
func start_snow_accumulation(delay: float = 0.0) -> 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)
|
||||
RenderingServer.global_shader_parameter_set("global_snow_start_time", Time.get_ticks_msec() / 1000.0 + delay)
|
||||
_flush_pending_weather_materials()
|
||||
|
||||
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)
|
||||
|
||||
func _get_snow_accumulation_delay() -> float:
|
||||
if actual_snow_amount > SNOW_ACCUMULATION_DELAY_THRESHOLD:
|
||||
return 0.0
|
||||
|
||||
return SNOW_ACCUMULATION_DELAY
|
||||
|
||||
func _flush_pending_weather_materials() -> void:
|
||||
var environment_manager := get_parent()
|
||||
if environment_manager != null and environment_manager.has_method("flush_pending_environment_nodes"):
|
||||
environment_manager.call("flush_pending_environment_nodes")
|
||||
|
||||
func _get_snow_amount_transition_duration(is_accumulating: bool) -> float:
|
||||
if environment_config == null:
|
||||
return 0.0
|
||||
|
||||
@@ -16,6 +16,7 @@ global uniform float global_snow_cap_flatness_start = 0.72;
|
||||
global uniform float global_snow_cap_flatness_end = 0.96;
|
||||
global uniform float global_snow_cap_noise_scale = 0.22;
|
||||
global uniform float global_snow_cap_noise_strength = 0.18;
|
||||
const float SNOW_VISUAL_RESPONSE = 0.55;
|
||||
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;
|
||||
@@ -86,6 +87,18 @@ float get_snow_progress() {
|
||||
return snow_progress;
|
||||
}
|
||||
|
||||
float get_visual_snow_progress(float snow_progress) {
|
||||
return pow(clamp(snow_progress, 0.0, 1.0), SNOW_VISUAL_RESPONSE);
|
||||
}
|
||||
|
||||
float get_snow_noise_mask(vec3 world_pos, float snow_progress) {
|
||||
float detail_noise = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
|
||||
float broad_noise = texture(noise_texture, world_pos.xz * snow_noise_scale * 0.35 + vec2(19.1, 7.4)).r;
|
||||
float combined_noise = mix(detail_noise, broad_noise, 0.35);
|
||||
float threshold = mix(0.92, 0.08, snow_progress);
|
||||
return smoothstep(threshold - 0.18, threshold + 0.18, combined_noise);
|
||||
}
|
||||
|
||||
float ripple_ring(vec2 uv, float time_offset) {
|
||||
float d = length(uv);
|
||||
float ring = sin(d * 30.0 - TIME * ripple_speed + time_offset) * 0.5 + 0.5;
|
||||
@@ -94,7 +107,7 @@ float ripple_ring(vec2 uv, float time_offset) {
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
float snow_progress = get_snow_progress();
|
||||
float snow_progress = get_visual_snow_progress(get_snow_progress());
|
||||
float snow_accumulation = snow_progress * global_snow_max_accumulation;
|
||||
vec3 world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
vec3 world_normal = normalize((MODEL_MATRIX * vec4(NORMAL, 0.0)).xyz);
|
||||
@@ -104,7 +117,7 @@ void vertex() {
|
||||
global_snow_cap_flatness_end,
|
||||
world_normal.y
|
||||
);
|
||||
float accumulation_growth = smoothstep(0.08, 0.65, snow_progress);
|
||||
float accumulation_growth = smoothstep(0.02, 0.45, snow_progress);
|
||||
float cap_noise = fbm(world_pos.xz * global_snow_cap_noise_scale + vec2(11.3, 4.7));
|
||||
float cap_variation = mix(1.0 - global_snow_cap_noise_strength, 1.0 + global_snow_cap_noise_strength, cap_noise);
|
||||
|
||||
@@ -118,6 +131,8 @@ void fragment() {
|
||||
vec3 world_pos = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
vec3 world_normal = normalize((INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
|
||||
float facing_up = clamp(world_normal.y, 0.0, 1.0);
|
||||
vec3 geometric_normal = normalize(cross(dFdx(world_pos), dFdy(world_pos)));
|
||||
float snow_facing_up = max(facing_up, abs(geometric_normal.y));
|
||||
float noise_val = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
|
||||
|
||||
//Snow
|
||||
@@ -127,14 +142,15 @@ void fragment() {
|
||||
float snow_edge = smoothstep(
|
||||
global_snow_threshold - snow_edge_softness,
|
||||
global_snow_threshold + snow_edge_softness,
|
||||
facing_up
|
||||
snow_facing_up
|
||||
);
|
||||
float flat_accumulation = smoothstep(0.0, 0.35, v_snow_cap_mask) * snow_accumulation;
|
||||
float snow_noise_mask = get_snow_noise_mask(world_pos, snow_progress);
|
||||
float snow_variation = mix(0.75, 1.15, noise_val);
|
||||
float snow_coverage = clamp(snow_progress * snow_variation + flat_accumulation * 0.25, 0.0, 1.0);
|
||||
float snow_coverage = clamp(mix(snow_progress * 0.35, snow_progress * snow_variation, snow_noise_mask) + flat_accumulation * 0.15, 0.0, 1.0);
|
||||
float snow_factor = max(snow_edge * snow_coverage, flat_accumulation);
|
||||
float snow_opacity = clamp(snow_factor, 0.0, 1.0);
|
||||
snow_opacity = max(snow_opacity, flat_accumulation * 0.9);
|
||||
snow_opacity = max(snow_opacity, flat_accumulation * mix(0.45, 0.9, snow_noise_mask));
|
||||
|
||||
float shade = mix(-snow_color_variation, snow_color_variation, noise_val);
|
||||
vec3 snow_albedo = clamp(global_snow_color.rgb + vec3(shade), 0.0, 1.0);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[gd_resource type="ShaderMaterial" format=3 uid="uid://cn5vw7unbqgve"]
|
||||
|
||||
[ext_resource type="Shader" uid="uid://dh3j2jp6defuk" path="res://core/daynight/weather_overlay.gdshader" id="1_weather"]
|
||||
[ext_resource type="Texture2D" uid="uid://bpswbjh4jj1ou" path="res://core/daynight/noise.tres" id="2_noise"]
|
||||
|
||||
[resource]
|
||||
render_priority = 0
|
||||
@@ -19,3 +20,4 @@ shader_parameter/wet_roughness = 0.05
|
||||
shader_parameter/rain_normal_strength = 0.4
|
||||
shader_parameter/puddle_noise_scale = 0.08
|
||||
shader_parameter/puddle_threshold = 0.45
|
||||
shader_parameter/noise_texture = ExtResource("2_noise")
|
||||
|
||||
@@ -8,7 +8,9 @@ global uniform float global_snow_melt_time = -1.0;
|
||||
global uniform float global_snow_melt_speed = 0.1;
|
||||
global uniform float global_snow_amount = 0.0;
|
||||
global uniform vec4 global_snow_color;
|
||||
const float SNOW_VISUAL_RESPONSE = 0.55;
|
||||
uniform float snow_edge_softness : hint_range(0.01, 0.5) = 0.15;
|
||||
uniform float snow_noise_scale : hint_range(0.01, 1.0) = 0.15;
|
||||
uniform float snow_color_variation : hint_range(0.0, 0.15) = 0.05;
|
||||
|
||||
|
||||
@@ -50,6 +52,18 @@ float get_snow_progress() {
|
||||
return snow_progress;
|
||||
}
|
||||
|
||||
float get_visual_snow_progress(float snow_progress) {
|
||||
return pow(clamp(snow_progress, 0.0, 1.0), SNOW_VISUAL_RESPONSE);
|
||||
}
|
||||
|
||||
float get_snow_noise_mask(vec3 world_pos, float snow_progress) {
|
||||
float detail_noise = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
|
||||
float broad_noise = texture(noise_texture, world_pos.xz * snow_noise_scale * 0.35 + vec2(19.1, 7.4)).r;
|
||||
float combined_noise = mix(detail_noise, broad_noise, 0.35);
|
||||
float threshold = mix(0.92, 0.08, snow_progress);
|
||||
return smoothstep(threshold - 0.18, threshold + 0.18, combined_noise);
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec3 world_pos = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
|
||||
@@ -57,14 +71,15 @@ void fragment() {
|
||||
float facing_up = 1.0;
|
||||
|
||||
// Snow accumulation
|
||||
float snow_amount = get_snow_progress();
|
||||
float snow_amount = get_visual_snow_progress(get_snow_progress());
|
||||
|
||||
// Plain surfaces fade in uniformly to avoid patchy strip-like accumulation.
|
||||
float snow_mask = smoothstep(0.0, 1.0, snow_amount);
|
||||
// Plain surfaces accumulate through world-space noise so flat snow is not uniform.
|
||||
float snow_noise_mask = get_snow_noise_mask(world_pos, snow_amount);
|
||||
float snow_mask = mix(snow_amount * 0.35, snow_amount, snow_noise_mask);
|
||||
snow_mask *= step(0.01, snow_amount);
|
||||
|
||||
// Snow color with slight variation
|
||||
float shade = fract(sin(dot(UV, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
float shade = texture(noise_texture, world_pos.xz * snow_noise_scale * 2.0 + vec2(3.7, 11.2)).r;
|
||||
shade = mix(-snow_color_variation, snow_color_variation, shade);
|
||||
vec3 snow_albedo = clamp(global_snow_color.rgb + vec3(shade), 0.0, 1.0);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
render_priority = 0
|
||||
shader = ExtResource("1_weather_plain")
|
||||
shader_parameter/snow_edge_softness = 0.15
|
||||
shader_parameter/snow_noise_scale = 0.15
|
||||
shader_parameter/snow_color_variation = 0.05
|
||||
shader_parameter/ripple_scale = 1.5
|
||||
shader_parameter/ripple_speed = 2.0
|
||||
|
||||
@@ -167,7 +167,7 @@ extends Resource
|
||||
@export var snow_threshold: float = 0.4 #Normal Y threshold for snow accumulation on surfaces
|
||||
@export var snow_accumulation_speed: float = 0.005 #Accumulation speed: 0.005 -> ~200s, 0.01 -> 100s, 0.02 -> 50s
|
||||
@export var snow_melt_speed: float = 0.05 #Speed at which accumulated snow melts away
|
||||
@export var show_snow_accumulation_volume: bool = true #Enables vertex snow buildup; when false snow only changes surface color
|
||||
@export var show_snow_accumulation_volume: bool = false #Enables vertex snow buildup; when false snow only changes surface color
|
||||
@export var snow_max_accumulation: float = 0.25 #Maximum accumulated snow factor applied to coverage and thickness
|
||||
@export var snow_color: Color = Color(0.9, 0.95, 1.0) #Albedo color of snow on surfaces
|
||||
@export var snow_cap_height: float = 0.03 #Maximum snow thickness extruded on flat surfaces
|
||||
|
||||
Reference in New Issue
Block a user