fix wind!
This commit is contained in:
@@ -11,10 +11,15 @@ extends Node3D
|
||||
@export var eye_line: int = 3
|
||||
@export var district_scale: float = 0.05
|
||||
|
||||
@export_group("Lamppost")
|
||||
@export var lamppost_wire_material: ShaderMaterial
|
||||
@export_range(0.01, 1.0) var wire_thickness: float = 0.05
|
||||
|
||||
var board: Dictionary = {}
|
||||
var last_pos_train: Vector2i = Vector2i(999999, 999999)
|
||||
var noise_generator: FastNoiseLite
|
||||
var altitude_generator: FastNoiseLite
|
||||
var wire_connections: Dictionary = {}
|
||||
|
||||
var manual_biome: Biome = null
|
||||
|
||||
@@ -51,8 +56,7 @@ func _update_set_pieces() -> void:
|
||||
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, "]")
|
||||
|
||||
print("Analyze: '", sp.name, "' | Need: [", sp.exclusive_biome, "] | Current biome is: [", local_biome, "]")
|
||||
if local_biome == sp.exclusive_biome:
|
||||
sp.show()
|
||||
sp.process_mode = Node.PROCESS_MODE_INHERIT
|
||||
@@ -60,23 +64,24 @@ func _update_set_pieces() -> void:
|
||||
else:
|
||||
sp.hide()
|
||||
sp.process_mode = Node.PROCESS_MODE_DISABLED
|
||||
print(" ❌ Temple is a invisible ghost.")
|
||||
print(" ❌ Temple is an invisible ghost.")
|
||||
|
||||
func _destroy_and_regenrate_world() -> void:
|
||||
#1. Turn off old temples
|
||||
#Turn off old temples
|
||||
_update_set_pieces()
|
||||
|
||||
#2. Destroy all models
|
||||
#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()
|
||||
|
||||
#3. Clean board
|
||||
#Clean board and wire connections
|
||||
board.clear()
|
||||
wire_connections.clear()
|
||||
|
||||
#4. Create train
|
||||
#Create train
|
||||
last_pos_train = Vector2i(999999, 999999)
|
||||
_train_radar()
|
||||
last_pos_train = Vector2i(999999, 999999)
|
||||
@@ -96,13 +101,22 @@ func _physics_process(_delta: float) -> void:
|
||||
_clean_far_chunks(current_pos)
|
||||
_train_radar()
|
||||
|
||||
func _generate_pieces_around_train(centro: Vector2i) -> void:
|
||||
func collect_all_chunkinfo(root: Node, list: Array[Node]) -> void:
|
||||
if root == null: return
|
||||
|
||||
if root.has_method("get_rotated_data") or "have_lamppost" in root:
|
||||
list.append(root)
|
||||
|
||||
for child in root.get_children():
|
||||
collect_all_chunkinfo(child, list)
|
||||
|
||||
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 = centro + Vector2i(x, z)
|
||||
var grid_pos = center + Vector2i(x, z)
|
||||
|
||||
if not board.has(grid_pos):
|
||||
var ce_obstacle = _register_cell_with_laser(grid_pos)
|
||||
var ce_obstacle = _register_cell_with_ray(grid_pos)
|
||||
if not ce_obstacle:
|
||||
_add_compatible_biome(grid_pos)
|
||||
|
||||
@@ -123,7 +137,7 @@ func _get_procedural_biome_name(value: float) -> String:
|
||||
var index = clamp(int(normalized_value * biome_list.size()), 0, biome_list.size() - 1)
|
||||
return biome_list[index].name
|
||||
|
||||
func _register_cell_with_laser(grid_pos: Vector2i) -> bool:
|
||||
func _register_cell_with_ray(grid_pos: Vector2i) -> bool:
|
||||
if board.has(grid_pos): return true
|
||||
|
||||
var world_pos = Vector3(grid_pos.x * chunk_size, 0, grid_pos.y * chunk_size)
|
||||
@@ -136,28 +150,72 @@ func _register_cell_with_laser(grid_pos: Vector2i) -> bool:
|
||||
|
||||
if result.size() > 0:
|
||||
var collider = result["collider"]
|
||||
var current_node = collider
|
||||
var root_chunk = collider
|
||||
var info_list: Array[Node] = []
|
||||
|
||||
#Find parent node
|
||||
while root_chunk != null and root_chunk != get_tree().root:
|
||||
collect_all_chunkinfo(root_chunk, info_list)
|
||||
if info_list.size() > 0:
|
||||
break
|
||||
root_chunk = root_chunk.get_parent()
|
||||
|
||||
var right_info_node = null
|
||||
|
||||
#Find closest chunk to the ray
|
||||
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)
|
||||
var dist = center_cell_pos.distance_to(pos_info)
|
||||
|
||||
if dist < min_distance:
|
||||
min_distance = dist
|
||||
right_info_node = info
|
||||
|
||||
#If no node is found use first element
|
||||
if right_info_node == null and info_list.size() > 0:
|
||||
right_info_node = info_list[0]
|
||||
|
||||
var exit_found = {"north": false, "est": false, "south": false, "west": false}
|
||||
var height_found = {"north": 0, "est": 0, "south": 0, "west": 0}
|
||||
var have_lamppost = false
|
||||
|
||||
while current_node != null and current_node != get_tree().root:
|
||||
if current_node.has_method("get_rotated_data"):
|
||||
var rotation_steps = roundi(rad_to_deg(current_node.global_rotation.y) / -90.0)
|
||||
var data = current_node.get_rotated_data(rotation_steps)
|
||||
#Get node info
|
||||
if right_info_node != null:
|
||||
if right_info_node.has_method("get_rotated_data"):
|
||||
var rotation_steps = roundi(rad_to_deg(right_info_node.global_rotation.y) / -90.0)
|
||||
var data = right_info_node.get_rotated_data(rotation_steps)
|
||||
exit_found = data["connections"]
|
||||
height_found = data["heights"]
|
||||
break
|
||||
current_node = current_node.get_parent()
|
||||
|
||||
if "have_lamppost" in right_info_node:
|
||||
have_lamppost = right_info_node.have_lamppost
|
||||
|
||||
#Add piece to the grid
|
||||
board[grid_pos] = {
|
||||
"type": "obstacle",
|
||||
"exit": exit_found,
|
||||
"heights": height_found,
|
||||
"node": root_chunk,
|
||||
"info": right_info_node,
|
||||
"have_lamppost": have_lamppost
|
||||
}
|
||||
|
||||
if have_lamppost:
|
||||
_connect_lamppost_wires(grid_pos)
|
||||
|
||||
board[grid_pos] = {"type": "obstacle", "exit": exit_found, "heights": height_found}
|
||||
return true
|
||||
return false
|
||||
|
||||
func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
||||
var req_conn_north = _needed_connections(grid_pos + Vector2i(0, -1), "south")
|
||||
var req_conn_est = _needed_connections(grid_pos + Vector2i(1, 0), "west")
|
||||
var req_conn_south = _needed_connections(grid_pos + Vector2i(0, 1), "north")
|
||||
var req_conn_west = _needed_connections(grid_pos + Vector2i(-1, 0), "est")
|
||||
var req_conn_north = _needed_connection(grid_pos + Vector2i(0, -1), "south")
|
||||
var req_conn_est = _needed_connection(grid_pos + Vector2i(1, 0), "west")
|
||||
var req_conn_south = _needed_connection(grid_pos + Vector2i(0, 1), "north")
|
||||
var req_conn_west = _needed_connection(grid_pos + Vector2i(-1, 0), "est")
|
||||
|
||||
var req_height_north = _needed_heights(grid_pos + Vector2i(0, -1), "south")
|
||||
var req_height_est = _needed_heights(grid_pos + Vector2i(1, 0), "west")
|
||||
@@ -172,8 +230,11 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
||||
|
||||
for scene in zone_catalogue:
|
||||
var test_chunk = scene.instantiate()
|
||||
|
||||
if test_chunk.has_method("get_rotated_data"):
|
||||
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
|
||||
|
||||
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"]
|
||||
@@ -221,30 +282,53 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
||||
new_chunk.position = Vector3(grid_pos.x * chunk_size, 0, grid_pos.y * chunk_size)
|
||||
new_chunk.rotation.y = choise.rotation * (-PI / 2.0)
|
||||
|
||||
board[grid_pos] = {"type": "biome", "exit": choise.data["connections"], "heights": choise.data["heights"], "nodo": new_chunk}
|
||||
else:
|
||||
push_warning("⚠️ One piece miss for position " + str(grid_pos) + "!")
|
||||
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 fmt_alt = func(req): return str(req) if req != -1 else "Free"
|
||||
#var fmt_conn = func(req): return "Yes" if req == 1 else ("No" if req == 0 else "Free")
|
||||
|
||||
print("We need missed piece -> North: ", fmt_alt.call(req_height_north), " | Est: ", fmt_alt.call(req_height_est), " | South: ", fmt_alt.call(req_height_south), " | West: ", fmt_alt.call(req_height_west))
|
||||
var have_lamppost = false
|
||||
if info_new != null and "have_lamppost" in new_chunk:
|
||||
have_lamppost = info_new.have_lamppost
|
||||
|
||||
board[grid_pos] = {
|
||||
"type": "bioma",
|
||||
"exit": choise.data["connections"],
|
||||
"heights": choise.data["heights"],
|
||||
"node": new_chunk,
|
||||
"info": info_new,
|
||||
"have_lamppost": have_lamppost
|
||||
}
|
||||
|
||||
if have_lamppost:
|
||||
_connect_lamppost_wires(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)
|
||||
|
||||
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 safe_heights = {
|
||||
"north": req_height_north if req_height_north != -1 else height_target,
|
||||
"est": req_height_est if req_height_est != -1 else height_target,
|
||||
"south": req_height_south if req_height_south != -1 else height_target,
|
||||
"west": req_height_west if req_height_west != -1 else height_target
|
||||
}
|
||||
board[grid_pos] = {"type": "biome", "exit": {"north":false, "est":false, "south":false, "west":false}, "heights": safe_heights, "node": backup}
|
||||
board[grid_pos] = {
|
||||
"type": "biome",
|
||||
"exit": {"north":false, "est":false, "south":false, "west":false},
|
||||
"heights": safe_heights,
|
||||
"node": backup,
|
||||
"info": info_backup,
|
||||
"have_lamppost": false
|
||||
}
|
||||
|
||||
func _needed_connections(near_pos: Vector2i, side_needed: String) -> int:
|
||||
func _needed_connection(near_pos: Vector2i, side_needed: String) -> int:
|
||||
if not board.has(near_pos):
|
||||
_register_cell_with_laser(near_pos)
|
||||
_register_cell_with_ray(near_pos)
|
||||
if board.has(near_pos) and board[near_pos].has("exit"):
|
||||
return 1 if board[near_pos]["exit"][side_needed] else 0
|
||||
return -1
|
||||
@@ -267,7 +351,9 @@ 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)
|
||||
var next_local_pos = rail_path.curve.sample_baked(next_progress, true)
|
||||
@@ -275,11 +361,11 @@ func _train_radar() -> void:
|
||||
|
||||
var f_x = roundi(next_global_pos.x / chunk_size)
|
||||
var f_z = roundi(next_global_pos.z / chunk_size)
|
||||
var next_biome = _get_procedural_biome_name(noise_generator.get_noise_2d(f_x, f_z))
|
||||
var future_biome = _get_procedural_biome_name(noise_generator.get_noise_2d(f_x, f_z))
|
||||
|
||||
if next_biome != current_biome:
|
||||
#distanza_cambio = step * chunk_size
|
||||
#prossimo_bioma = next_biome
|
||||
if future_biome != current_biome:
|
||||
#exchange_distance = step * chunk_size
|
||||
#next_biome = future_biome
|
||||
break
|
||||
|
||||
func _clean_far_chunks(centro_attuale: Vector2i) -> void:
|
||||
@@ -300,3 +386,186 @@ func _clean_far_chunks(centro_attuale: Vector2i) -> void:
|
||||
|
||||
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:
|
||||
var new_cell = board[new_board_pos]
|
||||
var new_root = new_cell["node"]
|
||||
var new_info = new_cell["info"]
|
||||
|
||||
if new_info == null: return
|
||||
if new_info is Node3D: new_info.force_update_transform()
|
||||
|
||||
var new_sx = _get_lampposts(new_info, "sx")
|
||||
var new_dx = _get_lampposts(new_info, "dx")
|
||||
if new_sx.is_empty() or new_dx.is_empty(): return
|
||||
|
||||
var new_id = new_root.get_instance_id()
|
||||
if not wire_connections.has(new_id): wire_connections[new_id] = 0
|
||||
|
||||
if wire_connections[new_id] >= 2: return
|
||||
|
||||
var p_sx_my_best = null; var p_dx_my_best = null
|
||||
var p_sx_your_best = null; var p_dx_your_best = null
|
||||
var best_closest_to_root = null
|
||||
var best_distance = 999999.0
|
||||
var ray_research = 3
|
||||
|
||||
for x in range(-ray_research, ray_research + 1):
|
||||
for z in range(-ray_research, ray_research + 1):
|
||||
if x == 0 and z == 0: continue
|
||||
|
||||
var closest_post = new_board_pos + Vector2i(x, z)
|
||||
if board.has(closest_post) and board[closest_post].get("have_lamppost", false):
|
||||
var closest_root = board[closest_post]["node"]
|
||||
var closest_info = board[closest_post]["info"]
|
||||
|
||||
if not is_instance_valid(closest_root) or closest_root == new_root or closest_info == null: continue
|
||||
|
||||
var closest_id = closest_root.get_instance_id()
|
||||
var closest_connections = wire_connections.get(closest_id, 0)
|
||||
|
||||
if closest_connections >= 2: continue
|
||||
|
||||
if closest_info is Node3D: closest_info.force_update_transform()
|
||||
var closest_sx = _get_lampposts(closest_info, "sx")
|
||||
var closest_dx = _get_lampposts(closest_info, "dx")
|
||||
if closest_sx.is_empty() or closest_dx.is_empty(): continue
|
||||
|
||||
for i_m in range(new_sx.size()):
|
||||
for i_t in range(closest_sx.size()):
|
||||
var my_c = (new_sx[i_m].global_position + new_dx[i_m].global_position) / 2.0
|
||||
var your_c = (closest_sx[i_t].global_position + closest_dx[i_t].global_position) / 2.0
|
||||
var dist = my_c.distance_to(your_c)
|
||||
|
||||
if dist < best_distance:
|
||||
best_distance = dist
|
||||
best_closest_to_root = closest_root
|
||||
p_sx_my_best = new_sx[i_m]
|
||||
p_dx_my_best = new_dx[i_m]
|
||||
p_sx_your_best = closest_sx[i_t]
|
||||
p_dx_your_best = closest_dx[i_t]
|
||||
|
||||
if best_closest_to_root == null:
|
||||
for x in range(-ray_research, ray_research + 1):
|
||||
for z in range(-ray_research, ray_research + 1):
|
||||
if x == 0 and z == 0: continue
|
||||
|
||||
var closest_pos = new_board_pos + Vector2i(x, z)
|
||||
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()
|
||||
var closest_sx = _get_lampposts(closest_info, "sx")
|
||||
var closest_dx = _get_lampposts(closest_info, "dx")
|
||||
if closest_sx.is_empty() or closest_dx.is_empty(): continue
|
||||
|
||||
for i_m in range(new_sx.size()):
|
||||
for i_t in range(closest_sx.size()):
|
||||
var c_mio = (new_sx[i_m].global_position + new_dx[i_m].global_position) / 2.0
|
||||
var c_tuo = (closest_sx[i_t].global_position + closest_dx[i_t].global_position) / 2.0
|
||||
var dist = c_mio.distance_to(c_tuo)
|
||||
|
||||
if dist < best_distance:
|
||||
best_distance = dist
|
||||
best_closest_to_root = closest_root
|
||||
p_sx_my_best = new_sx[i_m]
|
||||
p_dx_my_best = new_dx[i_m]
|
||||
p_sx_your_best = closest_sx[i_t]
|
||||
p_dx_your_best = closest_dx[i_t]
|
||||
|
||||
var max_dist = chunk_size * 8.0
|
||||
|
||||
if best_closest_to_root != null and best_distance < max_dist:
|
||||
var dist_streight = p_sx_my_best.global_position.distance_to(p_sx_your_best.global_position) + p_dx_my_best.global_position.distance_to(p_dx_your_best.global_position)
|
||||
var dist_cross = p_sx_my_best.global_position.distance_to(p_dx_your_best.global_position) + p_dx_my_best.global_position.distance_to(p_sx_your_best.global_position)
|
||||
|
||||
if dist_streight <= dist_cross:
|
||||
_draw_parable(p_sx_my_best.global_position, p_sx_your_best.global_position, new_root)
|
||||
_draw_parable(p_dx_my_best.global_position, p_dx_your_best.global_position, new_root)
|
||||
else:
|
||||
_draw_parable(p_sx_my_best.global_position, p_dx_your_best.global_position, new_root)
|
||||
_draw_parable(p_dx_my_best.global_position, p_sx_your_best.global_position, new_root)
|
||||
|
||||
wire_connections[new_id] += 1
|
||||
var closest_id = best_closest_to_root.get_instance_id()
|
||||
if not wire_connections.has(closest_id): wire_connections[closest_id] = 0
|
||||
wire_connections[closest_id] += 1
|
||||
|
||||
func _draw_parable(p1: Vector3, p2: Vector3, parent: Node3D) -> void:
|
||||
var segments = 15
|
||||
var lowering = 1.5
|
||||
var curve_points = []
|
||||
var sag_factors = []
|
||||
|
||||
for i in range(segments + 1):
|
||||
var t = float(i) / float(segments)
|
||||
var global_post = p1.lerp(p2, t)
|
||||
var gravity = lowering * (1.0 - pow(2.0 * t - 1.0, 2.0))
|
||||
global_post.y -= gravity
|
||||
|
||||
curve_points.append(parent.to_local(global_post))
|
||||
sag_factors.append(sin(t * PI))
|
||||
|
||||
var st = SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
|
||||
var lati = 4
|
||||
var ray = wire_thickness / 2.0
|
||||
|
||||
for i in range(curve_points.size() - 1):
|
||||
var p_current = curve_points[i]
|
||||
var p_next = curve_points[i+1]
|
||||
var sag_currnet = sag_factors[i]
|
||||
var sag_next = sag_factors[i+1]
|
||||
|
||||
var dir = (p_next - p_current).normalized()
|
||||
var up = Vector3.UP
|
||||
var right = dir.cross(up).normalized()
|
||||
if right.length_squared() < 0.01:
|
||||
right = dir.cross(Vector3.RIGHT).normalized()
|
||||
up = right.cross(dir).normalized()
|
||||
|
||||
for s in range(lati):
|
||||
var ang1 = (float(s) / lati) * TAU
|
||||
var ang2 = (float((s + 1) % lati) / lati) * TAU
|
||||
var offset1 = (right * cos(ang1) + up * sin(ang1)) * ray
|
||||
var offset2 = (right * cos(ang2) + up * sin(ang2)) * ray
|
||||
|
||||
st.set_color(Color(sag_currnet, 0, 0, 1))
|
||||
st.add_vertex(p_current + offset1)
|
||||
st.set_color(Color(sag_currnet, 0, 0, 1))
|
||||
st.add_vertex(p_current + offset2)
|
||||
st.set_color(Color(sag_next, 0, 0, 1))
|
||||
st.add_vertex(p_next + offset1)
|
||||
|
||||
st.set_color(Color(sag_currnet, 0, 0, 1))
|
||||
st.add_vertex(p_current + offset2)
|
||||
st.set_color(Color(sag_next, 0, 0, 1))
|
||||
st.add_vertex(p_next + offset2)
|
||||
st.set_color(Color(sag_next, 0, 0, 1))
|
||||
st.add_vertex(p_next + offset1)
|
||||
|
||||
var wire_node = MeshInstance3D.new()
|
||||
wire_node.mesh = st.commit()
|
||||
if lamppost_wire_material: wire_node.material_override = lamppost_wire_material
|
||||
parent.add_child(wire_node)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
[gd_scene format=3 uid="uid://ujv2f1l4d2ps"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ct2k25kslaxe5" path="res://core/biome_generator/biome_generator.gd" id="1_c7ilo"]
|
||||
[ext_resource type="Material" uid="uid://b8p1sjxisi522" path="res://core/biome_generator/wires.tres" id="2_w42pm"]
|
||||
|
||||
[node name="biome_generator" type="Node3D" unique_id=1861369341]
|
||||
script = ExtResource("1_c7ilo")
|
||||
lamppost_wire_material = ExtResource("2_w42pm")
|
||||
|
||||
@@ -12,12 +12,17 @@ class_name ChunkInfo
|
||||
@export var south: bool = false
|
||||
@export var west: bool = false
|
||||
|
||||
@export_group("Maring heights (level 0, 1, 2)")
|
||||
@export_group("Margin heights (level 0, 1, 2)")
|
||||
@export var height_north: int = 0
|
||||
@export var height_est: int = 0
|
||||
@export var height_south: int = 0
|
||||
@export var height_west: int = 0
|
||||
|
||||
@export_group("Lamppost")
|
||||
@export var have_lamppost: bool = false
|
||||
@export var connection_left: Array[Node3D]
|
||||
@export var connection_right: Array[Node3D]
|
||||
|
||||
func _ready() -> void:
|
||||
if exclusive_biome != "":
|
||||
add_to_group("set_pieces")
|
||||
|
||||
27
core/biome_generator/wires.gdshader
Normal file
27
core/biome_generator/wires.gdshader
Normal file
@@ -0,0 +1,27 @@
|
||||
shader_type spatial;
|
||||
render_mode blend_mix, depth_draw_opaque, cull_disabled;
|
||||
|
||||
//Wire color
|
||||
uniform vec4 albedo_color : source_color = vec4(0.1, 0.1, 0.1, 1.0);
|
||||
|
||||
global uniform float global_wind_strength;
|
||||
global uniform float global_wind_speed;
|
||||
|
||||
void vertex() {
|
||||
//COLOR.r is the drawing. 0 -> lampost (no move); 1.0 is the center of the wire
|
||||
float movement = COLOR.r;
|
||||
|
||||
//Create a wave (based on position and time to be random)
|
||||
float wind_wave = 0.0;
|
||||
if (global_wind_speed > 0.0 && global_wind_strength > 0.0) {
|
||||
wind_wave = sin(TIME * global_wind_speed + NODE_POSITION_WORLD.x * 0.5) * global_wind_strength;
|
||||
}
|
||||
|
||||
VERTEX.x += wind_wave * 0.1 * movement;
|
||||
VERTEX.z += wind_wave * 0.05 * movement;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = albedo_color.rgb;
|
||||
ROUGHNESS = 0.9;
|
||||
}
|
||||
1
core/biome_generator/wires.gdshader.uid
Normal file
1
core/biome_generator/wires.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://du8cu413q5scy
|
||||
7
core/biome_generator/wires.tres
Normal file
7
core/biome_generator/wires.tres
Normal file
@@ -0,0 +1,7 @@
|
||||
[gd_resource type="ShaderMaterial" format=3 uid="uid://b8p1sjxisi522"]
|
||||
|
||||
[ext_resource type="Shader" uid="uid://du8cu413q5scy" path="res://core/biome_generator/wires.gdshader" id="1_6saq1"]
|
||||
|
||||
[resource]
|
||||
render_priority = 0
|
||||
shader = ExtResource("1_6saq1")
|
||||
@@ -1,11 +1,11 @@
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
|
||||
global uniform float global_wind_speed;
|
||||
|
||||
uniform vec4 dust_color : source_color = vec4(1.0, 0.456, 0.125, 0.6);
|
||||
|
||||
//Wind -> negative x = to the left. positive y = to the bottom
|
||||
uniform vec2 wind_velocity = vec2(-0.2, 0.05);
|
||||
uniform vec2 wind_speed = vec2(-0.2, 0.05);
|
||||
uniform float wind_oscillation : hint_range(0.0, 1.0) = 0.3;
|
||||
uniform float dust_speed : hint_range(0.01, 1.0) = 0.15;
|
||||
|
||||
@@ -28,12 +28,13 @@ vec3 hash33(vec3 p3) {
|
||||
void fragment() {
|
||||
vec4 scene_color = texture(screen_texture, SCREEN_UV);
|
||||
float base_time = TIME * dust_speed;
|
||||
|
||||
|
||||
vec2 osc = vec2(sin(TIME * 0.5), cos(TIME * 0.3)) * wind_oscillation;
|
||||
vec2 final_wind = (wind_velocity + osc) * dust_speed;
|
||||
float wind_active = step(0.0001, abs(global_wind_speed));
|
||||
vec2 final_wind = ((wind_speed + osc) * dust_speed) * wind_active;
|
||||
|
||||
float final_particle_alpha = 0.0;
|
||||
|
||||
|
||||
//Thresolds (near, medium, far)
|
||||
vec3 layer_scales = vec3(20.0, 50.0, 100.0) / dust_density;
|
||||
vec3 layer_thresholds = vec3(0.96, 0.98, 0.99);
|
||||
@@ -70,4 +71,4 @@ void fragment() {
|
||||
vec4 dust_colored_particle = dust_color * final_particle_alpha;
|
||||
|
||||
COLOR = scene_color + dust_colored_particle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[resource]
|
||||
shader = ExtResource("1_80hx2")
|
||||
shader_parameter/dust_color = Color(1, 0.9019608, 0.7019608, 0.6)
|
||||
shader_parameter/wind_velocity = Vector2(-1, 0.5)
|
||||
shader_parameter/wind_speed = Vector2(-0.2, 0.05)
|
||||
shader_parameter/wind_oscillation = 0.0150000007125
|
||||
shader_parameter/dust_speed = 0.15
|
||||
shader_parameter/size_min = 0.010000000475
|
||||
|
||||
@@ -14,19 +14,6 @@
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ruhh7"]
|
||||
render_priority = 0
|
||||
shader = ExtResource("2_i3hjl")
|
||||
shader_parameter/cloud_scale = 0.05
|
||||
shader_parameter/cloud_speed = 0.05
|
||||
shader_parameter/direction = Vector2(0.5, 0.2)
|
||||
shader_parameter/sun_angle = Vector2(0.5, 0.5)
|
||||
shader_parameter/cloud_density = 0.4
|
||||
shader_parameter/center_sharpness = 0.14
|
||||
shader_parameter/shadow_color = Color(0, 0, 0, 1)
|
||||
shader_parameter/opacity_center = 0.5
|
||||
shader_parameter/opacity_edge = 0.2
|
||||
shader_parameter/fade_start = 150.0
|
||||
shader_parameter/fade_end = 300.0
|
||||
shader_parameter/height_fade_start = 10.0
|
||||
shader_parameter/height_fade_end = 50.0
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_r4tfj"]
|
||||
transparency = 2
|
||||
|
||||
@@ -70,9 +70,23 @@ func _ready() -> void:
|
||||
func ApplyWindNoiseToMaterials():
|
||||
var noise_tex = preload("res://core/daynight/noise.tres")
|
||||
for node in get_tree().get_nodes_in_group("wind_node"):
|
||||
if node is GeometryInstance3D and node.material_override != null:
|
||||
node.material_override.set_shader_parameter("wind_noise", noise_tex)
|
||||
|
||||
_apply_wind_noise_to_node(node, noise_tex)
|
||||
|
||||
func _apply_wind_noise_to_node(node: Node, noise_tex: Texture2D) -> void:
|
||||
if node is GeometryInstance3D:
|
||||
var material_override := node.material_override as ShaderMaterial
|
||||
if material_override:
|
||||
material_override.set_shader_parameter("wind_noise", noise_tex)
|
||||
|
||||
if node is MeshInstance3D:
|
||||
for surface_index in node.get_surface_override_material_count():
|
||||
var surface_material := node.get_surface_override_material(surface_index) as ShaderMaterial
|
||||
if surface_material:
|
||||
surface_material.set_shader_parameter("wind_noise", noise_tex)
|
||||
|
||||
for child in node.get_children():
|
||||
_apply_wind_noise_to_node(child, noise_tex)
|
||||
|
||||
func ApplyWeatherShaderToMaterials():
|
||||
var weather_shader = preload("res://core/daynight/weather_overlay.tres")
|
||||
|
||||
|
||||
134
core/daynight/grass_leaves.gdshader
Normal file
134
core/daynight/grass_leaves.gdshader
Normal file
@@ -0,0 +1,134 @@
|
||||
shader_type spatial;
|
||||
|
||||
render_mode specular_disabled, cull_disabled, ambient_light_disabled;
|
||||
|
||||
// --- GLOBAL UNIFORMS (Vento e Neve) ---
|
||||
global uniform float global_wind_scale;
|
||||
global uniform float global_wind_speed;
|
||||
global uniform float global_wind_strength;
|
||||
global uniform vec2 global_wind_direction;
|
||||
//global uniform sampler2D global_wind_noise : filter_linear_mipmap;
|
||||
global uniform float global_snow_amount;
|
||||
|
||||
// --- PARAMETRI ESTETICI ---
|
||||
uniform bool billboard_enabled = true;
|
||||
uniform bool wind_enabled = true;
|
||||
uniform vec4 base_color : source_color = vec4(0.2, 0.6, 0.3, 1.0);
|
||||
uniform sampler2D alpha_texture : source_color, filter_nearest;
|
||||
uniform float leaves_scale = 1.0;
|
||||
uniform float rotation_degrees = 0.0;
|
||||
uniform vec2 texture_offset = vec2(0.0, 0.0);
|
||||
uniform float opacity : hint_range(0.0, 1.0) = 1.0;
|
||||
|
||||
// ---> NUOVI PARAMETRI PER VARIAZIONE ERBA <---
|
||||
group_uniforms Grass_Variance;
|
||||
uniform sampler2D color_variance_noise : filter_linear_mipmap; // Trascina qui un FastNoiseLite
|
||||
uniform float variance_scale = 0.1; // Grandezza delle chiazze (più basso = chiazze più grandi)
|
||||
uniform vec4 variance_color : source_color = vec4(0.3, 0.5, 0.2, 1.0); // Colore delle chiazze (es: verde più scuro o giallastro)
|
||||
uniform float variance_intensity : hint_range(0.0, 1.0) = 0.4; // Quanto si vedono le chiazze
|
||||
|
||||
uniform vec4 snow_color : source_color = vec4(0.85, 0.9, 0.95, 1.0);
|
||||
|
||||
// --- CONTROLLO GRADIENTE E RANDOM ---
|
||||
uniform float height_min = 0.0;
|
||||
uniform float height_max = 5.0;
|
||||
uniform float shadow_intensity : hint_range(0.0, 1.0) = 0.5;
|
||||
uniform float highlight_intensity : hint_range(0.0, 1.0) = 0.3;
|
||||
uniform float light_steps : hint_range(1.0, 10.0) = 4.0;
|
||||
uniform float random_mix : hint_range(0.0, 1.0) = 0.3;
|
||||
|
||||
uniform float cast_shadow_strength : hint_range(0.0, 1.0) = 0.6;
|
||||
|
||||
varying vec3 v_final_color;
|
||||
varying float v_shade_factor;
|
||||
varying vec3 v_world_pos; // Passiamo la posizione mondo per il rumore
|
||||
|
||||
float hash(vec3 p) {
|
||||
p = fract(p * 0.1031);
|
||||
p += dot(p, p.yzx + 33.33);
|
||||
return fract((p.x + p.y) * p.z);
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
vec3 instance_pos = MODEL_MATRIX[3].xyz;
|
||||
v_world_pos = instance_pos; // Salviamo la posizione dell'istanza
|
||||
|
||||
// --- LOGICA VENTO ---
|
||||
float total_angle = radians(rotation_degrees);
|
||||
if (wind_enabled) {
|
||||
float time = TIME * global_wind_speed;
|
||||
vec2 noise_uv = (instance_pos.xz * global_wind_scale) + (time * global_wind_direction.xy * 0.5);
|
||||
//float noise_val = textureLod(wind_noise, noise_uv, 2.0).r;
|
||||
//float sway = sin(time + (noise_val * 10.0));
|
||||
float sway = sin(time + (0.1 * 10.0));
|
||||
total_angle += (sway * global_wind_strength);
|
||||
}
|
||||
|
||||
// --- CALCOLO COLORE ---
|
||||
float h_factor = clamp((instance_pos.y - height_min) / (height_max - height_min), 0.0, 1.0);
|
||||
float leaf_rand = hash(instance_pos);
|
||||
float combined_factor = mix(h_factor, leaf_rand, random_mix);
|
||||
combined_factor = ceil(combined_factor * light_steps) / light_steps;
|
||||
|
||||
v_shade_factor = combined_factor;
|
||||
|
||||
vec3 dark_color = base_color.rgb * (1.0 - shadow_intensity);
|
||||
vec3 light_color = base_color.rgb + (vec3(1.0) - base_color.rgb) * highlight_intensity;
|
||||
v_final_color = mix(dark_color, light_color, combined_factor);
|
||||
|
||||
// --- LOGICA TRASFORMAZIONE ---
|
||||
if (billboard_enabled) {
|
||||
vec3 view_pos_origin = (VIEW_MATRIX * vec4(instance_pos, 1.0)).xyz;
|
||||
vec2 offset = (UV - 0.5) * leaves_scale;
|
||||
|
||||
float c = cos(total_angle);
|
||||
float s = sin(total_angle);
|
||||
vec2 rotated_offset = vec2(offset.x * c - offset.y * s, offset.x * s + offset.y * c);
|
||||
|
||||
vec3 final_pos = view_pos_origin + vec3(rotated_offset.x, rotated_offset.y, 0.0);
|
||||
|
||||
MODELVIEW_MATRIX = mat4(1.0);
|
||||
MODELVIEW_MATRIX[3].xyz = final_pos;
|
||||
VERTEX = vec3(0.0);
|
||||
} else {
|
||||
float c = cos(total_angle);
|
||||
float s = sin(total_angle);
|
||||
|
||||
vec2 local_v = (VERTEX.xy) * leaves_scale;
|
||||
VERTEX.x = local_v.x * c - local_v.y * s;
|
||||
VERTEX.y = local_v.x * s + local_v.y * c;
|
||||
}
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec2 shifted_uv = UV + texture_offset;
|
||||
vec4 tex = texture(alpha_texture, shifted_uv);
|
||||
|
||||
// ---> LOGICA VARIAZIONE COLORE MONDO <---
|
||||
// Usiamo la posizione XZ del mondo per campionare il rumore
|
||||
float noise_sample = texture(color_variance_noise, v_world_pos.xz * variance_scale).r;
|
||||
// Applichiamo la variazione al colore finale dell'erba
|
||||
vec3 varied_grass_color = mix(v_final_color, variance_color.rgb, noise_sample * variance_intensity);
|
||||
|
||||
float top_mask = 1.0 - shifted_uv.y;
|
||||
float snow_mask = smoothstep(1.0 - global_snow_amount, 1.2 - global_snow_amount, top_mask);
|
||||
snow_mask *= step(0.01, global_snow_amount);
|
||||
|
||||
vec3 dark_snow = snow_color.rgb * (1.0 - shadow_intensity);
|
||||
vec3 shaded_snow = mix(dark_snow, snow_color.rgb, v_shade_factor);
|
||||
|
||||
// Mescoliamo il colore variato con la neve
|
||||
vec3 final_albedo = mix(varied_grass_color, shaded_snow, snow_mask);
|
||||
|
||||
ALBEDO = final_albedo;
|
||||
ALPHA = tex.r * opacity;
|
||||
ALPHA_SCISSOR_THRESHOLD = 0.5;
|
||||
|
||||
ROUGHNESS = 0.02;
|
||||
}
|
||||
|
||||
void light() {
|
||||
float shadow_factor = mix(1.0 - cast_shadow_strength, 1.0, ATTENUATION);
|
||||
float cutoff_mask = smoothstep(0.0, 0.05, ATTENUATION);
|
||||
DIFFUSE_LIGHT += (shadow_factor * LIGHT_COLOR) * cutoff_mask;
|
||||
}
|
||||
1
core/daynight/grass_leaves.gdshader.uid
Normal file
1
core/daynight/grass_leaves.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://8l8glwvvs7fb
|
||||
@@ -43,7 +43,7 @@ void vertex() {
|
||||
vec3 instance_pos = MODEL_MATRIX[3].xyz;
|
||||
|
||||
float total_angle = radians(rotation_degrees);
|
||||
if (wind_enabled) {
|
||||
if (wind_enabled && global_wind_speed > 0.0 && global_wind_strength > 0.0) {
|
||||
float time = TIME * global_wind_speed;
|
||||
vec2 noise_uv = (instance_pos.xz * global_wind_scale) + (time * global_wind_direction * 0.5);
|
||||
float noise_val = textureLod(wind_noise, noise_uv, 2.0).r;
|
||||
|
||||
101
core/daynight/water_ripple.gdshader
Normal file
101
core/daynight/water_ripple.gdshader
Normal file
@@ -0,0 +1,101 @@
|
||||
shader_type spatial;
|
||||
render_mode blend_mix, depth_draw_always;
|
||||
|
||||
// --- PARAMETRI COLORI ACQUA ---
|
||||
uniform vec4 deep_water_color : source_color = vec4(0.0, 0.1, 0.2, 1.0);
|
||||
uniform vec4 shallow_water_color : source_color = vec4(0.0, 0.4, 0.7, 1.0);
|
||||
// Impostato a 5.0 come piace a te per un'acqua super profonda!
|
||||
uniform float beer_law_factor : hint_range(0.0, 10.0) = 5.0;
|
||||
|
||||
// ---> PARAMETRI FAKE REFLECTION (SPECCHIATA) <---
|
||||
group_uniforms Fake_Reflection_Proximity;
|
||||
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
|
||||
uniform float reflection_strength : hint_range(0.0, 1.0) = 0.6;
|
||||
uniform float reflection_offset : hint_range(-0.5, 0.5) = 0.05; // Offset base
|
||||
// LA MAGIA DELLO SPECCHIO: Valori positivi (es. 0.1 o 0.2) capovolgeranno l'immagine
|
||||
uniform float reflection_stretch : hint_range(-1.0, 1.0) = 0.1;
|
||||
uniform float max_reflection_distance : hint_range(0.1, 10.0) = 1.5;
|
||||
|
||||
// ---> PARAMETRI RIPPLES <---
|
||||
group_uniforms Ripple_Settings;
|
||||
uniform vec4 ripple_color : source_color = vec4(1.0, 1.0, 1.0, 0.7);
|
||||
uniform float ripple_density : hint_range(0.0, 1.0) = 0.05;
|
||||
uniform float ripple_scale : hint_range(0.5, 20.0) = 3.0;
|
||||
uniform float ripple_speed : hint_range(0.1, 5.0) = 0.8;
|
||||
uniform float ripple_thickness : hint_range(0.001, 0.1) = 0.02;
|
||||
|
||||
uniform sampler2D depth_texture : hint_depth_texture, filter_linear_mipmap;
|
||||
|
||||
varying vec2 world_pos_xz;
|
||||
varying vec2 local_uv;
|
||||
|
||||
void vertex() {
|
||||
// Salviamo la posizione XZ e la UV locale per l'effetto specchio
|
||||
world_pos_xz = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xz;
|
||||
local_uv = UV;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
// --- 1. LOGICA PROFONDITÀ (Beer's Law) ---
|
||||
float depth = texture(depth_texture, SCREEN_UV).r;
|
||||
vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth);
|
||||
vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
|
||||
view.xyz /= view.w;
|
||||
float linear_depth = -view.z;
|
||||
float depth_difference = linear_depth + VERTEX.z;
|
||||
|
||||
float water_depth_gradient = exp(-depth_difference * beer_law_factor);
|
||||
vec4 base_water = mix(deep_water_color, shallow_water_color, water_depth_gradient);
|
||||
|
||||
// --- 2. LOGICA RIPPLES CASUALI ---
|
||||
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 ring = 0.0;
|
||||
if (is_active_cell > 0.0) {
|
||||
float local_time = fract(TIME * ripple_speed + random_val * 10.0);
|
||||
float dist = length(local_pos);
|
||||
ring = smoothstep(local_time - ripple_thickness, local_time, dist)
|
||||
- smoothstep(local_time, local_time + ripple_thickness, dist);
|
||||
ring *= (1.0 - local_time);
|
||||
}
|
||||
|
||||
// --- 3. FAKE REFLECTION SPECCHIATA E A CORTO RAGGIO ---
|
||||
vec2 ref_uv = SCREEN_UV;
|
||||
|
||||
// Il trucco per "capovolgere" il riflesso usando l'UV del piano dell'acqua
|
||||
ref_uv.y -= reflection_offset + (local_uv.y * reflection_stretch);
|
||||
|
||||
// Distorciamo il riflesso dove ci sono i ripples
|
||||
ref_uv += ring * 0.01;
|
||||
|
||||
vec3 screen_ref = textureLod(screen_texture, ref_uv, 0.0).rgb;
|
||||
|
||||
// Maschera di distanza (limita il riflesso solo alle cose vicine)
|
||||
float ref_depth_raw = texture(depth_texture, ref_uv).r;
|
||||
vec3 ref_ndc = vec3(ref_uv * 2.0 - 1.0, ref_depth_raw);
|
||||
vec4 ref_view = INV_PROJECTION_MATRIX * vec4(ref_ndc, 1.0);
|
||||
ref_view.xyz /= ref_view.w;
|
||||
float ref_linear_depth = -ref_view.z;
|
||||
|
||||
float distance_from_water = abs(ref_linear_depth - (-VERTEX.z));
|
||||
float reflection_mask = 1.0 - smoothstep(0.0, max_reflection_distance, distance_from_water);
|
||||
float is_sky = step(ref_depth_raw, 0.00001); // Protezione anti-cielo
|
||||
reflection_mask *= (1.0 - is_sky);
|
||||
|
||||
// --- 4. MIX FINALE ---
|
||||
vec3 final_rgb = mix(base_water.rgb, screen_ref, reflection_strength * reflection_mask);
|
||||
final_rgb = mix(final_rgb, ripple_color.rgb, ring * ripple_color.a);
|
||||
|
||||
ALBEDO = final_rgb;
|
||||
|
||||
// Alpha base dell'acqua + opacità dei ripples per farli sempre risaltare
|
||||
ALPHA = mix(0.98, 0.4, water_depth_gradient);
|
||||
ALPHA = clamp(ALPHA + (ring * ripple_color.a), 0.0, 1.0);
|
||||
|
||||
ROUGHNESS = 1.0;
|
||||
SPECULAR = 0.0;
|
||||
}
|
||||
1
core/daynight/water_ripple.gdshader.uid
Normal file
1
core/daynight/water_ripple.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://064bybt6le3h
|
||||
@@ -66,15 +66,15 @@ func _init(wind: GPUParticles3D, snow: GPUParticles3D,
|
||||
thunder_sounds = thundersounds
|
||||
rain_sounds = rainsounds
|
||||
|
||||
set_rain()
|
||||
init_rain()
|
||||
|
||||
set_fireflies()
|
||||
init_fireflies()
|
||||
|
||||
set_wind()
|
||||
init_wind()
|
||||
|
||||
set_snow()
|
||||
init_snow()
|
||||
|
||||
set_lightning()
|
||||
init_lightning()
|
||||
|
||||
create_sound_players()
|
||||
|
||||
@@ -124,7 +124,7 @@ func _process(delta: float) -> void:
|
||||
timer_next_lightning -= delta
|
||||
if timer_next_lightning <= 0.0:
|
||||
start_lightning()
|
||||
set_lightning_timer()
|
||||
init_lightning_timer()
|
||||
else:
|
||||
rain_intensity = move_toward(rain_intensity, 0.0, delta * 0.5)
|
||||
|
||||
@@ -281,7 +281,7 @@ func toggle_fireflies(value: bool):
|
||||
particles_fireflies.emitting = thereare_fireflies and is_night
|
||||
|
||||
#disable fireflies and set default values and materials
|
||||
func set_fireflies():
|
||||
func init_fireflies():
|
||||
if particles_fireflies:
|
||||
particles_fireflies.visible = true
|
||||
particles_fireflies.emitting = false
|
||||
@@ -299,8 +299,10 @@ func toggle_wind(value: bool):
|
||||
if particles_wind:
|
||||
particles_wind.emitting = is_windy
|
||||
|
||||
_apply_wind_state()
|
||||
|
||||
#disable wind and set default values and materials
|
||||
func set_wind():
|
||||
func init_wind():
|
||||
if particles_wind:
|
||||
particles_wind.visible = true
|
||||
particles_wind.emitting = false
|
||||
@@ -312,26 +314,36 @@ func set_wind():
|
||||
if environment_config:
|
||||
_apply_cloud_config()
|
||||
_apply_wind_config()
|
||||
_apply_dust_config()
|
||||
|
||||
func _apply_wind_config() -> void:
|
||||
RenderingServer.global_shader_parameter_set("global_wind_speed", environment_config.wind_speed)
|
||||
RenderingServer.global_shader_parameter_set("global_wind_direction", environment_config.wind_direction)
|
||||
RenderingServer.global_shader_parameter_set("global_wind_scale", environment_config.wind_scale)
|
||||
RenderingServer.global_shader_parameter_set("global_wind_strength", environment_config.wind_strength)
|
||||
if particles_wind:
|
||||
var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial
|
||||
if proc_mat_wind:
|
||||
var wind_direction_3d := Vector3(environment_config.wind_direction.x, 0.0, environment_config.wind_direction.y)
|
||||
if wind_direction_3d.length_squared() > 0.0:
|
||||
var wind_axis := wind_direction_3d.normalized()
|
||||
var wind_cross := wind_axis.cross(Vector3.UP)
|
||||
if wind_cross.length_squared() == 0.0:
|
||||
wind_cross = Vector3.FORWARD
|
||||
else:
|
||||
wind_cross = wind_cross.normalized()
|
||||
var wind_up := wind_cross.cross(wind_axis).normalized()
|
||||
proc_mat_wind.direction = wind_axis
|
||||
particles_wind.global_transform = Transform3D(Basis(wind_cross, wind_axis, wind_up), particles_wind.global_position)
|
||||
RenderingServer.global_shader_parameter_set("global_wind_direction", environment_config.wind_direction)
|
||||
RenderingServer.global_shader_parameter_set("global_wind_scale", environment_config.wind_scale)
|
||||
if particles_wind:
|
||||
var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial
|
||||
if proc_mat_wind:
|
||||
var wind_direction_3d := Vector3(environment_config.wind_direction.x, 0.0, environment_config.wind_direction.y)
|
||||
if wind_direction_3d.length_squared() > 0.0:
|
||||
var wind_axis := wind_direction_3d.normalized()
|
||||
var wind_cross := wind_axis.cross(Vector3.UP)
|
||||
if wind_cross.length_squared() == 0.0:
|
||||
wind_cross = Vector3.FORWARD
|
||||
else:
|
||||
wind_cross = wind_cross.normalized()
|
||||
var wind_up := wind_cross.cross(wind_axis).normalized()
|
||||
proc_mat_wind.direction = wind_axis
|
||||
particles_wind.global_transform = Transform3D(Basis(wind_cross, wind_axis, wind_up), particles_wind.global_position)
|
||||
|
||||
_apply_wind_state()
|
||||
|
||||
func _apply_wind_state() -> void:
|
||||
if environment_config == null:
|
||||
return
|
||||
|
||||
var active_wind_speed := environment_config.wind_speed if is_windy else 0.0
|
||||
var active_wind_strength := environment_config.wind_strength if is_windy else 0.0
|
||||
RenderingServer.global_shader_parameter_set("global_wind_speed", active_wind_speed)
|
||||
RenderingServer.global_shader_parameter_set("global_wind_strength", active_wind_strength)
|
||||
|
||||
func _apply_cloud_config() -> void:
|
||||
var dir = environment_config.wind_direction
|
||||
@@ -366,7 +378,7 @@ func toggle_storm(value: bool):
|
||||
is_storm = value
|
||||
|
||||
#set lightning
|
||||
func set_lightning():
|
||||
func init_lightning():
|
||||
lightning_light.name = "Lightning Light"
|
||||
lightning_light.transform = Transform3D(
|
||||
Vector3(-0.6238797, -0.342596, 0.7024259), # asse X
|
||||
@@ -381,7 +393,7 @@ func set_lightning():
|
||||
add_child(lightning_light)
|
||||
|
||||
create_lightning_sprite()
|
||||
set_lightning_timer()
|
||||
init_lightning_timer()
|
||||
|
||||
func create_lightning_sprite():
|
||||
lightning_sprite = Sprite3D.new()
|
||||
@@ -406,7 +418,7 @@ func create_lightning_sprite():
|
||||
add_child(lightning_sprite)
|
||||
|
||||
#set next lightning timer
|
||||
func set_lightning_timer():
|
||||
func init_lightning_timer():
|
||||
timer_next_lightning = randf_range(environment_config.lightning_min_time, environment_config.lightning_max_time)
|
||||
|
||||
func start_lightning():
|
||||
@@ -460,7 +472,7 @@ func _play_thunder_delayed(delay: float):
|
||||
#region Rain
|
||||
|
||||
#disable rain
|
||||
func set_rain():
|
||||
func init_rain():
|
||||
if particles_rain:
|
||||
particles_rain.visible = true
|
||||
particles_rain.emitting = false
|
||||
@@ -607,10 +619,10 @@ func toggle_snow(value: bool):
|
||||
if snow_tween and snow_tween.is_valid():
|
||||
snow_tween.kill()
|
||||
snow_tween = create_tween()
|
||||
snow_tween.tween_method(set_snow_amount, actual_snow_amount, target_snow_amount, environment_config.snow_transaction_time)
|
||||
snow_tween.tween_method(init_snow_amount, actual_snow_amount, target_snow_amount, environment_config.snow_transaction_time)
|
||||
|
||||
#disable snow and set default values and shader
|
||||
func set_snow(value: float = 0.0):
|
||||
func init_snow(value: float = 0.0):
|
||||
actual_snow_amount = value
|
||||
RenderingServer.global_shader_parameter_set("global_snow_amount", value)
|
||||
|
||||
@@ -625,7 +637,7 @@ func set_snow(value: float = 0.0):
|
||||
RenderingServer.global_shader_parameter_set("global_snow_start_time", -1.0)
|
||||
RenderingServer.global_shader_parameter_set("global_snow_melt_time", -1.0)
|
||||
|
||||
func set_snow_amount(value: float):
|
||||
func init_snow_amount(value: float):
|
||||
actual_snow_amount = value
|
||||
RenderingServer.global_shader_parameter_set("global_snow_amount", value)
|
||||
|
||||
@@ -663,4 +675,20 @@ func ApplyPostProcessBlurConfig() -> void:
|
||||
if blur_material:
|
||||
blur_material.set_shader_parameter("blur_amount", environment_config.blur_amount)
|
||||
|
||||
func _apply_dust_config() -> void:
|
||||
var dust_color: Color = environment_config.dust_color
|
||||
var dust_speed: float = environment_config.dust_speed
|
||||
var dust_density: float = environment_config.dust_density
|
||||
var dust_size_min: float = environment_config.dust_size_min
|
||||
var dust_size_max: float = environment_config.dust_size_max
|
||||
|
||||
if environment_dust:
|
||||
var dust_mat = environment_dust.material as ShaderMaterial
|
||||
if dust_mat:
|
||||
dust_mat.set_shader_parameter("dust_color", dust_color)
|
||||
dust_mat.set_shader_parameter("dust_speed", dust_speed)
|
||||
dust_mat.set_shader_parameter("dust_density", dust_density)
|
||||
dust_mat.set_shader_parameter("dust_size_min", dust_size_min)
|
||||
dust_mat.set_shader_parameter("dust_size_max", dust_size_max)
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -85,6 +85,13 @@ extends Resource
|
||||
@export var enable_environment_shadows: bool = true #Cloud shadow projection on terrain
|
||||
@export var blur_amount: float = 0.6
|
||||
|
||||
@export_group("Dust")
|
||||
@export var dust_color: Color = Color(1.0, 0.456, 0.125, 0.6) #dust color
|
||||
@export var dust_speed: float = 0.15 #dust speed
|
||||
@export var dust_density: float = 1.0 #dust density
|
||||
@export var dust_size_min: float = 0.02; #dust min size
|
||||
@export var dust_size_max: float = 0.2; #dust max size
|
||||
|
||||
#Shader materials used by weather and sky systems
|
||||
@export_group("Environment Materials")
|
||||
@export var material_fog: ShaderMaterial #Fog overlay shader material
|
||||
|
||||
Reference in New Issue
Block a user