mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 13:30:07 +01:00
This uses https://github.com/Rytelier/godot-sky-and-volumetric-clouds as a base, with several changes made: - Spheres are now used to represent radiance map reflections of varying roughness and metallic values. - A day/night cycle is now featured. - Mipmaps are enabled on the weather texture as an optimization. - The default radiance map settings are more conservative to account for the real-time sky shader. - This makes reflections lower quality, but it's not too noticeable in most real world scenes (especially if using GI techniques for reflections). - Debanding is now applied in the project settings, rather than on the sky shader. This is significantly faster (over 0.1 ms saved on a RX 6900 XT in 3840×2160). It also has the benefit of working on materials, which can exhibit banding if not textured. - The sky shader has debanding commented out in case it's needed. This debanding also applies to the lower half of the sky as well in this case, as it was required to get rid of noticeable banding on the lower half. - Cloud coverage and density uniform hints now allow values as low as 0.001. Co-authored-by: Rytelier <45795134+Rytelier@users.noreply.github.com> Co-authored-by: Clay John <claynjohn@gmail.com>
123 lines
5.0 KiB
GDScript
123 lines
5.0 KiB
GDScript
extends Node3D
|
||
|
||
const MOUSE_SENSITIVITY = 0.001
|
||
|
||
# The camera field of view to smoothly interpolate to.
|
||
@onready var desired_fov: float = $YawCamera/Camera3D.fov
|
||
|
||
|
||
func _ready() -> void:
|
||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||
|
||
|
||
func _process(delta: float) -> void:
|
||
# Make the slider follow the day/night cycle.
|
||
$Panel/MarginContainer/VBoxContainer/TimeOfDay/HSlider.value = $AnimationPlayer.current_animation_position
|
||
$WorldEnvironment.environment.sky.sky_material.set_shader_parameter("cloud_time_offset", $AnimationPlayer.current_animation_position)
|
||
|
||
$YawCamera/Camera3D.fov = lerpf($YawCamera/Camera3D.fov, desired_fov, 1.0 - exp(-delta * 10.0))
|
||
|
||
|
||
|
||
func _input(event: InputEvent) -> void:
|
||
if event.is_action_pressed("toggle_gui"):
|
||
$Panel.visible = not $Panel.visible
|
||
$Help.visible = not $Help.visible
|
||
|
||
if event.is_action_pressed("toggle_spheres"):
|
||
$Spheres.visible = not $Spheres.visible
|
||
|
||
if event.is_action_pressed("toggle_mouse_capture"):
|
||
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||
else:
|
||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||
|
||
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED and event is InputEventMouseMotion:
|
||
# Mouselook.
|
||
var relative_motion: Vector2 = event.screen_relative
|
||
$YawCamera.rotation.x = clampf($YawCamera.rotation.x - relative_motion.y * MOUSE_SENSITIVITY, -TAU * 0.25, TAU * 0.25)
|
||
$YawCamera.rotation.y -= relative_motion.x * MOUSE_SENSITIVITY
|
||
|
||
# Mouse wheel currently doesn't work in input actions. Hardcode mouse wheel as a workaround.
|
||
if event.is_action_pressed("increase_camera_fov") or Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_DOWN):
|
||
desired_fov = clampf(desired_fov + 5.0, 20.0, 120.0)
|
||
if event.is_action_pressed("decrease_camera_fov") or Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_UP):
|
||
desired_fov = clampf(desired_fov - 5.0, 20.0, 120.0)
|
||
|
||
|
||
func _on_time_of_day_value_changed(value: float) -> void:
|
||
# Update time of day.
|
||
$AnimationPlayer.seek(value)
|
||
# TODO: Display HH:MM time.
|
||
$Panel/MarginContainer/VBoxContainer/TimeOfDay/Value.text = str(value).pad_decimals(2)
|
||
|
||
|
||
func _on_speed_minus_pressed() -> void:
|
||
# Allow minimum value to be zero so that the special case can be reached for pausing.
|
||
$AnimationPlayer.speed_scale = clampf($AnimationPlayer.speed_scale * 0.5, 0.0, 12.8)
|
||
if $AnimationPlayer.speed_scale < 0.0499:
|
||
# Going below 0.5× speed; pause.
|
||
$AnimationPlayer.speed_scale = 0.0
|
||
|
||
update_speed_label()
|
||
|
||
|
||
func _on_speed_plus_pressed() -> void:
|
||
$AnimationPlayer.speed_scale = clampf($AnimationPlayer.speed_scale * 2.0, 0.05, 12.8)
|
||
if is_zero_approx($AnimationPlayer.speed_scale):
|
||
# Currently paused; resume playback.
|
||
$AnimationPlayer.speed_scale = 0.1
|
||
|
||
update_speed_label()
|
||
|
||
|
||
func update_speed_label() -> void:
|
||
# The default speed scale for this AnimationPlayer is internally 0.1, so multiply the displayed value by 10.
|
||
if is_zero_approx($AnimationPlayer.speed_scale):
|
||
$Panel/MarginContainer/VBoxContainer/TimeOfDay/CurrentSpeed.text = "Pause"
|
||
else:
|
||
$Panel/MarginContainer/VBoxContainer/TimeOfDay/CurrentSpeed.text = "%.2f×" % ($AnimationPlayer.speed_scale * 10)
|
||
|
||
|
||
func _on_cloud_coverage_value_changed(value: float) -> void:
|
||
$WorldEnvironment.environment.sky.sky_material.set_shader_parameter("cloud_coverage", value)
|
||
$Panel/MarginContainer/VBoxContainer/Clouds/CoverageValue.text = "%d%%" % (value * 100)
|
||
|
||
|
||
func _on_cloud_density_value_changed(value: float) -> void:
|
||
$WorldEnvironment.environment.sky.sky_material.set_shader_parameter("cloud_density", value)
|
||
$Panel/MarginContainer/VBoxContainer/Clouds/DensityValue.text = "%d%%" % (value * 100)
|
||
|
||
|
||
func _on_process_mode_item_selected(index: int) -> void:
|
||
match index:
|
||
0:
|
||
$WorldEnvironment.environment.sky.process_mode = Sky.PROCESS_MODE_QUALITY
|
||
$Panel/MarginContainer/VBoxContainer/RadianceSize.visible = true
|
||
# Reset radiance size as the engine forces radiance size to 256 after switching to the Real-Time process mode.
|
||
_on_radiance_size_item_selected($Panel/MarginContainer/VBoxContainer/RadianceSize/OptionButton.selected)
|
||
1:
|
||
$WorldEnvironment.environment.sky.process_mode = Sky.PROCESS_MODE_INCREMENTAL
|
||
$Panel/MarginContainer/VBoxContainer/RadianceSize.visible = true
|
||
# Reset radiance size as the engine forces radiance size to 256 after switching to the Real-Time process mode.
|
||
_on_radiance_size_item_selected($Panel/MarginContainer/VBoxContainer/RadianceSize/OptionButton.selected)
|
||
2:
|
||
$WorldEnvironment.environment.sky.process_mode = Sky.PROCESS_MODE_REALTIME
|
||
# Radiance size is forced to 256 by the engine when using Real-Time process mode.
|
||
$Panel/MarginContainer/VBoxContainer/RadianceSize.visible = false
|
||
|
||
|
||
func _on_radiance_size_item_selected(index: int) -> void:
|
||
match index:
|
||
0:
|
||
$WorldEnvironment.environment.sky.radiance_size = Sky.RADIANCE_SIZE_32
|
||
1:
|
||
$WorldEnvironment.environment.sky.radiance_size = Sky.RADIANCE_SIZE_64
|
||
2:
|
||
$WorldEnvironment.environment.sky.radiance_size = Sky.RADIANCE_SIZE_128
|
||
3:
|
||
$WorldEnvironment.environment.sky.radiance_size = Sky.RADIANCE_SIZE_256
|
||
4:
|
||
$WorldEnvironment.environment.sky.radiance_size = Sky.RADIANCE_SIZE_512
|