shader_type spatial; render_mode blend_mix, depth_draw_never; 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); uniform sampler2D noise_texture : filter_linear_mipmap, repeat_enable; uniform float noise_scale : hint_range(0.01, 1.0) = 0.15; uniform float noise_edge_softness : hint_range(0.01, 0.5) = 0.2; uniform float roughness_variation : hint_range(0.0, 0.3) = 0.15; uniform float color_variation : hint_range(0.0, 0.15) = 0.05; void fragment() { 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); } 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_pos = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz; vec3 world_normal = (INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz; float facing_up = clamp(world_normal.y, 0.0, 1.0); float noise_val = texture(noise_texture, world_pos.xz * noise_scale).r; float edge = smoothstep( global_snow_threshold - noise_edge_softness, global_snow_threshold + noise_edge_softness, facing_up + (noise_val - 0.5) * 0.4 ); float coverage = smoothstep(0.0, 0.6, noise_val + snow_amount - 0.4); float snow_factor = edge * coverage * snow_amount; float shade = mix(-color_variation, color_variation, noise_val); vec3 snow_albedo = clamp(global_snow_color.rgb + vec3(shade), 0.0, 1.0); float snow_roughness = mix(0.15 - roughness_variation, 0.15 + roughness_variation, noise_val); ALBEDO = snow_albedo; ROUGHNESS = snow_roughness; METALLIC = 0.0; ALPHA = snow_factor; }