From 36d6f29fd3e1ea4253adf9b0f1c64e5061d928cf Mon Sep 17 00:00:00 2001 From: Overside srl Date: Tue, 24 Mar 2026 13:56:36 +0100 Subject: [PATCH] create weather controller and daynight controller --- core/daynight/clouds_shadow.gdshader | 75 +++ core/daynight/clouds_shadow.gdshader.uid | 1 + core/daynight/day_night_controller.gd | 44 ++ core/daynight/day_night_controller.gd.uid | 1 + core/daynight/edge_detection_compositor.gd | 121 +++++ .../daynight/edge_detection_compositor.gd.uid | 1 + core/daynight/edge_detection_shader.glsl | 146 ++++++ .../edge_detection_shader.glsl.import | 14 + core/daynight/environment_management.tscn | 224 +++++++++ core/daynight/environment_manager.gd | 64 +++ core/daynight/environment_manager.gd.uid | 1 + core/daynight/fog.gdshader | 40 ++ core/daynight/fog.gdshader.uid | 1 + core/daynight/fogoverlay.gdshader | 29 ++ core/daynight/fogoverlay.gdshader.uid | 1 + core/daynight/god_ray.tscn | 37 ++ core/daynight/godrays.gd | 35 ++ core/daynight/godrays.gd.uid | 1 + core/daynight/godrays.gdshader | 43 ++ core/daynight/godrays.gdshader.uid | 1 + core/daynight/godrays.tres | 26 + core/daynight/lighting_albedo.png | Bin 0 -> 21405 bytes core/daynight/lighting_albedo.png.import | 41 ++ core/daynight/sky.gdshader | 141 ++++++ core/daynight/sky.gdshader.uid | 1 + core/daynight/snow.gdshader | 19 + core/daynight/snow.gdshader.uid | 1 + core/daynight/stars_albedo.png | Bin 0 -> 7890 bytes core/daynight/stars_albedo.png.import | 41 ++ core/daynight/weather_controller.gd | 452 ++++++++++++++++++ core/daynight/weather_controller.gd.uid | 1 + core/daynight/wind.gdshader | 18 + core/daynight/wind.gdshader.uid | 1 + core/environment_config.gd | 99 ++++ core/environment_config.gd.uid | 1 + core/environment_config_resource.tres | 7 + core/ui_events.gd | 7 + core/ui_events.gd.uid | 1 + docs/museums/daynight/camera_3d.gd | 70 +++ docs/museums/daynight/camera_3d.gd.uid | 1 + docs/museums/daynight/control.gd | 13 + docs/museums/daynight/control.gd.uid | 1 + docs/museums/daynight/museum_daynight.tscn | 180 +++++++ .../museum_daynight.tscn12025044106.tmp | 151 ++++++ project.godot | 33 ++ 45 files changed, 2186 insertions(+) create mode 100644 core/daynight/clouds_shadow.gdshader create mode 100644 core/daynight/clouds_shadow.gdshader.uid create mode 100644 core/daynight/day_night_controller.gd create mode 100644 core/daynight/day_night_controller.gd.uid create mode 100644 core/daynight/edge_detection_compositor.gd create mode 100644 core/daynight/edge_detection_compositor.gd.uid create mode 100644 core/daynight/edge_detection_shader.glsl create mode 100644 core/daynight/edge_detection_shader.glsl.import create mode 100644 core/daynight/environment_management.tscn create mode 100644 core/daynight/environment_manager.gd create mode 100644 core/daynight/environment_manager.gd.uid create mode 100644 core/daynight/fog.gdshader create mode 100644 core/daynight/fog.gdshader.uid create mode 100644 core/daynight/fogoverlay.gdshader create mode 100644 core/daynight/fogoverlay.gdshader.uid create mode 100644 core/daynight/god_ray.tscn create mode 100644 core/daynight/godrays.gd create mode 100644 core/daynight/godrays.gd.uid create mode 100644 core/daynight/godrays.gdshader create mode 100644 core/daynight/godrays.gdshader.uid create mode 100644 core/daynight/godrays.tres create mode 100644 core/daynight/lighting_albedo.png create mode 100644 core/daynight/lighting_albedo.png.import create mode 100644 core/daynight/sky.gdshader create mode 100644 core/daynight/sky.gdshader.uid create mode 100644 core/daynight/snow.gdshader create mode 100644 core/daynight/snow.gdshader.uid create mode 100644 core/daynight/stars_albedo.png create mode 100644 core/daynight/stars_albedo.png.import create mode 100644 core/daynight/weather_controller.gd create mode 100644 core/daynight/weather_controller.gd.uid create mode 100644 core/daynight/wind.gdshader create mode 100644 core/daynight/wind.gdshader.uid create mode 100644 core/environment_config.gd create mode 100644 core/environment_config.gd.uid create mode 100644 core/environment_config_resource.tres create mode 100644 core/ui_events.gd create mode 100644 core/ui_events.gd.uid create mode 100644 docs/museums/daynight/camera_3d.gd create mode 100644 docs/museums/daynight/camera_3d.gd.uid create mode 100644 docs/museums/daynight/control.gd create mode 100644 docs/museums/daynight/control.gd.uid create mode 100644 docs/museums/daynight/museum_daynight.tscn create mode 100644 docs/museums/daynight/museum_daynight.tscn12025044106.tmp diff --git a/core/daynight/clouds_shadow.gdshader b/core/daynight/clouds_shadow.gdshader new file mode 100644 index 0000000..b7ff113 --- /dev/null +++ b/core/daynight/clouds_shadow.gdshader @@ -0,0 +1,75 @@ +shader_type spatial; +render_mode unshaded, depth_test_disabled, cull_disabled; + +/* +uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest; +uniform sampler2D noise_texture : repeat_enable, filter_linear; + +uniform float cloud_scale : hint_range(0.001, 0.2) = 0.05; +uniform float cloud_speed : hint_range(0.0, 1.0) = 0.05; +uniform vec2 direction = vec2(1.0, 0.2); +uniform vec2 sun_angle = vec2(0.5, 0.5); + +group_uniforms Cloud_Shape; +uniform float cloud_density : hint_range(0.0, 1.0) = 0.5; +uniform float center_sharpness : hint_range(0.0, 0.99) = 0.7; + +group_uniforms Adjustment; +uniform vec3 shadow_color : source_color = vec3(0.0, 0.0, 0.0); +uniform float opacity_center : hint_range(0.0, 1.0) = 0.5; +uniform float opacity_edge : hint_range(0.0, 1.0) = 0.2; + +group_uniforms Fade_Depth; +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 + +void vertex() { + POSITION = vec4(VERTEX.xy, 1.0, 1.0); +} + +void fragment() { + float depth = texture(depth_texture, SCREEN_UV).x; + + if (depth >= 0.9999) { + ALPHA = 0.0; + } else { + vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth); + vec4 view_pos = INV_PROJECTION_MATRIX * vec4(ndc, 1.0); + view_pos /= view_pos.w; + vec4 world_pos = INV_VIEW_MATRIX * view_pos; + + //Distance and height fade + float dist = length(view_pos.xyz); + float dist_fade = smoothstep(fade_end, fade_start, dist); + float height_fade = smoothstep(height_fade_end, height_fade_start, world_pos.y); + + float final_fade = dist_fade * height_fade; + + if (final_fade <= 0.001) { + ALPHA = 0.0; + } else { + vec2 projected_xz = world_pos.xz + (world_pos.y * sun_angle); + vec2 uv = projected_xz * cloud_scale; + uv += TIME * cloud_speed * vec2(-direction.x, direction.y); + + float n = texture(noise_texture, uv).r; + + if (n < (1.0 - cloud_density)) { + ALPHA = 0.0; + } else { + float internal_n = (n - (1.0 - cloud_density)) / cloud_density; + float is_center = step(center_sharpness, internal_n); + + ALBEDO = shadow_color; + + //shade color based on height + ALPHA = mix(opacity_edge, opacity_center, is_center) * final_fade; + } + } + } +} +*/ \ No newline at end of file diff --git a/core/daynight/clouds_shadow.gdshader.uid b/core/daynight/clouds_shadow.gdshader.uid new file mode 100644 index 0000000..1d8aa61 --- /dev/null +++ b/core/daynight/clouds_shadow.gdshader.uid @@ -0,0 +1 @@ +uid://7vwkfffa5vao diff --git a/core/daynight/day_night_controller.gd b/core/daynight/day_night_controller.gd new file mode 100644 index 0000000..27d085c --- /dev/null +++ b/core/daynight/day_night_controller.gd @@ -0,0 +1,44 @@ +@tool +class_name DayNightController +extends Node + +#Time duration in seconds for a day +@export var day_duration: float = 120.0 + +#starting time +@export_range(0.0, 1.0) var start_time: float = 0.0 + +#Multiply for debug +@export var time_scale: float = 1.0 + +@export var paused: bool = false + +signal time_changed(time: float) + +var current_time: float = 0.0 + +func _ready() -> void: + current_time = start_time + update_time(current_time) + +func _process(delta: float) -> void: + if paused or day_duration <= 0.0: + return + + var increment: float = (delta * time_scale) / day_duration + current_time = wrapf(current_time + increment, 0.0, 1.0) + + update_time(current_time) + +func get_time_string() -> String: + var total_minutes: int = int(current_time * 1440.0) # 1440 = 24*60 + var hours: int = total_minutes / 60 + var minutes: int = total_minutes % 60 + return "%02d:%02d" % [hours, minutes] + +func set_time(t: float) -> void: + current_time = wrapf(t, 0.0, 1.0) + update_time(current_time) + +func update_time(currtime: float) -> void: + emit_signal("time_changed", currtime) diff --git a/core/daynight/day_night_controller.gd.uid b/core/daynight/day_night_controller.gd.uid new file mode 100644 index 0000000..105ccc0 --- /dev/null +++ b/core/daynight/day_night_controller.gd.uid @@ -0,0 +1 @@ +uid://bl05bf0o5tde8 diff --git a/core/daynight/edge_detection_compositor.gd b/core/daynight/edge_detection_compositor.gd new file mode 100644 index 0000000..938cfd6 --- /dev/null +++ b/core/daynight/edge_detection_compositor.gd @@ -0,0 +1,121 @@ +@tool +class_name EdgeDetectionCompositor +extends CompositorEffect + +var rd: RenderingDevice +var shader: RID +var pipeline: RID +var parameter_storage_buffer := RID() + + +func _init() -> void: + effect_callback_type = CompositorEffect.EFFECT_CALLBACK_TYPE_POST_OPAQUE + rd = RenderingServer.get_rendering_device() + RenderingServer.call_on_render_thread(_initialize_compute) + + var data := PackedFloat32Array() + data.resize(20) + data.fill(0) + var parameter_data := data.to_byte_array() + parameter_storage_buffer = rd.storage_buffer_create(parameter_data.size(), parameter_data) + + + +# System notifications, we want to react on the notification that +# alerts us we are about to be destroyed. +func _notification(what: int) -> void: + if what == NOTIFICATION_PREDELETE: + if shader.is_valid(): + # Freeing our shader will also free any dependents such as the pipeline! + rd.free_rid(shader) + + +#region Code in this region runs on the rendering thread. +# Compile our shader at initialization. +func _initialize_compute() -> void: + rd = RenderingServer.get_rendering_device() + if not rd: + return + + # Compile our shader. + var shader_file := load("res://core/daynight/edge_detection_shader.glsl") + var shader_spirv: RDShaderSPIRV = shader_file.get_spirv() + + shader = rd.shader_create_from_spirv(shader_spirv) + if shader.is_valid(): + pipeline = rd.compute_pipeline_create(shader) + + +# Called by the rendering thread every frame. +func _render_callback(p_effect_callback_type: EffectCallbackType, p_render_data: RenderData) -> void: + if rd and p_effect_callback_type == EFFECT_CALLBACK_TYPE_POST_OPAQUE and pipeline.is_valid(): + # Get our render scene buffers object, this gives us access to our render buffers. + # Note that implementation differs per renderer hence the need for the cast. + var render_scene_buffers := p_render_data.get_render_scene_buffers() + if render_scene_buffers: + # Get our render size, this is the 3D render resolution! + var size = render_scene_buffers.get_internal_size() + if size.x == 0 and size.y == 0: + return + + @warning_ignore("integer_division") + var x_groups : int = (size.x - 1.0) / 8.0 + 1.0 + @warning_ignore("integer_division") + var y_groups : int = (size.y - 1.0) / 8.0 + 1.0 + var z_groups := 1.0 + + + # Loop through views just in case we're doing stereo rendering. No extra cost if this is mono. + var view_count: int = render_scene_buffers.get_view_count() + for view in view_count: + # Get the RID for our color image, we will be reading from and writing to it. + var input_image: RID = render_scene_buffers.get_color_layer(view) + var input_depth: RID = render_scene_buffers.get_depth_layer(view) + var input_normal: RID = render_scene_buffers.get_texture("forward_clustered","normal_roughness") + + var texture_sampler = RDSamplerState.new() + texture_sampler = rd.sampler_create(texture_sampler) + + + var parameters := PackedFloat32Array([size.x, size.y, 0.0, 0.0]) + var inv_proj_mat := p_render_data.get_render_scene_data().get_cam_projection().inverse() + var inv_proj_mat_array := PackedVector4Array([inv_proj_mat.x, inv_proj_mat.y, inv_proj_mat.z, inv_proj_mat.w]) + + var parameter_data := parameters.to_byte_array() + parameter_data.append_array(inv_proj_mat_array.to_byte_array()) + rd.buffer_update(parameter_storage_buffer, 0, parameter_data.size(), parameter_data) + + var uniform_parameter := RDUniform.new() + uniform_parameter.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + uniform_parameter.binding = 0 + uniform_parameter.add_id(parameter_storage_buffer) + + # Create a uniform set, this will be cached, the cache will be cleared if our viewports configuration is changed. + var uniform_color := RDUniform.new() + uniform_color.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE + uniform_color.binding = 1 + uniform_color.add_id(input_image) + + var uniform_depth := RDUniform.new() + uniform_depth.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE + uniform_depth.binding = 2 + uniform_depth.add_id(texture_sampler) + uniform_depth.add_id(input_depth) + + var uniform_normal := RDUniform.new() + uniform_normal.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE + uniform_normal.binding = 3 + uniform_normal.add_id(texture_sampler) + uniform_normal.add_id(input_normal) + + var uniform_set := UniformSetCacheRD.get_cache(shader, 0, [uniform_parameter, uniform_color, uniform_depth, uniform_normal]) + + # Run our compute shader. + var compute_list := rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, pipeline) + rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0) + #rd.compute_list_set_push_constant(compute_list, push_constant.to_byte_array(), push_constant.size() * 4) + rd.compute_list_dispatch(compute_list, x_groups, y_groups, z_groups) + rd.compute_list_end() + rd.free_rid(texture_sampler) +#endregion diff --git a/core/daynight/edge_detection_compositor.gd.uid b/core/daynight/edge_detection_compositor.gd.uid new file mode 100644 index 0000000..1db8e72 --- /dev/null +++ b/core/daynight/edge_detection_compositor.gd.uid @@ -0,0 +1 @@ +uid://brcimd12tx3dm diff --git a/core/daynight/edge_detection_shader.glsl b/core/daynight/edge_detection_shader.glsl new file mode 100644 index 0000000..02dac2d --- /dev/null +++ b/core/daynight/edge_detection_shader.glsl @@ -0,0 +1,146 @@ +#[compute] +#version 450 +// FOR THIS PROJECT THE INNER LINES MADE WITH THE SCREEN NORMAL IS NOT BEING USED, BUT THE CODE IS STILL AVAILABLE IN THE FILE + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(set = 0, binding = 0, std430) readonly buffer Params { + vec2 raster_size; + vec2 reserved; + mat4 inv_proj_mat; +} params; + +layout(rgba16f, set = 0, binding = 1) uniform image2D color_image; +layout(set = 0, binding = 2) uniform sampler2D depth_texture; +layout(set = 0, binding = 3) uniform sampler2D normal_texture; + + +const vec2 offset = vec2(0.0001); +const float line_highlight = 0.1; +const float line_shadow = 0.55; + + +float GetLinearDepth(vec2 uv, float mask) { + float raw_depth = texture(depth_texture, uv).r * mask; + vec3 ndc = vec3(uv * 2.0 - 1.0, raw_depth); + vec4 view = params.inv_proj_mat * vec4(ndc, 1.0); + view.xyz /= view.w; + return -view.z; +} + + +vec4 GetNormal(vec2 uv, float mask){ + vec4 normal = texture(normal_texture, uv + offset) * mask; + return normal; +} + + +vec4 NormalRoughnessCompatibility(vec4 p_normal_roughness) { + float roughness = p_normal_roughness.w; + if (roughness > 0.5) { + roughness = 1.0 - roughness; + } + roughness /= (127.0 / 255.0); + vec4 normal_comp = vec4(normalize(p_normal_roughness.xyz * 2.0 - 1.0) * 0.5 + 0.5, roughness); + normal_comp = normal_comp * 2.0 - 1.0; + return normal_comp; +} + + +float NormalEdgeIndicator(vec3 normal_edge_bias, vec3 normal, vec3 neighbor_normal, float depth_difference){ + float normal_difference = dot(normal - neighbor_normal, normal_edge_bias); + float normal_indicator = clamp(smoothstep(-.01, .01, normal_difference), 0.0, 1.0); + float depth_indicator = clamp(sign(depth_difference * .25 + .0025), 0.0, 1.0); + return (1.0 - dot(normal, neighbor_normal)) * depth_indicator * normal_indicator; +} + + +void main() { + vec2 size = params.raster_size; + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + + if (uv.x >= size.x || uv.y >= size.y) { + return; + } + + vec2 uv_normalized = uv / size; + vec2 texel_size = 1.0 / size.xy; + + // 1. Leggiamo subito il canale Alpha (che in Godot contiene la Roughness codificata) + float raw_roughness = texture(normal_texture, uv_normalized + offset).a; + + // --- INIZIO TRUCCO ESCLUSIONE ERBA --- + // Decodifichiamo la roughness esattamente come fa Godot (preso dalla tua funzione in alto) + float actual_roughness = raw_roughness; + if (actual_roughness > 0.5) { + actual_roughness = 1.0 - actual_roughness; + } + actual_roughness /= (127.0 / 255.0); + + // Controlliamo se la roughness è quella "magica" dell'erba (0.02) + // Usiamo 0.005 come margine d'errore perché i float non sono mai precisi al 100% + if (abs(actual_roughness - 0.02) < 0.005) { + // Chiudiamo l'esecuzione per questo specifico pixel! + // Siccome non facciamo "imageStore", l'immagine mantiene i suoi colori + // originali senza che venga disegnata alcuna linea nera. + return; + } + // --- FINE TRUCCO --- + + // Da qui in poi, il codice prosegue normalmente solo per gli altri oggetti + + // UV ofssets + vec2 uv_offsets[4]; + uv_offsets[0] = uv_normalized + vec2(0.0, -1.0) * texel_size + offset; + uv_offsets[1] = uv_normalized + vec2(0.0, 1.0) * texel_size + offset; + uv_offsets[2] = uv_normalized + vec2(1.0, 0.0) * texel_size + offset; + uv_offsets[3] = uv_normalized + vec2(-1.0, 0.0) * texel_size + offset; + + float mask = ceil(raw_roughness); + + // Depth based Outlines + float depth_difference = 0.0; + float inv_depth_difference = 0.5; + float depth = GetLinearDepth(uv_normalized + offset, mask); + + for (int i = 0; i < uv_offsets.length(); i++){ + float dOff = GetLinearDepth(uv_offsets[i], mask); + depth_difference += clamp(dOff - depth, 0.0, 1.0); + inv_depth_difference += depth - dOff; + } + + inv_depth_difference = clamp(inv_depth_difference, 0.0, 1.0); + inv_depth_difference = clamp(smoothstep(0.9, 0.9, inv_depth_difference) * 10.0 , 0.0, 1.0); + depth_difference = smoothstep(0.45, 0.5, depth_difference); + + + // Normal based Innerlines + //float normal_difference = 0.0; + //vec3 normal_edge_bias = vec3(1.0, 1.0, 1.0); + //vec3 normal = NormalRoughnessCompatibility(GetNormal(uv_normalized, mask)).rgb; + + //for (int i = 0; i < uv_offsets.length(); i++){ + //vec3 n_offset = NormalRoughnessCompatibility(GetNormal(uv_offsets[i], mask)).rgb; + //normal_difference += NormalEdgeIndicator(normal_edge_bias, normal, n_offset, depth_difference); + //} + //normal_difference = smoothstep(0.2, 0.2, normal_difference); + //normal_difference = clamp(normal_difference - inv_depth_difference, 0.0, 1.0); + + + // Combine with screen render + + vec4 color = imageLoad(color_image, uv); + + vec3 outline = vec3(depth_difference); + //vec3 innerline = vec3(normal_difference) - outline; + //innerline = clamp(innerline, vec3(0.0), vec3(1.0)); + //float line_mask = depth_difference + normal_difference; + float line_mask = depth_difference; + + // Combine colors with lines + //vec4 color_with_lines = vec4(color.rgb + (innerline * line_highlight) - (color.rgb * outline * line_shadow), line_mask); + //vec4 color_with_lines = vec4(color.rgb - (color.rgb * outline * line_shadow), line_mask); + vec4 color_with_lines = mix(color, color * vec4(vec3(outline), 1.0) * vec4(vec3(line_shadow), 1.0), line_mask); + + imageStore(color_image, uv, color_with_lines); +} \ No newline at end of file diff --git a/core/daynight/edge_detection_shader.glsl.import b/core/daynight/edge_detection_shader.glsl.import new file mode 100644 index 0000000..626931f --- /dev/null +++ b/core/daynight/edge_detection_shader.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://cot8vqnj0h5by" +path="res://.godot/imported/edge_detection_shader.glsl-1a7158ec83d4a5f09c7cbc868285fb08.res" + +[deps] + +source_file="res://core/daynight/edge_detection_shader.glsl" +dest_files=["res://.godot/imported/edge_detection_shader.glsl-1a7158ec83d4a5f09c7cbc868285fb08.res"] + +[params] + diff --git a/core/daynight/environment_management.tscn b/core/daynight/environment_management.tscn new file mode 100644 index 0000000..b0231f8 --- /dev/null +++ b/core/daynight/environment_management.tscn @@ -0,0 +1,224 @@ +[gd_scene format=3 uid="uid://cmuvmmp7xam4o"] + +[ext_resource type="Script" uid="uid://d27xbipk650kf" path="res://core/daynight/environment_manager.gd" id="1_wecen"] +[ext_resource type="Script" uid="uid://butda6k2tli3o" path="res://core/environment_config.gd" id="2_h6hjk"] +[ext_resource type="Shader" uid="uid://7vwkfffa5vao" path="res://core/daynight/clouds_shadow.gdshader" id="2_i3hjl"] +[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://b6l166fnyto24" path="res://core/daynight/fogoverlay.gdshader" id="7_i6gqj"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ruhh7"] +render_priority = 0 +shader = ExtResource("2_i3hjl") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_r4tfj"] +transparency = 2 +alpha_scissor_threshold = 0.0 +alpha_antialiasing_mode = 0 +disable_ambient_light = true +albedo_color = Color(0.8523133, 0.64268667, 0.43305993, 1) +billboard_mode = 3 +particles_anim_h_frames = 1 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_b5atu"] +render_priority = 0 +shader = ExtResource("2_r4tfj") + +[sub_resource type="Resource" id="Resource_r4tfj"] +script = ExtResource("2_h6hjk") +material_fog = SubResource("ShaderMaterial_b5atu") +material_drops = SubResource("StandardMaterial3D_r4tfj") +material_clouds = SubResource("ShaderMaterial_ruhh7") +rain_fade_time = null +snow_fade_time = null +metadata/_custom_type_script = "uid://butda6k2tli3o" + +[sub_resource type="Gradient" id="Gradient_i3hjl"] +offsets = PackedFloat32Array(0, 0.49019608, 1) +colors = PackedColorArray(0, 0, 0, 0, 1, 0.8980392, 0.3764706, 1, 1, 1, 1, 0) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_djqkg"] +gradient = SubResource("Gradient_i3hjl") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_i3hjl"] +emission_shape = 3 +emission_box_extents = Vector3(20, 3, 20) +gravity = Vector3(0, 0.2, 0) +color_ramp = SubResource("GradientTexture1D_djqkg") +turbulence_enabled = true + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_djqkg"] +transparency = 1 +vertex_color_use_as_albedo = true +emission_enabled = true +emission = Color(0.94509804, 0.827451, 0.09411765, 1) +emission_energy_multiplier = 16.0 +billboard_mode = 3 +particles_anim_h_frames = 1 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="QuadMesh" id="QuadMesh_b5atu"] +material = SubResource("StandardMaterial3D_djqkg") +size = Vector2(0.1, 0.1) + +[sub_resource type="Gradient" id="Gradient_djqkg"] +offsets = PackedFloat32Array(0, 0.491, 1) +colors = PackedColorArray(0, 0, 0, 0, 1, 1, 1, 0.7647059, 0, 0, 0, 0) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_b5atu"] +gradient = SubResource("Gradient_djqkg") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_ruhh7"] +lifetime_randomness = 0.5 +emission_shape_scale = Vector3(5, 5, 5) +emission_shape = 3 +emission_box_extents = Vector3(25, 5, 25) +direction = Vector3(0, 1, 0) +initial_velocity_min = 6.0 +initial_velocity_max = 6.0 +gravity = Vector3(0, 0, 0) +color_ramp = SubResource("GradientTexture1D_b5atu") + +[sub_resource type="Curve" id="Curve_b5atu"] +_data = [Vector2(0.00440529, 0.49729878), 0.0, 0.0, 0, 0, Vector2(0.4977974, 0.988911), 0.0, 0.0, 0, 0, Vector2(1, 0.50284326), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_cer0u"] +render_priority = 0 +shader = ExtResource("5_djqkg") + +[sub_resource type="TubeTrailMesh" id="TubeTrailMesh_vo82p"] +material = SubResource("ShaderMaterial_cer0u") +custom_aabb = AABB(20, 20, 20, 0, 0, 0) +radius = 0.06 +radial_steps = 16 +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) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_ruhh7"] +gradient = SubResource("Gradient_b5atu") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_cer0u"] +particle_flag_align_y = true +emission_shape_scale = Vector3(50, 10, 50) +emission_shape = 3 +emission_box_extents = Vector3(1, 1, 1) +direction = Vector3(0, -1, 0) +spread = 0.0 +initial_velocity_min = 2.5 +initial_velocity_max = 5.0 +gravity = Vector3(0, -2, 0) +scale_max = 10.0 +color_ramp = SubResource("GradientTexture1D_ruhh7") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_b5atu"] +transparency = 1 +emission_enabled = true +emission = Color(1, 1, 1, 1) +emission_energy_multiplier = 0.2 +billboard_mode = 3 +particles_anim_h_frames = 1 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="QuadMesh" id="QuadMesh_ruhh7"] +material = SubResource("StandardMaterial3D_b5atu") +size = Vector2(0.2, 0.2) + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_b5atu"] +particle_flag_align_y = true +emission_shape_scale = Vector3(50, 10, 50) +emission_shape = 3 +emission_box_extents = Vector3(1, 1, 1) +direction = Vector3(0, -1, 0) +spread = 0.0 +initial_velocity_min = 10.0 +initial_velocity_max = 25.0 +gravity = Vector3(0, -9, 0) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ruhh7"] +transparency = 2 +alpha_scissor_threshold = 0.5 +alpha_antialiasing_mode = 0 +disable_ambient_light = true +albedo_color = Color(0.4745098, 0.69411767, 0.7607843, 0.7411765) +billboard_mode = 3 +particles_anim_h_frames = 1 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="QuadMesh" id="QuadMesh_cer0u"] +material = SubResource("StandardMaterial3D_ruhh7") +size = Vector2(0.05, 0.8) + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ik86e"] +shader = ExtResource("7_i6gqj") +shader_parameter/fog_color = Color(0.85, 0.9, 0.95, 1) +shader_parameter/clear_center_radius = 0.39200001862 +shader_parameter/edge_softness = 0.30900001397898 +shader_parameter/max_opacity = 0.10000000475 + +[node name="EnvironmentManager" type="Node3D" unique_id=1611939731 node_paths=PackedStringArray("particles_wind", "particles_snow", "particles_fireflies", "particles_rain")] +script = ExtResource("1_wecen") +environment_config = SubResource("Resource_r4tfj") +particles_wind = NodePath("Particles_Wind") +particles_snow = NodePath("Particles_Snow") +particles_fireflies = NodePath("Particles_Fireflies") +particles_rain = NodePath("Particles_Rain") +godray = ExtResource("5_411rw") + +[node name="Particles_Fireflies" type="GPUParticles3D" parent="." unique_id=947538133] +visible = false +emitting = false +amount = 60 +lifetime = 4.0 +process_material = SubResource("ParticleProcessMaterial_i3hjl") +draw_pass_1 = SubResource("QuadMesh_b5atu") + +[node name="Particles_Wind" type="GPUParticles3D" parent="." unique_id=1238214694] +transform = Transform3D(-0.9999756, -8.742171e-08, -0.0069812723, -0.0069812723, -3.051611e-10, 0.9999756, -8.742171e-08, 1, -3.051611e-10, 0, 4.573, 21.04) +visible = false +emitting = false +amount = 100 +lifetime = 3.0 +fixed_fps = 60 +process_material = SubResource("ParticleProcessMaterial_ruhh7") +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) +visible = false +emitting = false +amount = 2000 +lifetime = 4.0 +process_material = SubResource("ParticleProcessMaterial_cer0u") +draw_pass_1 = SubResource("QuadMesh_ruhh7") + +[node name="Particles_Rain" type="GPUParticles3D" parent="." unique_id=1543042897] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 30, 0) +visible = false +cast_shadow = 0 +extra_cull_margin = 10.0 +emitting = false +amount = 5000 +lifetime = 1.5 +process_material = SubResource("ParticleProcessMaterial_b5atu") +draw_pass_1 = SubResource("QuadMesh_cer0u") + +[node name="FogOverlay" type="ColorRect" parent="." unique_id=1694754918] +visible = false +material = SubResource("ShaderMaterial_ik86e") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/core/daynight/environment_manager.gd b/core/daynight/environment_manager.gd new file mode 100644 index 0000000..7582ea1 --- /dev/null +++ b/core/daynight/environment_manager.gd @@ -0,0 +1,64 @@ +@tool +class_name EnvironmentManagerRoot +extends Node3D + +@export var environment_config: EnvironmentConfig + +@export_group("Particles") +@export var particles_wind: GPUParticles3D +@export var particles_snow: GPUParticles3D +@export var particles_fireflies: GPUParticles3D +@export var particles_rain: GPUParticles3D +@export var godray: PackedScene +@export var fog_overlay: ColorRect + +#environment nodes +@onready var sun: DirectionalLight3D = $"../DirectionalLight3D" +@onready var environment: WorldEnvironment = $"../WorldEnvironment" + +var day_night_controller: DayNightController +var weather_controller: WeatherController + +var day_tween: Tween +var day_time: float = 0.0 + +func _ready() -> void: + + if day_night_controller == null: + day_night_controller = DayNightController.new() + day_night_controller.name = "DayNightController" + day_night_controller.time_changed.connect(select_day_time) + add_child(day_night_controller) + + if weather_controller == null: + weather_controller = WeatherController.new( + particles_wind, + particles_snow, + particles_fireflies, + particles_rain, + godray, + sun, + environment, + environment_config + ) + weather_controller.name = "WeatherController" + add_child(weather_controller) + +func select_day_time(normalized_time: float) -> void: + # Convert 0.0-1.0 normalized time to range used by atmosphere lerps + # morning (dawn→noon) = 1.0-2.0, afternoon/night (noon→midnight) = 2.0-3.0 + if normalized_time < 0.5: + # 0.0→0.5 maps to 1.0→2.0 (morning to afternoon) + day_time = 1.0 + (normalized_time / 0.5) + else: + # 0.5→1.0 maps to 2.0→3.0 (afternoon to night) + day_time = 2.0 + ((normalized_time - 0.5) / 0.5) + + if day_tween and day_tween.is_valid(): + day_tween.kill() + day_tween = create_tween() + day_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + day_tween.tween_property(self, "day_time", day_time, 3.0) + + if weather_controller: + weather_controller.day_time = day_time diff --git a/core/daynight/environment_manager.gd.uid b/core/daynight/environment_manager.gd.uid new file mode 100644 index 0000000..54cf977 --- /dev/null +++ b/core/daynight/environment_manager.gd.uid @@ -0,0 +1 @@ +uid://d27xbipk650kf diff --git a/core/daynight/fog.gdshader b/core/daynight/fog.gdshader new file mode 100644 index 0000000..2bb1c50 --- /dev/null +++ b/core/daynight/fog.gdshader @@ -0,0 +1,40 @@ +shader_type spatial; +render_mode unshaded, depth_draw_never, cull_disabled, blend_mix; +/* +group_uniforms TextureCheck; +uniform sampler2D fog_noise : repeat_enable, filter_linear_mipmap; +uniform bool use_red_as_alpha = true; + +group_uniforms Settings; +uniform vec4 fog_color : source_color = vec4(0.8, 0.85, 0.9, 0.5); +uniform vec2 scroll_speed = vec2(0.05, 0.01); +uniform vec2 texture_scale = vec2(1.0, 1.0); + +group_uniforms Edges; +uniform float edge_softness_y : hint_range(0.0, 0.5) = 0.2; +uniform float edge_softness_x : hint_range(0.0, 0.5) = 0.1; + +group_uniforms Illumination; +uniform float night_intensity : hint_range(0.0, 1.0) = 0.0; +uniform vec3 sun_color : source_color = vec3(1.0); + +void fragment() { + vec2 moving_uv = UV * texture_scale + (TIME * scroll_speed); + vec4 noise_tex = texture(fog_noise, moving_uv); + + float noise_alpha = noise_tex.a; + if (use_red_as_alpha) { + noise_alpha = noise_tex.r; + } + + float fade_y = smoothstep(0.0, edge_softness_y, UV.y) * smoothstep(1.0, 1.0 - edge_softness_y, UV.y); + float fade_x = smoothstep(0.0, edge_softness_x, UV.x) * smoothstep(1.0, 1.0 - edge_softness_x, UV.x); + float edge_mask = fade_x * fade_y; + + //Paint fog with sun color + vec3 tinted_fog = fog_color.rgb * sun_color; + vec3 dark_fog = tinted_fog * 0.5; + ALBEDO = mix(tinted_fog, dark_fog, night_intensity); + + ALPHA = fog_color.a * noise_alpha * edge_mask; +}*/ \ No newline at end of file diff --git a/core/daynight/fog.gdshader.uid b/core/daynight/fog.gdshader.uid new file mode 100644 index 0000000..a3beb67 --- /dev/null +++ b/core/daynight/fog.gdshader.uid @@ -0,0 +1 @@ +uid://cq4vlcj8cuvge diff --git a/core/daynight/fogoverlay.gdshader b/core/daynight/fogoverlay.gdshader new file mode 100644 index 0000000..bcac8a5 --- /dev/null +++ b/core/daynight/fogoverlay.gdshader @@ -0,0 +1,29 @@ +shader_type canvas_item; + +// Colore della tua nebbia (scegli un colore che stia bene col tuo Skybox) +uniform vec4 fog_color : source_color = vec4(0.85, 0.9, 0.95, 1.0); + +// Quanto è grande lo spazio pulito al centro per il treno +uniform float clear_center_radius : hint_range(0.0, 1.0) = 0.4; + +// Quanto è morbida la sfumatura della nebbia verso i bordi +uniform float edge_softness : hint_range(0.01, 1.0) = 0.5; + +// Opacità massima ai bordi estremi dello schermo +uniform float max_opacity : hint_range(0.0, 1.0) = 0.8; + +void fragment() { + // Calcola la distanza del pixel dal centro dello schermo (0.5, 0.5) + float dist_from_center = distance(SCREEN_UV, vec2(0.5)); + + // Crea una maschera morbida circolare + // Al centro (distanza < clear_center) sarà 0.0 (trasparente) + // Verso i bordi salirà dolcemente fino a 1.0 (opaco) + float fog_amount = smoothstep(clear_center_radius, clear_center_radius + edge_softness, dist_from_center); + + // Moltiplica per l'opacità massima desiderata + fog_amount *= max_opacity; + + // Applica il colore della nebbia solo dove serve + COLOR = vec4(fog_color.rgb, fog_color.a * fog_amount); +} \ No newline at end of file diff --git a/core/daynight/fogoverlay.gdshader.uid b/core/daynight/fogoverlay.gdshader.uid new file mode 100644 index 0000000..b9bdf7d --- /dev/null +++ b/core/daynight/fogoverlay.gdshader.uid @@ -0,0 +1 @@ +uid://b6l166fnyto24 diff --git a/core/daynight/god_ray.tscn b/core/daynight/god_ray.tscn new file mode 100644 index 0000000..54bd4ba --- /dev/null +++ b/core/daynight/god_ray.tscn @@ -0,0 +1,37 @@ +[gd_scene format=3 uid="uid://dyxvcf2l8ba5x"] + +[ext_resource type="Shader" uid="uid://caavljcth87so" path="res://core/daynight/godrays.gdshader" id="1_qxph4"] +[ext_resource type="Script" uid="uid://d0kgbg142recf" path="res://core/daynight/godrays.gd" id="2_v3yr3"] + +[sub_resource type="PlaneMesh" id="PlaneMesh_l01hg"] +size = Vector2(2, 10) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_llprl"] +noise_type = 3 +seed = 4 +frequency = 0.0096 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_kavln"] +noise = SubResource("FastNoiseLite_llprl") +seamless = true + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_joqvq"] +render_priority = 0 +shader = ExtResource("1_qxph4") +shader_parameter/noise_texture = SubResource("NoiseTexture2D_kavln") +shader_parameter/ray_color = Color(1, 0.78431374, 0.27058825, 1) +shader_parameter/base_alpha = 1.0 +shader_parameter/noise_stretching = 3.17200010317 +shader_parameter/noise_scale = 1.0 +shader_parameter/scrolling_speed = Vector2(0, 0.15) +shader_parameter/depth_softness = 1.0 +shader_parameter/edge_fade_power = 2.0 +shader_parameter/intensity_multiplier = 0.5330000253175 + +[node name="GodRay" type="Node3D" unique_id=1679441931] + +[node name="GodRays" type="MeshInstance3D" parent="." unique_id=341055819] +transform = Transform3D(3.39, 0, 0, 0, -3.1996737e-07, 13, 0, -7.32, -5.68248e-07, 0, 0, 0) +mesh = SubResource("PlaneMesh_l01hg") +surface_material_override/0 = SubResource("ShaderMaterial_joqvq") +script = ExtResource("2_v3yr3") diff --git a/core/daynight/godrays.gd b/core/daynight/godrays.gd new file mode 100644 index 0000000..899f31f --- /dev/null +++ b/core/daynight/godrays.gd @@ -0,0 +1,35 @@ +extends MeshInstance3D + +@export_group("Animation") +@export var life_time: float = 8.0 +@export var fade_in_time: float = 4.0 +@export var max_base_alpha: float = 1.0 + +func _ready(): + var mat = get_active_material(0).duplicate() + set_surface_override_material(0, mat) + + #add_to_group("camere") + + #set alpha to 0 before first frame to avoid "pop" + mat.set_shader_parameter("base_alpha", 0.0) + + animate_godray(mat) + +func animate_godray(mat: ShaderMaterial): + var tween_alpha = create_tween() + tween_alpha.tween_property(mat, "shader_parameter/base_alpha", max_base_alpha, fade_in_time).from(0.0) + + var tween_intensity = create_tween() + #tween from 1.0 to 2.0 + tween_intensity.tween_property(mat, "shader_parameter/intensity_multiplier", 0.2, life_time * 0.3).from(1.0) + #tween to 0.5 + tween_intensity.tween_property(mat, "shader_parameter/intensity_multiplier", 0.5, life_time * 0.3) + #tween to 0.0 + tween_intensity.tween_property(mat, "shader_parameter/intensity_multiplier", 0.0, life_time * 0.4) + + tween_intensity.tween_callback(queue_free) + + var tween_edge = create_tween() + tween_edge.tween_property(mat, "shader_parameter/edge_fade_power", 0.5, life_time * 0.5).from(2.0) + tween_edge.tween_property(mat, "shader_parameter/edge_fade_power", 2.0, life_time * 0.5) diff --git a/core/daynight/godrays.gd.uid b/core/daynight/godrays.gd.uid new file mode 100644 index 0000000..5461a2b --- /dev/null +++ b/core/daynight/godrays.gd.uid @@ -0,0 +1 @@ +uid://d0kgbg142recf diff --git a/core/daynight/godrays.gdshader b/core/daynight/godrays.gdshader new file mode 100644 index 0000000..26ddb60 --- /dev/null +++ b/core/daynight/godrays.gdshader @@ -0,0 +1,43 @@ +shader_type spatial; +render_mode blend_add, depth_draw_never, cull_disabled, unshaded; + +uniform sampler2D depth_texture : hint_depth_texture, filter_nearest; +uniform sampler2D noise_texture : repeat_enable, filter_linear; + +uniform vec3 ray_color : source_color = vec3(1.0, 0.9, 0.7); +uniform float base_alpha : hint_range(0.0, 1.0) = 0.5; + +group_uniforms Noise_Stretching; +uniform float noise_stretching : hint_range(1.0, 50.0) = 20.0; +uniform float noise_scale : hint_range(0.1, 10.0) = 1.0; +uniform vec2 scrolling_speed = vec2(0.0, -0.1); + +group_uniforms Fades; +uniform float depth_softness = 1.0; +uniform float edge_fade_power = 2.0; + +uniform float intensity_multiplier : hint_range(0.0, 1.0) = 0.0; + +void fragment() { + vec2 stretchy_uv = UV * noise_scale; + + stretchy_uv.x *= noise_stretching; + + stretchy_uv += TIME * scrolling_speed; + + float noise = texture(noise_texture, stretchy_uv).r; + + float depth = textureLod(depth_texture, SCREEN_UV, 0.0).r; + vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0); + vec3 pixel_position = upos.xyz / upos.w; + float depth_fade = clamp((VERTEX.z - pixel_position.z) / depth_softness, 0.0, 1.0); + + float edge_fade = smoothstep(0.0, 0.5, UV.x) * smoothstep(1.0, 0.5, UV.x); + edge_fade = pow(edge_fade, edge_fade_power); // Rende la sfumatura più o meno aggressiva + + float vertical_fade = smoothstep(0.0, 0.2, UV.y) * smoothstep(1.0, 0.7, UV.y); + + ALBEDO = ray_color; + + ALPHA = noise * base_alpha * depth_fade * edge_fade * vertical_fade * intensity_multiplier; +} \ No newline at end of file diff --git a/core/daynight/godrays.gdshader.uid b/core/daynight/godrays.gdshader.uid new file mode 100644 index 0000000..bb07ff8 --- /dev/null +++ b/core/daynight/godrays.gdshader.uid @@ -0,0 +1 @@ +uid://caavljcth87so diff --git a/core/daynight/godrays.tres b/core/daynight/godrays.tres new file mode 100644 index 0000000..fa82953 --- /dev/null +++ b/core/daynight/godrays.tres @@ -0,0 +1,26 @@ +[gd_resource type="ShaderMaterial" format=3 uid="uid://cwbxvmtih5wsc"] + +[ext_resource type="Shader" uid="uid://dkmdtejrbks8n" path="res://Shaders/godrays.gdshader" id="1_pbkwa"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_xa3jw"] +noise_type = 3 +seed = 4 +frequency = 0.0096 +metadata/_preview_in_3d_space_ = true + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_eyx0r"] +noise = SubResource("FastNoiseLite_xa3jw") +seamless = true + +[resource] +render_priority = 0 +shader = ExtResource("1_pbkwa") +shader_parameter/noise_texture = SubResource("NoiseTexture2D_eyx0r") +shader_parameter/ray_color = Color(0.99999994, 0.782454, 0.2698755, 1) +shader_parameter/base_alpha = 1.0 +shader_parameter/noise_stretching = 3.17200010317 +shader_parameter/noise_scale = 1.0 +shader_parameter/scrolling_speed = Vector2(0, 0.15) +shader_parameter/depth_softness = 1.0 +shader_parameter/edge_fade_power = 2.0 +shader_parameter/intensity_multiplier = 0.5330000253175 diff --git a/core/daynight/lighting_albedo.png b/core/daynight/lighting_albedo.png new file mode 100644 index 0000000000000000000000000000000000000000..f02eaf1fd1f3c5fb15b94df76fb01a1120039455 GIT binary patch literal 21405 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 Pt&1XTk*6w7Tuu5v`)`*P literal 0 HcmV?d00001 diff --git a/core/daynight/lighting_albedo.png.import b/core/daynight/lighting_albedo.png.import new file mode 100644 index 0000000..1357131 --- /dev/null +++ b/core/daynight/lighting_albedo.png.import @@ -0,0 +1,41 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://csihlq3annhfu" +path.s3tc="res://.godot/imported/lighting_albedo.png-9b144a7d6c28cf34aed8366e91547306.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://core/daynight/lighting_albedo.png" +dest_files=["res://.godot/imported/lighting_albedo.png-9b144a7d6c28cf34aed8366e91547306.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/core/daynight/sky.gdshader b/core/daynight/sky.gdshader new file mode 100644 index 0000000..91a3a2f --- /dev/null +++ b/core/daynight/sky.gdshader @@ -0,0 +1,141 @@ +shader_type sky; + +uniform vec3 sky_top_color : source_color; +uniform vec3 sky_horizon_color : source_color; +uniform float night_intensity : hint_range(0.0, 1.0) = 0.0; + +group_uniforms Clouds; +uniform sampler2D cloud_noise : filter_linear_mipmap, repeat_enable; +uniform vec3 sun_color : source_color = vec3(1.0); +uniform vec4 cloud_center_color : source_color = vec4(1.0, 1.0, 1.0, 1.0); +uniform vec4 cloud_edge_color : source_color = vec4(0.8, 0.85, 0.9, 1.0); +uniform vec2 cloud_direction = vec2(0.5, 0.2); +uniform float cloud_speed : hint_range(0.0, 2.0) = 0.1; +uniform float cloud_scale = 0.5; +uniform float cloud_threshold : hint_range(0.0, 1.0) = 0.5; +uniform float cloud_edge_thickness : hint_range(0.0, 0.5) = 0.1; +uniform float cloud_edge_softness : hint_range(0.0, 0.5) = 0.05; + +group_uniforms Fixed_Start; +uniform float star_density : hint_range(0.0, 2000.0) = 1500.0; +uniform float star_rarity : hint_range(100.0, 5000.0) = 2500.0; +uniform float star_scale_variation : hint_range(0.0, 1.0) = 0.5; + +group_uniforms Shooting_Stars; +uniform sampler2D shooting_star_texture : hint_default_black, filter_linear_mipmap; +uniform vec4 shooting_star_color : source_color = vec4(1.0, 0.9, 0.7, 1.0); +uniform float shooting_star_density : hint_range(0.0, 1.0) = 0.3; +uniform float shooting_star_speed : hint_range(0.1, 3.0) = 1.0; +uniform float shooting_star_scale : hint_range(0.1, 20.0) = 5.0; +uniform float shooting_star_lifetime : hint_range(0.1, 1.0) = 0.5; +uniform float shooting_star_travel_dist : hint_range(1.0, 30.0) = 15.0; + + +//Utility +float hash(vec3 p) { + p = fract(p * 0.1031); + p += dot(p, p.yzx + 33.33); + return fract((p.x + p.y) * p.z); +} + +vec2 hash2(vec3 p) { + float h1 = hash(p); + float h2 = hash(p + vec3(57.1, 13.7, 9.3)); + return vec2(h1, h2); +} + +vec3 hash3(float seed) { + vec3 p = fract(vec3(seed) * vec3(0.1031, 0.1030, 0.0973)); + p += dot(p, p.yzx + 33.33); + return fract((p.xxy + p.yzz) * p.zyx); +} + + +void sky() { + float sky_v = clamp(EYEDIR.y, 0.0, 1.0); + vec3 final_sky = mix(sky_horizon_color, sky_top_color, sky_v); + + if (night_intensity > 0.05) { + + //Fixed Start + vec3 star_pos = EYEDIR * star_density; + vec2 rnd = hash2(star_pos); + float star_shape = pow(rnd.x, star_rarity); + float scale_factor = mix(1.0, (rnd.y * 0.8 + 0.2), star_scale_variation); + star_shape *= scale_factor; + star_shape *= pow(sky_v, 4.0); + float twinkle_speed = TIME * (1.0 + rnd.y * 5.0); + float twinkle_phase = rnd.x * 100.0; + float twinkle = sin(twinkle_speed + twinkle_phase) * 0.25 + 0.75; + star_shape *= twinkle; + final_sky += star_shape * night_intensity; + + //Shooting Stars + if (shooting_star_density > 0.001) { + float time_scaled = TIME * shooting_star_speed; + float time_seed = floor(time_scaled); + float time_progress = fract(time_scaled); + vec3 shoot_rnd = hash3(time_seed); + + if (shoot_rnd.z < shooting_star_density * night_intensity) { + vec3 center = normalize(vec3(shoot_rnd.x * 2.0 - 1.0, shoot_rnd.y * 0.6 + 0.4, shoot_rnd.z * 2.0 - 1.0)); + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(up, center)); + vec3 bitangent = cross(center, tangent); + + float random_angle = hash(vec3(time_seed)) * 6.28318; + float s = sin(random_angle); + float c = cos(random_angle); + + vec3 flight_axis = tangent * c - bitangent * s; + vec3 side_axis = tangent * s + bitangent * c; + + if (flight_axis.y > 0.0) { + flight_axis = -flight_axis; + side_axis = -side_axis; + } + + float proj_x = dot(EYEDIR, side_axis); + float proj_y = dot(EYEDIR, flight_axis); + float proj_z = dot(EYEDIR, center); + + if (proj_z > 0.0) { + vec2 uv = vec2(proj_x, -proj_y) * shooting_star_scale; + uv.y += (time_progress - (shooting_star_lifetime * 0.5)) * shooting_star_travel_dist; + uv.x += 0.5; + + float bounds = step(0.0, uv.x) * step(uv.x, 1.0) * step(0.0, uv.y) * step(uv.y, 1.0); + + if (bounds > 0.5) { + float star_tex = texture(shooting_star_texture, uv).r; + float fade_in = smoothstep(0.0, shooting_star_lifetime * 0.2, time_progress); + float fade_out = 1.0 - smoothstep(shooting_star_lifetime * 0.7, shooting_star_lifetime, time_progress); + float fade = fade_in * fade_out; + final_sky += star_tex * shooting_star_color.rgb * night_intensity * fade; + } + } + } + } + } + + //Clouds + vec2 cloud_uv = EYEDIR.xz / (EYEDIR.y + 0.5); + cloud_uv = cloud_uv * cloud_scale + (TIME * cloud_direction * cloud_speed); + float noise = texture(cloud_noise, cloud_uv).r; + float cloud_alpha = smoothstep(cloud_threshold, cloud_threshold + cloud_edge_softness, noise); + float color_gradient = smoothstep(cloud_threshold, cloud_threshold + cloud_edge_thickness, noise); + + vec3 tinted_center = cloud_center_color.rgb * sun_color; + vec3 tinted_edge = cloud_edge_color.rgb * sun_color; + vec3 day_cloud_color = mix(tinted_edge, tinted_center, color_gradient); + + vec3 night_cloud_color = sky_top_color * 0.4; + vec3 current_cloud_color = mix(day_cloud_color, night_cloud_color, night_intensity); + + cloud_alpha *= smoothstep(0.1, 0.4, EYEDIR.y); + + //Apply clouds to sky + final_sky = mix(final_sky, current_cloud_color, cloud_alpha); + + COLOR = final_sky; +} \ No newline at end of file diff --git a/core/daynight/sky.gdshader.uid b/core/daynight/sky.gdshader.uid new file mode 100644 index 0000000..951c77b --- /dev/null +++ b/core/daynight/sky.gdshader.uid @@ -0,0 +1 @@ +uid://bneoex8xpmcm8 diff --git a/core/daynight/snow.gdshader b/core/daynight/snow.gdshader new file mode 100644 index 0000000..e914066 --- /dev/null +++ b/core/daynight/snow.gdshader @@ -0,0 +1,19 @@ +shader_type spatial; +render_mode blend_mix, depth_draw_opaque; + +global uniform float global_snow_amount; + +uniform vec4 snow_color : source_color = vec4(0.95, 0.98, 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); + + ALBEDO = snow_color.rgb; + ALPHA = snow_mask; + + ROUGHNESS = 0.3; + SPECULAR = 0.5; +} \ No newline at end of file diff --git a/core/daynight/snow.gdshader.uid b/core/daynight/snow.gdshader.uid new file mode 100644 index 0000000..d764cee --- /dev/null +++ b/core/daynight/snow.gdshader.uid @@ -0,0 +1 @@ +uid://cjd72g8cgjear diff --git a/core/daynight/stars_albedo.png b/core/daynight/stars_albedo.png new file mode 100644 index 0000000000000000000000000000000000000000..6d745aaa5c78ac121485761f0006804c98bea7cb GIT binary patch literal 7890 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 void: + particles_wind = wind + particles_snow = snow + particles_fireflies = fireflies + particles_rain = rain + godray = ray + sun = thesun + environment = theenvironment + environment_config = environmentconfig + + set_rain() + + set_fireflies() + + set_wind() + + set_snow() + + set_lightning() + +func _ready() -> void: + #connect events + UIEvents.toggle_rain.connect(toggle_rain) + UIEvents.toggle_snow.connect(toggle_snow) + UIEvents.toggle_wind.connect(toggle_wind) + UIEvents.toggle_fireflies.connect(toggle_fireflies) + +func _process(delta: float) -> void: + var base_tint: Color + var base_sky_top: Color + var base_sky_horizon: Color + var base_fog_color: Color + var base_fog_density: float + var base_bloom: float + var base_exposure: float + var base_grad_top: Color + var base_grad_bot: Color + var base_grad_intensity: float + var base_rotation_sun: Vector3 + + var storm_is_active = is_raining and is_snowing + + if storm_is_active: + rain_intensity = move_toward(rain_intensity, 1.0, delta * 0.5) + if is_raining: + timer_next_lightning -= delta + if timer_next_lightning <= 0.0: + start_lightning() + set_lightning_timer() + else: + rain_intensity = move_toward(rain_intensity, 0.0, delta * 0.5) + + if environment_config.material_clouds: + var current_density = lerp(0.4, 1.0, rain_intensity) + environment_config.material_clouds.set_shader_parameter("cloud_density", current_density) + var current_sharpness = lerp(0.14, 0.0, rain_intensity) + environment_config.material_clouds.set_shader_parameter("center_sharpness", current_sharpness) + + if day_time <= 2.0: + var t = day_time - 1.0 + base_tint = environment_config.morning_color.lerp(environment_config.afternoon_color, t) + base_sky_top = environment_config.sky_top_morning.lerp(environment_config.sky_top_afternoon, t) + base_sky_horizon = environment_config.sky_horizon_morning.lerp(environment_config.sky_horizon_afternoon, t) + base_fog_color = environment_config.fog_color_morning.lerp(environment_config.fog_color_afternoon, t) + base_fog_density = lerp(environment_config.fog_density_morning, environment_config.fog_density_afternoon, t) + base_bloom = lerp(environment_config.glow_morning, environment_config.glow_afternoon, t) + base_exposure = lerp(environment_config.exposure_morning, environment_config.exposure_afternoon, t) + base_grad_top = environment_config.grad_top_morning.lerp(environment_config.grad_top_afternoon, t) + base_grad_bot = environment_config.grad_top_morning.lerp(environment_config.grad_bot_afternoon, t) + base_grad_intensity = lerp(environment_config.grad_intensity_morning, environment_config.grad_intensity_afternoon, t) + base_rotation_sun = environment_config.sun_rotation_morning.lerp(environment_config.sun_rotation_afternoon, t) + else: + var t = day_time - 2.0 + base_tint = environment_config.afternoon_color.lerp(environment_config.night_color, t) + base_sky_top = environment_config.sky_top_afternoon.lerp(environment_config.sky_top_night, t) + base_sky_horizon = environment_config.sky_horizon_afternoon.lerp(environment_config.sky_horizon_night, t) + base_fog_color = environment_config.fog_color_afternoon.lerp(environment_config.fog_color_night, t) + base_fog_density = lerp(environment_config.fog_density_afternoon, environment_config.fog_density_night, t) + base_bloom = lerp(environment_config.glow_afternoon, environment_config.glow_night, t) + base_exposure = lerp(environment_config.exposure_afternoon, environment_config.exposure_night, t) + base_grad_top = environment_config.grad_top_afternoon.lerp(environment_config.grad_top_night, t) + base_grad_bot = environment_config.grad_bot_afternoon.lerp(environment_config.grad_bot_night, t) + base_grad_intensity = lerp(environment_config.grad_intensity_afternoon, environment_config.grad_intensity_night, t) + base_rotation_sun = environment_config.sun_rotation_afternoon.lerp(environment_config.sun_rotation_night, t) + + var final_tint = base_tint.lerp(base_tint * environment_config.rain_mode_color, rain_intensity) + var final_sky_top = base_sky_top.lerp(base_sky_top * environment_config.rain_mode_color, rain_intensity) + 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) + + #Shader parameters for global trunk_shader + var final_grad_top = base_grad_top.lerp(base_grad_top * environment_config.rain_mode_color, rain_intensity) + var final_grad_bot = base_grad_bot.lerp(base_grad_bot * environment_config.rain_mode_color, rain_intensity) + + RenderingServer.global_shader_parameter_set("global_gradient_color_top", final_grad_top) + RenderingServer.global_shader_parameter_set("global_gradient_color_bot", final_grad_bot) + RenderingServer.global_shader_parameter_set("global_gradient_intensity", base_grad_intensity) + + var night_val = clamp(day_time - 2.0, 0.0, 1.0) + + #Snow exposure compensation + var snow_light_attenuation = lerp(1.0, 0.55, actual_snow_amount * (1.0 - night_val)) + var snow_glow_attenuation = lerp(1.0, 0.5, actual_snow_amount) + + var final_bloom = lerp(base_bloom, base_bloom * 0.5, rain_intensity) * snow_glow_attenuation + + # We calculate the final exposure by applying snow damping directly to the camera exposure + var final_esposizione = base_exposure * snow_light_attenuation + + var reflected_color = Color(0.4, 0.5, 0.6, 1.0) + var drops_color = final_sky_horizon.lerp(reflected_color, 0.15) + drops_color = drops_color.lerp(drops_color * 0.4, night_val) + + if environment_config.material_drops: + environment_config.material_drops.albedo_color = drops_color + + if sun: + sun.light_color = final_tint + sun.rotation_degrees = base_rotation_sun + #var target_energy = lerp(1.0, night_light_energy, night_val) + + # Sunlight scales normally based on weather/night (global exposure does the rest of the work) + #sun.light_energy = lerp(target_energy, target_energy * 0.4, rain_intensity) + + if environment and environment.environment: + environment.environment.ambient_light_color = final_tint + + # Apply fog + environment.environment.fog_enabled = true + environment.environment.fog_light_color = final_fog_color + environment.environment.fog_density = final_fog_density + + # Apply glow + environment.environment.glow_enabled = true + environment.environment.glow_intensity = final_bloom + + # Make sure the Tonemap Mode in the Environment is set to ACES or Filmic for best results! + environment.environment.tonemap_exposure = final_esposizione + + var sky_mat = environment.environment.sky.sky_material as ShaderMaterial + if sky_mat: + sky_mat.set_shader_parameter("sky_top_color", final_sky_top) + sky_mat.set_shader_parameter("sky_horizon_color", final_sky_horizon) + sky_mat.set_shader_parameter("sun_color", final_tint) + sky_mat.set_shader_parameter("night_intensity", night_val) + + if environment_config.material_fog: + environment_config.material_fog.set_shader_parameter("night_intensity", night_val) + environment_config.material_fog.set_shader_parameter("sun_color", final_tint) + + var e_night = day_time >= 2.5 + + #if nodo_polvere: + #nodo_polvere.visible = (not storm_is_active and not e_night) + + if particles_fireflies: + particles_fireflies.emitting = (not storm_is_active and e_night and thereare_fireflies) + + if particles_wind: + particles_wind.emitting = (not storm_is_active and not e_night and is_windy) + +#region fireflies +func toggle_fireflies(value: bool): + thereare_fireflies = value + +#disable fireflies and set default values and materials +func set_fireflies(): + if particles_fireflies: + particles_fireflies.visible = true + particles_fireflies.emitting = false + particles_fireflies.amount = environment_config.fireflies_amount + var proc_mat = particles_fireflies.process_material as ParticleProcessMaterial + if proc_mat: + proc_mat.emission_box_extents = Vector3(environment_config.fireflies_spawn_ray, environment_config.fireflies_spawn_height, environment_config.fireflies_spawn_ray) +#endregion + +#region Wind +func toggle_wind(value: bool): + is_windy = value + +#disable wind and set default values and materials +func set_wind(): + if particles_wind: + particles_wind.visible = true + particles_wind.emitting = false + particles_wind.amount = environment_config.wind_amount + var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial + if proc_mat_wind: + proc_mat_wind.emission_box_extents = Vector3(environment_config.wind_spawn_ray, environment_config.wind_spawn_height, environment_config.wind_spawn_ray) +#endregion + +#region Lightning +#set lightning +func set_lightning(): + lightning_light.name = "Lightning Light" + lightning_light.transform = Transform3D( + Vector3(-0.6238797, -0.342596, 0.7024259), # asse X + Vector3(0.0, 0.89879405, 0.43837115), # asse Y + Vector3(-0.7815204, 0.27349085, -0.56073934), # asse Z + Vector3(0.0, 0.0, 30.411049) # origine + ) + + lightning_light.light_color = Color(0.8, 1.0, 1.0, 1.0) + lightning_light.light_energy = 0.0 + lightning_light.shadow_enabled = true + add_child(lightning_light) + + create_lightning_sprite() + set_lightning_timer() + +func create_lightning_sprite(): + lightning_sprite = Sprite3D.new() + lightning_sprite.name = "Lightning Sprite" + + lightning_sprite.transform = Transform3D( + Basis( + Vector3(4, 0, 0), + Vector3(0, 7.32, 0), + Vector3(0, 0, 7.3) + ), + Vector3(0, 17.324, 30.411049) + ) + + lightning_sprite.modulate = Color(1, 1, 1, 0) + lightning_sprite.billboard = BaseMaterial3D.BILLBOARD_ENABLED + lightning_sprite.alpha_cut = SpriteBase3D.ALPHA_CUT_DISCARD + + #Add Texture + lightning_sprite.texture = load(environment_config.lightning_texture) + + add_child(lightning_sprite) + +#set next lightning timer +func set_lightning_timer(): + timer_next_lightning = randf_range(environment_config.lightning_min_time, environment_config.lightning_max_time) + +func start_lightning(): + if lightning_light: + var tween_luce = create_tween() + lightning_light.light_energy = 5.0 + + tween_luce.tween_interval(0.05) + tween_luce.tween_callback(func(): lightning_light.light_energy = 0.0) + tween_luce.tween_interval(0.05) + tween_luce.tween_callback(func(): lightning_light.light_energy = 2.0) + tween_luce.tween_method(func(val): lightning_light.light_energy = val, 2.0, 0.0, 0.2) + + var lightning_number = randi_range(environment_config.lightning_min, environment_config.lightning_max) + + for i in lightning_number: + if lightning_sprite: + var angolo_casuale = randf() * TAU + var distanza = randf_range(10.0, 40.0) + + lightning_sprite.position = Vector3(cos(angolo_casuale) * distanza, 10.0, sin(angolo_casuale) * distanza) + + lightning_sprite.modulate = environment_config.lightning_color + lightning_sprite.modulate.a = 1.0 + + var s = randf_range(environment_config.lightning_scale_min, environment_config.lightning_scale_max) + lightning_sprite.scale = Vector3(s, s, s) + + var tween_sprite = create_tween() + tween_sprite.tween_interval(0.2) + tween_sprite.tween_property(lightning_sprite, "modulate:a", 0.0, 0.4) + + if lightning_number > 1: + await get_tree().create_timer(randf_range(0.05, 0.15)).timeout +#endregion + +#region Rain + +#disable rain +func set_rain(): + if particles_rain: + particles_rain.visible = true + particles_rain.emitting = false + +func toggle_rain(value: bool): + is_raining = value + + if not particles_rain: + return + + if is_raining and is_snowing: + toggle_snow(false) + + if rain_tween and rain_tween.is_valid(): + rain_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) + 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()) + +func trigger_morning() -> void: + spawn_single_godray() + +func trigger_after_rain() -> void: + if day_time < 2.5: + var count: int = randi_range(1, environment_config.godray_max_rain) + for i in count: + spawn_single_godray() + +func spawn_single_godray() -> void: + var ray: Node3D = godray.instantiate() + get_tree().current_scene.add_child(ray) + + var random_x: float = randf_range(-environment_config.godray_spawn_radius, environment_config.godray_spawn_radius) + var random_z: float = randf_range(-environment_config.godray_spawn_radius, environment_config.godray_spawn_radius) + + #TODO: FLAVIO: fix global position using the camera position if needed + ray.global_position = Vector3(random_x, environment_config.godray_spawn_height, random_z) + ray.rotation_degrees = environment_config.godray_rotation_degrees + ray.scale = environment_config.godray_scale + + var godray_tween: Tween = create_tween() + godray_tween.tween_interval(2.0) + godray_tween.tween_property(ray, "scale", Vector3.ZERO, 2.0).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_SINE) + godray_tween.tween_callback(ray.queue_free) +#endregion + +#region Snow + +func toggle_snow(value: bool): + is_snowing = value + + if is_snowing and is_raining: + toggle_rain(false) + + # Fade particelle neve + if particles_snow: + if snow_particles_tween and snow_particles_tween.is_valid(): + snow_particles_tween.kill() + + if is_snowing: + particles_snow.amount_ratio = 0.0 + particles_snow.visible = true + 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) + 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 + 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) + +#disable snow and set default values and shader +func set_snow(value: float = 0.0): + 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 + +func set_snow_amount(value: float): + actual_snow_amount = value + RenderingServer.global_shader_parameter_set("global_snow_amount", value) + +#endregion + +#func _genera_evento_meteo_casuale() -> void: + #sto_cambiando_in_cinematic = true + # + #var scelta = randi() % 3 + # + #if scelta == 0: + #var nuovo_orario = randi() % 3 + #if menu_giornata: + #menu_giornata.selected = nuovo_orario + #_on_giornata_selezionata(nuovo_orario) + # + #elif scelta == 1: + #if not is_snowing: + #var piove = randf() > 0.5 + #if bottone_pioggia: + #bottone_pioggia.set_pressed_no_signal(piove) + #_on_pioggia_toggled(piove) + # + #elif scelta == 2: + #if not is_snowing: + #if not is_raining: + #if bottone_pioggia: + #bottone_pioggia.set_pressed_no_signal(true) + #_on_pioggia_toggled(true) + #_scatena_fulmine() + diff --git a/core/daynight/weather_controller.gd.uid b/core/daynight/weather_controller.gd.uid new file mode 100644 index 0000000..595d2a9 --- /dev/null +++ b/core/daynight/weather_controller.gd.uid @@ -0,0 +1 @@ +uid://33hfgtk73je1 diff --git a/core/daynight/wind.gdshader b/core/daynight/wind.gdshader new file mode 100644 index 0000000..6c258a0 --- /dev/null +++ b/core/daynight/wind.gdshader @@ -0,0 +1,18 @@ +shader_type spatial; +render_mode unshaded; +/* +uniform float time_scale = 3.0; +uniform float wave_amplitude = 0.5; +uniform float wave_frequency = 1.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; +} + +void fragment() { + ALBEDO = COLOR.rgb; + ALPHA = COLOR.a; +}*/ \ No newline at end of file diff --git a/core/daynight/wind.gdshader.uid b/core/daynight/wind.gdshader.uid new file mode 100644 index 0000000..01567b9 --- /dev/null +++ b/core/daynight/wind.gdshader.uid @@ -0,0 +1 @@ +uid://bb1jjwe31fl7o diff --git a/core/environment_config.gd b/core/environment_config.gd new file mode 100644 index 0000000..de1c8bc --- /dev/null +++ b/core/environment_config.gd @@ -0,0 +1,99 @@ +@tool +class_name EnvironmentConfig +extends Resource + +@export_group("Directional Lights and Environment") +@export var morning_color: Color = Color(1.0, 0.9, 0.8, 1.0) +@export var afternoon_color: Color = Color(1.0, 0.6, 0.2, 1.0) +@export var night_color: Color = Color(0.1, 0.1, 0.3, 1.0) + +@export_group("Sun Rotation") +@export var sun_rotation_morning: Vector3 = Vector3(-15.0, 45.0, 0.0) +@export var sun_rotation_afternoon: Vector3 = Vector3(-75.0, 10.0, 0.0) +@export var sun_rotation_night: Vector3 = Vector3(-35.0, -120.0, 0.0) + +@export_group("General Exposition") +@export var exposure_morning: float = 1.0 +@export var exposure_afternoon: float = 0.95 +@export var exposure_night: float = 0.4 + +@export_group("Sky Colors - Top") +@export var sky_top_morning: Color = Color(0.35, 0.65, 0.9, 1.0) +@export var sky_top_afternoon: Color = Color(0.7, 0.45, 0.2, 1.0) +@export var sky_top_night: Color = Color(0.05, 0.05, 0.15, 1.0) + +@export_group("Sky Color - Horizon") +@export var sky_horizon_morning: Color = Color(0.75, 0.85, 0.95, 1.0) +@export var sky_horizon_afternoon: Color = Color(0.95, 0.65, 0.35, 1.0) +@export var sky_horizon_night: Color = Color(0.15, 0.1, 0.25, 1.0) + +@export_subgroup("Gradient - Top") +@export var grad_top_morning: Color = Color(0.8, 0.4, 0.2, 1.0) +@export var grad_top_afternoon: Color = Color(0.2, 0.3, 0.5, 1.0) +@export var grad_top_night: Color = Color(0.05, 0.05, 0.1, 1.0) + +@export_subgroup("Gradient - Bottom") +@export var grad_bot_morning: Color = Color(0.5, 0.2, 0.1, 1.0) +@export var grad_bot_afternoon: Color = Color(0.1, 0.15, 0.25, 1.0) +@export var grad_bot_night: Color = Color(0.01, 0.01, 0.05, 1.0) + +@export_subgroup("Gradient Intensity") +@export var grad_intensity_morning: float = 0.5 +@export var grad_intensity_afternoon: float = 0.3 +@export var grad_intensity_night: float = 0.8 + +@export_group("Fog") +@export var fog_color_morning: Color = Color(0.75, 0.85, 0.95, 1.0) +@export var fog_color_afternoon: Color = Color(0.95, 0.65, 0.35, 1.0) +@export var fog_color_night: Color = Color(0.15, 0.1, 0.25, 1.0) +@export var fog_density_morning: float = 0.005 +@export var fog_density_afternoon: float = 0.002 +@export var fog_density_night: float = 0.015 + +@export_group("Glow") +@export var glow_morning: float = 1.2 +@export var glow_afternoon: float = 0.8 +@export var glow_night: float = 2.0 + +@export_group("Environment Materials") +@export var material_fog: ShaderMaterial +@export var material_drops: StandardMaterial3D +@export var material_clouds: ShaderMaterial + +@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_group("Lightning and Thunders") +@export var lightning_min_time: float = 5.0 +@export var lightning_max_time: float = 15.0 +@export var lightning_color: Color = Color(1.0, 1.0, 0.8, 1.0) +@export var lightning_min: int = 1 +@export var lightning_max: int = 3 +@export var lightning_scale_min: float = 1.0 +@export var lightning_scale_max: float = 3.0 +@export var lightning_texture: String = "res://core/daynight/lighting_albedo.png" +@export var weather_event_interval: float = 8.0 + +@export_group("God Rays") +@export var godray_max_rain: int = 8 +@export var godray_spawn_radius: float = 15.0 +@export var godray_spawn_offset: Vector3 = Vector3(15.0, 5.0, -15.0) +@export var godray_rotation_degrees: Vector3 = Vector3(-45.0, 45.0, -30.0) +@export var godray_spawn_height: float = 5.0 +@export var godray_scale: Vector3 = Vector3(2.0, 6.0, 2.0) + +@export_group("Snow") +@export var snow_amount: int = 2000 +@export var snow_transaction_time: float = 10.0 +@export var snow_fade_time: float = 5.0 + +@export_group("Wind") +@export var wind_amount: int = 100 +@export var wind_spawn_ray: float = 25.0 +@export var wind_spawn_height: float = 5.0 + +@export_group("Fireflies") +@export var fireflies_amount: int = 60 +@export var fireflies_spawn_ray: float = 20.0 +@export var fireflies_spawn_height: float = 3.0 diff --git a/core/environment_config.gd.uid b/core/environment_config.gd.uid new file mode 100644 index 0000000..316c9b7 --- /dev/null +++ b/core/environment_config.gd.uid @@ -0,0 +1 @@ +uid://butda6k2tli3o diff --git a/core/environment_config_resource.tres b/core/environment_config_resource.tres new file mode 100644 index 0000000..55b938a --- /dev/null +++ b/core/environment_config_resource.tres @@ -0,0 +1,7 @@ +[gd_resource type="Resource" script_class="DayNightConfig" format=3 uid="uid://bem36s551mtw8"] + +[ext_resource type="Script" uid="uid://butda6k2tli3o" path="res://resources/environment_config.gd" id="1_u2jy3"] + +[resource] +script = ExtResource("1_u2jy3") +metadata/_custom_type_script = "uid://butda6k2tli3o" diff --git a/core/ui_events.gd b/core/ui_events.gd new file mode 100644 index 0000000..1b24a02 --- /dev/null +++ b/core/ui_events.gd @@ -0,0 +1,7 @@ +extends Node + +#Weather signals +signal toggle_rain(value: bool) +signal toggle_snow(value: bool) +signal toggle_wind(value: bool) +signal toggle_fireflies(value: bool) diff --git a/core/ui_events.gd.uid b/core/ui_events.gd.uid new file mode 100644 index 0000000..df41f25 --- /dev/null +++ b/core/ui_events.gd.uid @@ -0,0 +1 @@ +uid://dehu28iq27mbn diff --git a/docs/museums/daynight/camera_3d.gd b/docs/museums/daynight/camera_3d.gd new file mode 100644 index 0000000..62ea50b --- /dev/null +++ b/docs/museums/daynight/camera_3d.gd @@ -0,0 +1,70 @@ +extends Camera3D + +@export_group("Movement") +@export var move_speed: float = 10.0 +@export var fast_move_multiplier: float = 3.0 +@export var move_smoothing: float = 10.0 + +@export_group("Look") +@export var mouse_sensitivity: float = 0.3 +@export var invert_y: bool = false + +var _velocity: Vector3 = Vector3.ZERO +var _yaw: float = 0.0 # Y rotation +var _pitch: float = 0.0 # X rotation +var _is_active: bool = false + +func _ready() -> void: + #Current rotation + _yaw = rotation_degrees.y + _pitch = rotation_degrees.x + +func _unhandled_input(event: InputEvent) -> void: + #Activate camera movement using mouse right button + if event is InputEventMouseButton: + if event.button_index == MOUSE_BUTTON_RIGHT: + _is_active = event.pressed + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if _is_active else Input.MOUSE_MODE_VISIBLE + + if event is InputEventMouseMotion and _is_active: + _yaw -= event.relative.x * mouse_sensitivity + var pitch_delta = event.relative.y * mouse_sensitivity + _pitch += pitch_delta if invert_y else -pitch_delta + _pitch = clamp(_pitch, -89.0, 89.0) + + if event.is_action_pressed("ui_cancel"): + _is_active = false + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + +func _physics_process(delta: float) -> void: + rotation_degrees.y = _yaw + rotation_degrees.x = _pitch + + if not _is_active: + _velocity = _velocity.lerp(Vector3.ZERO, move_smoothing * delta) + position += _velocity * delta + return + + var input_dir := Vector3.ZERO + + if Input.is_key_pressed(KEY_W) or Input.is_key_pressed(KEY_UP): + input_dir -= basis.z # avanti + if Input.is_key_pressed(KEY_S) or Input.is_key_pressed(KEY_DOWN): + input_dir += basis.z # indietro + if Input.is_key_pressed(KEY_A) or Input.is_key_pressed(KEY_LEFT): + input_dir -= basis.x # sinistra + if Input.is_key_pressed(KEY_D) or Input.is_key_pressed(KEY_RIGHT): + input_dir += basis.x # destra + if Input.is_key_pressed(KEY_E) or Input.is_key_pressed(KEY_PAGEUP): + input_dir += Vector3.UP # su (world space) + if Input.is_key_pressed(KEY_Q) or Input.is_key_pressed(KEY_PAGEDOWN): + input_dir += Vector3.DOWN # giù (world space) + + if input_dir != Vector3.ZERO: + input_dir = input_dir.normalized() + + var speed := move_speed * fast_move_multiplier if Input.is_key_pressed(KEY_SHIFT) else move_speed + + var target_velocity := input_dir * speed + _velocity = _velocity.lerp(target_velocity, move_smoothing * delta) + position += _velocity * delta diff --git a/docs/museums/daynight/camera_3d.gd.uid b/docs/museums/daynight/camera_3d.gd.uid new file mode 100644 index 0000000..0146cd0 --- /dev/null +++ b/docs/museums/daynight/camera_3d.gd.uid @@ -0,0 +1 @@ +uid://ccdd52apoh4ir diff --git a/docs/museums/daynight/control.gd b/docs/museums/daynight/control.gd new file mode 100644 index 0000000..0d251a1 --- /dev/null +++ b/docs/museums/daynight/control.gd @@ -0,0 +1,13 @@ +extends Control + +func _on_rain_toggled(toggled_on: bool) -> void: + UIEvents.toggle_rain.emit(toggled_on) + +func _on_snow_toggled(toggled_on: bool) -> void: + UIEvents.toggle_snow.emit(toggled_on) + +func _on_wind_toggled(toggled_on: bool) -> void: + UIEvents.toggle_wind.emit(toggled_on) + +func _on_fireflies_toggled(toggled_on: bool) -> void: + UIEvents.toggle_fireflies.emit(toggled_on) diff --git a/docs/museums/daynight/control.gd.uid b/docs/museums/daynight/control.gd.uid new file mode 100644 index 0000000..2e02358 --- /dev/null +++ b/docs/museums/daynight/control.gd.uid @@ -0,0 +1 @@ +uid://cx2tlvxhvatj5 diff --git a/docs/museums/daynight/museum_daynight.tscn b/docs/museums/daynight/museum_daynight.tscn new file mode 100644 index 0000000..07ad532 --- /dev/null +++ b/docs/museums/daynight/museum_daynight.tscn @@ -0,0 +1,180 @@ +[gd_scene format=3 uid="uid://bjkhawylawqof"] + +[ext_resource type="PackedScene" uid="uid://cmuvmmp7xam4o" path="res://core/daynight/environment_management.tscn" id="1_daynt"] +[ext_resource type="Shader" uid="uid://bneoex8xpmcm8" path="res://core/daynight/sky.gdshader" id="3_jiovi"] +[ext_resource type="Texture2D" uid="uid://dest0qa7vaid0" path="res://core/daynight/stars_albedo.png" id="4_abyor"] +[ext_resource type="Script" uid="uid://brcimd12tx3dm" path="res://core/daynight/edge_detection_compositor.gd" id="5_jgh18"] +[ext_resource type="Script" uid="uid://cx2tlvxhvatj5" path="res://docs/museums/daynight/control.gd" id="6_q52t1"] +[ext_resource type="Script" uid="uid://ccdd52apoh4ir" path="res://docs/museums/daynight/camera_3d.gd" id="7_p2t1d"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_jiovi"] +fractal_lacunarity = 1.915 +fractal_gain = 0.53 +fractal_weighted_strength = 0.35 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_abyor"] +noise = SubResource("FastNoiseLite_jiovi") +seamless = true + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_abyor"] +shader = ExtResource("3_jiovi") +shader_parameter/sky_top_color = Color(0, 0.84999996, 1.5999999, 1) +shader_parameter/sky_horizon_color = Color(0.55, 1.0500001, 1.55, 1) +shader_parameter/night_intensity = 0.0 +shader_parameter/cloud_noise = SubResource("NoiseTexture2D_abyor") +shader_parameter/sun_color = Color(1, 1.1999999, 1.4000001, 1) +shader_parameter/cloud_center_color = Color(1, 1, 1, 1) +shader_parameter/cloud_edge_color = Color(0.8, 0.85, 0.9, 1) +shader_parameter/cloud_direction = Vector2(0.5, 0.2) +shader_parameter/cloud_speed = 0.1 +shader_parameter/cloud_scale = 0.5 +shader_parameter/cloud_threshold = 0.5 +shader_parameter/cloud_edge_thickness = 0.406000019285 +shader_parameter/cloud_edge_softness = 0.0 +shader_parameter/star_density = 1500.0 +shader_parameter/star_rarity = 2500.0 +shader_parameter/star_scale_variation = 0.5 +shader_parameter/shooting_star_texture = ExtResource("4_abyor") +shader_parameter/shooting_star_color = Color(0.38431373, 0.61960787, 0.23137255, 1) +shader_parameter/shooting_star_density = 1.0 +shader_parameter/shooting_star_speed = 1.0 +shader_parameter/shooting_star_scale = 5.0 +shader_parameter/shooting_star_lifetime = 0.5 +shader_parameter/shooting_star_travel_dist = 15.0 + +[sub_resource type="Sky" id="Sky_50i22"] +sky_material = SubResource("ShaderMaterial_abyor") + +[sub_resource type="Environment" id="Environment_icuhg"] +background_mode = 2 +sky = SubResource("Sky_50i22") +ambient_light_color = Color(1, 1.1999999, 1.4000001, 1) +tonemap_exposure = 1.05 +ssao_enabled = true +ssao_radius = 0.5 +ssao_intensity = 14.0 +ssao_detail = 0.0 +ssil_enabled = true +glow_enabled = true +glow_levels/4 = 1.0 +glow_intensity = 1.6 +glow_strength = 0.65 +glow_bloom = 1.0 +fog_enabled = true +fog_mode = 1 +fog_light_color = Color(0.55, 1.0500001, 1.55, 1) +fog_density = 0.008 +fog_sky_affect = 0.0 + +[sub_resource type="CompositorEffect" id="CompositorEffect_q52t1"] +resource_local_to_scene = false +resource_name = "" +enabled = true +effect_callback_type = 1 +access_resolved_color = false +access_resolved_depth = false +needs_motion_vectors = false +needs_normal_roughness = false +script = ExtResource("5_jgh18") +metadata/_custom_type_script = "uid://brcimd12tx3dm" + +[sub_resource type="Compositor" id="Compositor_jbfcc"] +compositor_effects = Array[CompositorEffect]([SubResource("CompositorEffect_q52t1")]) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_p2t1d"] +albedo_color = Color(0.135, 0.45, 0.18224995, 1) + +[sub_resource type="BoxMesh" id="BoxMesh_p2t1d"] +size = Vector3(200, 0.08, 200) + +[node name="Museum" type="Node3D" unique_id=1411616506] + +[node name="DayNight" parent="." unique_id=1578787116 instance=ExtResource("1_daynt")] + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=6398994] +environment = SubResource("Environment_icuhg") +compositor = SubResource("Compositor_jbfcc") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=565189502] +transform = Transform3D(0.17364818, 0.69636416, 0.69636416, 0, 0.7071067, -0.7071067, -0.9848075, 0.12278782, 0.12278782, 0, 0, 0) +light_color = Color(1, 1.1999999, 1.4000001, 1) +light_indirect_energy = 0.0 +light_volumetric_fog_energy = 0.0 +shadow_enabled = true +shadow_bias = 0.2 +shadow_normal_bias = 0.0 +shadow_opacity = 0.97 +shadow_blur = 0.4 +directional_shadow_mode = 0 +directional_shadow_fade_start = 0.9 + +[node name="Control" type="Control" parent="." unique_id=1032167802] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("6_q52t1") + +[node name="Snow" type="CheckButton" parent="Control" unique_id=1267493556] +layout_mode = 0 +offset_left = 21.0 +offset_top = 13.0 +offset_right = 109.0 +offset_bottom = 44.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_focus_color = Color(0, 0, 0, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1) +text = "Snow" + +[node name="Rain" type="CheckButton" parent="Control" unique_id=1387886007] +layout_mode = 0 +offset_left = 21.0 +offset_top = 41.0 +offset_right = 109.0 +offset_bottom = 72.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_focus_color = Color(0, 0, 0, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1) +text = "Rain" + +[node name="Wind" type="CheckButton" parent="Control" unique_id=1160113828] +layout_mode = 0 +offset_left = 21.0 +offset_top = 71.0 +offset_right = 109.0 +offset_bottom = 102.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_focus_color = Color(0, 0, 0, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1) +text = "Wind" + +[node name="Fireflies" type="CheckButton" parent="Control" unique_id=1177089839] +layout_mode = 0 +offset_left = 21.0 +offset_top = 100.0 +offset_right = 130.0 +offset_bottom = 131.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_focus_color = Color(0, 0, 0, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1) +text = "Fireflies" + +[node name="Camera3D" type="Camera3D" parent="." unique_id=1893906598] +transform = Transform3D(1, 0, 0, 0, 0.99452555, -0.10449375, 0, 0.10449375, 0.99452555, 0.48949432, 25.39013, 0) +script = ExtResource("7_p2t1d") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1335123628] +material_override = SubResource("StandardMaterial3D_p2t1d") +mesh = SubResource("BoxMesh_p2t1d") + +[connection signal="toggled" from="Control/Snow" to="Control" method="_on_snow_toggled"] +[connection signal="toggled" from="Control/Rain" to="Control" method="_on_rain_toggled"] +[connection signal="toggled" from="Control/Wind" to="Control" method="_on_wind_toggled"] diff --git a/docs/museums/daynight/museum_daynight.tscn12025044106.tmp b/docs/museums/daynight/museum_daynight.tscn12025044106.tmp new file mode 100644 index 0000000..b66be9f --- /dev/null +++ b/docs/museums/daynight/museum_daynight.tscn12025044106.tmp @@ -0,0 +1,151 @@ +[gd_scene format=3 uid="uid://bjkhawylawqof"] + +[ext_resource type="Script" uid="uid://d27xbipk650kf" path="res://core/daynight/day_night.gd" id="1_o8twy"] +[ext_resource type="Script" uid="uid://butda6k2tli3o" path="res://core/environment_config.gd" id="2_ecsq1"] +[ext_resource type="Shader" uid="uid://bneoex8xpmcm8" path="res://core/daynight/sky.gdshader" id="3_jiovi"] +[ext_resource type="Texture2D" uid="uid://dest0qa7vaid0" path="res://core/daynight/stars_albedo.png" id="4_abyor"] +[ext_resource type="Script" uid="uid://brcimd12tx3dm" path="res://core/daynight/edge_detection_compositor.gd" id="5_jgh18"] +[ext_resource type="Script" uid="uid://cx2tlvxhvatj5" path="res://docs/museums/daynight/control.gd" id="6_q52t1"] + +[sub_resource type="Resource" id="Resource_50i22"] +script = ExtResource("2_ecsq1") +metadata/_custom_type_script = "uid://butda6k2tli3o" + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_jiovi"] +fractal_lacunarity = 1.915 +fractal_gain = 0.53 +fractal_weighted_strength = 0.35 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_abyor"] +noise = SubResource("FastNoiseLite_jiovi") +seamless = true + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_abyor"] +shader = ExtResource("3_jiovi") +shader_parameter/sky_top_color = Color(0.35, 0.65, 0.9, 1) +shader_parameter/sky_horizon_color = Color(0.75, 0.85, 0.95, 1) +shader_parameter/night_intensity = 0.0 +shader_parameter/cloud_noise = SubResource("NoiseTexture2D_abyor") +shader_parameter/sun_color = Color(1, 0.9, 0.8, 1) +shader_parameter/cloud_center_color = Color(1, 1, 1, 1) +shader_parameter/cloud_edge_color = Color(0.8, 0.85, 0.9, 1) +shader_parameter/cloud_direction = Vector2(0.5, 0.2) +shader_parameter/cloud_speed = 0.1 +shader_parameter/cloud_scale = 0.5 +shader_parameter/cloud_threshold = 0.5 +shader_parameter/cloud_edge_thickness = 0.406000019285 +shader_parameter/cloud_edge_softness = 0.0 +shader_parameter/star_density = 1500.0 +shader_parameter/star_rarity = 2500.0 +shader_parameter/star_scale_variation = 0.5 +shader_parameter/shooting_star_texture = ExtResource("4_abyor") +shader_parameter/shooting_star_color = Color(0.38431373, 0.61960787, 0.23137255, 1) +shader_parameter/shooting_star_density = 1.0 +shader_parameter/shooting_star_speed = 1.0 +shader_parameter/shooting_star_scale = 5.0 +shader_parameter/shooting_star_lifetime = 0.5 +shader_parameter/shooting_star_travel_dist = 15.0 + +[sub_resource type="Sky" id="Sky_50i22"] +sky_material = SubResource("ShaderMaterial_abyor") + +[sub_resource type="Environment" id="Environment_icuhg"] +background_mode = 2 +sky = SubResource("Sky_50i22") +ambient_light_color = Color(1, 0.9, 0.8, 1) +ssao_enabled = true +ssao_radius = 0.5 +ssao_intensity = 14.0 +ssao_detail = 0.0 +ssil_enabled = true +glow_enabled = true +glow_levels/4 = 1.0 +glow_intensity = 1.2 +glow_strength = 0.65 +glow_bloom = 1.0 +fog_enabled = true +fog_mode = 1 +fog_light_color = Color(0.75, 0.85, 0.95, 1) +fog_density = 0.005 +fog_sky_affect = 0.0 + +[sub_resource type="CompositorEffect" id="CompositorEffect_q52t1"] +resource_local_to_scene = false +resource_name = "" +enabled = true +effect_callback_type = 1 +access_resolved_color = false +access_resolved_depth = false +needs_motion_vectors = false +needs_normal_roughness = false +script = ExtResource("5_jgh18") +metadata/_custom_type_script = "uid://brcimd12tx3dm" + +[sub_resource type="Compositor" id="Compositor_jbfcc"] +compositor_effects = Array[CompositorEffect]([SubResource("CompositorEffect_q52t1")]) + +[node name="Museum" type="Node3D" unique_id=1411616506] + +[node name="DayNightRoot" type="Node3D" parent="." unique_id=1578787116] +script = ExtResource("1_o8twy") +environment_config = SubResource("Resource_50i22") + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=6398994] +environment = SubResource("Environment_icuhg") +compositor = SubResource("Compositor_jbfcc") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=565189502] +transform = Transform3D(0.70710677, -0.1830127, 0.68301266, 0, 0.9659258, 0.25881904, -0.70710677, -0.1830127, 0.68301266, 0, 0, 0) +light_color = Color(1, 0.9, 0.8, 1) +light_indirect_energy = 0.0 +light_volumetric_fog_energy = 0.0 +shadow_enabled = true +shadow_bias = 0.2 +shadow_normal_bias = 0.0 +shadow_opacity = 0.97 +shadow_blur = 0.4 +directional_shadow_mode = 0 +directional_shadow_fade_start = 0.9 + +[node name="Control" type="Control" parent="." unique_id=1032167802] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("6_q52t1") + +[node name="Snow" type="CheckButton" parent="Control" unique_id=1267493556] +layout_mode = 0 +offset_left = 21.0 +offset_top = 13.0 +offset_right = 109.0 +offset_bottom = 44.0 +text = "Snow" + +[node name="Rain" type="CheckButton" parent="Control" unique_id=1387886007] +layout_mode = 0 +offset_left = 21.0 +offset_top = 41.0 +offset_right = 109.0 +offset_bottom = 72.0 +text = "Rain" + +[node name="Wind" type="CheckButton" parent="Control" unique_id=1160113828] +layout_mode = 0 +offset_left = 21.0 +offset_top = 71.0 +offset_right = 109.0 +offset_bottom = 102.0 +text = "Wind" + +[node name="Fireflies" type="CheckButton" parent="Control" unique_id=1177089839] +layout_mode = 0 +offset_left = 21.0 +offset_top = 100.0 +offset_right = 130.0 +offset_bottom = 131.0 +text = "Fireflies" + +[connection signal="toggled" from="Control/Snow" to="Control" method="_on_snow_toggled"] +[connection signal="toggled" from="Control/Rain" to="Control" method="_on_rain_toggled"] +[connection signal="toggled" from="Control/Wind" to="Control" method="_on_wind_toggled"] diff --git a/project.godot b/project.godot index ab77a38..f4e8f42 100644 --- a/project.godot +++ b/project.godot @@ -11,13 +11,46 @@ config_version=5 [application] config/name="tgcc" +run/main_scene="uid://bjkhawylawqof" config/features=PackedStringArray("4.6", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +UIEvents="*uid://dehu28iq27mbn" + +[display] + +window/size/viewport_width=1920 +window/size/viewport_height=1080 +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" + [physics] 3d/physics_engine="Jolt Physics" [rendering] +textures/canvas_textures/default_texture_filter=2 rendering_device/driver.windows="d3d12" +anti_aliasing/quality/use_taa=true + +[shader_globals] + +global_gradient_color_bot={ +"type": "color", +"value": Color(0, 0, 0, 1) +} +global_gradient_color_top={ +"type": "color", +"value": Color(0, 0, 0, 1) +} +global_gradient_intensity={ +"type": "float", +"value": 0.0 +} +global_snow_amount={ +"type": "float", +"value": 0.0 +}