Skip to content

Commit

Permalink
Merge pull request #23 from Maaack/shader-cache-refactor
Browse files Browse the repository at this point in the history
Shader cache refactor
  • Loading branch information
Maaack authored Feb 28, 2024
2 parents ffe1de5 + 9e0e470 commit 0efa3db
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 99 deletions.
2 changes: 1 addition & 1 deletion ATTRIBUTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
## Collaborators

### Godot Game Template
Author: [Marek Belski](https://github.com/Maaack)
Author: [Marek Belski and contributors](https://github.com/Maaack/Godot-Game-Template/graphs/contributors)
Source: [github: Godot-Game-Template](https://github.com/Maaack/Godot-Game-Template)
License: [MIT License](LICENSE.txt)

Expand Down
2 changes: 1 addition & 1 deletion ATTRIBUTION_example.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ Source: [git-scm.com](https://git-scm.com/downloads)
License: [GNU General Public License version 2](https://opensource.org/licenses/GPL-2.0)

#### Godot Game Template
Author: [Marek Belski](https://github.com/Maaack)
Author: [Marek Belski and contributors](https://github.com/Maaack/Godot-Game-Template/graphs/contributors)
Source: [github: Godot-Game-Template](https://github.com/Maaack/Godot-Game-Template)
License: [MIT License](LICENSE.txt)
2 changes: 1 addition & 1 deletion App/Scenes/Credits/Credits.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ text = "[center]
[font_size=48]Collaborators[/font_size]
[font_size=32]Godot Game Template[/font_size]
Author: [url=https://github.com/Maaack]Marek Belski[/url]
Author: [url=https://github.com/Maaack/Godot-Game-Template/graphs/contributors]Marek Belski and contributors[/url]
Source: [url=https://github.com/Maaack/Godot-Game-Template]github: Godot-Game-Template[/url]
License: [url=LICENSE.txt]MIT License[/url]
Expand Down
2 changes: 0 additions & 2 deletions App/Scenes/InitApp/InitApp.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ extends Node

@export_file("*.tscn") var _loading_screen : String
@export_file("*.tscn") var _next_scene : String
@export_file("*.tscn") var _game_scene : String
@export var _use_loading_screen : bool = false

func _load_next_scene():
Expand All @@ -15,5 +14,4 @@ func _ready():
AppLog.app_opened()
AppSettings.set_from_config_and_window(get_window())
SceneLoader.set_loading_screen(_loading_screen)
SceneLoader.set_main_game_scene_path(_game_scene)
call_deferred("_load_next_scene")
103 changes: 27 additions & 76 deletions App/Scenes/LoadingScreen/LoadingScreen.gd
Original file line number Diff line number Diff line change
@@ -1,103 +1,54 @@
class_name LoadingScreen
extends CanvasLayer

const LOADING_COMPLETE_TEXT = "Loading Complete!"
const LOADING_COMPLETE_TEXT_WAITING = "Any Moment Now..."
const LOADING_TEXT = "Loading..."
const LOADING_TEXT_WAITING = "Still Loading..."

const QUADMESH_PLACEHOLDER = preload("res://App/Scenes/LoadingScreen/QuadMeshPlaceholder.tscn")

enum StallStage{STARTED, WAITING, GIVE_UP}

@export_dir var _spatial_shader_material_dir : String = "res://Assets/Materials/"
@export var _cache_spatial_shader : bool = false

var _stall_stage : StallStage = StallStage.STARTED
var _loading_complete : bool = false
var _loading_progress : float = 0.0 :
var _scene_loading_complete : bool = false
var _scene_loading_progress : float = 0.0 :
set(value):
if value <= _loading_progress:
if value <= _scene_loading_progress:
return
_loading_progress = value
%ProgressBar.value = _loading_progress/2 + _caching_progress/2 \
if _cache_spatial_shader and SceneLoader.is_loading_main_game_scene() \
else _loading_progress
_scene_loading_progress = value
update_total_loading_progress()
_reset_loading_stage()

var _caching_progress : float = 0.0 :

var _changing_to_next_scene : bool = false
var _total_loading_progress : float = 0.0 :
set(value):
if value <= _caching_progress:
if value <= _total_loading_progress:
return
_caching_progress = value
%ProgressBar.value = _loading_progress/2 + _caching_progress/2 \
if _cache_spatial_shader and SceneLoader.is_loading_main_game_scene() \
else _loading_progress

var _changing_to_next_scene : bool = false
_total_loading_progress = value
%ProgressBar.value = _total_loading_progress

func update_total_loading_progress():
_total_loading_progress = _scene_loading_progress

func _reset_loading_stage():
_stall_stage = StallStage.STARTED
%LoadingTimer.start()

func _try_loading_next_scene():
if not _scene_loading_complete:
return
_load_next_scene()

func _load_next_scene():
if _changing_to_next_scene:
return
_changing_to_next_scene = true
if _cache_spatial_shader and SceneLoader.is_loading_main_game_scene():
_show_all_draw_passes_once()
else:
SceneLoader.change_scene_to_resource()

func _show_all_draw_passes_once():
var all_materials = _traverse_folders(_spatial_shader_material_dir)
var total_material_count = all_materials.size()
var cached_material_count = 0
for material_path in all_materials:
_load_material(material_path)
cached_material_count += 1
_caching_progress = float(cached_material_count) / total_material_count
_load_world_scene()

func _traverse_folders(dir_path:String) -> PackedStringArray:
var material_list:PackedStringArray = []
var dir = DirAccess.open(dir_path)
if not dir:
push_error("An error occurred when trying to access the path ", dir_path)
return []

if dir.list_dir_begin() != OK:
push_error("An error occurred when trying to access the path ", dir_path)
return []

var file_name = dir.get_next()
while file_name != "":
if not dir.current_is_dir():
if not file_name.ends_with(".import") and not file_name.ends_with(".png"):
material_list.append(dir_path + file_name)
else:
var subfolder_name = file_name
if subfolder_name != "." and subfolder_name != ".." and subfolder_name != "Noise":
material_list.append_array(_traverse_folders(dir_path + subfolder_name + "/"))
file_name = dir.get_next()

return material_list

func _load_material(path:String):
var material_shower = QUADMESH_PLACEHOLDER.instantiate()
var material := ResourceLoader.load(path) as Material
material_shower.set_surface_override_material(0, material)
%SpatialShaderTypeCaches.add_child(material_shower)

func _load_world_scene():
SceneLoader.change_scene_to_resource()
SceneLoader.call_deferred("change_scene_to_resource")

func _process(_delta):
if _loading_complete:
call_deferred("_load_next_scene")
_try_loading_next_scene()
var status = SceneLoader.get_status()
match(status):
ResourceLoader.THREAD_LOAD_IN_PROGRESS:
_loading_progress = SceneLoader.get_progress()
_scene_loading_progress = SceneLoader.get_progress()
match _stall_stage:
StallStage.STARTED:
%ErrorMessage.hide()
Expand All @@ -108,16 +59,16 @@ func _process(_delta):
StallStage.GIVE_UP:
if %ErrorMessage.visible:
return
if _loading_progress == 0:
if _scene_loading_progress == 0:
%ErrorMessage.dialog_text = "Loading Error: Failed to start."
if OS.has_feature("web"):
%ErrorMessage.dialog_text += "\nTry refreshing the page."
else:
%ErrorMessage.dialog_text = "Loading Error: Failed at %d%%." % (_loading_progress * 100.0)
%ErrorMessage.dialog_text = "Loading Error: Failed at %d%%." % (_scene_loading_progress * 100.0)
%ErrorMessage.popup_centered()
ResourceLoader.THREAD_LOAD_LOADED:
_loading_progress = 1.0
_loading_complete = true
_scene_loading_progress = 1.0
_scene_loading_complete = true
match _stall_stage:
StallStage.STARTED:
%ErrorMessage.hide()
Expand Down
8 changes: 0 additions & 8 deletions App/Scenes/LoadingScreen/LoadingScreen.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
process_mode = 3
layer = 20
script = ExtResource("1_gbk34")
_cache_spatial_shader = true

[node name="Control" type="Control" parent="."]
layout_mode = 3
Expand Down Expand Up @@ -53,12 +52,5 @@ wait_time = 10.0
one_shot = true
autostart = true

[node name="SpatialShaderTypeCaches" type="Node3D" parent="."]
unique_name_in_owner = true

[node name="Camera3D" type="Camera3D" parent="SpatialShaderTypeCaches"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1.408)
current = true

[connection signal="confirmed" from="Control/ErrorMessage" to="." method="_on_error_message_confirmed"]
[connection signal="timeout" from="LoadingTimer" to="." method="_on_loading_timer_timeout"]
11 changes: 2 additions & 9 deletions App/Scripts/SceneLoader.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ extends Node
signal scene_loaded

var _loading_screen : PackedScene
var _game_scene_path : String
var _scene_path : String
var _loaded_resource : Resource
var _background_loading : bool
Expand Down Expand Up @@ -54,14 +53,8 @@ func set_loading_screen(loading_screen_path : String) -> void:
return
_loading_screen = load(loading_screen_path)

func set_main_game_scene_path(main_game_scene_path : String) -> void:
if main_game_scene_path == "":
push_warning("game screen path is empty")
return
_game_scene_path = main_game_scene_path

func is_loading_main_game_scene() -> bool:
return _game_scene_path == _scene_path
func is_loading_scene(check_scene_path) -> bool:
return check_scene_path == _scene_path

func has_loading_screen() -> bool:
return _loading_screen != null
Expand Down
2 changes: 1 addition & 1 deletion Extras/Scenes/InitApp/InitApp.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
[ext_resource type="PackedScene" uid="uid://brp0f5m041sho" path="res://App/Scenes/InitApp/InitApp.tscn" id="1_jg7hl"]

[node name="InitApp" instance=ExtResource("1_jg7hl")]
_loading_screen = "res://Extras/Scenes/LoadingScreen/LoadingScreenWithShaderCaching.tscn"
_next_scene = "res://Extras/Scenes/Opening/Opening.tscn"
_game_scene = "res://Extras/Scenes/GameScene/GameUI.tscn"
86 changes: 86 additions & 0 deletions Extras/Scenes/LoadingScreen/LoadingScreenWithShaderCaching.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
extends LoadingScreen

const QUADMESH_PLACEHOLDER = preload("res://Extras/Scenes/LoadingScreen/QuadMeshPlaceholder.tscn")

@export_dir var _spatial_shader_material_dir : String
@export_file("*.tscn") var _cache_shaders_scene : String
@export_group("Advanced")
@export var _matching_extensions : Array[String] = [".tres", ".material", ".res"]
@export var _ignore_subfolders : Array[String] = [".", ".."]
@export var _shader_delay_timer : float = 0.1

var _loading_shader_cache : bool = false

var _caching_progress : float = 0.0 :
set(value):
if value <= _caching_progress:
return
_caching_progress = value
update_total_loading_progress()
_reset_loading_stage()

func can_load_shader_cache():
return not _spatial_shader_material_dir.is_empty() and \
not _cache_shaders_scene.is_empty() and \
SceneLoader.is_loading_scene(_cache_shaders_scene)

func update_total_loading_progress():
var partial_total = _scene_loading_progress
if can_load_shader_cache():
partial_total += _caching_progress
partial_total /= 2
_total_loading_progress = partial_total

func _try_loading_next_scene():
if can_load_shader_cache() and not _loading_shader_cache:
_loading_shader_cache = true
_show_all_draw_passes_once()
if can_load_shader_cache() and _caching_progress < 1.0:
return
super._try_loading_next_scene()

func _show_all_draw_passes_once():
var all_materials = _traverse_folders(_spatial_shader_material_dir)
var total_material_count = all_materials.size()
var cached_material_count = 0
for material_path in all_materials:
_load_material(material_path)
cached_material_count += 1
_caching_progress = float(cached_material_count) / total_material_count
if _shader_delay_timer > 0:
await(get_tree().create_timer(_shader_delay_timer).timeout)

func _traverse_folders(dir_path:String) -> PackedStringArray:
var material_list:PackedStringArray = []
if not dir_path.ends_with("/"):
dir_path += "/"
var dir = DirAccess.open(dir_path)
if not dir:
push_error("failed to access the path ", dir_path)
return []
if dir.list_dir_begin() != OK:
push_error("failed to access the path ", dir_path)
return []
var file_name = dir.get_next()
while file_name != "":
if not dir.current_is_dir():
var matches : bool = false
for extension in _matching_extensions:
if file_name.ends_with(extension):
matches = true
break
if matches:
material_list.append(dir_path + file_name)
else:
var subfolder_name = file_name
if not subfolder_name in _ignore_subfolders:
material_list.append_array(_traverse_folders(dir_path + subfolder_name))
file_name = dir.get_next()

return material_list

func _load_material(path:String):
var material_shower = QUADMESH_PLACEHOLDER.instantiate()
var material := ResourceLoader.load(path) as Material
material_shower.set_surface_override_material(0, material)
%SpatialShaderTypeCaches.add_child(material_shower)
19 changes: 19 additions & 0 deletions Extras/Scenes/LoadingScreen/LoadingScreenWithShaderCaching.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[gd_scene load_steps=3 format=3 uid="uid://geb2nqrjbxqt"]

[ext_resource type="PackedScene" uid="uid://cd0jbh4metflb" path="res://App/Scenes/LoadingScreen/LoadingScreen.tscn" id="1_87itf"]
[ext_resource type="Script" path="res://Extras/Scenes/LoadingScreen/LoadingScreenWithShaderCaching.gd" id="2_wgd8a"]

[node name="LoadingScreen" instance=ExtResource("1_87itf")]
script = ExtResource("2_wgd8a")
_spatial_shader_material_dir = "res://Extras/Materials"
_cache_shaders_scene = "res://Extras/Scenes/GameScene/GameUI.tscn"
_matching_extensions = Array[String]([".tres", ".material", ".res"])
_ignore_subfolders = Array[String]([".", ".."])
_shader_delay_timer = 0.1

[node name="SpatialShaderTypeCaches" type="Node3D" parent="." index="2"]
unique_name_in_owner = true

[node name="Camera3D" type="Camera3D" parent="SpatialShaderTypeCaches" index="0"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1.408)
current = true
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ The `Extras/` folder holds components that extend the core application.
- End Credits
- Level Advancement
- Logging Scripts
- Shader Pre-caching
- Additional Inherited Scenes from `App/`:
- `OptionsMenu.tscn`
- `MasterOptionsMenu.tscn`
- `MainMenu.tscn`
- `PauseMenu.tscn`
- `InitApp.tscn`
- `LoadingScreenWithShaderCaching.tscn`


### How it Works
Expand Down

0 comments on commit 0efa3db

Please sign in to comment.