settings.gd 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. extends Control
  2. # Window project settings:
  3. # - Stretch mode is set to `canvas_items` (`2d` in Godot 3.x)
  4. # - Stretch aspect is set to `expand`
  5. @onready var world_environment := $WorldEnvironment
  6. @onready var directional_light := $Node3D/DirectionalLight3D
  7. @onready var camera := $Node3D/Camera3D
  8. @onready var fps_label := $FPSLabel
  9. @onready var resolution_label := $ResolutionLabel
  10. var counter := 0.0
  11. # When the screen changes size, we need to update the 3D
  12. # viewport quality setting. If we don't do this, the viewport will take
  13. # the size from the main viewport.
  14. var viewport_start_size := Vector2(
  15. ProjectSettings.get_setting(&"display/window/size/viewport_width"),
  16. ProjectSettings.get_setting(&"display/window/size/viewport_height")
  17. )
  18. func _ready() -> void:
  19. get_viewport().size_changed.connect(update_resolution_label)
  20. update_resolution_label()
  21. # Disable V-Sync to uncap framerate on supported platforms. This makes performance comparison
  22. # easier on high-end machines that easily reach the monitor's refresh rate.
  23. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
  24. func _process(delta: float) -> void:
  25. counter += delta
  26. # Hide FPS label until it's initially updated by the engine (this can take up to 1 second).
  27. fps_label.visible = counter >= 1.0
  28. fps_label.text = "%d FPS (%.2f mspf)" % [Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second()]
  29. # Color FPS counter depending on framerate.
  30. # The Gradient resource is stored as metadata within the FPSLabel node (accessible in the inspector).
  31. fps_label.modulate = fps_label.get_meta("gradient").sample(remap(Engine.get_frames_per_second(), 0, 180, 0.0, 1.0))
  32. func update_resolution_label() -> void:
  33. var viewport_render_size = get_viewport().size * get_viewport().scaling_3d_scale
  34. resolution_label.text = "3D viewport resolution: %d × %d (%d%%)" \
  35. % [viewport_render_size.x, viewport_render_size.y, round(get_viewport().scaling_3d_scale * 100)]
  36. func _on_HideShowButton_toggled(show_settings: bool) -> void:
  37. # Option to hide the settings so you can see the changes to the 3d world better.
  38. var button := $HideShowButton
  39. var settings_menu := $SettingsMenu
  40. if show_settings:
  41. button.text = "Hide settings"
  42. else:
  43. button.text = "Show settings"
  44. settings_menu.visible = show_settings
  45. # Video settings.
  46. func _on_ui_scale_option_button_item_selected(index: int) -> void:
  47. # For changing the UI, we take the viewport size, which we set in the project settings.
  48. var new_size := viewport_start_size
  49. if index == 0: # Smaller (66%)
  50. new_size *= 1.5
  51. elif index == 1: # Small (80%)
  52. new_size *= 1.25
  53. elif index == 2: # Medium (100%) (default)
  54. new_size *= 1.0
  55. elif index == 3: # Large (133%)
  56. new_size *= 0.75
  57. elif index == 4: # Larger (200%)
  58. new_size *= 0.5
  59. get_tree().root.set_content_scale_size(new_size)
  60. func _on_quality_slider_value_changed(value: float) -> void:
  61. get_viewport().scaling_3d_scale = value
  62. update_resolution_label()
  63. func _on_filter_option_button_item_selected(index: int) -> void:
  64. # Viewport scale mode setting.
  65. if index == 0: # Bilinear (Fastest)
  66. get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR
  67. # FSR Sharpness is only effective when the scaling mode is FSR 1.0 or 2.2.
  68. %FSRSharpnessLabel.visible = false
  69. %FSRSharpnessSlider.visible = false
  70. elif index == 1: # FSR 1.0 (Fast)
  71. get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_FSR
  72. # FSR Sharpness is only effective when the scaling mode is FSR 1.0 or 2.2.
  73. %FSRSharpnessLabel.visible = true
  74. %FSRSharpnessSlider.visible = true
  75. elif index == 2: # FSR 2.2 (Fast)
  76. get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_FSR2
  77. # FSR Sharpness is only effective when the scaling mode is FSR 1.0 or 2.2.
  78. %FSRSharpnessLabel.visible = true
  79. %FSRSharpnessSlider.visible = true
  80. func _on_fsr_sharpness_slider_value_changed(value: float) -> void:
  81. # Lower FSR sharpness values result in a sharper image.
  82. # Invert the slider so that higher values result in a sharper image,
  83. # which is generally expected from users.
  84. get_viewport().fsr_sharpness = 2.0 - value
  85. func _on_vsync_option_button_item_selected(index: int) -> void:
  86. # Vsync is enabled by default.
  87. # Vertical synchronization locks framerate and makes screen tearing not visible at the cost of
  88. # higher input latency and stuttering when the framerate target is not met.
  89. # Adaptive V-Sync automatically disables V-Sync when the framerate target is not met, and enables
  90. # V-Sync otherwise. This prevents suttering and reduces input latency when the framerate target
  91. # is not met, at the cost of visible tearing.
  92. if index == 0: # Disabled (default)
  93. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
  94. elif index == 1: # Adaptive
  95. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ADAPTIVE)
  96. elif index == 2: # Enabled
  97. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
  98. func _on_limit_fps_slider_value_changed(value: float):
  99. # The maximum number of frames per second that can be rendered.
  100. # A value of 0 means "no limit".
  101. Engine.max_fps = value
  102. func _on_msaa_option_button_item_selected(index: int) -> void:
  103. # Multi-sample anti-aliasing. High quality, but slow. It also does not smooth out the edges of
  104. # transparent (alpha scissor) textures.
  105. if index == 0: # Disabled (default)
  106. get_viewport().msaa_3d = Viewport.MSAA_DISABLED
  107. elif index == 1: # 2×
  108. get_viewport().msaa_3d = Viewport.MSAA_2X
  109. elif index == 2: # 4×
  110. get_viewport().msaa_3d = Viewport.MSAA_4X
  111. elif index == 3: # 8×
  112. get_viewport().msaa_3d = Viewport.MSAA_8X
  113. func _on_taa_option_button_item_selected(index: int) -> void:
  114. # Temporal antialiasing. Smooths out everything including specular aliasing, but can introduce
  115. # ghosting artifacts and blurring in motion. Moderate performance cost.
  116. get_viewport().use_taa = index == 1
  117. func _on_fxaa_option_button_item_selected(index: int) -> void:
  118. # Fast approximate anti-aliasing. Much faster than MSAA (and works on alpha scissor edges),
  119. # but blurs the whole scene rendering slightly.
  120. get_viewport().screen_space_aa = int(index == 1) as Viewport.ScreenSpaceAA
  121. func _on_fullscreen_option_button_item_selected(index: int) -> void:
  122. # To change between winow, fullscreen and other window modes,
  123. # set the root mode to one of the options of Window.MODE_*.
  124. # Other modes are maximized and minimized.
  125. if index == 0: # Disabled (default)
  126. get_tree().root.set_mode(Window.MODE_WINDOWED)
  127. elif index == 1: # Fullscreen
  128. get_tree().root.set_mode(Window.MODE_FULLSCREEN)
  129. elif index == 2: # Exclusive Fullscreen
  130. get_tree().root.set_mode(Window.MODE_EXCLUSIVE_FULLSCREEN)
  131. func _on_fov_slider_value_changed(value: float) -> void:
  132. camera.fov = value
  133. # Quality settings.
  134. func _on_shadow_size_option_button_item_selected(index):
  135. if index == 0: # Minimum
  136. RenderingServer.directional_shadow_atlas_set_size(512, true)
  137. # Adjust shadow bias according to shadow resolution.
  138. # Higher resultions can use a lower bias without suffering from shadow acne.
  139. directional_light.shadow_bias = 0.06
  140. # Disable positional (omni/spot) light shadows entirely to further improve performance.
  141. # These often don't contribute as much to a scene compared to directional light shadows.
  142. get_viewport().positional_shadow_atlas_size = 0
  143. if index == 1: # Very Low
  144. RenderingServer.directional_shadow_atlas_set_size(1024, true)
  145. directional_light.shadow_bias = 0.04
  146. get_viewport().positional_shadow_atlas_size = 1024
  147. if index == 2: # Low
  148. RenderingServer.directional_shadow_atlas_set_size(2048, true)
  149. directional_light.shadow_bias = 0.03
  150. get_viewport().positional_shadow_atlas_size = 2048
  151. if index == 3: # Medium (default)
  152. RenderingServer.directional_shadow_atlas_set_size(4096, true)
  153. directional_light.shadow_bias = 0.02
  154. get_viewport().positional_shadow_atlas_size = 4096
  155. if index == 4: # High
  156. RenderingServer.directional_shadow_atlas_set_size(8192, true)
  157. directional_light.shadow_bias = 0.01
  158. get_viewport().positional_shadow_atlas_size = 8192
  159. if index == 5: # Ultra
  160. RenderingServer.directional_shadow_atlas_set_size(16384, true)
  161. directional_light.shadow_bias = 0.005
  162. get_viewport().positional_shadow_atlas_size = 16384
  163. func _on_shadow_filter_option_button_item_selected(index):
  164. if index == 0: # Very Low
  165. RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_HARD)
  166. RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_HARD)
  167. if index == 1: # Low
  168. RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_VERY_LOW)
  169. RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_VERY_LOW)
  170. if index == 2: # Medium (default)
  171. RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_LOW)
  172. RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_LOW)
  173. if index == 3: # High
  174. RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_MEDIUM)
  175. RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_MEDIUM)
  176. if index == 4: # Very High
  177. RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_HIGH)
  178. RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_HIGH)
  179. if index == 5: # Ultra
  180. RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_ULTRA)
  181. RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_ULTRA)
  182. func _on_mesh_lod_option_button_item_selected(index):
  183. if index == 0: # Very Low
  184. get_viewport().mesh_lod_threshold = 8.0
  185. if index == 0: # Low
  186. get_viewport().mesh_lod_threshold = 4.0
  187. if index == 1: # Medium
  188. get_viewport().mesh_lod_threshold = 2.0
  189. if index == 2: # High (default)
  190. get_viewport().mesh_lod_threshold = 1.0
  191. if index == 3: # Ultra
  192. # Always use highest LODs to avoid any form of pop-in.
  193. get_viewport().mesh_lod_threshold = 0.0
  194. # Effect settings.
  195. func _on_ss_reflections_option_button_item_selected(index: int) -> void:
  196. # This is a setting that is attached to the environment.
  197. # If your game requires you to change the environment,
  198. # then be sure to run this function again to make the setting effective.
  199. if index == 0: # Disabled (default)
  200. world_environment.environment.set_ssr_enabled(false)
  201. elif index == 1: # Low
  202. world_environment.environment.set_ssr_enabled(true)
  203. world_environment.environment.set_ssr_max_steps(8)
  204. elif index == 2: # Medium
  205. world_environment.environment.set_ssr_enabled(true)
  206. world_environment.environment.set_ssr_max_steps(32)
  207. elif index == 3: # High
  208. world_environment.environment.set_ssr_enabled(true)
  209. world_environment.environment.set_ssr_max_steps(56)
  210. func _on_ssao_option_button_item_selected(index: int) -> void:
  211. # This is a setting that is attached to the environment.
  212. # If your game requires you to change the environment,
  213. # then be sure to run this function again to make the setting effective.
  214. if index == 0: # Disabled (default)
  215. world_environment.environment.ssao_enabled = false
  216. if index == 1: # Very Low
  217. world_environment.environment.ssao_enabled = true
  218. RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_VERY_LOW, true, 0.5, 2, 50, 300)
  219. if index == 2: # Low
  220. world_environment.environment.ssao_enabled = true
  221. RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_LOW, true, 0.5, 2, 50, 300)
  222. if index == 3: # Medium
  223. world_environment.environment.ssao_enabled = true
  224. RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_MEDIUM, true, 0.5, 2, 50, 300)
  225. if index == 4: # High
  226. world_environment.environment.ssao_enabled = true
  227. RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_HIGH, true, 0.5, 2, 50, 300)
  228. if index == 5: # Ultra
  229. world_environment.environment.ssao_enabled = true
  230. RenderingServer.environment_set_ssao_quality(RenderingServer.ENV_SSAO_QUALITY_ULTRA, true, 0.5, 2, 50, 300)
  231. func _on_ssil_option_button_item_selected(index: int) -> void:
  232. # This is a setting that is attached to the environment.
  233. # If your game requires you to change the environment,
  234. # then be sure to run this function again to make the setting effective.
  235. if index == 0: # Disabled (default)
  236. world_environment.environment.ssil_enabled = false
  237. if index == 1: # Very Low
  238. world_environment.environment.ssil_enabled = true
  239. RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_VERY_LOW, true, 0.5, 4, 50, 300)
  240. if index == 2: # Low
  241. world_environment.environment.ssil_enabled = true
  242. RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_LOW, true, 0.5, 4, 50, 300)
  243. if index == 3: # Medium
  244. world_environment.environment.ssil_enabled = true
  245. RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_MEDIUM, true, 0.5, 4, 50, 300)
  246. if index == 4: # High
  247. world_environment.environment.ssil_enabled = true
  248. RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_HIGH, true, 0.5, 4, 50, 300)
  249. if index == 5: # Ultra
  250. world_environment.environment.ssil_enabled = true
  251. RenderingServer.environment_set_ssil_quality(RenderingServer.ENV_SSIL_QUALITY_ULTRA, true, 0.5, 4, 50, 300)
  252. func _on_sdfgi_option_button_item_selected(index: int) -> void:
  253. # This is a setting that is attached to the environment.
  254. # If your game requires you to change the environment,
  255. # then be sure to run this function again to make the setting effective.
  256. if index == 0: # Disabled (default)
  257. world_environment.environment.sdfgi_enabled = false
  258. if index == 1: # Low
  259. world_environment.environment.sdfgi_enabled = true
  260. RenderingServer.gi_set_use_half_resolution(true)
  261. if index == 2: # High
  262. world_environment.environment.sdfgi_enabled = true
  263. RenderingServer.gi_set_use_half_resolution(false)
  264. func _on_glow_option_button_item_selected(index: int) -> void:
  265. # This is a setting that is attached to the environment.
  266. # If your game requires you to change the environment,
  267. # then be sure to run this function again to make the setting effective.
  268. if index == 0: # Disabled (default)
  269. world_environment.environment.glow_enabled = false
  270. if index == 1: # Low
  271. world_environment.environment.glow_enabled = true
  272. RenderingServer.environment_glow_set_use_bicubic_upscale(false)
  273. if index == 2: # High
  274. world_environment.environment.glow_enabled = true
  275. RenderingServer.environment_glow_set_use_bicubic_upscale(true)
  276. func _on_volumetric_fog_option_button_item_selected(index: int) -> void:
  277. if index == 0: # Disabled (default)
  278. world_environment.environment.volumetric_fog_enabled = false
  279. if index == 1: # Low
  280. world_environment.environment.volumetric_fog_enabled = true
  281. RenderingServer.environment_set_volumetric_fog_filter_active(false)
  282. if index == 2: # High
  283. world_environment.environment.volumetric_fog_enabled = true
  284. RenderingServer.environment_set_volumetric_fog_filter_active(true)
  285. # Adjustment settings.
  286. func _on_brightness_slider_value_changed(value: float) -> void:
  287. # This is a setting that is attached to the environment.
  288. # If your game requires you to change the environment,
  289. # then be sure to run this function again to make the setting effective.
  290. # The slider value is clamped between 0.5 and 4.
  291. world_environment.environment.set_adjustment_brightness(value)
  292. func _on_contrast_slider_value_changed(value: float) -> void:
  293. # This is a setting that is attached to the environment.
  294. # If your game requires you to change the environment,
  295. # then be sure to run this function again to make the setting effective.
  296. # The slider value is clamped between 0.5 and 4.
  297. world_environment.environment.set_adjustment_contrast(value)
  298. func _on_saturation_slider_value_changed(value: float) -> void:
  299. # This is a setting that is attached to the environment.
  300. # If your game requires you to change the environment,
  301. # then be sure to run this function again to make the setting effective.
  302. # The slider value is clamped between 0.5 and 10.
  303. world_environment.environment.set_adjustment_saturation(value)
  304. # Quality presets.
  305. func _on_very_low_preset_pressed() -> void:
  306. %TAAOptionButton.selected = 0
  307. %MSAAOptionButton.selected = 0
  308. %FXAAOptionButton.selected = 0
  309. %ShadowSizeOptionButton.selected = 0
  310. %ShadowFilterOptionButton.selected = 0
  311. %MeshLODOptionButton.selected = 0
  312. %SDFGIOptionButton.selected = 0
  313. %GlowOptionButton.selected = 0
  314. %SSAOOptionButton.selected = 0
  315. %SSReflectionsOptionButton.selected = 0
  316. %SSILOptionButton.selected = 0
  317. %VolumetricFogOptionButton.selected = 0
  318. update_preset()
  319. func _on_low_preset_pressed() -> void:
  320. %TAAOptionButton.selected = 0
  321. %MSAAOptionButton.selected = 0
  322. %FXAAOptionButton.selected = 1
  323. %ShadowSizeOptionButton.selected = 1
  324. %ShadowFilterOptionButton.selected = 1
  325. %MeshLODOptionButton.selected = 1
  326. %SDFGIOptionButton.selected = 0
  327. %GlowOptionButton.selected = 0
  328. %SSAOOptionButton.selected = 0
  329. %SSReflectionsOptionButton.selected = 0
  330. %SSILOptionButton.selected = 0
  331. %VolumetricFogOptionButton.selected = 0
  332. update_preset()
  333. func _on_medium_preset_pressed() -> void:
  334. %TAAOptionButton.selected = 1
  335. %MSAAOptionButton.selected = 0
  336. %FXAAOptionButton.selected = 0
  337. %ShadowSizeOptionButton.selected = 2
  338. %ShadowFilterOptionButton.selected = 2
  339. %MeshLODOptionButton.selected = 1
  340. %SDFGIOptionButton.selected = 1
  341. %GlowOptionButton.selected = 1
  342. %SSAOOptionButton.selected = 1
  343. %SSReflectionsOptionButton.selected = 1
  344. %SSILOptionButton.selected = 0
  345. %VolumetricFogOptionButton.selected = 1
  346. update_preset()
  347. func _on_high_preset_pressed() -> void:
  348. %TAAOptionButton.selected = 1
  349. %MSAAOptionButton.selected = 0
  350. %FXAAOptionButton.selected = 0
  351. %ShadowSizeOptionButton.selected = 3
  352. %ShadowFilterOptionButton.selected = 3
  353. %MeshLODOptionButton.selected = 2
  354. %SDFGIOptionButton.selected = 1
  355. %GlowOptionButton.selected = 2
  356. %SSAOOptionButton.selected = 2
  357. %SSReflectionsOptionButton.selected = 2
  358. %SSILOptionButton.selected = 2
  359. %VolumetricFogOptionButton.selected = 2
  360. update_preset()
  361. func _on_ultra_preset_pressed() -> void:
  362. %TAAOptionButton.selected = 1
  363. %MSAAOptionButton.selected = 1
  364. %FXAAOptionButton.selected = 0
  365. %ShadowSizeOptionButton.selected = 4
  366. %ShadowFilterOptionButton.selected = 4
  367. %MeshLODOptionButton.selected = 3
  368. %SDFGIOptionButton.selected = 2
  369. %GlowOptionButton.selected = 2
  370. %SSAOOptionButton.selected = 3
  371. %SSReflectionsOptionButton.selected = 3
  372. %SSILOptionButton.selected = 3
  373. %VolumetricFogOptionButton.selected = 2
  374. update_preset()
  375. func update_preset() -> void:
  376. # Simulate options being manually selected to run their respective update code.
  377. %TAAOptionButton.item_selected.emit(%TAAOptionButton.selected)
  378. %MSAAOptionButton.item_selected.emit(%MSAAOptionButton.selected)
  379. %FXAAOptionButton.item_selected.emit(%FXAAOptionButton.selected)
  380. %ShadowSizeOptionButton.item_selected.emit(%ShadowSizeOptionButton.selected)
  381. %ShadowFilterOptionButton.item_selected.emit(%ShadowFilterOptionButton.selected)
  382. %MeshLODOptionButton.item_selected.emit(%MeshLODOptionButton.selected)
  383. %SDFGIOptionButton.item_selected.emit(%SDFGIOptionButton.selected)
  384. %GlowOptionButton.item_selected.emit(%GlowOptionButton.selected)
  385. %SSAOOptionButton.item_selected.emit(%SSAOOptionButton.selected)
  386. %SSReflectionsOptionButton.item_selected.emit(%SSReflectionsOptionButton.selected)
  387. %SSILOptionButton.item_selected.emit(%SSILOptionButton.selected)
  388. %VolumetricFogOptionButton.item_selected.emit(%VolumetricFogOptionButton.selected)