update snow management
This commit is contained in:
@@ -4,6 +4,15 @@ extends Node3D
|
||||
const NOISE_TEXTURE: Texture2D = preload("res://core/daynight/noise.tres")
|
||||
const WEATHER_SHADER: Material = preload("res://core/daynight/weather_overlay.tres")
|
||||
const DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME: int = 32 #how many update of the environment (apply materials) will be done per frame
|
||||
const FORCE_WEATHER_MATERIAL_PATH_PARTS: PackedStringArray = [
|
||||
"/chunk/material/field.tres",
|
||||
"/chunk/material/grassflat_chunk.tres",
|
||||
"/chunk/material/path_chunk.tres",
|
||||
"/chunk/material/railway_chunk.tres",
|
||||
"/chunk/material/terrain.tres",
|
||||
"/chunk/prop/house/house.tres",
|
||||
"/chunk/prop/house/house_emissiv.tres",
|
||||
]
|
||||
|
||||
@export var environment_config: EnvironmentConfig
|
||||
|
||||
@@ -157,9 +166,17 @@ func _restore_keyboard_action_events() -> void:
|
||||
_blocked_keyboard_events_by_action.clear()
|
||||
|
||||
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"):
|
||||
if _should_queue_dynamic_environment_node(node):
|
||||
_queue_dynamic_environment_node(node)
|
||||
|
||||
func _should_queue_dynamic_environment_node(node: Node) -> bool:
|
||||
if node.is_in_group("wind_node"):
|
||||
return true
|
||||
if node.is_in_group("weather_vegetables_node"):
|
||||
return true
|
||||
|
||||
return node is Node3D
|
||||
|
||||
func _queue_dynamic_environment_node(node: Node) -> void:
|
||||
if not is_instance_valid(node):
|
||||
return
|
||||
@@ -205,7 +222,7 @@ func _apply_dynamic_environment_materials(node: Node) -> void:
|
||||
if node.is_in_group("wind_node"):
|
||||
_apply_wind_noise_to_node(node, NOISE_TEXTURE)
|
||||
|
||||
if node.is_in_group("weather_node") or node.is_in_group("weather_vegetables_node"):
|
||||
if node is Node3D:
|
||||
_apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
|
||||
|
||||
if _should_ignore_weather_overlay(node):
|
||||
@@ -231,11 +248,9 @@ func _apply_wind_noise_to_node(node: Node, noise_tex: Texture2D) -> void:
|
||||
_apply_wind_noise_to_node(child, noise_tex)
|
||||
|
||||
func ApplyWeatherShaderToMaterials():
|
||||
for node in get_tree().get_nodes_in_group("weather_node"):
|
||||
_apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
|
||||
|
||||
for node in get_tree().get_nodes_in_group("weather_vegetables_node"):
|
||||
_apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
|
||||
var current_scene := get_tree().current_scene
|
||||
if current_scene != null:
|
||||
_apply_weather_overlay_to_node(current_scene, _get_weather_overlay_material(current_scene))
|
||||
|
||||
func _get_weather_overlay_material(node: Node) -> Material:
|
||||
if not node.is_in_group("weather_overlay_no_noise"):
|
||||
@@ -255,13 +270,21 @@ func _apply_weather_overlay_to_node(node: Node, material: Material) -> void:
|
||||
return
|
||||
|
||||
if node is GeometryInstance3D:
|
||||
if _should_clear_weather_overlay(node) or _geometry_uses_alpha_texture(node):
|
||||
if _geometry_should_never_receive_weather_overlay(node):
|
||||
node.material_overlay = null
|
||||
elif _should_clear_weather_overlay(node) and not _geometry_forces_weather_overlay(node):
|
||||
node.material_overlay = null
|
||||
elif _geometry_uses_alpha_texture(node) or _geometry_should_skip_weather_overlay(node):
|
||||
node.material_overlay = null
|
||||
else:
|
||||
node.material_overlay = material
|
||||
|
||||
var child_material := _get_weather_overlay_material(node)
|
||||
if child_material == WEATHER_SHADER and material == weather_shader_no_noise:
|
||||
child_material = material
|
||||
|
||||
for child in node.get_children():
|
||||
_apply_weather_overlay_to_node(child, material)
|
||||
_apply_weather_overlay_to_node(child, child_material)
|
||||
|
||||
func _clear_weather_overlay_from_node(node: Node) -> void:
|
||||
if node is GeometryInstance3D:
|
||||
@@ -289,11 +312,99 @@ func _geometry_uses_alpha_texture(node: GeometryInstance3D) -> bool:
|
||||
|
||||
return false
|
||||
|
||||
func _geometry_should_never_receive_weather_overlay(node: GeometryInstance3D) -> bool:
|
||||
if node is GPUParticles3D:
|
||||
return true
|
||||
|
||||
var node_name := String(node.name).to_lower()
|
||||
return node_name.contains("cloud") or node_name.contains("fog") or node_name.contains("godray")
|
||||
|
||||
func _geometry_should_skip_weather_overlay(node: GeometryInstance3D) -> bool:
|
||||
if _geometry_forces_weather_overlay(node):
|
||||
return false
|
||||
if _node_name_indicates_water(node):
|
||||
return true
|
||||
|
||||
var has_material: bool = false
|
||||
var all_materials_ignored: bool = true
|
||||
var material_override := node.material_override
|
||||
if material_override != null:
|
||||
has_material = true
|
||||
all_materials_ignored = all_materials_ignored and _material_ignores_weather_overlay(material_override)
|
||||
|
||||
if node is MeshInstance3D:
|
||||
for surface_index in node.get_surface_override_material_count():
|
||||
var surface_material: Material = node.get_surface_override_material(surface_index)
|
||||
if surface_material == null:
|
||||
continue
|
||||
|
||||
has_material = true
|
||||
all_materials_ignored = all_materials_ignored and _material_ignores_weather_overlay(surface_material)
|
||||
|
||||
if node.mesh:
|
||||
for surface_index in node.mesh.get_surface_count():
|
||||
var mesh_material: Material = node.mesh.surface_get_material(surface_index)
|
||||
if mesh_material == null:
|
||||
continue
|
||||
|
||||
has_material = true
|
||||
all_materials_ignored = all_materials_ignored and _material_ignores_weather_overlay(mesh_material)
|
||||
|
||||
return has_material and all_materials_ignored
|
||||
|
||||
func _geometry_forces_weather_overlay(node: GeometryInstance3D) -> bool:
|
||||
if _material_forces_weather_overlay(node.material_override):
|
||||
return true
|
||||
|
||||
if node is MeshInstance3D:
|
||||
for surface_index in node.get_surface_override_material_count():
|
||||
if _material_forces_weather_overlay(node.get_surface_override_material(surface_index)):
|
||||
return true
|
||||
|
||||
if node.mesh:
|
||||
for surface_index in node.mesh.get_surface_count():
|
||||
if _material_forces_weather_overlay(node.mesh.surface_get_material(surface_index)):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func _material_forces_weather_overlay(material: Material) -> bool:
|
||||
if material == null:
|
||||
return false
|
||||
|
||||
var resource_path := material.resource_path.to_lower()
|
||||
for path_part in FORCE_WEATHER_MATERIAL_PATH_PARTS:
|
||||
if resource_path.contains(path_part):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func _node_name_indicates_water(node: Node) -> bool:
|
||||
var node_name := String(node.name).to_lower()
|
||||
return node_name.begins_with("water") or node_name.contains("/water")
|
||||
|
||||
func _material_ignores_weather_overlay(material: Material) -> bool:
|
||||
if material == null:
|
||||
return false
|
||||
|
||||
var resource_path := material.resource_path.to_lower()
|
||||
if resource_path.contains("/water") or resource_path.contains("water_"):
|
||||
return true
|
||||
if resource_path.contains("/cloud/") or resource_path.contains("cloud"):
|
||||
return true
|
||||
|
||||
var base_material := material as BaseMaterial3D
|
||||
if base_material != null:
|
||||
return base_material.transparency != BaseMaterial3D.TRANSPARENCY_DISABLED or base_material.albedo_color.a < 0.99
|
||||
|
||||
return false
|
||||
|
||||
func _shader_material_uses_alpha_texture(material: ShaderMaterial) -> bool:
|
||||
if material == null or material.shader == null:
|
||||
return false
|
||||
|
||||
return material.shader.code.find("alpha_texture") != -1
|
||||
var shader_code := material.shader.code
|
||||
return shader_code.find("alpha_texture") != -1 or shader_code.find("ALPHA") != -1 or shader_code.find("opacity") != -1
|
||||
|
||||
func _should_ignore_weather_overlay(node: Node) -> bool:
|
||||
return node.is_in_group("weather_overlay_ignore")
|
||||
|
||||
Reference in New Issue
Block a user