diff --git a/World/Environment/Lightning.gd b/World/Environment/Lightning.gd index d27b1f3a..4a7d90f7 100644 --- a/World/Environment/Lightning.gd +++ b/World/Environment/Lightning.gd @@ -1,43 +1,68 @@ extends Node3D - +func set_enabled(val): + if has_node("Timer"): + if enabled: + get_node("Timer").start() + else: + get_node("Timer").stop() @export var enabled := false : - set(is_enabled): - enabled = is_enabled - if has_node("Timer"): - if enabled: - get_node("Timer").start() - else: - get_node("Timer").stop() -@export var time_interval_from := 0.1 -@export var time_interval_to := 10 - + set(val): + enabled = val + set_enabled(val) + +# Randomly choose a number (in seconds) in the interval for +# spawning a new lightning +@export var spawn_interval_from := 0.5 +@export var spawn_interval_to := 10.0 + +# Distance between center and lightning +@export var min_distance := 500 +@export var max_distance := 2000 + +# Gradient when the lightning is on/off (i.e. flickering) +@export var gradient_on: Gradient +@export var gradient_off: Gradient + +func set_color(val): + if has_node("MeshInstance3d/LightNing"): + get_node("MeshInstance3d/LightNing").light_color = color + if has_node("MeshInstance3d"): + get_node("MeshInstance3d").material_override.emission = color +@export var color: Color : + set(val): + color = val + set_color(val) + +# 0 => north, 90 => east, 180 => south, 270 => west +@export var rot_degrees := 0.0 : + set(deg): rot_degrees = deg @onready var light = $MeshInstance3d/LightNing -@onready var lightning_mesh = $MeshInstance3d @onready var line: Line2D = $MeshInstance3d/SubViewport/Line2d -@onready var timer = $Timer var center_node: Node3D func _ready(): - timer.timeout.connect(_on_timer_timeout) - if enabled: timer.start() + $Timer.timeout.connect(_on_timer_timeout) + set_enabled(enabled) + set_color(color) func _create_lightning_branch(num_segments: int): line.clear_points() - line.add_point(Vector2(50, 0)) - $MeshInstance3d/SubViewport/Sprite2D.position = Vector2(50, 6) + line.add_point(Vector2(0, 0)) for i in range(num_segments): var point_before = line.points[i] - line.add_point(Vector2(_sample_gaussian(0.5) + point_before.x * randf(), _sample_gaussian(0.8) + point_before.y)) -# $MeshInstance3d/SubViewport/Sprite2D2.position = line.get_point_position(num_segments) + line.add_point(Vector2( + _sample_gaussian(1.5) + point_before.x * randf(), + _sample_gaussian(0.8) + point_before.y)) -# Approximate via central limit theorem (Irwin-Hall) +# Approximate a number via central limit theorem (Irwin Hall) func _sample_gaussian(stdev_multiplier: float): + # aprox gauss will be approximately 6 var approx_gauss = 12 for i in range(12): approx_gauss -= randf() @@ -46,34 +71,45 @@ func _sample_gaussian(stdev_multiplier: float): func _animate_(): + # Rotate the light accordingly self.light.look_at(center_node.position) var tween_lighting = create_tween() var tween_light = create_tween() - for i in range(randf_range(3, 6)): - var time_light_on = randf_range(.05, .1) - var time_light_off = randf_range(.05, .1) + # Simulate "flickering" of lightning + for i in range(randf_range(2, 5)): + var time_light_on = randf_range(.05, .2) + var time_light_off = randf_range(.15, .15) - var energy_light_on = randf_range(.4, 1.) - var energy_light_off = randf_range(.0, .5) + var dist_to_center = $MeshInstance3d.position.distance_to(center_node.position) + var distance_multiplier = remap(dist_to_center, min_distance, max_distance, 1.5, 0.5) + var energy_light_on = randf_range(1., 5.) - tween_lighting.tween_property(self.line, "default_color:a", energy_light_off, time_light_off) - tween_lighting.tween_property(self.line, "default_color:a", energy_light_on, time_light_on) + tween_lighting.tween_property(line, "gradient", gradient_off, time_light_off) + tween_lighting.tween_property(line, "gradient", gradient_on, time_light_on) - tween_light.tween_property(self.light, "light_energy", energy_light_off, time_light_off) - tween_light.tween_property(self.light, "light_energy", energy_light_on, time_light_on) + tween_light.tween_property( + light, "light_energy", 0.3 * distance_multiplier, time_light_off) + tween_light.tween_property( + light, "light_energy", energy_light_on * distance_multiplier, time_light_on) - tween_light.tween_property(self.light, "light_energy", 0.0, 5.1) - tween_lighting.tween_property(self.line, "default_color:a", 0.0, 5.1) + # Reset to invisible + tween_light.tween_property(light, "light_energy", 0.0, 0.2) + tween_lighting.tween_property(line, "gradient", gradient_off, 0.2) func fire(): - _create_lightning_branch(30) - $MeshInstance3d.position = center_node.position + Vector3(randi_range(-3000, 3000), 0, randi_range(-3000, 3000)) + _create_lightning_branch(randi_range(10, 50)) + var rand_angle = randf_range(rot_degrees - 10, rot_degrees + 10) + $MeshInstance3d.position = center_node.position + Vector3( + 0, 0, randi_range(-min_distance, -max_distance)) + $MeshInstance3d.position = center_node.position + \ + ($MeshInstance3d.position - center_node.position).rotated(Vector3.UP, deg_to_rad(rand_angle)) _animate_() +# Repeating call of this function on timer timeout func _on_timer_timeout(): fire() - timer.wait_time = randf_range(time_interval_from, time_interval_to) + $Timer.wait_time = randf_range(spawn_interval_from, spawn_interval_to) diff --git a/World/Environment/Lightning.gdshader b/World/Environment/Lightning.gdshader new file mode 100644 index 00000000..3fa10e45 --- /dev/null +++ b/World/Environment/Lightning.gdshader @@ -0,0 +1,5 @@ +shader_type canvas_item; + +void fragment() { + // Place fragment code here. +} diff --git a/World/Environment/Lightning.tscn b/World/Environment/Lightning.tscn index 0c3ae98d..859ac9de 100644 --- a/World/Environment/Lightning.tscn +++ b/World/Environment/Lightning.tscn @@ -1,7 +1,14 @@ -[gd_scene load_steps=6 format=3 uid="uid://cib4g5bstb1xa"] +[gd_scene load_steps=7 format=3 uid="uid://cib4g5bstb1xa"] [ext_resource type="Script" path="res://World/Environment/Lightning.gd" id="1_2eur0"] -[ext_resource type="Texture2D" uid="uid://b4u8j5mea7xd4" path="res://Resources/Textures/RainSplash.png" id="2_xe28t"] + +[sub_resource type="Gradient" id="Gradient_gnng6"] +offsets = PackedFloat32Array(0, 0.431373, 1) +colors = PackedColorArray(0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0) + +[sub_resource type="Gradient" id="Gradient_kbe6e"] +offsets = PackedFloat32Array(1) +colors = PackedColorArray(1, 1, 1, 0) [sub_resource type="ViewportTexture" id="ViewportTexture_schoq"] viewport_path = NodePath("MeshInstance3d/SubViewport") @@ -9,6 +16,7 @@ viewport_path = NodePath("MeshInstance3d/SubViewport") [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_dju3a"] resource_local_to_scene = true transparency = 1 +cull_mode = 2 albedo_texture = SubResource("ViewportTexture_schoq") emission_enabled = true emission = Color(0.462745, 0.537255, 1, 1) @@ -16,19 +24,22 @@ emission_energy_multiplier = 10.0 billboard_mode = 2 [sub_resource type="PlaneMesh" id="PlaneMesh_h6sm4"] -size = Vector2(150, 750) +size = Vector2(500, 500) orientation = 2 [node name="Lightning" type="Node3D"] script = ExtResource("1_2eur0") enabled = true -time_interval_to = 1 +spawn_interval_to = 3.0 +gradient_on = SubResource("Gradient_gnng6") +gradient_off = SubResource("Gradient_kbe6e") +color = Color(0.788235, 0.776471, 1, 1) +rot_degrees = 180.0 [node name="Timer" type="Timer" parent="."] autostart = true [node name="MeshInstance3d" type="MeshInstance3D" parent="."] -transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -443.156, -88.0528, -0.99136) material_override = SubResource("StandardMaterial3D_dju3a") mesh = SubResource("PlaneMesh_h6sm4") @@ -38,22 +49,20 @@ transparent_bg = true handle_input_locally = false msaa_2d = 3 use_taa = true -size = Vector2i(100, 500) +size = Vector2i(500, 500) render_target_update_mode = 4 -[node name="Sprite2D" type="Sprite2D" parent="MeshInstance3d/SubViewport"] -scale = Vector2(0.05, 0.05) -texture = ExtResource("2_xe28t") - [node name="Line2d" type="Line2D" parent="MeshInstance3d/SubViewport"] width = 2.0 default_color = Color(0.501961, 0.541176, 1, 1) +gradient = SubResource("Gradient_gnng6") [node name="LightNing" type="DirectionalLight3D" parent="MeshInstance3d"] -transform = Transform3D(-0.605916, -0.326285, 0.725538, 0, 0.912019, 0.410148, -0.795529, 0.248515, -0.552607, 0, -0.018, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 500, 0) rotation_edit_mode = 2 +layers = 7 light_color = Color(0.72549, 0.839216, 0.945098, 1) light_energy = 0.0 -light_indirect_energy = 5.0 -light_volumetric_fog_energy = 5.0 +light_indirect_energy = 0.1 +light_volumetric_fog_energy = 0.5 shadow_enabled = true diff --git a/World/Environment/WorldEnvironment.gd b/World/Environment/WorldEnvironment.gd index 4c255f72..dde61939 100644 --- a/World/Environment/WorldEnvironment.gd +++ b/World/Environment/WorldEnvironment.gd @@ -79,3 +79,7 @@ func _set_light_energy(new_energy): func set_lightning_enabled(enabled: bool): $Lightning.enabled = enabled + + +func set_lightning_rotation(rotation_deg: float): + $Lightning.rot_degrees = rotation_deg diff --git a/World/Environment/WorldEnvironment.tscn b/World/Environment/WorldEnvironment.tscn index cedab250..ce6fea03 100644 --- a/World/Environment/WorldEnvironment.tscn +++ b/World/Environment/WorldEnvironment.tscn @@ -76,4 +76,3 @@ mesh = SubResource("SphereMesh_v0nf7") [node name="Rain" parent="." instance=ExtResource("6_wusnq")] [node name="Lightning" parent="." instance=ExtResource("7_canqr")] -enabled = true diff --git a/World/WeatherManager.gd b/World/WeatherManager.gd index 05c1489f..42b359ab 100644 --- a/World/WeatherManager.gd +++ b/World/WeatherManager.gd @@ -10,6 +10,7 @@ signal rain_density_changed(new_rain_density) signal rain_drop_size_changed(new_rain_density) signal rain_enabled_changed(enabled) signal lightning_enabled_changed(enabled) +signal lightning_rotation_changed(rotation_degrees) # 0..100 = "clear visibility".."strong haziness" var visibility = 0 : @@ -69,4 +70,10 @@ var lightning_enabled := false : return lightning_enabled set(enabled): lightning_enabled = enabled + lightning_enabled_changed.emit(lightning_enabled) + +var lightning_rotation := 0 : + set(val): + lightning_rotation = val + lightning_rotation_changed.emit(lightning_rotation) diff --git a/World/World.gd b/World/World.gd index ffed1e51..6def70f3 100644 --- a/World/World.gd +++ b/World/World.gd @@ -25,6 +25,7 @@ func _ready(): $WeatherManager.rain_density_changed.connect($WorldEnvironment.apply_rain_density) $WeatherManager.rain_drop_size_changed.connect($WorldEnvironment.apply_rain_drop_size) $WeatherManager.lightning_enabled_changed.connect($WorldEnvironment.set_lightning_enabled) + $WeatherManager.lightning_rotation_changed.connect($WorldEnvironment.set_lightning_rotation) $PositionManager.new_center_node.connect(func(center_node: Node3D): _add_remote_transform(center_node, $WorldEnvironment/Rain, "RainRemoteTransformer"))