14 Commits

Author SHA1 Message Date
8c7f1c3c82 fix stutter 2026-04-30 16:21:08 +02:00
b7308c5d66 fix fog 2026-04-30 12:20:12 +02:00
ff93a7ab2c add fog 2026-04-30 07:13:34 +02:00
122ec189eb fix water colors 2026-04-30 06:55:28 +02:00
889334e7a3 fix snow and water ripples + add water colors 2026-04-30 06:53:54 +02:00
Matteo Sonaglioni
ead4e557c4 Squashed commit of the following:
commit d8496f4cc7
Author: Matteo Sonaglioni <sonaglioni.matteo7@gmail.com>
Date:   Wed Apr 29 11:01:07 2026 +0200

    tweak enviromentconfig

commit 84538679f3
Author: Matteo Sonaglioni <sonaglioni.matteo7@gmail.com>
Date:   Wed Apr 29 09:29:48 2026 +0200

    museum_map
2026-04-29 11:02:24 +02:00
Matteo Sonaglioni
b868584b78 Squashed commit of the following:
commit 53646e36f0
Author: Matteo Sonaglioni <sonaglioni.matteo7@gmail.com>
Date:   Thu Apr 23 17:24:36 2026 +0200

    map - zoos

commit 88dd7c3ad8
Author: Matteo Sonaglioni <sonaglioni.matteo7@gmail.com>
Date:   Thu Apr 23 16:48:14 2026 +0200

    fix railway chunk
2026-04-28 10:06:03 +02:00
d668804038 add label to see current weather 2026-04-24 17:51:49 +02:00
e8f2c4db84 add random weather function 2026-04-24 17:44:43 +02:00
72c933ba73 add random start for train o start from a stop 2026-04-24 17:08:24 +02:00
8f02afa796 update snow parameters 2026-04-24 16:18:36 +02:00
211455f5da fix materials for wind and add new snow system 2026-04-24 15:36:10 +02:00
ab87c7f478 fix set shader on nodes 2026-04-24 12:22:46 +02:00
b95e8598b2 some fix 2026-04-24 10:58:07 +02:00
47 changed files with 2551 additions and 720 deletions

View File

