Skip to content

Commit

Permalink
feat: finishes lightning scene, adds more exposed options
Browse files Browse the repository at this point in the history
Lightning effects are visually polished and many options are exposed as export variables (color and albedo gradient, distance, spawn-interval).

Lightnings are now more "grouped" and arent just randomly spawned around the player; can be adjusted via rotation degrees

Refs: #312
  • Loading branch information
Mathias Baumgartinger~ committed Aug 7, 2023
1 parent fa859d9 commit ecd188c
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 48 deletions.
104 changes: 70 additions & 34 deletions World/Environment/Lightning.gd
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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)
5 changes: 5 additions & 0 deletions World/Environment/Lightning.gdshader
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
shader_type canvas_item;

void fragment() {
// Place fragment code here.
}
35 changes: 22 additions & 13 deletions World/Environment/Lightning.tscn
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
[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")

[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)
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")

Expand All @@ -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
4 changes: 4 additions & 0 deletions World/Environment/WorldEnvironment.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 0 additions & 1 deletion World/Environment/WorldEnvironment.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions World/WeatherManager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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 :
Expand Down Expand Up @@ -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)
1 change: 1 addition & 0 deletions World/World.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down

0 comments on commit ecd188c

Please sign in to comment.