-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Co-authored-by: Clay John <[email protected]>
- Loading branch information
1 parent
63d1cd9
commit d07c18d
Showing
19 changed files
with
1,297 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# 3D Sky Shaders | ||
|
||
An example of a sky shader in Godot. This shader features real-time volumetric | ||
clouds and physical sky with Raleigh and Mie scattering, which causes the sky's | ||
colors to adjust automatically depending on the sun angle. The sun's angle is set | ||
automatically from the first DirectionalLight3D node in the scene | ||
(unless its sky mode is **Light Only**). | ||
|
||
Physical sky features are based on the built-in PhysicalSkyMaterial, while | ||
volumetric clouds were added after converting PhysicalSkyMaterial to a | ||
ShaderMaterial using the **Convert to ShaderMaterial** button in the editor | ||
resource dropdown. | ||
|
||
> **Warning** | ||
> | ||
> Sky shaders are rendered every frame if they use the `TIME` variable or are | ||
> otherwise updated every frame (e.g. if an uniform is updated in `_process()` | ||
> or with an AnimationPlayer). This has a significant performance impact for | ||
> complex sky shaders. The performance impact can be reduced by adjusting the | ||
> radiance map properties in Environment, but it will remain significant. | ||
> | ||
> The shader in this demo project is expensive, and is intended to be used in | ||
> games where most of the sky remains visible at all times (such as flight | ||
> simulators). | ||
> | ||
> Optimizations to sky shader rendering are planned in future Godot releases. | ||
Language: GDScript | ||
|
||
Renderer: Forward Plus | ||
|
||
## How does it work? | ||
|
||
The day/night cycle is performed using an AnimationPlayer node that adjusts node | ||
properties and the sky shader parameters in real-time. | ||
|
||
Spheres with varying levels of roughness and metallic materials are instanced using | ||
a [`@tool` script](https://docs.godotengine.org/en/latest/tutorials/plugins/running_code_in_the_editor.html) | ||
so that they don't have to be created manually in the editor, yet they can still be previewed within the editor. | ||
|
||
## Screenshots | ||
|
||
 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[gd_resource type="Environment" load_steps=2 format=2] | ||
|
||
[sub_resource type="ProceduralSky" id=1] | ||
|
||
[resource] | ||
background_mode = 2 | ||
sky = SubResource( 1 ) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
[remap] | ||
|
||
importer="texture" | ||
type="CompressedTexture2D" | ||
uid="uid://ckaq2n0hvlwq1" | ||
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex" | ||
metadata={ | ||
"vram_texture": false | ||
} | ||
|
||
[deps] | ||
|
||
source_file="res://icon.png" | ||
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"] | ||
|
||
[params] | ||
|
||
compress/mode=0 | ||
compress/high_quality=false | ||
compress/lossy_quality=0.7 | ||
compress/hdr_compression=1 | ||
compress/normal_map=0 | ||
compress/channel_pack=0 | ||
mipmaps/generate=false | ||
mipmaps/limit=-1 | ||
roughness/mode=0 | ||
roughness/src_normal="" | ||
process/fix_alpha_border=true | ||
process/premult_alpha=false | ||
process/normal_map_invert_y=false | ||
process/hdr_as_srgb=false | ||
process/hdr_clamp_exposure=false | ||
process/size_limit=0 | ||
detect_3d/compress_to=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
extends Node3D | ||
|
||
var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") | ||
|
||
# The camera field of view to smoothly interpolate to. | ||
@onready var desired_fov = $YawCamera/Camera3D.fov | ||
|
||
func _ready(): | ||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED | ||
|
||
|
||
func _process(_delta): | ||
# 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, 0.2) | ||
|
||
|
||
|
||
func _input(event): | ||
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. | ||
# Compensate motion speed to be resolution-independent (based on the window height). | ||
var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height | ||
$YawCamera.rotation.x += relative_motion.y * 0.001 | ||
$YawCamera.rotation.y += relative_motion.x * 0.001 | ||
|
||
# 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, 150.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, 150.0) | ||
|
||
|
||
func _on_time_of_day_value_changed(value): | ||
# 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(): | ||
# 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(): | ||
$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(): | ||
# 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): | ||
$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): | ||
$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): | ||
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): | ||
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 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
[remap] | ||
|
||
importer="3d_texture" | ||
type="CompressedTexture3D" | ||
uid="uid://48aujjq3b6pj" | ||
path="res://.godot/imported/perlworlnoise.png-3a040af7870a245e2e85a129517a2537.ctex3d" | ||
metadata={ | ||
"vram_texture": false | ||
} | ||
|
||
[deps] | ||
|
||
source_file="res://perlworlnoise.png" | ||
dest_files=["res://.godot/imported/perlworlnoise.png-3a040af7870a245e2e85a129517a2537.ctex3d"] | ||
|
||
[params] | ||
|
||
compress/mode=0 | ||
compress/high_quality=false | ||
compress/lossy_quality=0.7 | ||
compress/hdr_compression=1 | ||
compress/channel_pack=0 | ||
mipmaps/generate=true | ||
mipmaps/limit=-1 | ||
slices/horizontal=128 | ||
slices/vertical=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
; Engine configuration file. | ||
; It's best edited using the editor UI and not directly, | ||
; since the parameters that go here are not all obvious. | ||
; | ||
; Format: | ||
; [section] ; section goes between [] | ||
; param=value ; assign values to parameters | ||
|
||
config_version=5 | ||
|
||
[application] | ||
|
||
config/name="3D Sky Shaders" | ||
config/description="A short educational sample showing one way of using sky shaders to render real time volumetric cloudscapes." | ||
run/main_scene="res://Main.tscn" | ||
config/features=PackedStringArray("4.0") | ||
config/icon="res://icon.png" | ||
|
||
[display] | ||
|
||
window/stretch/mode="canvas_items" | ||
window/stretch/aspect="expand" | ||
window/vsync/use_vsync=false | ||
|
||
[input] | ||
|
||
toggle_mouse_capture={ | ||
"deadzone": 0.5, | ||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"echo":false,"script":null) | ||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194341,"key_label":0,"unicode":0,"echo":false,"script":null) | ||
] | ||
} | ||
toggle_gui={ | ||
"deadzone": 0.5, | ||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"echo":false,"script":null) | ||
] | ||
} | ||
toggle_spheres={ | ||
"deadzone": 0.5, | ||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"echo":false,"script":null) | ||
] | ||
} | ||
increase_camera_fov={ | ||
"deadzone": 0.5, | ||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"echo":false,"script":null) | ||
] | ||
} | ||
decrease_camera_fov={ | ||
"deadzone": 0.5, | ||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null) | ||
] | ||
} | ||
|
||
[rendering] | ||
|
||
anti_aliasing/quality/msaa_3d=2 | ||
anti_aliasing/quality/use_debanding=true | ||
vram_compression/import_etc2=false |
Empty file.
Binary file not shown.
Oops, something went wrong.