@@ -1,5 +1,9 @@
extends Node3D
const CHUNK_GENERATION_STEPS_PER_FRAME: int = 2
const CHUNK_CLEANUP_STEPS_PER_FRAME: int = 4
const LAMPPOST_WIRE_STEPS_PER_FRAME: int = 1
@export_group("Rails")
@export var rail_path: Path3D
@@ -20,6 +24,12 @@ var last_pos_train: Vector2i = Vector2i(999999, 999999)
var noise_generator: FastNoiseLite
var altitude_generator: FastNoiseLite
var wire_connections: Dictionary = {}
var chunk_candidate_cache: Dictionary = {}
var pending_generation_cells: Array[Vector2i] = []
var pending_cleanup_cells: Array[Vector2i] = []
var pending_wire_cells: Array[Vector2i] = []
var pending_wire_lookup: Dictionary = {}
var pending_radar_update: bool = false
var manual_biome: Biome = null
@@ -36,6 +46,7 @@ func _ready() -> void:
altitude_generator.seed = randi()
altitude_generator.frequency = district_scale * 0.5
_warm_chunk_candidate_cache()
_update_set_pieces()
func _update_set_pieces() -> void:
@@ -47,7 +58,7 @@ func _update_set_pieces() -> void:
if not "exclusive_biome" in sp or sp.exclusive_biome == "":
print("⚠️ Set Piece '", sp.name, "' not have exclusive biome -> always visible.")
continue
var local_biome = ""
if manual_biome != null:
local_biome = manual_biome.nome
@@ -55,7 +66,7 @@ func _update_set_pieces() -> void:
var grid_x = roundi(sp.global_position.x / chunk_size)
var grid_z = roundi(sp.global_position.z / chunk_size)
local_biome = _get_procedural_biome_name(noise_generator.get_noise_2d(grid_x, grid_z))
print("Analyze: '", sp.name, "' | Need: [", sp.exclusive_biome, "] | Current biome is: [", local_biome, "]")
if local_biome == sp.exclusive_biome:
sp.show()
@@ -67,15 +78,18 @@ func _update_set_pieces() -> void:
print(" ❌ Temple is an invisible ghost.")
func _destroy_and_regenrate_world() -> void:
_warm_chunk_candidate_cache()
_clear_pending_world_work()
#Turn off old temples
_update_set_pieces()
#Destroy all models
for pos in board.keys():
var cella = board[pos]
if cella["tipo"] == "bioma":
if cella.has("nodo") and is_instance_valid(cella["nodo"]):
cella["nodo"].queue_free()
if cella["type"] != "obstacle":
if cella.has("node") and is_instance_valid(cella["node"]):
cella["node"].queue_free()
#Clean board and wire connections
board.clear()
@@ -83,9 +97,20 @@ func _destroy_and_regenrate_world() -> void:
#Create train
last_pos_train = Vector2i(999999, 999999)
_train_radar()
last_pos_train = Vector2i(999999, 999999)
_train_radar()
if rail_path != null and rail_path.train_instance != null:
var train_pos = rail_path.train_instance.global_position
var current_pos = Vector2i(roundi(train_pos.x / chunk_size), roundi(train_pos.z / chunk_size))
_refresh_world_work(current_pos)
pending_radar_update = true
func _process(_delta: float) -> void:
_drain_cleanup_queue()
_drain_generation_queue()
_drain_wire_queue()
if pending_radar_update:
pending_radar_update = false
_train_radar()
func _physics_process(_delta: float) -> void:
if rail_path == null or rail_path.train_instance == null: return
@@ -97,9 +122,8 @@ func _physics_process(_delta: float) -> void:
if current_pos != last_pos_train:
last_pos_train = current_pos
_generate_pieces_around_train(current_pos)
_clean_far_chunks(current_pos)
_train_radar()
_refresh_world_work(current_pos)
pending_radar_update = true
func collect_all_chunkinfo(root: Node, list: Array[Node]) -> void:
if root == null: return
@@ -110,11 +134,173 @@ func collect_all_chunkinfo(root: Node, list: Array[Node]) -> void:
for child in root.get_children():
collect_all_chunkinfo(child, list)
func _warm_chunk_candidate_cache() -> void:
var unique_scenes: Dictionary = {}
for biome in biome_list:
if biome == null:
continue
for scene in biome.available_chunks:
if scene == null:
continue
unique_scenes[_get_chunk_scene_cache_key(scene)] = scene
if manual_biome != null:
for scene in manual_biome.available_chunks:
if scene == null:
continue
unique_scenes[_get_chunk_scene_cache_key(scene)] = scene
for scene in unique_scenes.values():
_get_chunk_scene_metadata(scene)
func _get_chunk_scene_cache_key(scene: PackedScene) -> String:
if scene == null:
return ""
if scene.resource_path != "":
return scene.resource_path
return "scene_%s" % scene.get_instance_id()
func _get_chunk_scene_metadata(scene: PackedScene) -> Dictionary:
if scene == null:
return {}
var key = _get_chunk_scene_cache_key(scene)
if chunk_candidate_cache.has(key):
return chunk_candidate_cache[key]
var preview_chunk = scene.instantiate()
var info_list: Array[Node] = []
collect_all_chunkinfo(preview_chunk, info_list)
var info_node = info_list[0] if info_list.size() > 0 else null
if info_node == null or not info_node.has_method("get_rotated_data"):
preview_chunk.queue_free()
chunk_candidate_cache[key] = {}
return {}
var info_path: NodePath = NodePath(".")
if info_node != preview_chunk:
info_path = preview_chunk.get_path_to(info_node)
var rotations = []
for rot in range(4):
rotations.append({
"rotation": rot,
"data": info_node.get_rotated_data(rot)
})
var metadata = {
"info_path": info_path,
"rotations": rotations,
"has_lamppost": "have_lamppost" in info_node and info_node.have_lamppost,
}
preview_chunk.queue_free()
chunk_candidate_cache[key] = metadata
return metadata
func _get_cached_chunk_info(instance: Node, scene: PackedScene) -> Node:
var metadata = _get_chunk_scene_metadata(scene)
if metadata.is_empty():
return null
var info_path: NodePath = metadata["info_path"]
if String(info_path) == ".":
return instance
return instance.get_node_or_null(info_path)
func _clear_pending_world_work() -> void:
pending_generation_cells.clear()
pending_cleanup_cells.clear()
pending_wire_cells.clear()
pending_wire_lookup.clear()
pending_radar_update = false
func _refresh_world_work(center: Vector2i) -> void:
_rebuild_generation_queue(center)
_rebuild_cleanup_queue(center)
func _rebuild_generation_queue(center: Vector2i) -> void:
pending_generation_cells.clear()
for radius in range(eye_line + 1):
for x in range(-radius, radius + 1):
for z in range(-radius, radius + 1):
if maxi(abs(x), abs(z)) != radius:
continue
var grid_pos = center + Vector2i(x, z)
if board.has(grid_pos):
continue
pending_generation_cells.append(grid_pos)
func _rebuild_cleanup_queue(center: Vector2i) -> void:
pending_cleanup_cells.clear()
var safe_margin = 2
for grid_pos in board.keys():
var cell = board[grid_pos]
if cell["type"] == "obstacle":
continue
var dist_x = abs(grid_pos.x - center.x)
var dist_z = abs(grid_pos.y - center.y)
if dist_x > eye_line + safe_margin or dist_z > eye_line + safe_margin:
pending_cleanup_cells.append(grid_pos)
func _drain_generation_queue() -> void:
var processed = 0
while processed < CHUNK_GENERATION_STEPS_PER_FRAME and not pending_generation_cells.is_empty():
var grid_pos = pending_generation_cells.pop_front()
if board.has(grid_pos):
continue
var is_obstacle = _register_cell_with_ray(grid_pos)
if not is_obstacle:
_add_compatible_biome(grid_pos)
processed += 1
func _drain_cleanup_queue() -> void:
var processed = 0
while processed < CHUNK_CLEANUP_STEPS_PER_FRAME and not pending_cleanup_cells.is_empty():
var grid_pos = pending_cleanup_cells.pop_front()
if not board.has(grid_pos):
continue
var cell = board[grid_pos]
if cell["type"] == "obstacle":
continue
if cell.has("node") and is_instance_valid(cell["node"]):
cell["node"].queue_free()
board.erase(grid_pos)
processed += 1
func _queue_lamppost_wire_connection(grid_pos: Vector2i) -> void:
if pending_wire_lookup.has(grid_pos):
return
pending_wire_lookup[grid_pos] = true
pending_wire_cells.append(grid_pos)
func _drain_wire_queue() -> void:
var processed = 0
while processed < LAMPPOST_WIRE_STEPS_PER_FRAME and not pending_wire_cells.is_empty():
var grid_pos = pending_wire_cells.pop_front()
pending_wire_lookup.erase(grid_pos)
if not board.has(grid_pos):
continue
if not board[grid_pos].get("have_lamppost", false):
continue
_connect_lamppost_wires(grid_pos)
processed += 1
func _generate_pieces_around_train(center: Vector2i) -> void:
for x in range(-eye_line, eye_line + 1):
for z in range(-eye_line, eye_line + 1):
var grid_pos = center + Vector2i(x, z)
if not board.has(grid_pos):
var ce_obstacle = _register_cell_with_ray(grid_pos)
if not ce_obstacle:
@@ -166,7 +352,7 @@ func _register_cell_with_ray(grid_pos: Vector2i) -> bool:
if info_list.size() > 0:
var min_distance = 999999.0
var center_cell_pos = Vector3(world_pos.x, 0, world_pos.z)
for info in info_list:
if info is Node3D:
var pos_info = Vector3(info.global_position.x, 0, info.global_position.z)
@@ -191,7 +377,7 @@ func _register_cell_with_ray(grid_pos: Vector2i) -> bool:
var data = right_info_node.get_rotated_data(rotation_steps)
exit_found = data["connections"]
height_found = data["heights"]
if "have_lamppost" in right_info_node:
have_lamppost = right_info_node.have_lamppost
@@ -206,7 +392,7 @@ func _register_cell_with_ray(grid_pos: Vector2i) -> bool:
}
if have_lamppost:
_connect_lamppost_wires(grid_pos)
_queue_lamppost_wire_connection(grid_pos)
return true
return false
@@ -229,43 +415,40 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
var valid_candidates = []
for scene in zone_catalogue:
var test_chunk = scene.instantiate()
var test_list: Array[Node] = []
collect_all_chunkinfo(test_chunk, test_list)
var info_test = test_list[0] if test_list.size() > 0 else null
var metadata = _get_chunk_scene_metadata(scene)
if metadata.is_empty():
continue
if info_test != null and info_test.has_method("get_rotated_data"):
for rot in range(4):
var data = test_chunk.get_rotated_data(rot)
var u_conn = data["connections"]
var u_height = data["heights"]
for candidate in metadata["rotations"]:
var rot = candidate["rotation"]
var data = candidate["data"]
var u_conn = data["connections"]
var u_height = data["heights"]
var match_conn_n = (req_conn_north == -1) or ((req_conn_north == 1) == u_conn["north"])
var match_conn_e = (req_conn_est == -1) or ((req_conn_est == 1) == u_conn["est"])
var match_conn_s = (req_conn_south == -1) or ((req_conn_south == 1) == u_conn["south"])
var match_conn_o = (req_conn_west == -1) or ((req_conn_west == 1) == u_conn["west"])
var match_alt_n = (req_height_north == -1) or (req_height_north == u_height["north"])
var match_alt_e = (req_height_est == -1) or (req_height_est == u_height["est"])
var match_alt_s = (req_height_south == -1) or (req_height_south == u_height["south"])
var match_alt_o = (req_height_west == -1) or (req_height_west == u_height["west"])
var diff_n = abs(u_height["north"] - height_target) if req_height_north == -1 else 0
var diff_e = abs(u_height["est"] - height_target) if req_height_est == -1 else 0
var diff_s = abs(u_height["south"] - height_target) if req_height_south == -1 else 0
var diff_o = abs(u_height["west"] - height_target) if req_height_west == -1 else 0
var excessive_jumps = diff_n > 1 or diff_e > 1 or diff_s > 1 or diff_o > 1
if match_conn_n and match_conn_e and match_conn_s and match_conn_o and match_alt_n and match_alt_e and match_alt_s and match_alt_o and not excessive_jumps:
var score = 0
if req_height_north == -1 and u_height["north"] == height_target: score += 1
if req_height_est == -1 and u_height["est"] == height_target: score += 1
if req_height_south == -1 and u_height["south"] == height_target: score += 1
if req_height_west == -1 and u_height["west"] == height_target: score += 1
var match_conn_n = (req_conn_north == -1) or ((req_conn_north == 1) == u_conn["north"])
var match_conn_e = (req_conn_est == -1) or ((req_conn_est == 1) == u_conn["est"])
var match_conn_s = (req_conn_south == -1) or ((req_conn_south == 1) == u_conn["south"])
var match_conn_o = (req_conn_west == -1) or ((req_conn_west == 1) == u_conn["west"])
var match_alt_n = (req_height_north == -1) or (req_height_north == u_height["north"])
var match_alt_e = (req_height_est == -1) or (req_height_est == u_height["est"])
var match_alt_s = (req_height_south == -1) or (req_height_south == u_height["south"])
var match_alt_o = (req_height_west == -1) or (req_height_west == u_height["west"])
var diff_n = abs(u_height["north"] - height_target) if req_height_north == -1 else 0
var diff_e = abs(u_height["est"] - height_target) if req_height_est == -1 else 0
var diff_s = abs(u_height["south"] - height_target) if req_height_south == -1 else 0
var diff_o = abs(u_height["west"] - height_target) if req_height_west == -1 else 0
var excessive_jumps = diff_n > 1 or diff_e > 1 or diff_s > 1 or diff_o > 1
if match_conn_n and match_conn_e and match_conn_s and match_conn_o and match_alt_n and match_alt_e and match_alt_s and match_alt_o and not excessive_jumps:
var score = 0
if req_height_north == -1 and u_height["north"] == height_target: score += 1
if req_height_est == -1 and u_height["est"] == height_target: score += 1
if req_height_south == -1 and u_height["south"] == height_target: score += 1
if req_height_west == -1 and u_height["west"] == height_target: score += 1
valid_candidates.append({"scene": scene, "rotation": rot, "data": data, "score": score})
test_chunk.queue_free()
valid_candidates.append({"scene": scene, "rotation": rot, "data": data, "score": score})
if valid_candidates.size() > 0:
var max_score = -1
@@ -278,16 +461,14 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
var choise = best_candidate.pick_random()
var new_chunk = choise.scene.instantiate()
add_child(new_chunk)
new_chunk.position = Vector3(grid_pos.x * chunk_size, 0, grid_pos.y * chunk_size)
new_chunk.rotation.y = choise.rotation * (-PI / 2.0)
add_child(new_chunk)
var new_list: Array[Node] = []
collect_all_chunkinfo(new_chunk, new_list)
var info_new = new_list[0] if new_list.size() > 0 else null
var info_new = _get_cached_chunk_info(new_chunk, choise.scene)
var have_lamppost = false
if info_new != null and "have_lamppost" in new_chunk:
if info_new != null and "have_lamppost" in info_new:
have_lamppost = info_new.have_lamppost
board[grid_pos] = {
@@ -300,16 +481,14 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
}
if have_lamppost:
_connect_lamppost_wires(grid_pos)
_queue_lamppost_wire_connection(grid_pos)
else:
var backup = zone_catalogue[0].instantiate()
add_child(backup)
backup.position = Vector3(grid_pos.x * chunk_size, 0, grid_pos.y * chunk_size)
add_child(backup)
var backup_list: Array[Node] = []
collect_all_chunkinfo(backup, backup_list)
var info_backup = backup_list[0] if backup_list.size() > 0 else null
var info_backup = _get_cached_chunk_info(backup, zone_catalogue[0])
var safe_heights = {
"north": req_height_north if req_height_north != -1 else height_target,
@@ -351,8 +530,6 @@ func _train_radar() -> void:
var current_progress = rail_path.train_progress
var total_length = rail_path.curve.get_baked_length()
#var exchange_distance = 0.0
#var next_biome = ""
for step in range(1, 31):
var next_progress = wrapf(current_progress + (step * chunk_size), 0.0, total_length)
@@ -364,44 +541,18 @@ func _train_radar() -> void:
var future_biome = _get_procedural_biome_name(noise_generator.get_noise_2d(f_x, f_z))
if future_biome != current_biome:
#exchange_distance = step * chunk_size
#next_biome = future_biome
break
func _clean_far_chunks(centro_attuale: Vector2i) -> void:
var cells_to_remove = []
var safe_margin = 2
for grid_pos in board.keys():
var cell = board[grid_pos]
if cell["type"] == "obstacle": continue
var dist_x = abs(grid_pos.x - centro_attuale.x)
var dist_z = abs(grid_pos.y - centro_attuale.y)
if dist_x > eye_line + safe_margin or dist_z > eye_line + safe_margin:
if cell.has("node") and is_instance_valid(cell["node"]):
cell["node"].queue_free()
cells_to_remove.append(grid_pos)
for pos in cells_to_remove:
board.erase(pos)
func _get_lampposts(info_node: Node, side: String) -> Array[Node3D]:
var lampposts: Array[Node3D] = []
if side == "sx":
if "connection_left" in info_node and info_node.connection_left != null:
for p in info_node.connection_left:
if is_instance_valid(p): lampposts.append(p)
#if lampposts.is_empty() and "nodo_attacco_sx" in nodo_info and is_instance_valid(nodo_info.get("nodo_attacco_sx")):
# lampposts.append(nodo_info.get("nodo_attacco_sx"))
else:
if "connection_right" in info_node and info_node.connection_right != null:
for p in info_node.connection_right:
if is_instance_valid(p): lampposts.append(p)
#if lampposts.is_empty() and "nodo_attacco_dx" in nodo_info and is_instance_valid(nodo_info.get("nodo_attacco_dx")):
# lampposts.append(nodo_info.get("nodo_attacco_dx"))
return lampposts
func _connect_lamppost_wires(new_board_pos: Vector2i) -> void:
@@ -471,7 +622,7 @@ func _connect_lamppost_wires(new_board_pos: Vector2i) -> void:
if board.has(closest_pos) and board[closest_pos].get("have_lamppost", false):
var closest_root = board[closest_pos]["node"]
var closest_info = board[closest_pos]["info"]
if not is_instance_valid(closest_root) or closest_root == new_root or closest_info == null: continue
if closest_info is Node3D: closest_info.force_update_transform()

View File

@@ -47,15 +47,112 @@ var next_stop_index: int = 0
var stop_multiply: float = 1.0
var is_restarting: bool = false
var tween_restart: Tween
var environment_config: EnvironmentConfig
func _ready() -> void:
_cache_environment_config()
if curve != null and curve.get_baked_length() > 0:
build_rails()
build_train()
_plan_stops()
_apply_initial_train_start()
else:
print("WARNING: Draw Path3D for rails!")
func _cache_environment_config() -> void:
var parent_node: Node = get_parent()
if parent_node != null:
var day_night_node := parent_node.get_node_or_null("DayNight") as EnvironmentManagerRoot
if day_night_node != null:
environment_config = day_night_node.environment_config
return
var current_scene: Node = get_tree().current_scene
if current_scene == null:
return
for child in current_scene.get_children():
var environment_manager := child as EnvironmentManagerRoot
if environment_manager != null:
environment_config = environment_manager.environment_config
return
func _apply_initial_train_start() -> void:
if train_instance == null or curve == null:
return
var total_length: float = curve.get_baked_length()
if total_length <= 0.0:
return
#start from a random position
if environment_config != null and environment_config.train_start_from_random_position:
train_progress = randf() * total_length
_update_next_stop_index_from_progress()
elif environment_config != null and not stop_offset.is_empty():
#start from a specific stop
var stop_index: int = clampi(environment_config.train_start_stop_index, 0, stop_offset.size() - 1)
train_progress = stop_offset[stop_index]
_set_next_stop_index_from_current(stop_index)
else:
train_progress = wrapf(train_progress, 0.0, total_length)
_update_next_stop_index_from_progress()
_snap_train_to_progress()
func _set_next_stop_index_from_current(current_stop_index: int) -> void:
if stop_offset.is_empty():
next_stop_index = 0
return
if train_speed >= 0.0:
next_stop_index = (current_stop_index + 1) % stop_offset.size()
else:
next_stop_index = current_stop_index - 1
if next_stop_index < 0:
next_stop_index = stop_offset.size() - 1
func _update_next_stop_index_from_progress() -> void:
if stop_offset.is_empty():
next_stop_index = 0
return
if train_speed >= 0.0:
next_stop_index = 0
for i in range(stop_offset.size()):
if stop_offset[i] > train_progress + 0.001:
next_stop_index = i
return
return
next_stop_index = stop_offset.size() - 1
for i in range(stop_offset.size() - 1, -1, -1):
if stop_offset[i] < train_progress - 0.001:
next_stop_index = i
return
func _snap_train_to_progress() -> void:
if train_instance == null or curve == null:
return
var total_length: float = curve.get_baked_length()
if total_length <= 0.0:
return
train_progress = wrapf(train_progress, 0.0, total_length)
var center_position: Vector3 = to_global(curve.sample_baked(train_progress, true))
var prog_forward: float = wrapf(train_progress + 2.0, 0.0, total_length)
var forward_position: Vector3 = to_global(curve.sample_baked(prog_forward, true))
train_instance.global_position = center_position
if center_position.distance_to(forward_position) > 0.01:
train_instance.look_at(forward_position, Vector3.UP)
train_instance.rotate_y(PI)
if cameras:
cameras.global_position = center_position
cameras.global_basis = train_instance.global_basis
func build_rails() -> void:
var mat_wood = StandardMaterial3D.new()
mat_wood.albedo_color = Color(0.35, 0.2, 0.1)

View File

@@ -0,0 +1,7 @@
[gd_resource type="NoiseTexture2D" format=3 uid="uid://b2xcpt2y8v32x"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_oqwsk"]
[resource]
noise = SubResource("FastNoiseLite_oqwsk")
seamless = true

View File

@@ -1,9 +1,17 @@
shader_type canvas_item;
// Cattura tutto quello che c'è sotto questo nodo
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
uniform float blur_amount : hint_range(0.0, 5.0) = 2.5;
uniform float focus_size : hint_range(0.0, 1.0) = 0.4;
uniform float transition_softness : hint_range(0.01, 1.0) = 0.3;
void fragment() {
COLOR = textureLod(screen_texture, SCREEN_UV, blur_amount);
}
float dist_from_center = abs(SCREEN_UV.y - 0.5);
float mask = smoothstep(focus_size / 2.0, (focus_size / 2.0) + transition_softness, dist_from_center);
// Applica il blur
vec4 blurred_screen = textureLod(screen_texture, SCREEN_UV, blur_amount * mask);
COLOR = blurred_screen;
}

View File

@@ -9,6 +9,7 @@
[ext_resource type="Material" uid="uid://codq5gx71rj4o" path="res://core/daynight/environment_dust_material.tres" id="8_amaf0"]
[ext_resource type="Shader" uid="uid://bkn6eqgbn37jx" path="res://core/daynight/blur.gdshader" id="9_amaf0"]
[ext_resource type="Shader" uid="uid://b5wa82soyhsqm" path="res://core/daynight/environment_shadows.gdshader" id="10_tuauy"]
[ext_resource type="Texture2D" uid="uid://b2xcpt2y8v32x" path="res://core/daynight/FogNoise.tres" id="11_tuauy"]
[ext_resource type="FastNoiseLite" uid="uid://c0mtwrkptjcuw" path="res://core/daynight/environment_shadows_noise_clouds.tres" id="11_yn8v8"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ruhh7"]
@@ -40,9 +41,55 @@ shader_parameter/sun_color = Color(0.2841828, 0.2023238, 0.27953526, 1)
[sub_resource type="Resource" id="Resource_r4tfj"]
script = ExtResource("2_h6hjk")
morning_color = Color(0.93333334, 0.78039217, 0.6039216, 1)
afternoon_color = Color(0.9490196, 0.62352943, 0.38039216, 1)
night_color = Color(0.18431373, 0.18431373, 0.4862745, 1)
sun_rotation_morning = Vector3(-50, -90, 0)
sun_rotation_afternoon = Vector3(-120, -90, 0)
sun_rotation_night = Vector3(-130, -90, 0)
night_light_energy = 1.0
exposure_morning = 0.8
exposure_afternoon = 0.7
exposure_night = 0.7
sky_top_morning = Color(0.11764706, 0.35686275, 0.5411765, 1)
sky_top_afternoon = Color(0.7019608, 0.4509804, 0.2, 1)
sky_top_night = Color(0.050980393, 0.050980393, 0.14901961, 1)
sky_horizon_morning = Color(0.4627451, 0.6745098, 0.8627451, 1)
sky_horizon_afternoon = Color(0.93333334, 0.6, 0.8039216, 1)
sky_horizon_night = Color(0.14901961, 0.101960786, 0.2509804, 1)
grad_top_morning = Color(0.7921569, 0.8784314, 0.95686275, 1)
grad_top_afternoon = Color(0.8627451, 0.24313726, 0.5411765, 1)
grad_top_night = Color(0.16470589, 0.16470589, 0.26666668, 1)
grad_bot_morning = Color(0.05882353, 0.078431375, 0.21568628, 1)
grad_bot_afternoon = Color(0.2509804, 0.019607844, 0.043137256, 1)
grad_intensity_morning = 0.05
grad_intensity_afternoon = 0.1
grad_intensity_night = 0.5
fog_color_morning = Color(0.7490196, 0.8509804, 0.9490196, 1)
fog_color_afternoon = Color(0.9647059, 0.5882353, 0.7607843, 1)
fog_color_night = Color(0.14901961, 0.101960786, 0.2509804, 1)
fog_density_morning = 0.01
fog_density_afternoon = 0.02
glow_morning = 0.4
glow_night = 0.6
material_fog = SubResource("ShaderMaterial_b5atu")
material_drops = SubResource("StandardMaterial3D_r4tfj")
material_clouds = SubResource("ShaderMaterial_ruhh7")
lightning_color = Color(1, 0.9843137, 0.4627451, 1)
lightning_min = 2
lightning_max = 4
lightning_scale_min = 2.0
lightning_scale_max = 5.0
godray_max_rain = 60
godray_spawn_radius = 100.0
godray_spawn_offset = Vector3(20, 80, 20)
godray_rotation_degrees = Vector3(50, 30, 0)
godray_scale = Vector3(2, 25, 50)
snow_amount = 2000.0
wind_amount = 50
cloud_speed = 0.01
fireflies_amount = 550
fireflies_spawn_ray = 60.0
metadata/_custom_type_script = "uid://butda6k2tli3o"
[sub_resource type="Gradient" id="Gradient_i3hjl"]
@@ -85,7 +132,7 @@ gradient = SubResource("Gradient_djqkg")
lifetime_randomness = 0.5
emission_shape_scale = Vector3(5, 5, 5)
emission_shape = 3
emission_box_extents = Vector3(25, 5, 25)
emission_box_extents = Vector3(1, 1, 1)
direction = Vector3(0, 1, 0)
initial_velocity_min = 6.0
initial_velocity_max = 6.0
@@ -99,10 +146,9 @@ point_count = 3
[sub_resource type="ShaderMaterial" id="ShaderMaterial_cer0u"]
render_priority = 0
shader = ExtResource("5_djqkg")
shader_parameter/wave_frequency = 1.0
shader_parameter/base_amplitude = 0.5
shader_parameter/secondary_ratio = 0.6
shader_parameter/time_scale_base = 3.0
shader_parameter/time_scale = 3.065
shader_parameter/wave_amplitude = 0.3
shader_parameter/wave_frequency = 0.25
[sub_resource type="TubeTrailMesh" id="TubeTrailMesh_vo82p"]
material = SubResource("ShaderMaterial_cer0u")
@@ -174,7 +220,9 @@ size = Vector2(0.05, 0.8)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_kavln"]
shader = ExtResource("9_amaf0")
shader_parameter/blur_amount = 0.6000000285
shader_parameter/blur_amount = 0.50000002375
shader_parameter/focus_size = 0.54400002584
shader_parameter/transition_softness = 0.00999999977648
[sub_resource type="QuadMesh" id="QuadMesh_sxgg7"]
size = Vector2(2, 2)
@@ -184,12 +232,12 @@ noise = ExtResource("11_yn8v8")
seamless = true
[sub_resource type="ShaderMaterial" id="ShaderMaterial_oqt1s"]
render_priority = 0
render_priority = -1
shader = ExtResource("10_tuauy")
shader_parameter/noise_texture = SubResource("NoiseTexture2D_0fcg4")
shader_parameter/cloud_scale = 0.0070000003325
shader_parameter/cloud_speed = 0.0030000001425
shader_parameter/direction = Vector2(0.5, 0.2)
shader_parameter/direction = Vector2(0.1, 0.025)
shader_parameter/sun_angle = Vector2(0.5, 0.5)
shader_parameter/cloud_density = 0.400000019
shader_parameter/center_sharpness = 0.138000006555
@@ -201,7 +249,23 @@ shader_parameter/fade_end = 800.000035625
shader_parameter/height_fade_start = 10.0
shader_parameter/height_fade_end = 50.0
[node name="EnvironmentManager" type="Node3D" unique_id=1611939731 node_paths=PackedStringArray("particles_wind", "particles_snow", "particles_fireflies", "particles_rain", "environment_dust", "blur", "environment_shadows")]
[sub_resource type="QuadMesh" id="QuadMesh_yn8v8"]
size = Vector2(2, 2)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_sxgg7"]
render_priority = 2
shader = ExtResource("2_r4tfj")
shader_parameter/fog_noise = ExtResource("11_tuauy")
shader_parameter/use_red_as_alpha = true
shader_parameter/fog_color = Color(0.8, 0.8509804, 0.9019608, 0.2509804)
shader_parameter/scroll_speed = Vector2(0, 0.01)
shader_parameter/texture_scale = Vector2(1, 1)
shader_parameter/edge_softness_y = 0.16400000779
shader_parameter/edge_softness_x = 0.5
shader_parameter/night_intensity = 0.0
shader_parameter/sun_color = Color(1, 1, 1, 1)
[node name="EnvironmentManager" type="Node3D" unique_id=1611939731 node_paths=PackedStringArray("particles_wind", "particles_snow", "particles_fireflies", "particles_rain", "environment_dust", "blur", "environment_shadows", "fog")]
script = ExtResource("1_wecen")
environment_config = SubResource("Resource_r4tfj")
particles_wind = NodePath("Particles_Wind")
@@ -212,6 +276,7 @@ godray = ExtResource("5_411rw")
environment_dust = NodePath("EnvironmentDust")
blur = NodePath("Blur")
environment_shadows = NodePath("EnvironmentCloudsShadows")
fog = NodePath("Fog")
[node name="Particles_Fireflies" type="GPUParticles3D" parent="." unique_id=947538133]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
@@ -222,9 +287,10 @@ process_material = SubResource("ParticleProcessMaterial_i3hjl")
draw_pass_1 = SubResource("QuadMesh_b5atu")
[node name="Particles_Wind" type="GPUParticles3D" parent="." unique_id=1238214694]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 50, 0)
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, 50, 0)
cast_shadow = 0
emitting = false
amount = 100
amount = 25
lifetime = 3.0
fixed_fps = 60
process_material = SubResource("ParticleProcessMaterial_ruhh7")
@@ -271,3 +337,15 @@ mouse_filter = 2
extra_cull_margin = 16384.0
mesh = SubResource("QuadMesh_sxgg7")
surface_material_override/0 = SubResource("ShaderMaterial_oqt1s")
[node name="Fog" type="Node3D" parent="." unique_id=1626352238]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Fog" unique_id=96635311]
transform = Transform3D(-42.075005, 7.553328e-06, 1.7196172e-13, 0, -3.7766642e-06, 45, 3.6783138e-06, 86.4, 1.9670128e-06, -41.926987, 14, 0)
mesh = SubResource("QuadMesh_yn8v8")
surface_material_override/0 = SubResource("ShaderMaterial_sxgg7")
[node name="MeshInstance3D2" type="MeshInstance3D" parent="Fog" unique_id=10121049]
transform = Transform3D(-42.075005, 7.553328e-06, 1.7196172e-13, 0, -3.7766642e-06, 45, 3.6783138e-06, 86.4, 1.9670128e-06, 59.320038, 14, 0)
mesh = SubResource("QuadMesh_yn8v8")
surface_material_override/0 = SubResource("ShaderMaterial_sxgg7")

