123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- extends Control
- # Window project settings:
- # - Stretch mode is set to `canvas_items` (`2d` in Godot 3.x)
- # - Stretch aspect is set to `expand`
- @onready var world_environment := $WorldEnvironment
- @onready var directional_light := $Node3D/DirectionalLight3D
- @onready var camera := $Node3D/Camera3D
- @onready var fps_label := $FPSLabel
- @onready var resolution_label := $ResolutionLabel
- var counter := 0.0
- # When the screen changes size, we need to update the 3D
- # viewport quality setting. If we don't do this, the viewport will take
- # the size from the main viewport.
- var viewport_start_size := Vector2(
- ProjectSettings.get_setting(&"display/window/size/viewport_width"),
- ProjectSettings.get_setting(&"display/window/size/viewport_height")
- )
- func _ready() -> void:
- get_viewport().size_changed.connect(self.update_resolution_label)
- update_resolution_label()
- # Disable V-Sync to uncap framerate on supported platforms. This makes performance comparison
- # easier on high-end machines that easily reach the monitor's refresh rate.
- DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
- func _process(delta: float) -> void:
- counter += delta
- # Hide FPS label until it's initially updated by the engine (this can take up to 1 second).
- fps_label.visible = counter >= 1.0
- fps_label.text = "%d FPS (%.2f mspf)" % [Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second()]
- # Color FPS counter depending on framerate.
- # The Gradient resource is stored as metadata within the FPSLabel node (accessible in the inspector).
- fps_label.modulate = fps_label.get_meta("gradient").sample(remap(Engine.get_frames_per_second(), 0, 180, 0.0, 1.0))
- func update_resolution_label() -> void:
- var viewport_render_size = get_viewport().size * get_viewport().scaling_3d_scale
- resolution_label.text = "3D viewport resolution: %d × %d (%d%%)" \
- % [viewport_render_size.x, viewport_render_size.y, round(get_viewport().scaling_3d_scale * 100)]
- func _on_HideShowButton_toggled(show_settings: bool) -> void:
- # Option to hide the settings so you can see the changes to the 3d world better.
- var button := $HideShowButton
- var settings_menu := $SettingsMenu
- if show_settings:
- button.text = "Hide settings"
- else:
- button.text = "Show settings"
- settings_menu.visible = show_settings
- # Video settings.
- func _on_ui_scale_option_button_item_selected(index: int) -> void:
- # For changing the UI, we take the viewport size, which we set in the project settings.
- var new_size := viewport_start_size
- if index == 0: # Smaller (66%)
- new_size *= 1.5
- elif index == 1: # Small (80%)
- new_size *= 1.25
- elif index == 2: # Medium (100%) (default)
- new_size *= 1.0
- elif index == 3: # Large (133%)
- new_size *= 0.75
- elif index == 4: # Larger (200%)
- new_size *= 0.5
- get_tree().root.set_content_scale_size(new_size)
- func _on_quality_slider_value_changed(value: float) -> void:
- get_viewport().scaling_3d_scale = value
- update_resolution_label()
- func _on_filter_option_button_item_selected(index: int) -> void:
- # Viewport scale mode setting.
- if index == 0: # Bilinear (Fastest)
- get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR
- # FSR Sharpness is only effective when the scaling mode is FSR 1.0.
- %FSRSharpnessLabel.visible = false
- %FSRSharpnessSlider.visible = false
- elif index == 1: # FSR 1.0 (Fast)
- get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_FSR
- # FSR Sharpness is only effective when the scaling mode is FSR 1.0.
- %FSRSharpnessLabel.visible = true
- %FSRSharpnessSlider.visible = true
- func _on_fsr_sharpness_slider_value_changed(value: float) -> void:
- # Lower FSR sharpness values result in a sharper image.
- # Invert the slider so that higher values result in a sharper image,
- # which is generally expected from users.
- get_viewport().fsr_sharpness = 2.0 - value
- func _on_vsync_option_button_item_selected(index: int) -> void:
- # Vsync is enabled by default.
- # Vertical synchronization locks framerate and makes screen tearing not visible at the cost of
- # higher input latency and stuttering when the framerate target is not met.
- # Adaptive V-Sync automatically disables V-Sync when the framerate target is not met, and enables
- # V-Sync otherwise. This prevents suttering and reduces input latency when the framerate target
- # is not met, at the cost of visible tearing.
- if index == 0: # Disabled (default)
- DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
- elif index == 1: # Adaptive
- DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ADAPTIVE)
- elif index == 2: # Enabled
- DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
- func _on_limit_fps_slider_value_changed(value: float):
- # The maximum number of frames per second that can be rendered.
- # A value of 0 means "no limit".
- Engine.max_fps = value
- func _on_msaa_option_button_item_selected(index: int) -> void:
- # Multi-sample anti-aliasing. High quality, but slow. It also does not smooth out the edges of
- # transparent (alpha scissor) textures.
- if index == 0: # Disabled (default)
- get_viewport().msaa_3d = Viewport.MSAA_DISABLED
- elif index == 1: # 2×
- get_viewport().msaa_3d = Viewport.MSAA_2X
- elif index == 2: # 4×
- get_viewport().msaa_3d = Viewport.MSAA_4X
- elif index == 3: # 8×
- get_viewport().msaa_3d = Viewport.MSAA_8X
- func _on_taa_option_button_item_selected(index: int) -> void:
- # Temporal antialiasing. Smooths out everything including specular aliasing, but can introduce
- # ghosting artifacts and blurring in motion. Moderate performance cost.
- get_viewport().use_taa = index == 1
- func _on_fxaa_option_button_item_selected(index: int) -> void:
- # Fast approximate anti-aliasing. Much faster than MSAA (and works on alpha scissor edges),
- # but blurs the whole scene rendering slightly.
- get_viewport().screen_space_aa = int(index == 1) as Viewport.ScreenSpaceAA
- func _on_fullscreen_option_button_item_selected(index: int) -> void:
- # To change between winow, fullscreen and other window modes,
- # set the root mode to one of the options of Window.MODE_*.
- # Other modes are maximized and minimized.
- if index == 0: # Disabled (default)
- get_tree().root.set_mode(Window.MODE_WINDOWED)
- elif index == 1: # Fullscreen
- get_tree().root.set_mode(Window.MODE_FULLSCREEN)
- elif index == 2: # Exclusive Fullscreen
- get_tree().root.set_mode(Window.MODE_EXCLUSIVE_FULLSCREEN)
- func _on_fov_slider_value_changed(value: float) -> void:
- camera.fov = value
- # Quality settings.
- func _on_shadow_size_option_button_item_selected(index):
- if index == 0: # Minimum
- RenderingServer.directional_shadow_atlas_set_size(512, true)
- # Adjust shadow bias according to shadow resolution.
- # Higher resultions can use a lower bias without suffering from shadow acne.
- directional_light.shadow_bias = 0.06
- # Disable positional (omni/spot) light shadows entirely to further improve performance.
- # These often don't contribute as much to a scene compared to directional light shadows.
- get_viewport().positional_shadow_atlas_size = 0
- if index == 1: # Very Low
- RenderingServer.directional_shadow_atlas_set_size(1024, true)
- directional_light.shadow_bias = 0.04
- get_viewport().positional_shadow_atlas_size = 1024
- if index == 2: # Low
- RenderingServer.directional_shadow_atlas_set_size(2048, true)
- directional_light.shadow_bias = 0.03
- get_viewport().positional_shadow_atlas_size = 2048
- if index == 3: # Medium (default)
- RenderingServer.directional_shadow_atlas_set_size(4096, true)
- directional_light.shadow_bias = 0.02
- get_viewport().positional_shadow_atlas_size = 4096
- if index == 4: # High
- RenderingServer.directional_shadow_atlas_set_size(8192, true)
- directional_light.shadow_bias = 0.01
- get_viewport().positional_shadow_atlas_size = 8192
- if index == 5: # Ultra
- RenderingServer.directional_shadow_atlas_set_size(16384, true)
- directional_light.shadow_bias = 0.005
- get_viewport().positional_shadow_atlas_size = 16384
- func _on_shadow_filter_option_button_item_selected(index):
- if index == 0: # Very Low
- RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_HARD)
- RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_HARD)
- if index == 1: # Low
- RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_VERY_LOW)
- RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_VERY_LOW)
- if index == 2: # Medium (default)
- RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_LOW)
- RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_LOW)
- if index == 3: # High
- RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_MEDIUM)
- RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_MEDIUM)
- if index == 4: # Very High
- RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_HIGH)
- RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_HIGH)
- if index == 5: # Ultra
- RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_ULTRA)
- RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_ULTRA)
- func _on_mesh_lod_option_button_item_selected(index):
- if index == 0: # Very Low
- get_viewport().mesh_lod_threshold = 8.0
- if index == 0: # Low
- get_viewport().mesh_lod_threshold = 4.0
- if index == 1: # Medium
- get_viewport().mesh_lod_threshold = 2.0
- if index == 2: # High (default)
- get_viewport().mesh_lod_threshold = 1.0
- if index == 3: # Ultra
- # Always use highest LODs to avoid any form of pop-in.
- get_viewport().mesh_lod_threshold = 0.0
- # Effect settings.
- func _on_ss_reflections_option_button_item_selected(index: int) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- if index == 0: # Disabled (default)
- world_environment.environment.set_ssr_enabled(false)
- elif index == 1: # Low
- world_environment.environment.set_ssr_enabled(true)
- world_environment.environment.set_ssr_max_steps(8)
- elif index == 2: # Medium
- world_environment.environment.set_ssr_enabled(true)
- world_environment.environment.set_ssr_max_steps(32)
- elif index == 3: # High
- world_environment.environment.set_ssr_enabled(true)
- world_environment.environment.set_ssr_max_steps(56)
- func _on_ssao_option_button_item_selected(index: int) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- if index == 0: # Disabled (default)
- world_environment.environment.ssao_enabled = false
- if index == 1: # Very Low
- world_environment.environment.ssao_enabled = true
- RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_VERY_LOW, true, 0.5, 2, 50, 300)
- if index == 2: # Low
- world_environment.environment.ssao_enabled = true
- RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_VERY_LOW, true, 0.5, 2, 50, 300)
- if index == 3: # Medium
- world_environment.environment.ssao_enabled = true
- RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_MEDIUM, true, 0.5, 2, 50, 300)
- if index == 4: # High
- world_environment.environment.ssao_enabled = true
- RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_HIGH, true, 0.5, 2, 50, 300)
- func _on_ssil_option_button_item_selected(index: int) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- if index == 0: # Disabled (default)
- world_environment.environment.ssil_enabled = false
- if index == 1: # Very Low
- world_environment.environment.ssil_enabled = true
- RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_VERY_LOW, true, 0.5, 4, 50, 300)
- if index == 2: # Low
- world_environment.environment.ssil_enabled = true
- RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_LOW, true, 0.5, 4, 50, 300)
- if index == 3: # Medium
- world_environment.environment.ssil_enabled = true
- RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_MEDIUM, true, 0.5, 4, 50, 300)
- if index == 4: # High
- world_environment.environment.ssil_enabled = true
- RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_HIGH, true, 0.5, 4, 50, 300)
- func _on_sdfgi_option_button_item_selected(index: int) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- if index == 0: # Disabled (default)
- world_environment.environment.sdfgi_enabled = false
- if index == 1: # Low
- world_environment.environment.sdfgi_enabled = true
- RenderingServer.gi_set_use_half_resolution(true)
- if index == 2: # High
- world_environment.environment.sdfgi_enabled = true
- RenderingServer.gi_set_use_half_resolution(false)
- func _on_glow_option_button_item_selected(index: int) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- if index == 0: # Disabled (default)
- world_environment.environment.glow_enabled = false
- if index == 1: # Low
- world_environment.environment.glow_enabled = true
- if index == 2: # High
- world_environment.environment.glow_enabled = true
- func _on_volumetric_fog_option_button_item_selected(index: int) -> void:
- if index == 0: # Disabled (default)
- world_environment.environment.volumetric_fog_enabled = false
- if index == 1: # Low
- world_environment.environment.volumetric_fog_enabled = true
- RenderingServer.environment_set_volumetric_fog_filter_active(false)
- if index == 2: # High
- world_environment.environment.volumetric_fog_enabled = true
- RenderingServer.environment_set_volumetric_fog_filter_active(true)
- # Adjustment settings.
- func _on_brightness_slider_value_changed(value: float) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- # The slider value is clamped between 0.5 and 4.
- world_environment.environment.set_adjustment_brightness(value)
- func _on_contrast_slider_value_changed(value: float) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- # The slider value is clamped between 0.5 and 4.
- world_environment.environment.set_adjustment_contrast(value)
- func _on_saturation_slider_value_changed(value: float) -> void:
- # This is a setting that is attached to the environment.
- # If your game requires you to change the environment,
- # then be sure to run this function again to make the setting effective.
- # The slider value is clamped between 0.5 and 10.
- world_environment.environment.set_adjustment_saturation(value)
- # Quality presets.
- func _on_very_low_preset_pressed() -> void:
- %TAAOptionButton.selected = 0
- %MSAAOptionButton.selected = 0
- %FXAAOptionButton.selected = 0
- %ShadowSizeOptionButton.selected = 0
- %ShadowFilterOptionButton.selected = 0
- %MeshLODOptionButton.selected = 0
- %SDFGIOptionButton.selected = 0
- %GlowOptionButton.selected = 0
- %SSAOOptionButton.selected = 0
- %SSReflectionsOptionButton.selected = 0
- %SSILOptionButton.selected = 0
- %VolumetricFogOptionButton.selected = 0
- update_preset()
- func _on_low_preset_pressed() -> void:
- %TAAOptionButton.selected = 0
- %MSAAOptionButton.selected = 0
- %FXAAOptionButton.selected = 1
- %ShadowSizeOptionButton.selected = 1
- %ShadowFilterOptionButton.selected = 1
- %MeshLODOptionButton.selected = 1
- %SDFGIOptionButton.selected = 0
- %GlowOptionButton.selected = 0
- %SSAOOptionButton.selected = 0
- %SSReflectionsOptionButton.selected = 0
- %SSILOptionButton.selected = 0
- %VolumetricFogOptionButton.selected = 0
- update_preset()
- func _on_medium_preset_pressed() -> void:
- %TAAOptionButton.selected = 1
- %MSAAOptionButton.selected = 0
- %FXAAOptionButton.selected = 0
- %ShadowSizeOptionButton.selected = 2
- %ShadowFilterOptionButton.selected = 2
- %MeshLODOptionButton.selected = 1
- %SDFGIOptionButton.selected = 1
- %GlowOptionButton.selected = 1
- %SSAOOptionButton.selected = 1
- %SSReflectionsOptionButton.selected = 1
- %SSILOptionButton.selected = 0
- %VolumetricFogOptionButton.selected = 1
- update_preset()
- func _on_high_preset_pressed() -> void:
- %TAAOptionButton.selected = 1
- %MSAAOptionButton.selected = 0
- %FXAAOptionButton.selected = 0
- %ShadowSizeOptionButton.selected = 3
- %ShadowFilterOptionButton.selected = 3
- %MeshLODOptionButton.selected = 2
- %SDFGIOptionButton.selected = 1
- %GlowOptionButton.selected = 2
- %SSAOOptionButton.selected = 2
- %SSReflectionsOptionButton.selected = 2
- %SSILOptionButton.selected = 2
- %VolumetricFogOptionButton.selected = 2
- update_preset()
- func _on_ultra_preset_pressed() -> void:
- %TAAOptionButton.selected = 1
- %MSAAOptionButton.selected = 1
- %FXAAOptionButton.selected = 0
- %ShadowSizeOptionButton.selected = 4
- %ShadowFilterOptionButton.selected = 4
- %MeshLODOptionButton.selected = 3
- %SDFGIOptionButton.selected = 2
- %GlowOptionButton.selected = 2
- %SSAOOptionButton.selected = 3
- %SSReflectionsOptionButton.selected = 3
- %SSILOptionButton.selected = 3
- %VolumetricFogOptionButton.selected = 2
- update_preset()
- func update_preset() -> void:
- # Simulate options being manually selected to run their respective update code.
- %TAAOptionButton.item_selected.emit(%TAAOptionButton.selected)
- %MSAAOptionButton.item_selected.emit(%MSAAOptionButton.selected)
- %FXAAOptionButton.item_selected.emit(%FXAAOptionButton.selected)
- %ShadowSizeOptionButton.item_selected.emit(%ShadowSizeOptionButton.selected)
- %ShadowFilterOptionButton.item_selected.emit(%ShadowFilterOptionButton.selected)
- %MeshLODOptionButton.item_selected.emit(%MeshLODOptionButton.selected)
- %SDFGIOptionButton.item_selected.emit(%SDFGIOptionButton.selected)
- %GlowOptionButton.item_selected.emit(%GlowOptionButton.selected)
- %SSAOOptionButton.item_selected.emit(%SSAOOptionButton.selected)
- %SSReflectionsOptionButton.item_selected.emit(%SSReflectionsOptionButton.selected)
- %SSILOptionButton.item_selected.emit(%SSILOptionButton.selected)
- %VolumetricFogOptionButton.item_selected.emit(%VolumetricFogOptionButton.selected)
|