View File

@@ -1,6 +1,11 @@
class_name EnvironmentManagerRoot
extends Node3D
const NOISE_TEXTURE: Texture2D = preload("res://core/daynight/noise.tres")
const WEATHER_SHADER: Material = preload("res://core/daynight/weather_overlay.tres")
const WEATHER_PLAIN_SHADER: Material = preload("res://core/daynight/weather_plain_shader.tres")
const DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME: int = 2 #how many update of the environment (apply materials) will be done per frame
@export var environment_config: EnvironmentConfig
@export_group("Camera")
@@ -16,6 +21,7 @@ extends Node3D
@export var environment_dust: ColorRect
@export var blur: ColorRect
@export var environment_shadows: MeshInstance3D
@export var fog: Node3D
@export_group("Sound")
@export var thunder_sounds: Array[AudioStream]
@@ -30,9 +36,13 @@ var weather_controller: WeatherController
var day_tween: Tween
var day_time: float = 0.0
var pending_environment_nodes: Dictionary = {}
func _ready() -> void:
#connect shader when new node is added
get_tree().node_added.connect(_on_tree_node_added)
#set noise texture 2d to materials in special group
ApplyWindNoiseToMaterials()
#set weather overlay (snow + rain) to materials in special group
@@ -55,6 +65,7 @@ func _ready() -> void:
godray,
environment_dust,
blur,
fog,
environment_shadows,
sun,
environment,
@@ -67,10 +78,67 @@ func _ready() -> void:
weather_controller.name = "WeatherController"
add_child(weather_controller)
func _process(_delta: float) -> void:
_process_pending_environment_nodes()
func _on_tree_node_added(node: Node) -> void:
if node.is_in_group("wind_node") or node.is_in_group("weather_node") or node.is_in_group("weather_vegetables_node"):
_queue_dynamic_environment_node(node)
func _queue_dynamic_environment_node(node: Node) -> void:
if not is_instance_valid(node):
return
var ancestor = node.get_parent()
while ancestor != null:
if pending_environment_nodes.has(ancestor.get_instance_id()):
return
ancestor = ancestor.get_parent()
var stale_ids: Array[int] = []
for node_id in pending_environment_nodes.keys():
var pending_node = pending_environment_nodes[node_id]
if not is_instance_valid(pending_node):
stale_ids.append(node_id)
continue
if node.is_ancestor_of(pending_node):
stale_ids.append(node_id)
for node_id in stale_ids:
pending_environment_nodes.erase(node_id)
pending_environment_nodes[node.get_instance_id()] = node
func _process_pending_environment_nodes() -> void:
var processed = 0
for node_id in pending_environment_nodes.keys():
if processed >= DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME:
break
var node = pending_environment_nodes[node_id]
pending_environment_nodes.erase(node_id)
if not is_instance_valid(node):
continue
_apply_dynamic_environment_materials(node)
processed += 1
func _apply_dynamic_environment_materials(node: Node) -> void:
if not is_instance_valid(node):
return
if node.is_in_group("wind_node"):
_apply_wind_noise_to_node(node, NOISE_TEXTURE)
if node.is_in_group("weather_node"):
_apply_weather_overlay_to_node(node, WEATHER_SHADER)
if node.is_in_group("weather_vegetables_node"):
_apply_weather_overlay_to_node(node, WEATHER_PLAIN_SHADER)
func ApplyWindNoiseToMaterials():
var noise_tex = preload("res://core/daynight/noise.tres")
for node in get_tree().get_nodes_in_group("wind_node"):
_apply_wind_noise_to_node(node, noise_tex)
_apply_wind_noise_to_node(node, NOISE_TEXTURE)
func _apply_wind_noise_to_node(node: Node, noise_tex: Texture2D) -> void:
if node is GeometryInstance3D:
@@ -88,25 +156,18 @@ func _apply_wind_noise_to_node(node: Node, noise_tex: Texture2D) -> void:
_apply_wind_noise_to_node(child, noise_tex)
func ApplyWeatherShaderToMaterials():
var weather_shader = preload("res://core/daynight/weather_overlay.tres")
for node in get_tree().get_nodes_in_group("weather_node"):
if node is GeometryInstance3D:
node.material_overlay = weather_shader
else:
for child in node.get_children():
if child is GeometryInstance3D:
child.material_overlay = weather_shader
break
_apply_weather_overlay_to_node(node, WEATHER_SHADER)
var weather_plain_shader = preload("res://core/daynight/weather_plain_shader.tres")
for node in get_tree().get_nodes_in_group("weather_vegetables_node"):
if node is GeometryInstance3D:
node.material_overlay = weather_plain_shader
else:
for child in node.get_children():
if child is GeometryInstance3D:
child.material_overlay = weather_plain_shader
break
_apply_weather_overlay_to_node(node, WEATHER_PLAIN_SHADER)
func _apply_weather_overlay_to_node(node: Node, material: Material) -> void:
if node is GeometryInstance3D:
node.material_overlay = material
for child in node.get_children():
_apply_weather_overlay_to_node(child, material)
func select_day_time(normalized_time: float) -> void:
#set show_day_time_debug = true to show debug on screen

114
core/daynight/snow_cap.gd Normal file
View File

@@ -0,0 +1,114 @@
## Procedural snow cap geometry for flat roofs and vehicles.
extends Node3D
enum PlacementMode {
AUTO_TARGET_AABB,
MANUAL_SURFACE,
}
const SNOW_CAP_SHADER: Shader = preload("res://core/daynight/snow_cap.gdshader")
@export var placement_mode: PlacementMode = PlacementMode.AUTO_TARGET_AABB
@export var target_path: NodePath
@export var size_inset: Vector2 = Vector2(0.25, 1.0)
@export var position_offset: Vector3 = Vector3(0.0, -0.08, 0.0)
@export var max_snow_height: float = 0.2
@export_range(1, 24) var subdivide_width: int = 6
@export_range(1, 24) var subdivide_depth: int = 18
@export var manual_surface_center: Vector3 = Vector3.ZERO
@export var manual_surface_size: Vector2 = Vector2(2.0, 6.0)
var _mesh_instance: MeshInstance3D
func _ready() -> void:
add_to_group("weather_overlay_ignore")
_ensure_mesh_instance()
_rebuild()
func rebuild() -> void:
_rebuild()
func _ensure_mesh_instance() -> void:
_mesh_instance = get_node_or_null("SnowCapMesh") as MeshInstance3D
if _mesh_instance != null:
return
_mesh_instance = MeshInstance3D.new()
_mesh_instance.name = "SnowCapMesh"
_mesh_instance.add_to_group("weather_overlay_ignore")
add_child(_mesh_instance)
func _rebuild() -> void:
var cap_width: float = 0.0
var cap_depth: float = 0.0
var cap_surface_center := Vector3.ZERO
if placement_mode == PlacementMode.MANUAL_SURFACE:
cap_width = manual_surface_size.x
cap_depth = manual_surface_size.y
cap_surface_center = manual_surface_center
else:
var target_mesh: MeshInstance3D = get_node_or_null(target_path) as MeshInstance3D
if target_mesh == null:
if _mesh_instance:
_mesh_instance.visible = false
return
var target_aabb: AABB = _get_target_aabb(target_mesh)
cap_width = max(target_aabb.size.x - size_inset.x, 0.1)
cap_depth = max(target_aabb.size.z - size_inset.y, 0.1)
cap_surface_center = Vector3(
target_aabb.position.x + target_aabb.size.x * 0.5,
target_aabb.position.y + target_aabb.size.y,
target_aabb.position.z + target_aabb.size.z * 0.5
)
var cap_center := cap_surface_center + Vector3(0.0, max_snow_height * 0.5, 0.0)
var box_mesh := BoxMesh.new()
box_mesh.size = Vector3(cap_width, max_snow_height, cap_depth)
box_mesh.subdivide_width = subdivide_width
box_mesh.subdivide_depth = subdivide_depth
_mesh_instance.mesh = box_mesh
_mesh_instance.position = cap_center + position_offset
_mesh_instance.material_override = _build_material(cap_width, cap_depth)
_mesh_instance.visible = true
func _build_material(cap_width: float, cap_depth: float) -> ShaderMaterial:
var material := ShaderMaterial.new()
material.shader = SNOW_CAP_SHADER
material.set_shader_parameter("max_height", max_snow_height)
material.set_shader_parameter("half_width", cap_width * 0.5)
material.set_shader_parameter("half_depth", cap_depth * 0.5)
return material
func _get_target_aabb(target_mesh: MeshInstance3D) -> AABB:
var points: Array[Vector3] = []
for point in _get_aabb_points(target_mesh.get_aabb()):
points.append(target_mesh.transform * point)
var merged := AABB(points[0], Vector3.ZERO)
for point in points:
merged = merged.expand(point)
return merged
func _get_aabb_points(aabb: AABB) -> Array[Vector3]:
var p: Vector3 = aabb.position
var s: Vector3 = aabb.size
return [
p,
p + Vector3(s.x, 0.0, 0.0),
p + Vector3(0.0, s.y, 0.0),
p + Vector3(0.0, 0.0, s.z),
p + Vector3(s.x, s.y, 0.0),
p + Vector3(s.x, 0.0, s.z),
p + Vector3(0.0, s.y, s.z),
p + s,
]

View File

@@ -0,0 +1 @@
uid://bxc6ketfgedxw

View File

@@ -0,0 +1,114 @@
shader_type spatial;
render_mode blend_mix, cull_back, depth_draw_opaque;
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 vec4 global_snow_color = vec4(0.92, 0.96, 1.0, 1.0);
uniform float max_height : hint_range(0.02, 1.0) = 0.2;
uniform float half_width : hint_range(0.01, 20.0) = 1.0;
uniform float half_depth : hint_range(0.01, 20.0) = 1.0;
uniform float noise_scale : hint_range(0.05, 2.0) = 0.35;
uniform float noise_strength : hint_range(0.0, 0.4) = 0.18;
uniform float edge_rounding : hint_range(0.0, 0.3) = 0.12;
uniform float side_shade : hint_range(0.2, 1.0) = 0.82;
uniform float sparkle_strength : hint_range(0.0, 0.1) = 0.03;
varying float v_snow_amount;
varying float v_noise;
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
}
float value_noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
vec2 u = f * f * (3.0 - 2.0 * f);
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}
float fbm(vec2 p) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
for (int i = 0; i < 4; i++) {
value += value_noise(p * frequency) * amplitude;
frequency *= 2.0;
amplitude *= 0.5;
}
return clamp(value, 0.0, 1.0);
}
float get_snow_amount() {
float snow_amount = 0.0;
if (global_snow_start_time >= 0.0) {
snow_amount = clamp(
(TIME - global_snow_start_time) * global_snow_accumulation_speed,
0.0,
1.0
);
}
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 *= (1.0 - melt);
}
return snow_amount;
}
void vertex() {
vec3 base_vertex = VERTEX;
vec3 world_pos = (MODEL_MATRIX * vec4(base_vertex, 1.0)).xyz;
float snow_amount = get_snow_amount();
float noise_val = fbm(world_pos.xz * noise_scale);
float thickness = max_height * snow_amount * mix(
1.0 - noise_strength,
1.0 + noise_strength,
noise_val
);
float footprint_growth = smoothstep(0.0, 0.35, snow_amount);
float from_bottom = clamp((base_vertex.y + max_height * 0.5) / max_height, 0.0, 1.0);
VERTEX.y = -max_height * 0.5 + thickness * from_bottom;
VERTEX.x *= mix(0.92, 1.0, footprint_growth);
VERTEX.z *= mix(0.94, 1.0, footprint_growth);
float edge_x = abs(base_vertex.x) / max(half_width, 0.001);
float edge_z = abs(base_vertex.z) / max(half_depth, 0.001);
float edge_mask = smoothstep(0.55, 1.0, max(edge_x, edge_z));
float top_mask = smoothstep(0.6, 1.0, from_bottom) * snow_amount;
float round_factor = edge_rounding * edge_mask * top_mask;
VERTEX.x *= 1.0 - round_factor;
VERTEX.z *= 1.0 - round_factor;
v_snow_amount = snow_amount;
v_noise = noise_val;
}
void fragment() {
if (v_snow_amount <= 0.001) {
ALPHA = 0.0;
ALBEDO = global_snow_color.rgb;
ROUGHNESS = 1.0;
SPECULAR = 0.0;
} else {
float facing_up = clamp(NORMAL.y, 0.0, 1.0);
float shade = mix(-sparkle_strength, sparkle_strength, v_noise);
vec3 snow_albedo = clamp(global_snow_color.rgb + vec3(shade), 0.0, 1.0);
ALBEDO = mix(snow_albedo * side_shade, snow_albedo, facing_up);
ROUGHNESS = mix(0.95, 0.72, facing_up);
SPECULAR = 0.18;
ALPHA = smoothstep(0.0, 0.28, v_snow_amount);
}
}

View File

@@ -0,0 +1 @@
uid://c7js7ytvewmab

View File

@@ -2,6 +2,7 @@ shader_type spatial;
render_mode blend_mix, depth_draw_always;
global uniform float global_rain_intensity;
global uniform vec4 global_water_color = vec4(0.285, 0.534, 0.487, 1.0);
//Water color
uniform vec4 deep_water_color : source_color = vec4(0.0, 0.1, 0.2, 1.0);
@@ -44,12 +45,14 @@ void fragment() {
float water_depth_gradient = exp(-depth_difference * beer_law_factor);
vec4 base_water = mix(deep_water_color, shallow_water_color, water_depth_gradient);
float rain_intensity = clamp(global_rain_intensity, 0.0, 1.0);
base_water.rgb = mix(base_water.rgb, global_water_color.rgb, 0.7);
vec2 pos = world_pos_xz * ripple_scale;
vec2 cell = floor(pos);
vec2 local_pos = fract(pos) - 0.5;
float random_val = fract(sin(dot(cell, vec2(12.9898, 78.233))) * 43758.5453);
float is_active_cell = step(1.0 - ripple_density, random_val);
float active_ripple_density = ripple_density * rain_intensity;
float is_active_cell = step(1.0 - active_ripple_density, random_val);
float ring = 0.0;
if (is_active_cell > 0.0) {

View File

@@ -14,6 +14,7 @@ var godray: PackedScene
var environment_dust: ColorRect
var blur: ColorRect
var environment_shadows: MeshInstance3D
var fog: Node3D
var sun: DirectionalLight3D
var environment: WorldEnvironment
@@ -49,10 +50,11 @@ var current_wind_speed: float = 0.0
var current_wind_strength: float = 0.0
var current_wind_fade: float = 0.0
var max_wind_amount: int = 0
var random_weather_restore_tween: Tween
func _init(wind: GPUParticles3D, snow: GPUParticles3D,
fireflies: GPUParticles3D, rain: GPUParticles3D, ray: PackedScene,
dust: ColorRect, blurr: ColorRect, envshadows: MeshInstance3D,
dust: ColorRect, blurr: ColorRect, thefog: Node3D, envshadows: MeshInstance3D,
thesun: DirectionalLight3D, theenvironment: WorldEnvironment, environmentconfig: EnvironmentConfig,
thecamera: Camera3D, thecamerapivot: Node3D, thundersounds: Array[AudioStream], rainsounds: Array[AudioStream]) -> void:
particles_wind = wind
@@ -63,6 +65,7 @@ func _init(wind: GPUParticles3D, snow: GPUParticles3D,
sun = thesun
environment_dust = dust
blur = blurr
fog = thefog
environment_shadows = envshadows
environment = theenvironment
environment_config = environmentconfig
@@ -86,6 +89,7 @@ func _init(wind: GPUParticles3D, snow: GPUParticles3D,
toggle_dust(environment_config.enable_dust)
toggle_blur(environment_config.enable_blur)
toggle_fog(environment_config.enable_fog)
#set camera pivot if available
if camera_pivot:
@@ -98,11 +102,14 @@ func _ready() -> void:
UIEvents.toggle_snow.connect(toggle_snow)
UIEvents.toggle_wind.connect(toggle_wind)
UIEvents.wind_change.connect(change_wind_strength)
UIEvents.trigger_random_weather.connect(trigger_random_weather_event)
UIEvents.toggle_fireflies.connect(toggle_fireflies)
UIEvents.toggle_storm.connect(toggle_storm)
UIEvents.toggle_dust.connect(toggle_dust)
UIEvents.toggle_blur.connect(toggle_blur)
UIEvents.toggle_fog.connect(toggle_fog)
UIEvents.toggle_shadows.connect(toggle_shadows)
_emit_weather_event_label()
func _process(delta: float) -> void:
@@ -122,6 +129,7 @@ func _process(delta: float) -> void:
var base_grad_top: Color
var base_grad_bot: Color
var base_grad_intensity: float
var base_water_color: Color
var base_rotation_sun: Vector3
if is_raining:
@@ -149,6 +157,7 @@ func _process(delta: float) -> void:
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_water_color = environment_config.water_color_morning.lerp(environment_config.water_color_afternoon, t)
base_rotation_sun = environment_config.sun_rotation_morning.lerp(environment_config.sun_rotation_afternoon, t)
else:
var t = day_time - 2.0
@@ -162,6 +171,7 @@ func _process(delta: float) -> void:
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_water_color = environment_config.water_color_afternoon.lerp(environment_config.water_color_night, t)
base_rotation_sun = environment_config.sun_rotation_afternoon.lerp(environment_config.sun_rotation_night, t)
var weather_color = environment_config.rain_mode_color
@@ -173,6 +183,7 @@ func _process(delta: float) -> void:
var final_sky_horizon = base_sky_horizon.lerp(base_sky_horizon * weather_color, clamp(rain_intensity, 0.0, 1.0))
var final_fog_color = base_fog_color.lerp(base_fog_color * weather_color, clamp(rain_intensity, 0.0, 1.0))
var final_fog_density = lerp(base_fog_density, base_fog_density * 4.0, clamp(rain_intensity, 0.0, 1.0))
var final_water_color = base_water_color.darkened(clamp(environment_config.water_darkening_rain, 0.0, 1.0) * clamp(rain_intensity, 0.0, 1.0))
final_tint = final_tint.lerp(final_tint * environment_config.snow_mode_color, actual_snow_amount)
final_sky_top = final_sky_top.lerp(final_sky_top * environment_config.snow_mode_color, actual_snow_amount)
@@ -186,6 +197,7 @@ func _process(delta: float) -> void:
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)
RenderingServer.global_shader_parameter_set("global_water_color", final_water_color)
var night_val = clamp(day_time - 2.0, 0.0, 1.0)
@@ -265,6 +277,23 @@ func _get_weather_anchor_position() -> Variant:
return camera.global_position
return null
func _get_weather_anchor_basis() -> Variant:
var source_basis: Basis
if camera_pivot and is_instance_valid(camera_pivot):
source_basis = camera_pivot.global_basis
elif camera and is_instance_valid(camera):
source_basis = camera.global_basis
else:
return null
var forward := -source_basis.z
forward.y = 0.0
if forward.length_squared() <= 0.0001:
return Basis.IDENTITY
forward = forward.normalized()
var right := forward.cross(Vector3.UP).normalized()
return Basis(right, Vector3.UP, -forward)
func _follow_camera() -> void:
var cam_pos = _get_weather_anchor_position()
if cam_pos == null:
@@ -277,6 +306,12 @@ func _follow_camera() -> void:
particles_wind.global_position = Vector3(cam_pos.x, cam_pos.y, cam_pos.z)
if particles_fireflies:
particles_fireflies.global_position = Vector3(cam_pos.x, particles_fireflies.position.y, cam_pos.z)
if fog:
fog.global_position = Vector3(cam_pos.x, fog.global_position.y, cam_pos.z)
#used to follow camera pivot or camera
var anchor_basis = _get_weather_anchor_basis()
if anchor_basis != null:
fog.global_basis = anchor_basis
#endregion
#region Fireflies
@@ -307,6 +342,7 @@ func toggle_wind(value: bool):
particles_wind.emitting = is_windy
_apply_wind_state()
_emit_weather_event_label()
#disable wind and set default values and materials
func init_wind():
@@ -410,6 +446,51 @@ func _update_wind_amount_from_strength(value: float) -> void:
environment_config.wind_amount = roundi(max_wind_amount * amount_ratio)
func trigger_random_weather_event(duration: float = 0.0) -> void:
if random_weather_restore_tween and random_weather_restore_tween.is_valid():
random_weather_restore_tween.kill()
var previous_rain: bool = is_raining
var previous_snow: bool = is_snowing
var previous_wind: bool = is_windy
var previous_storm: bool = is_storm
var random_event_index: int = randi_range(0, 3)
match random_event_index:
0:
_apply_weather_event_state(false, true, false, false)
1:
_apply_weather_event_state(true, false, false, false)
2:
_apply_weather_event_state(false, false, true, false)
_:
_apply_weather_event_state(true, false, false, true)
if duration > 0.0:
random_weather_restore_tween = create_tween()
random_weather_restore_tween.tween_interval(duration)
random_weather_restore_tween.tween_callback(func():
_apply_weather_event_state(previous_rain, previous_snow, previous_wind, previous_storm)
)
func _apply_weather_event_state(rain_enabled: bool, snow_enabled: bool, wind_enabled: bool, storm_enabled: bool = false) -> void:
if is_storm and not storm_enabled:
toggle_storm(false)
if is_raining and not rain_enabled:
toggle_rain(false)
if is_snowing and not snow_enabled:
toggle_snow(false)
if is_windy and not wind_enabled:
toggle_wind(false)
if not is_raining and rain_enabled:
toggle_rain(true)
if not is_snowing and snow_enabled:
toggle_snow(true)
if not is_windy and wind_enabled:
toggle_wind(true)
if not is_storm and storm_enabled:
toggle_storm(true)
func _apply_cloud_config() -> void:
var dir = environment_config.wind_direction
var cloud_scale = environment_config.cloud_scale
@@ -441,6 +522,7 @@ func _apply_cloud_config() -> void:
func toggle_storm(value: bool):
is_storm = value
_emit_weather_event_label()
#set lightning
func init_lightning():
@@ -554,6 +636,7 @@ func toggle_rain(value: bool):
is_raining = value
if not particles_rain:
_emit_weather_event_label()
return
if is_raining and is_snowing:
@@ -587,6 +670,7 @@ func toggle_rain(value: bool):
trigger_after_rain())
puddle_tween = create_tween()
puddle_tween.tween_method(set_puddle_amount, puddle_amount, 0.0, environment_config.puddle_dry_time)
_emit_weather_event_label()
func trigger_morning() -> void:
spawn_single_godray()
@@ -685,6 +769,23 @@ func toggle_snow(value: bool):
snow_tween.kill()
snow_tween = create_tween()
snow_tween.tween_method(init_snow_amount, actual_snow_amount, target_snow_amount, environment_config.snow_transaction_time)
_emit_weather_event_label()
func _emit_weather_event_label() -> void:
var weather_label := "Weather: Clear"
if is_storm:
weather_label = "Weather: Storm"
else:
var active_events: Array[String] = []
if is_snowing:
active_events.append("Snow")
if is_raining:
active_events.append("Rain")
if is_windy:
active_events.append("Wind")
if not active_events.is_empty():
weather_label = "Weather: %s" % " + ".join(active_events)
UIEvents.weather_event_changed.emit(weather_label)
#disable snow and set default values and shader
func init_snow(value: float = 0.0):
@@ -699,6 +800,13 @@ func init_snow(value: float = 0.0):
RenderingServer.global_shader_parameter_set("global_snow_color", environment_config.snow_color)
RenderingServer.global_shader_parameter_set("global_snow_accumulation_speed", environment_config.snow_accumulation_speed)
RenderingServer.global_shader_parameter_set("global_snow_melt_speed", environment_config.snow_melt_speed)
RenderingServer.global_shader_parameter_set("global_snow_max_accumulation", environment_config.snow_max_accumulation)
RenderingServer.global_shader_parameter_set("global_snow_cap_enabled", environment_config.show_snow_accumulation_volume)
RenderingServer.global_shader_parameter_set("global_snow_cap_height", environment_config.snow_cap_height)
RenderingServer.global_shader_parameter_set("global_snow_cap_flatness_start", environment_config.snow_cap_flatness_start)
RenderingServer.global_shader_parameter_set("global_snow_cap_flatness_end", environment_config.snow_cap_flatness_end)
RenderingServer.global_shader_parameter_set("global_snow_cap_noise_scale", environment_config.snow_cap_noise_scale)
RenderingServer.global_shader_parameter_set("global_snow_cap_noise_strength", environment_config.snow_cap_noise_strength)
RenderingServer.global_shader_parameter_set("global_snow_start_time", -1.0)
RenderingServer.global_shader_parameter_set("global_snow_melt_time", -1.0)
@@ -728,6 +836,10 @@ func toggle_blur(value: bool) -> void:
ApplyPostProcessBlurConfig()
func toggle_fog(value: bool) -> void:
if fog:
fog.visible = value
func toggle_shadows(value: bool) -> void:
if environment_shadows:
environment_shadows.visible = value

View File

@@ -6,8 +6,16 @@ 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_amount = 0.0;
global uniform float global_snow_threshold = 0.5;
global uniform vec4 global_snow_color = vec4(0.92, 0.96, 1.0, 1.0);
global uniform float global_snow_max_accumulation = 0.72;
global uniform bool global_snow_cap_enabled = true;
global uniform float global_snow_cap_height = 0.06;
global uniform float global_snow_cap_flatness_start = 0.72;
global uniform float global_snow_cap_flatness_end = 0.96;
global uniform float global_snow_cap_noise_scale = 0.22;
global uniform float global_snow_cap_noise_strength = 0.18;
uniform float snow_noise_scale : hint_range(0.01, 1.0) = 0.15;
uniform float snow_edge_softness : hint_range(0.01, 0.5) = 0.2;
uniform float snow_roughness_variation : hint_range(0.0, 0.3) = 0.15;
@@ -29,6 +37,58 @@ uniform float puddle_threshold : hint_range(0.0, 0.8) = 0.45;
uniform sampler2D noise_texture : filter_linear_mipmap, repeat_enable;
varying float v_snow_amount;
varying float v_snow_cap_mask;
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
}
float value_noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
vec2 u = f * f * (3.0 - 2.0 * f);
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}
float fbm(vec2 p) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
for (int i = 0; i < 3; i++) {
value += value_noise(p * frequency) * amplitude;
frequency *= 2.0;
amplitude *= 0.5;
}
return clamp(value, 0.0, 1.0);
}
float get_snow_progress() {
bool has_snow_timeline = global_snow_start_time >= 0.0 || global_snow_melt_time >= 0.0;
float snow_progress = clamp(global_snow_amount, 0.0, 1.0);
if (has_snow_timeline) {
snow_progress = 0.0;
if (global_snow_start_time >= 0.0) {
snow_progress = 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_progress *= (1.0 - melt);
}
}
return snow_progress;
}
float ripple_ring(vec2 uv, float time_offset) {
float d = length(uv);
float ring = sin(d * 30.0 - TIME * ripple_speed + time_offset) * 0.5 + 0.5;
@@ -36,6 +96,27 @@ float ripple_ring(vec2 uv, float time_offset) {
return ring * fade;
}
void vertex() {
float snow_progress = get_snow_progress();
float snow_accumulation = snow_progress * global_snow_max_accumulation;
vec3 world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
vec3 world_normal = normalize((MODEL_MATRIX * vec4(NORMAL, 0.0)).xyz);
float flat_surface = smoothstep(
max(global_snow_threshold, global_snow_cap_flatness_start),
global_snow_cap_flatness_end,
world_normal.y
);
float accumulation_growth = smoothstep(0.08, 0.65, snow_progress);
float cap_noise = fbm(world_pos.xz * global_snow_cap_noise_scale + vec2(11.3, 4.7));
float cap_variation = mix(1.0 - global_snow_cap_noise_strength, 1.0 + global_snow_cap_noise_strength, cap_noise);
v_snow_amount = snow_progress;
v_snow_cap_mask = flat_surface * accumulation_growth * cap_variation * (global_snow_cap_enabled ? 1.0 : 0.0);
VERTEX += NORMAL * (global_snow_cap_height * snow_accumulation * v_snow_cap_mask);
}
void fragment() {
vec3 world_pos = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
vec3 world_normal = normalize((INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
@@ -43,25 +124,23 @@ void fragment() {
float noise_val = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
//Snow
float snow_amount = 0.0;
if (global_snow_start_time >= 0.0) {
snow_amount = clamp((TIME - global_snow_start_time) * global_snow_accumulation_speed, 0.0, 1.0);
}
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 *= (1.0 - melt);
}
float snow_progress = v_snow_amount;
float snow_accumulation = snow_progress * global_snow_max_accumulation;
float snow_edge = smoothstep(
global_snow_threshold - snow_edge_softness,
global_snow_threshold + snow_edge_softness,
facing_up + (noise_val - 0.5) * 0.4
);
float snow_coverage = smoothstep(0.0, 0.6, noise_val + snow_amount - 0.4);
float snow_factor = snow_edge * snow_coverage * snow_amount;
float flat_accumulation = smoothstep(0.0, 0.35, v_snow_cap_mask) * snow_accumulation;
float snow_coverage = smoothstep(0.0, 0.6, noise_val + snow_progress - 0.4 + flat_accumulation * 0.25);
float snow_factor = max(snow_edge * snow_coverage * snow_progress, flat_accumulation);
float snow_opacity = smoothstep(0.04, 0.28, snow_factor);
snow_opacity = max(snow_opacity, flat_accumulation * 0.9);
float shade = mix(-snow_color_variation, snow_color_variation, noise_val);
vec3 snow_albedo = clamp(global_snow_color.rgb + vec3(shade), 0.0, 1.0);
snow_albedo = mix(snow_albedo, vec3(1.0), 0.18 + snow_opacity * 0.12);
float snow_rough = mix(0.15 - snow_roughness_variation, 0.15 + snow_roughness_variation, noise_val);
//Rain
@@ -173,7 +252,7 @@ void fragment() {
ALBEDO = snow_albedo;
ROUGHNESS = snow_rough;
METALLIC = 0.0;
ALPHA = snow_factor;
ALPHA = snow_opacity;
} else {
ALBEDO = rain_albedo;
ROUGHNESS = rain_rough;

View File

@@ -7,16 +7,13 @@ global uniform float global_snow_accumulation_speed;
global uniform float global_snow_melt_time;
global uniform float global_snow_melt_speed;
global uniform vec4 global_snow_color;
// Rain globals
global uniform float global_rain_intensity;
global uniform float global_rain_puddle_amount;
// Snow parameters
uniform float snow_edge_softness : hint_range(0.01, 0.5) = 0.15;
uniform float snow_color_variation : hint_range(0.0, 0.15) = 0.05;
// Rain wetness parameters
global uniform float global_rain_intensity;
global uniform float global_rain_puddle_amount;
uniform float ripple_scale : hint_range(0.1, 5.0) = 1.5;
uniform float ripple_speed : hint_range(0.5, 5.0) = 2.0;
uniform float ripple_layers : hint_range(1.0, 4.0) = 3.0;

View File

@@ -1,7 +1,21 @@
[gd_resource type="ShaderMaterial" format=3]
[gd_resource type="ShaderMaterial" format=3 uid="uid://b34bnqbrtxktw"]
[ext_resource type="Shader" path="res://core/daynight/weather_plain_shader.gdshader" id="1_weather_plain"]
[ext_resource type="Shader" uid="uid://do8puw7u8dvry" path="res://core/daynight/weather_plain_shader.gdshader" id="1_weather_plain"]
[ext_resource type="Texture2D" uid="uid://bpswbjh4jj1ou" path="res://core/daynight/noise.tres" id="2_noise"]
[resource]
render_priority = 0
shader = ExtResource("1_weather_plain")
shader_parameter/snow_edge_softness = 0.15
shader_parameter/snow_color_variation = 0.05
shader_parameter/ripple_scale = 1.5
shader_parameter/ripple_speed = 2.0
shader_parameter/ripple_layers = 3.0
shader_parameter/streak_scale = 2.0
shader_parameter/streak_speed = 0.8
shader_parameter/wetness_darkening = 0.25
shader_parameter/wet_roughness = 0.05
shader_parameter/rain_normal_strength = 0.4
shader_parameter/puddle_noise_scale = 0.08
shader_parameter/puddle_threshold = 0.45
shader_parameter/noise_texture = ExtResource("2_noise")

View File

@@ -1,31 +1,26 @@
shader_type spatial;
render_mode unshaded;
global uniform float global_wind_speed = 1.0; //0.0 = calm, 1.0 = normal, 2.0+ = strong
global uniform vec2 global_wind_direction = vec2(1.0, 0.0);
uniform float wave_frequency = 1.0;
uniform float base_amplitude = 0.5;
uniform float secondary_ratio = 0.6;
uniform float time_scale_base = 3.0;
// --- PARAMETRI ---
uniform float time_scale = 3.0;
uniform float wave_amplitude = 0.5; // Quanto curva a destra/sinistra
uniform float wave_frequency = 1.0; // Ogni quanto fa la curva
void vertex() {
float random_seed_offset = INSTANCE_CUSTOM.x * 100.0;
float scaled_time = (TIME + random_seed_offset) * (time_scale_base * global_wind_speed);
float amplitude = base_amplitude * global_wind_speed;
vec2 wind_dir = normalize(global_wind_direction);
vec2 wind_perp = vec2(-wind_dir.y, wind_dir.x); //90° perpendicular
float primary_sway = sin(VERTEX.y * wave_frequency + scaled_time) * amplitude;
float secondary_sway = sin(VERTEX.y * wave_frequency * 1.3 + scaled_time * 0.7 + 1.57)
* (amplitude * secondary_ratio);
VERTEX.x += primary_sway * wind_dir.x + secondary_sway * wind_perp.x;
VERTEX.z += primary_sway * wind_dir.y + secondary_sway * wind_perp.y;
// Creiamo un offset unico per ogni particella in modo che non si muovano tutte uguali
float random_seed_offset = INSTANCE_CUSTOM.x * 100.0;
float scaled_time = (TIME + random_seed_offset) * time_scale;
// Applichiamo SOLO la curva morbida all'asse X (o Z, a seconda di come orienti la scena)
// Usiamo VERTEX.y per far sì che la curva si propaghi lungo tutta la lunghezza della scia
VERTEX.x += sin(VERTEX.y * wave_frequency + scaled_time) * wave_amplitude;
// Niente più "VERTEX.y += t;", quindi niente più teletrasporti!
}
void fragment() {
// Il colore e l'alpha (per lo spawn dolce e la morte lenta)
// vengono comandati dalla Color Ramp del GPUParticles3D!
ALBEDO = COLOR.rgb;
ALPHA = COLOR.a;
}

View File

@@ -81,8 +81,9 @@ extends Resource
#Post-process effect toggles (initial values)
@export_group("Post Process")
@export var enable_dust: bool = false #Floating dust particles overlay
@export var enable_blur: bool = false #Screen blur effect
@export var enable_blur: bool = true #Screen blur effect
@export var enable_environment_shadows: bool = true #Cloud shadow projection on terrain
@export var enable_fog: bool = false #Enable fog around the train
@export var blur_amount: float = 0.6
@export_group("Dust")
@@ -133,15 +134,27 @@ extends Resource
@export var godray_spawn_height: float = 5.0 #Y world position where god rays spawn
@export var godray_scale: Vector3 = Vector3(2.0, 6.0, 2.0) #Scale of the god ray mesh
#Train start settings
@export_group("Train Start")
@export var train_start_from_random_position: bool = false #When enabled the train starts from a random offset on the rail curve instead of a stop
@export_range(0, 64, 1, "or_greater") var train_start_stop_index: int = 1 #Stop index used for the train start when random start is disabled
#Snow settings
@export_group("Snow")
@export var snow_amount: float = 0.0 #Initial snow coverage amount (0.0 = none, 1.0 = full)
@export var snow_transaction_time: float = 10.0 #Seconds for snow shader to fully transition in/out
@export var snow_fade_time: float = 5.0 #Seconds for snow particles to fade in/out
@export var snow_threshold: float = 0.4 #Normal Y threshold for snow accumulation on surfaces
@export var snow_accumulation_speed: float = 0.02 #Accumulation speed: 0.1 -> 10s, 0.05 -> 20s, 0.02 -> 50s, 0.2 -> 5s
@export var snow_accumulation_speed: float = 0.014 #Accumulation speed: 0.1 -> 10s, 0.05 -> 20s, 0.02 -> 50s, 0.012 -> ~83s
@export var snow_melt_speed: float = 0.05 #Speed at which accumulated snow melts away
@export var show_snow_accumulation_volume: bool = true #Enables vertex snow buildup; when false snow only changes surface color
@export var snow_max_accumulation: float = 0.25 #Maximum accumulated snow factor applied to coverage and thickness
@export var snow_color: Color = Color(0.9, 0.95, 1.0) #Albedo color of snow on surfaces
@export var snow_cap_height: float = 0.03 #Maximum snow thickness extruded on flat surfaces
@export var snow_cap_flatness_start: float = 0.85 #Surface normal Y where cap buildup starts
@export var snow_cap_flatness_end: float = 0.96 #Surface normal Y where cap buildup reaches full effect
@export var snow_cap_noise_scale: float = 0.22 #Noise scale used to vary the snow cap silhouette
@export var snow_cap_noise_strength: float = 0.12 #How much the cap noise changes the accumulated thickness
@export var snow_mode_color: Color = Color(0.556, 0.62, 0.683, 1.0) #Sky/light darkening color during snow
#Wind settings
@@ -152,7 +165,7 @@ extends Resource
@export var wind_direction: Vector2 = Vector2(0.5, 0.4) #Global wind direction (XZ)
@export var wind_speed: float = 0.2 #Global wind animation speed
@export var wind_scale: float = 0.025 #Global wind noise scale
@export var wind_strength: float = 0.6 #Global wind displacement strength
@export var wind_strength: float = 0.3 #Global wind displacement strength
@export var cloud_scale: float = 0.5 #Cloud noise scale in sky shader
@export var cloud_speed: float = 0.05 #Cloud movement speed in sky shader
@export_range(0.01, 1.0) var cloud_scale_envshadows_rate: float = 0.01 #Cloud scale multiplier for environment shadows
@@ -164,3 +177,10 @@ extends Resource
@export var fireflies_amount: int = 60 #Number of firefly particles
@export var fireflies_spawn_ray: float = 20.0 #Horizontal spawn radius
@export var fireflies_spawn_height: float = 3.0 #Vertical spawn range
#Water settings
@export_group("Water")
@export var water_color_morning: Color = Color(0.285, 0.534, 0.487, 1.0) #Tint for morning
@export var water_color_afternoon: Color = Color(0.889, 0.733, 0.205, 1.0) #Tint for afternoon (sunset)
@export var water_color_night: Color = Color(0.728, 0.54, 0.986, 1.0); #Tint for night
@export var water_darkening_rain: float = 0.7 #Percentage of darkening when is rainy

View File

@@ -10,6 +10,10 @@ signal toggle_wind(value: bool)
@warning_ignore("unused_signal")
signal wind_change(value: float)
@warning_ignore("unused_signal")
signal trigger_random_weather(duration: float)
@warning_ignore("unused_signal")
signal weather_event_changed(description: String)
@warning_ignore("unused_signal")
signal toggle_fireflies(value: bool)
@warning_ignore("unused_signal")
signal toggle_storm(value: bool)
@@ -23,6 +27,8 @@ signal toggle_dust(value: bool)
signal toggle_blur(value: bool)
@warning_ignore("unused_signal")
signal toggle_shadows(value: bool)
@warning_ignore("unused_signal")
signal toggle_fog(value: bool)
#day cycle signals
@warning_ignore("unused_signal")

View File

@@ -349,6 +349,30 @@ theme_override_colors/font_outline_color = Color(1, 1, 1, 1)
button_pressed = true
text = "Shadows"
[node name="RandomWeather" type="Button" parent="Control" unique_id=1047710802]
layout_mode = 0
offset_left = 12.0
offset_top = 289.0
offset_right = 157.0
offset_bottom = 320.0
theme_override_colors/font_color = Color(1, 1, 1, 1)
theme_override_colors/font_focus_color = Color(1, 1, 1, 1)
theme_override_colors/font_pressed_color = Color(1, 1, 1, 1)
theme_override_colors/font_hover_color = Color(1, 1, 1, 1)
theme_override_colors/font_hover_pressed_color = Color(1, 1, 1, 1)
theme_override_colors/font_outline_color = Color(1, 1, 1, 1)
text = "Random Weather (10\")"
[node name="WeatherEventLabel" type="Label" parent="Control" unique_id=641424797]
layout_mode = 0
offset_left = 1656.0
offset_top = 11.0
offset_right = 1908.0
offset_bottom = 34.0
theme_override_colors/font_color = Color(1, 1, 1, 1)
theme_override_colors/font_outline_color = Color(1, 1, 1, 1)
text = "Weather: Clear"
[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"]
@@ -361,3 +385,4 @@ text = "Shadows"
[connection signal="toggled" from="Control/Blur" to="Control" method="_on_blur_toggled"]
[connection signal="toggled" from="Control/Pause" to="Control" method="_on_pause_toggled"]
[connection signal="toggled" from="Control/Shadows" to="Control" method="_on_shadows_toggled"]
[connection signal="pressed" from="Control/RandomWeather" to="Control" method="_on_random_weather_pressed"]

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
extends Control
@onready var day_night: EnvironmentManagerRoot = $"../DayNight"
@onready var weather_event_label: Label = $WeatherEventLabel
@onready var day_time_label: Label = $DayTimeLabel
@onready var day_time_slider: HSlider = $DayTimeSlider
@onready var wind_slider: HSlider = $WindSlider
@@ -9,9 +10,11 @@ extends Control
func _ready() -> void:
UIEvents.day_time_changed.connect(_on_day_time_changed)
UIEvents.day_time_option_changed.connect(_on_day_time_option_changed)
UIEvents.weather_event_changed.connect(_on_weather_event_changed)
if day_night != null and day_night.environment_config != null and wind_slider != null:
wind_slider.set_value_no_signal(day_night.environment_config.wind_strength)
_sync_day_time_ui()
_on_weather_event_changed("Weather: Clear")
func _on_rain_toggled(toggled_on: bool) -> void:
UIEvents.toggle_rain.emit(toggled_on)
@@ -25,10 +28,13 @@ func _on_wind_toggled(toggled_on: bool) -> void:
func _on_wind_slider_value_changed(value: float) -> void:
UIEvents.wind_change.emit(value)
func _on_random_weather_pressed() -> void:
UIEvents.trigger_random_weather.emit(10.0)
func _on_fireflies_toggled(toggled_on: bool) -> void:
UIEvents.toggle_fireflies.emit(toggled_on)
func _on_storm_toggled(toggled_on: bool) -> void:
func _on_storm_toggled(toggled_on: bool) -> void:
UIEvents.toggle_storm.emit(toggled_on)
func _on_day_time_slider_value_changed(value: float) -> void:
@@ -45,6 +51,10 @@ func _on_day_time_changed(value: float, time_string: String) -> void:
label_text = "Time %s | nt %.3f | dt %.3f" % [time_string, value, day_night.day_time]
day_time_label.text = label_text
func _on_weather_event_changed(description: String) -> void:
if weather_event_label:
weather_event_label.text = description
func _on_fog_overlay_toggled(toggled_on: bool) -> void:
UIEvents.toggle_fog_overlay.emit(toggled_on)
@@ -86,3 +96,6 @@ func _on_day_time_option_changed(index: int) -> void:
func _on_option_button_item_selected(index: int) -> void:
UIEvents.time_option_item_changed.emit(index)
func _on_fog_toggled(toggled_on: bool) -> void:
UIEvents.toggle_fog.emit(toggled_on)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,57 @@
[gd_scene format=3 uid="uid://b7rhqxsyv87r1"]
[ext_resource type="PackedScene" uid="uid://cjv1e8pc6gde1" path="res://tgcc/chunk/countryside/scene/chunk_country_corner_01.tscn" id="1_eexnc"]
[ext_resource type="PackedScene" uid="uid://dqoai3665vb0a" path="res://tgcc/chunk/countryside/scene/chunk_country_corner_02.tscn" id="2_jh6kr"]
[ext_resource type="PackedScene" uid="uid://crlk31ecl480n" path="res://tgcc/chunk/countryside/scene/chunk_country_corner_03.tscn" id="3_pftht"]
[ext_resource type="PackedScene" uid="uid://brpp7fe5noq8v" path="res://tgcc/chunk/countryside/scene/chunk_country_cross_3_01.tscn" id="4_jexg3"]
[ext_resource type="PackedScene" uid="uid://qmt8bkiksgj3" path="res://tgcc/chunk/countryside/scene/chunk_country_cross_3_02.tscn" id="5_hieqo"]
[ext_resource type="PackedScene" uid="uid://d1tfkhuktwthn" path="res://tgcc/chunk/countryside/scene/chunk_country_cross_3_03.tscn" id="6_re3ik"]
[ext_resource type="PackedScene" uid="uid://c73yk6858dmwn" path="res://tgcc/chunk/countryside/scene/chunk_country_cross_4_01.tscn" id="7_v47u4"]
[ext_resource type="PackedScene" uid="uid://b8blm6bwintf7" path="res://tgcc/chunk/countryside/scene/chunk_country_empty_01.tscn" id="8_bag0j"]
[ext_resource type="PackedScene" uid="uid://b002wu5ltuqi4" path="res://tgcc/chunk/countryside/scene/chunk_country_end_01.tscn" id="9_1vyrv"]
[ext_resource type="PackedScene" uid="uid://dtfmvcbninrcu" path="res://tgcc/chunk/countryside/scene/chunk_country_end_02.tscn" id="10_sdnjr"]
[ext_resource type="PackedScene" uid="uid://h6xj43vo84uf" path="res://tgcc/chunk/countryside/scene/chunk_country_straight_01.tscn" id="11_arwwt"]
[ext_resource type="PackedScene" uid="uid://cu2chsjh8wuvp" path="res://tgcc/chunk/countryside/scene/chunk_country_straight_02.tscn" id="12_l62i2"]
[ext_resource type="PackedScene" uid="uid://pxmcy0lhne5d" path="res://tgcc/chunk/countryside/scene/chunk_country_straight_03.tscn" id="13_f3g5s"]
[node name="ZooCountryside" type="Node3D" unique_id=1742985179]
[node name="country" type="Node3D" parent="." unique_id=672430814]
[node name="chunk_country_corner_01" parent="country" unique_id=200417581 instance=ExtResource("1_eexnc")]
[node name="chunk_country_corner_02" parent="country" unique_id=85657005 instance=ExtResource("2_jh6kr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 22.5)
[node name="chunk_country_corner_03" parent="country" unique_id=1046737870 instance=ExtResource("3_pftht")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 45)
[node name="chunk_country_cross3_01" parent="country" unique_id=319840865 instance=ExtResource("4_jexg3")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -22.5, 0, 0)
[node name="chunk_country_cross3_02" parent="country" unique_id=1492245999 instance=ExtResource("5_hieqo")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -22.5, 0, 22.5)
[node name="chunk_country_cross3_03" parent="country" unique_id=643218732 instance=ExtResource("6_re3ik")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -22.5, 0, 45)
[node name="chunk_country_cross4_01" parent="country" unique_id=680431911 instance=ExtResource("7_v47u4")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -45, 0, 0)
[node name="chunk_country_empty_01" parent="country" unique_id=385761952 instance=ExtResource("8_bag0j")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -67.5, 0, 0)
[node name="chunk_country_end_01" parent="country" unique_id=913263516 instance=ExtResource("9_1vyrv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -90, 0, 0)
[node name="chunk_country_end_02" parent="country" unique_id=1712924087 instance=ExtResource("10_sdnjr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -90, 0, 22.5)
[node name="chunk_country_straight_01" parent="country" unique_id=926368352 instance=ExtResource("11_arwwt")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -113, 0, 0)
[node name="chunk_country_straight_02" parent="country" unique_id=1847746456 instance=ExtResource("12_l62i2")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -113, 0, 22.5)
[node name="chunk_country_straight_03" parent="country" unique_id=626808879 instance=ExtResource("13_f3g5s")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -113, 0, 45)

View File

@@ -0,0 +1,36 @@
[gd_scene format=3 uid="uid://bvjiqu363c15p"]
[ext_resource type="PackedScene" uid="uid://cl2ast2tk7ifw" path="res://tgcc/chunk/railway/scene/chunk_railway_curve.tscn" id="14_ttcft"]
[ext_resource type="PackedScene" uid="uid://cewdxvcpqb53f" path="res://tgcc/chunk/railway/scene/chunk_railway_station_doubleside.tscn" id="15_oi62p"]
[ext_resource type="PackedScene" uid="uid://bup6gwlxos0w2" path="res://tgcc/chunk/railway/scene/chunk_railway_station_hero.tscn" id="16_birpm"]
[ext_resource type="PackedScene" uid="uid://d3pcshw2bioic" path="res://tgcc/chunk/railway/scene/chunk_railway_station_oneside.tscn" id="17_esgqd"]
[ext_resource type="PackedScene" uid="uid://bqxpqhla2kogq" path="res://tgcc/chunk/railway/scene/chunk_railway_straight.tscn" id="18_5ivsh"]
[ext_resource type="PackedScene" uid="uid://c3ub6rj0tlt6q" path="res://tgcc/chunk/railway/scene/chunk_railway_straight_2.tscn" id="19_yd4l5"]
[ext_resource type="PackedScene" uid="uid://f53hfrjaxkwa" path="res://tgcc/chunk/railway/scene/chunk_railway_straight_bridge.tscn" id="20_h1ucl"]
[node name="ZooCountryside" type="Node3D" unique_id=1742985179]
[node name="country" type="Node3D" parent="." unique_id=672430814]
[node name="railway" type="Node3D" parent="." unique_id=1626602327]
[node name="chunk_railway_curve" parent="railway" unique_id=238887300 instance=ExtResource("14_ttcft")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14, 0, -20)
[node name="chunk_railway_station_doubleside" parent="railway" unique_id=1591869611 instance=ExtResource("15_oi62p")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16, 0, 46)
[node name="chunk_railway_station_hero" parent="railway" unique_id=1050909298 instance=ExtResource("16_birpm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 29, 0, 25)
[node name="chunk_railway_station_oneside" parent="railway" unique_id=310632835 instance=ExtResource("17_esgqd")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16, 0, 24)
[node name="chunk_railway_straight" parent="railway" unique_id=1509029322 instance=ExtResource("18_5ivsh")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 29, 0, 0)
[node name="chunk_railway_straight_2" parent="railway" unique_id=476549215 instance=ExtResource("19_yd4l5")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 29, 0, -23)
[node name="chunk_railway_straight_bridge" parent="railway" unique_id=1049036234 instance=ExtResource("20_h1ucl")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 29, 0, -46)

View File

@@ -11,8 +11,9 @@ config_version=5
[application]
config/name="tgcc"
run/main_scene="uid://cae0mnf353dy3"
run/main_scene="uid://38qpxwbpvd28"
config/features=PackedStringArray("4.6", "Forward Plus")
run/max_fps=60
config/icon="uid://bfar1kk3pgq8f"
[autoload]
@@ -23,6 +24,7 @@ UIEvents="*uid://dehu28iq27mbn"
window/size/viewport_width=1920
window/size/viewport_height=1080
window/size/mode=3
window/stretch/mode="canvas_items"
window/stretch/aspect="expand"
@@ -112,3 +114,35 @@ global_wind_fade={
"type": "float",
"value": 1.2
}
global_snow_cap_height={
"type": "float",
"value": 0.0
}
global_snow_cap_flatness_start={
"type": "float",
"value": 0.0
}
global_snow_cap_flatness_end={
"type": "float",
"value": 0.0
}
global_snow_cap_noise_scale={
"type": "float",
"value": 0.0
}
global_snow_cap_noise_strength={
"type": "float",
"value": 0.0
}
global_snow_max_accumulation={
"type": "float",
"value": 0.0
}
global_snow_cap_enabled={
"type": "bool",
"value": false
}
global_water_color={
"type": "color",
"value": Color(0, 0, 0, 1)
}

View File

@@ -110,7 +110,7 @@ surface_material_override/1 = ExtResource("4_w66q1")
surface_material_override/0 = ExtResource("4_w66q1")
surface_material_override/1 = ExtResource("6_333a0")
[node name="MSH_Staccioanta_1_001" parent="." index="8" unique_id=2137478487]
[node name="MSH_Staccioanta_1_001" parent="." index="8" unique_id=2137478487 groups=["weather_node"]]
surface_material_override/0 = ExtResource("7_333a0")
[node name="Palo_001" parent="." index="9" unique_id=1395117968]

View File

@@ -60,7 +60,7 @@ surface_material_override/1 = ExtResource("2_6ig2p")
[node name="Grass_009" parent="." index="1" unique_id=629886419]
surface_material_override/0 = ExtResource("2_6ig2p")
[node name="MSH_Staccioanta_1_009" parent="." index="2" unique_id=802806256]
[node name="MSH_Staccioanta_1_009" parent="." index="2" unique_id=802806256 groups=["weather_node"]]
surface_material_override/0 = ExtResource("3_wjrum")
[node name="Strada_007" parent="." index="3" unique_id=1200357449 groups=["weather_node"]]

View File

@@ -103,7 +103,7 @@ surface_material_override/1 = ExtResource("4_yg4ko")
[node name="MSH_Staccioanta_1_007" parent="." index="8" unique_id=166305032]
surface_material_override/0 = ExtResource("6_k52wx")
[node name="PaliLuci_003" parent="." index="9" unique_id=718749193]
[node name="PaliLuci_003" parent="." index="9" unique_id=718749193 groups=["weather_node"]]
surface_material_override/0 = ExtResource("7_yg4ko")
surface_material_override/1 = ExtResource("7_yg4ko")

View File

@@ -91,7 +91,7 @@ visible = false
[node name="FlowerG_003" parent="." index="5" unique_id=65871813 groups=["weather_node", "wind_node"]]
visible = false
[node name="Grass_008" parent="." index="6" unique_id=1853173495 groups=["weather_vegetables_node", "wind_node"]]
[node name="Grass_008" parent="." index="6" unique_id=1853173495]
surface_material_override/0 = ExtResource("2_cltnj")
[node name="House_M_3" parent="." index="7" unique_id=155596536 groups=["weather_node"]]
@@ -104,14 +104,14 @@ surface_material_override/1 = ExtResource("7_0r8cm")
surface_material_override/0 = ExtResource("7_0r8cm")
surface_material_override/1 = ExtResource("6_pjysl")
[node name="MSH_Staccioanta_1_005" parent="." index="9" unique_id=1042751383]
[node name="MSH_Staccioanta_1_005" parent="." index="9" unique_id=1042751383 groups=["weather_node"]]
surface_material_override/0 = ExtResource("8_hmdr4")
[node name="PaliLuci_002" parent="." index="10" unique_id=1504995410]
surface_material_override/0 = ExtResource("3_aj7xj")
surface_material_override/1 = ExtResource("3_aj7xj")
[node name="Panchina_002" parent="." index="11" unique_id=876085859]
[node name="Panchina_002" parent="." index="11" unique_id=876085859 groups=["weather_node"]]
surface_material_override/0 = ExtResource("8_hmdr4")
[node name="Strada_006" parent="." index="12" unique_id=76888486 groups=["weather_node"]]

View File

@@ -154,7 +154,7 @@ south = true
[node name="Argini_005" parent="." index="0" unique_id=255857931]
surface_material_override/0 = ExtResource("2_t65ww")
[node name="Bags" parent="." index="1" unique_id=2117673123 groups=["weather_node"]]
[node name="Bags" parent="." index="1" unique_id=2117673123]
surface_material_override/0 = SubResource("ShaderMaterial_q2s76")
[node name="Cart" parent="." index="2" unique_id=884973125]
@@ -191,14 +191,14 @@ surface_material_override/0 = ExtResource("5_sy58u")
surface_material_override/1 = ExtResource("5_sy58u")
surface_material_override/2 = ExtResource("6_eev23")
[node name="Statue" parent="." index="11" unique_id=1814801509 groups=["weather_node"]]
[node name="Statue" parent="." index="11" unique_id=1814801509]
surface_material_override/0 = ExtResource("5_sy58u")
surface_material_override/1 = ExtResource("7_q2s76")
[node name="Water_006" parent="." index="12" unique_id=1352334701]
surface_material_override/0 = ExtResource("10_r4bww")
[node name="WoodPile" parent="." index="13" unique_id=1088104699 groups=["weather_node"]]
[node name="WoodPile" parent="." index="13" unique_id=1088104699]
surface_material_override/0 = ExtResource("11_iulsg")
surface_material_override/1 = ExtResource("12_ytk0o")
surface_material_override/2 = SubResource("ShaderMaterial_ytk0o")

View File

@@ -0,0 +1,24 @@
[gd_resource type="ShaderMaterial" format=3 uid="uid://xrxl0d5h6f6s"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="1_rl1n5"]
[resource]
render_priority = 0
shader = ExtResource("1_rl1n5")
shader_parameter/albedo_color = Color(0.74859685, 0.72101974, 0.57504904, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(3, 3)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 1.5
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0

View File

@@ -0,0 +1,24 @@
[gd_resource type="ShaderMaterial" format=3 uid="uid://chppialx3cyph"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="1_vresk"]
[resource]
render_priority = 0
shader = ExtResource("1_vresk")
shader_parameter/albedo_color = Color(0.48413807, 0.37183177, 0.06357419, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 10.0
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0

View File

@@ -0,0 +1,24 @@
[gd_resource type="ShaderMaterial" format=3 uid="uid://c8fkccysike5l"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="1_ndadq"]
[resource]
render_priority = 0
shader = ExtResource("1_ndadq")
shader_parameter/albedo_color = Color(0.49797475, 0.22462493, 0.1484783, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 10.0
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0

View File

@@ -2,13 +2,13 @@
[ext_resource type="Shader" uid="uid://8l8glwvvs7fb" path="res://core/daynight/grass_leaves.gdshader" id="1_yw70r"]
[ext_resource type="Texture2D" uid="uid://bm0roy74xo3ce" path="res://tgcc/chunk/prop/flower/bush_alpha.png" id="2_rv6bf"]
[ext_resource type="Texture2D" path="res://tgcc/chunk/prop/flower/bush_colornoise.tres" id="3_t3pfi"]
[ext_resource type="Texture2D" uid="uid://bkuv31yvqmqr2" path="res://tgcc/chunk/prop/flower/bush_colornoise.tres" id="3_t3pfi"]
[resource]
render_priority = 0
shader = ExtResource("1_yw70r")
shader_parameter/billboard_enabled = true
shader_parameter/wind_enabled = false
shader_parameter/wind_enabled = true
shader_parameter/base_color = Color(0.2509804, 0.44705883, 0.20392157, 1)
shader_parameter/alpha_texture = ExtResource("2_rv6bf")
shader_parameter/leaves_scale = 0.65

View File

@@ -8,7 +8,7 @@
render_priority = 0
shader = ExtResource("1_28e45")
shader_parameter/billboard_enabled = true
shader_parameter/wind_enabled = false
shader_parameter/wind_enabled = true
shader_parameter/base_color = Color(0, 0.42745098, 0.9843137, 1)
shader_parameter/alpha_texture = ExtResource("2_4kf4f")
shader_parameter/leaves_scale = 0.365

View File

@@ -16,7 +16,7 @@ seamless = true
render_priority = 0
shader = ExtResource("1_a5yde")
shader_parameter/billboard_enabled = true
shader_parameter/wind_enabled = false
shader_parameter/wind_enabled = true
shader_parameter/base_color = Color(0.3882353, 0.52156866, 0.20784314, 1)
shader_parameter/alpha_texture = ExtResource("2_4hc02")
shader_parameter/leaves_scale = 0.65
@@ -24,13 +24,13 @@ shader_parameter/rotation_degrees = 180.0
shader_parameter/texture_offset = Vector2(0, 0)
shader_parameter/opacity = 1.0
shader_parameter/color_variance_noise = SubResource("NoiseTexture2D_4hc02")
shader_parameter/variance_scale = 0.15
shader_parameter/variance_scale = 0.06
shader_parameter/variance_color = Color(0.3, 0.5, 0.2, 1)
shader_parameter/variance_intensity = 0.750000035625
shader_parameter/variance_intensity = 0.350000016625
shader_parameter/snow_color = Color(0.85, 0.9, 0.95, 1)
shader_parameter/height_min = 0.0
shader_parameter/height_max = 5.0
shader_parameter/shadow_intensity = 0.70000003325
shader_parameter/shadow_intensity = 0.6000000285
shader_parameter/highlight_intensity = 0.10000000475
shader_parameter/light_steps = 8.600000361
shader_parameter/random_mix = 0.0150000007125

View File

@@ -7,7 +7,7 @@
render_priority = 0
shader = ExtResource("1_0cuwq")
shader_parameter/billboard_enabled = true
shader_parameter/wind_enabled = false
shader_parameter/wind_enabled = true
shader_parameter/base_color = Color(0.103467666, 0.34917185, 0.14285779, 1)
shader_parameter/alpha_texture = ExtResource("2_ldsj3")
shader_parameter/leaves_scale = 0.92

View File

@@ -7,7 +7,7 @@
render_priority = 0
shader = ExtResource("1_vpd27")
shader_parameter/billboard_enabled = true
shader_parameter/wind_enabled = false
shader_parameter/wind_enabled = true
shader_parameter/base_color = Color(0.14700681, 0.45590013, 0.22758594, 1)
shader_parameter/alpha_texture = ExtResource("2_wl0p2")
shader_parameter/leaves_scale = 0.46
@@ -21,3 +21,4 @@ shader_parameter/highlight_intensity = 0.0
shader_parameter/light_steps = 10.0
shader_parameter/random_mix = 0.010000000475
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/wetness_darkening = 0.25

View File

@@ -0,0 +1,24 @@
[gd_resource type="ShaderMaterial" format=3 uid="uid://bamlo2a2cen7j"]
[ext_resource type="Shader" uid="uid://cs0xl7pc6e26h" path="res://core/daynight/tree_leaves.gdshader" id="1_1pbmj"]
[ext_resource type="Texture2D" uid="uid://c3grftlmap4q5" path="res://tgcc/chunk/prop/tree/leaf1_alpha.png" id="2_iw3ik"]
[resource]
render_priority = 0
shader = ExtResource("1_1pbmj")
shader_parameter/billboard_enabled = true
shader_parameter/wind_enabled = true
shader_parameter/base_color = Color(0.9549616, 0.54784274, 0.71385026, 1)
shader_parameter/alpha_texture = ExtResource("2_iw3ik")
shader_parameter/leaves_scale = 0.5
shader_parameter/rotation_degrees = 180.0
shader_parameter/texture_offset = Vector2(0, 0)
shader_parameter/opacity = 1.0
shader_parameter/height_min = 3.1
shader_parameter/height_max = 5.43
shader_parameter/shadow_intensity = 0.800000038
shader_parameter/highlight_intensity = 0.0
shader_parameter/light_steps = 10.0
shader_parameter/random_mix = 0.0
shader_parameter/cast_shadow_strength = 0.0
shader_parameter/wetness_darkening = 0.25

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,205 @@
[gd_scene format=3 uid="uid://cm1ts0kkpbret"]
[gd_scene format=3 uid="uid://1c1ion0qnho4"]
[node name="Map1" type="Node3D" unique_id=636684781]
[ext_resource type="PackedScene" uid="uid://cl2ast2tk7ifw" path="res://tgcc/chunk/railway/scene/chunk_railway_curve.tscn" id="1_p62h3"]
[ext_resource type="PackedScene" uid="uid://bqxpqhla2kogq" path="res://tgcc/chunk/railway/scene/chunk_railway_straight.tscn" id="2_e76ix"]
[ext_resource type="PackedScene" uid="uid://c3ub6rj0tlt6q" path="res://tgcc/chunk/railway/scene/chunk_railway_straight_2.tscn" id="3_wf82y"]
[ext_resource type="PackedScene" uid="uid://f53hfrjaxkwa" path="res://tgcc/chunk/railway/scene/chunk_railway_straight_bridge.tscn" id="4_l8ggx"]
[ext_resource type="PackedScene" uid="uid://d3pcshw2bioic" path="res://tgcc/chunk/railway/scene/chunk_railway_station_oneside.tscn" id="5_bn4ba"]
[ext_resource type="PackedScene" uid="uid://cewdxvcpqb53f" path="res://tgcc/chunk/railway/scene/chunk_railway_station_doubleside.tscn" id="6_t5p8i"]
[ext_resource type="PackedScene" uid="uid://bup6gwlxos0w2" path="res://tgcc/chunk/railway/scene/chunk_railway_station_hero.tscn" id="7_8nm7p"]
[ext_resource type="Script" uid="uid://dboerd4a6dwj7" path="res://core/biome_generator/rails.gd" id="8_w775f"]
[ext_resource type="PackedScene" uid="uid://dvk3bytqn3m5s" path="res://tgcc/train/main_train.tscn" id="9_haiv3"]
[sub_resource type="Curve3D" id="Curve3D_rfork"]
closed = true
bake_interval = 150.82
_data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, -4.372, 0, 140, 0, 0, 0, 0, 0, 0, -20.963, 0, 160, 0, 0, 0, 0, 0, 0, -40.62518, 0, 168.52754, 0, 0, 0, 0, 0, 0, -60, 0, 170, 0, 0, 0, 0, 0, 0, -80, 0, 170, 0, 0, 0, 0, 0, 0, -100, 0, 170, 0, 0, 0, 0, 0, 0, -120.42937, 0, 171.50279, 0, 0, 0, 0, 0, 0, -141.41747, 7.6293945e-06, 180.5982, 0, 0, 0, 0, 0, 0, -155.77005, 7.6293945e-06, 198.35184, 0, 0, 0, 0, 0, 0, -160.14105, 7.6293945e-06, 219.80951, 0, 0, 0, 0, 0, 0, -163.99007, 7.6293945e-06, 239.36005, 0, 0, 0, 0, 0, 0, -175.77509, 7.6293945e-06, 256.16028, 0, 0, 0, 0, 0, 0, -195.62283, 7.6293945e-06, 267.46912, 0, 0, 0, 0, 0, 0, -219.9999, 7.6293945e-06, 270.11758, 0, 0, 0, 0, 0, 0, -240, 0, 270.118, 0, 0, 0, 0, 0, 0, -260, 0, 270.118, 0, 0, 0, 0, 0, 0, -275.19666, 7.6293945e-06, 270.55228, 0, 0, 0, 0, 0, 0, -294.2925, 7.6293945e-06, 276.05307, 0, 0, 0, 0, 0, 0, -307.19006, 7.6293945e-06, 286.9095, 0, 0, 0, 0, 0, 0, -317.32443, 7.6293945e-06, 303.14682, 0, 0, 0, 0, 0, 0, -320, 0, 320, 0, 0, 0, 0, 0, 0, -320, 0, 340, 0, 0, 0, 0, 0, 0, -320, 0, 360, 0, 0, 0, 0, 0, 0, -320, 0, 380, 0, 0, 0, 0, 0, 0, -316.78876, 7.6293945e-06, 396.91193, 0, 0, 0, 0, 0, 0, -307.68207, 7.6293945e-06, 412.70596, 0, 0, 0, 0, 0, 0, -291.08273, 7.6293945e-06, 424.7491, 0, 0, 0, 0, 0, 0, -270, 0, 429.994, 0, 0, 0, 0, 0, 0, -250, 0, 429.994, 0, 0, 0, 0, 0, 0, -229.90146, 7.6293945e-06, 433.90823, 0, 0, 0, 0, 0, 0, -217.15442, 7.6293945e-06, 442.98242, 0, 0, 0, 0, 0, 0, -204.60803, 7.6293945e-06, 459.93704, 0, 0, 0, 0, 0, 0, -200, 0, 480, 0, 0, 0, 0, 0, 0, -200, 0, 500, 0, 0, 0, 0, 0, 0, -195.5338, 7.6293945e-06, 520.0368, 0, 0, 0, 0, 0, 0, -184.9173, 7.6293945e-06, 535.07776, 0, 0, 0, 0, 0, 0, -170.36423, 7.6293945e-06, 545.0799, 0, 0, 0, 0, 0, 0, -150.56184, 0, 549.8127, 0, 0, 0, 0, 0, 0, -130, 0, 550, 0, 0, 0, 0, 0, 0, -110, 0, 550, 0, 0, 0, 0, 0, 0, -90, 0, 550, 0, 0, 0, 0, 0, 0, -70, 0, 550, 0, 0, 0, 0, 0, 0, -50, 0, 550, 0, 0, 0, 0, 0, 0, -29.862535, 7.6293945e-06, 545.3371, 0, 0, 0, 0, 0, 0, -13.215244, 7.6293945e-06, 533.0626, 0, 0, 0, 0, 0, 0, -4.098665, 7.6293945e-06, 519.6814, 0, 0, 0, 0, 0, 0, -0.048213482, 7.6293945e-06, 500.107, 0, 0, 0, 0, 0, 0, 3.7920675, 7.6293945e-06, 480.64902, 0, 0, 0, 0, 0, 0, 13.513225, 7.6293945e-06, 465.9133, 0, 0, 0, 0, 0, 0, 29.76715, 7.6293945e-06, 454.41486, 0, 0, 0, 0, 0, 0, 49.711926, 7.6293945e-06, 450.12488, 0, 0, 0, 0, 0, 0, 70, 0, 450, 0, 0, 0, 0, 0, 0, 90, 0, 450, 0, 0, 0, 0, 0, 0, 110.055405, 7.6293945e-06, 445.42627, 0, 0, 0, 0, 0, 0, 126.975784, 7.6293945e-06, 432.8683, 0, 0, 0, 0, 0, 0, 136.95703, 7.6293945e-06, 417.5506, 0, 0, 0, 0, 0, 0, 140, 0, 400, 0, 0, 0, 0, 0, 0, 140, 0, 380, 0, 0, 0, 0, 0, 0, 140, 0, 360, 0, 0, 0, 0, 0, 0, 140, 0, 340, 0, 0, 0, 0, 0, 0, 140, 0, 320, 0, 0, 0, 0, 0, 0, 140, 0, 300, 0, 0, 0, 0, 0, 0, 140, 0, 280, 0, 0, 0, 0, 0, 0, 140, 0, 260, 0, 0, 0, 0, 0, 0, 140, 0, 240, 0, 0, 0, 0, 0, 0, 140, 0, 220, 0, 0, 0, 0, 0, 0, 140, 0, 200, 0, 0, 0, 0, 0, 0, 140, 0, 180, 0, 0, 0, 0, 0, 0, 140, 0, 160, 0, 0, 0, 0, 0, 0, 140, 0, 140, 0, 0, 0, 0, 0, 0, 140, 0, 120, 0, 0, 0, 0, 0, 0, 140, 0, 100, 0, 0, 0, 0, 0, 0, 140, 0, 80, 0, 0, 0, 0, 0, 0, 140, 0, 60, 0, 0, 0, 0, 0, 0, 140, 0, 40, 0, 0, 0, 0, 0, 0, 140, 0, 20, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, 136.2151, 7.6293945e-06, -18.930761, 0, 0, 0, 0, 0, 0, 124.47424, 7.6293945e-06, -35.771675, 0, 0, 0, 0, 0, 0, 109.556854, 7.6293945e-06, -45.911987, 0, 0, 0, 0, 0, 0, 90, 0, -50, 0, 0, 0, 0, 0, 0, 70, 0, -50, 0, 0, 0, 0, 0, 0, 50, 0, -50, 0, 0, 0, 0, 0, 0, 30.626865, 7.6293945e-06, -46.35706, 0, 0, 0, 0, 0, 0, 14.519331, 7.6293945e-06, -35.468895, 0, 0, 0, 0, 0, 0, 3.52941, 7.6293945e-06, -19.590664),
"tilts": PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
}
point_count = 93
[node name="MainMap" type="Node3D" unique_id=1895741703]
[node name="Chunk_Rettilineo_1" parent="." unique_id=1071973766 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -20, 0, 0)
[node name="Chunk_Rettilineo_7" parent="." unique_id=1975081224 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -180, 0, -60)
[node name="Chunk_Rettilineo_8" parent="." unique_id=1509029322 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -180, 0, -80)
[node name="Chunk_Rettilineo_9" parent="." unique_id=943097880 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -180, 0, -100)
[node name="Chunk_Rettilineo_23" parent="." unique_id=822048833 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 40, 0, 80)
[node name="Chunk_Rettilineo_10" parent="." unique_id=1524384646 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -280, 0, -220)
[node name="Chunk_Rettilineo_12" parent="." unique_id=353270627 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -280, 0, -260)
[node name="Chunk_Rettilineo_2" parent="." unique_id=1793918166 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -40, 0, 0)
[node name="Chunk_Rettilineo_3" parent="." unique_id=543135047 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -120, 0, 0)
[node name="Chunk_Rettilineo_13" parent="." unique_id=961447101 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -340, 0, -320)
[node name="Chunk_Rettilineo_15" parent="." unique_id=1577793966 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -560, 0, -60)
[node name="Chunk_Rettilineo_41" parent="." unique_id=419871232 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -460, 0, 60)
[node name="Chunk_Rettilineo_42" parent="." unique_id=655667034 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -460, 0, 80)
[node name="Chunk_Rettilineo_18" parent="." unique_id=1807861125 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -560, 0, -120)
[node name="Chunk_Rettilineo_19" parent="." unique_id=393889196 instance=ExtResource("2_e76ix")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -560, 0, -140)
[node name="Chunk_Rettilineo_20" parent="." unique_id=2020455059 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -380, 0, -320)
[node name="Chunk_Rettilineo_22" parent="." unique_id=1449864588 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -500, 0, -200)
[node name="Chunk_Rettilineo_25" parent="." unique_id=333148847 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -20, 0, 140)
[node name="Chunk_Rettilineo_26" parent="." unique_id=252365188 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -40, 0, 140)
[node name="Chunk_Rettilineo_27" parent="." unique_id=1581441361 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -60, 0, 140)
[node name="Chunk_Rettilineo_28" parent="." unique_id=1771140547 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -80, 0, 140)
[node name="Chunk_Rettilineo_29" parent="." unique_id=54905051 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -100, 0, 140)
[node name="Chunk_Rettilineo_30" parent="." unique_id=703827150 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -120, 0, 140)
[node name="Chunk_Rettilineo_31" parent="." unique_id=900124592 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -140, 0, 140)
[node name="Chunk_Rettilineo_32" parent="." unique_id=1947969458 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -160, 0, 140)
[node name="Chunk_Rettilineo_34" parent="." unique_id=80065513 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -200, 0, 140)
[node name="Chunk_Rettilineo_35" parent="." unique_id=334693195 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -220, 0, 140)
[node name="Chunk_Rettilineo_36" parent="." unique_id=2090559410 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -240, 0, 140)
[node name="Chunk_Rettilineo_37" parent="." unique_id=1722039130 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -260, 0, 140)
[node name="Chunk_Rettilineo_38" parent="." unique_id=1907313452 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -280, 0, 140)
[node name="Chunk_Rettilineo_39" parent="." unique_id=1432572710 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -300, 0, 140)
[node name="Chunk_Rettilineo_43" parent="." unique_id=618705912 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -400, 0, 140)
[node name="Chunk_Rettilineo_44" parent="." unique_id=1635344020 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -380, 0, 140)
[node name="Chunk_Rettilineo_45" parent="." unique_id=1080549903 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -360, 0, 140)
[node name="Chunk_Rettilineo_46" parent="." unique_id=1463785184 instance=ExtResource("2_e76ix")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -340, 0, 140)
[node name="Chunk_Curva_1" parent="." unique_id=217311849 instance=ExtResource("1_p62h3")]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -160, 0, -20)
[node name="Chunk_Curva_2" parent="." unique_id=1726282883 instance=ExtResource("1_p62h3")]
transform = Transform3D(1.1924881e-08, 0, 1, 0, 1, 0, -1, 0, 1.1924881e-08, -200, 0, -140)
[node name="Chunk_Curva_4" parent="." unique_id=1502775253 instance=ExtResource("1_p62h3")]
transform = Transform3D(1.1924881e-08, 0, 1, 0, 1, 0, -1, 0, 1.1924881e-08, -300, 0, -300)
[node name="Chunk_Curva_5" parent="." unique_id=1702985674 instance=ExtResource("1_p62h3")]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -420, 0, -300)
[node name="Chunk_Curva_7" parent="." unique_id=900475946 instance=ExtResource("1_p62h3")]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -540, 0, -180)
[node name="Chunk_Curva_8" parent="." unique_id=1373490401 instance=ExtResource("1_p62h3")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -540, 0, -20)
[node name="Chunk_Curva_9" parent="." unique_id=416011584 instance=ExtResource("1_p62h3")]
transform = Transform3D(-4.371138e-08, 0, 1, 0, 1, 0, -1, 0, -4.371138e-08, -480, 0, 20)
[node name="Chunk_Curva_12" parent="." unique_id=1152394557 instance=ExtResource("1_p62h3")]
transform = Transform3D(-4.3711395e-08, 0, -1, 0, 1, 0, 1, 0, -4.3711395e-08, -440, 0, 120)
[node name="Chunk_Curva_10" parent="." unique_id=1111805374 instance=ExtResource("1_p62h3")]
transform = Transform3D(-4.371138e-08, 0, 1, 0, 1, 0, -1, 0, -4.371138e-08, 20, 0, 20)
[node name="Chunk_Curva_11" parent="." unique_id=621280730 instance=ExtResource("1_p62h3")]
transform = Transform3D(1, 0, -7.1054274e-15, 0, 1, 0, 7.1054274e-15, 0, 1, 20, 0, 120)
[node name="Chunk_Curva_6" parent="." unique_id=1027826232 instance=ExtResource("1_p62h3")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -460, 0, -220)
[node name="Chunk_Curva_3" parent="." unique_id=37751000 instance=ExtResource("1_p62h3")]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -260, 0, -180)
[node name="Chunk_Rettilineo_F3" parent="." unique_id=1719977594 instance=ExtResource("3_wf82y")]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -280, 0, -240)
[node name="Chunk_Rettilineo_Ponte" parent="." unique_id=1180892866 instance=ExtResource("4_l8ggx")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -320, 0, 140)
[node name="Chunk_Rettilineo_Ponte2" parent="." unique_id=1304906338 instance=ExtResource("4_l8ggx")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 40, 0, 60)
[node name="Chunk_Rettilineo_Ponte4" parent="." unique_id=503627087 instance=ExtResource("4_l8ggx")]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -100, 0, 0)
[node name="Chunk_Rettilineo_Ponte3" parent="." unique_id=1295432069 instance=ExtResource("4_l8ggx")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -440, 0, -260)
[node name="Blockout_Stazione2" parent="." unique_id=987402604 instance=ExtResource("5_bn4ba")]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -360, 0, -320)
[node name="Blockout_Stazione4" parent="." unique_id=401626378 instance=ExtResource("6_t5p8i")]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -180, 0, 140)
[node name="Blockout_Stazione3Hero" parent="." unique_id=149959015 instance=ExtResource("7_8nm7p")]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -60, 0, 0)
[node name="Blockout_Stazione3Hero2" parent="." unique_id=1050909298 instance=ExtResource("7_8nm7p")]
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, -560, 0, -80)
[node name="Path3D" type="Path3D" parent="." unique_id=1199296875]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -10, 2, -0.10099983)
curve = SubResource("Curve3D_rfork")
script = ExtResource("8_w775f")
train_model = ExtResource("9_haiv3")
[node name="Marker3D" type="Marker3D" parent="Path3D" unique_id=1654492319]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -79.7581, -1.6046681, 162.65833)
[node name="Marker3D2" type="Marker3D" parent="Path3D" unique_id=1991094419]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.8526325, 0, 109.44846)
[node name="Marker3D3" type="Marker3D" parent="Path3D" unique_id=1964527552]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 154.80806, 0, 230.03177)