From 92921487211bf1cf859027fedf076afafb43215e Mon Sep 17 00:00:00 2001 From: Akio Gaule <10719597+akioCL@users.noreply.github.com> Date: Thu, 2 May 2024 22:51:58 -0400 Subject: [PATCH] Add exponential and exponential squared fog modes (#17866) Add density clamp to deferred fog Add tests for new attributes of deferred fog Signed-off-by: Akio Gaule <10719597+akioCL@users.noreply.github.com> --- .../Atom/atom_utils/atom_constants.py | 37 +- ...a_AtomEditorComponents_DeferredFogAdded.py | 397 ++++++++++-------- .../Shaders/ScreenSpace/DeferredFog.azsl | 25 +- .../Feature/ScreenSpace/DeferredFogParams.inl | 4 + .../DeferredFogSettingsInterface.h | 9 + .../Source/ScreenSpace/DeferredFogPass.cpp | 17 + .../Code/Source/ScreenSpace/DeferredFogPass.h | 3 + .../ScreenSpace/DeferredFogBus.h | 1 + .../ScreenSpace/DeferredFogComponentConfig.h | 9 + .../EditorDeferredFogComponent.cpp | 66 ++- 10 files changed, 369 insertions(+), 199 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py index 77f8b4e479a9..2b0e2210cf00 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py @@ -186,6 +186,13 @@ 'PlanetCenterAtLocalOrigin': 2, } +# Fog Mode +FOG_MODES = { + 'Linear': 0, + 'Exponential': 1, + 'ExponentialSquared': 2 +} + # Level list used in Editor Level Load Test # WARNING: "Sponza" level is sandboxed due to an intermittent failure. LEVEL_LIST = ["hermanubis", "hermanubis_high", "macbeth_shaderballs", "PbrMaterialChart", "ShadowTest"] @@ -392,6 +399,13 @@ def deferred_fog(property: str = 'name') -> str: - 'Octaves Blend Factor' Blend factor between the noise octaves (0.0, 1.0). - 'Enable Turbulence Properties' Enables Turbulence Properties (bool). - 'Enable Fog Layer' Enables the fog layer (bool). + - 'Fog Mode' Set the fog formula + (enum, Uses above dictionary FOG_MODES) + Linear: f = (end - d)/(end - start) + Exponential: f = 1/exp(d * density) + ExponentialSquared: f = 1/exp((d * density)^2) + - 'Fog Density': Density control for Exponential and ExponentialSquared modes. + - 'Fog Density Clamp': The maximum density that the fog can reach. :param property: From the last element of the property tree path. Default 'name' for component name string. :return: Full property path OR component name if no property specified. """ @@ -400,18 +414,21 @@ def deferred_fog(property: str = 'name') -> str: 'requires': [AtomComponentProperties.postfx_layer()], 'Enable Deferred Fog': 'Controller|Configuration|Enable Deferred Fog', 'Fog Color': 'Controller|Configuration|Fog Color', - 'Fog Start Distance': 'Controller|Configuration|Fog Start Distance', - 'Fog End Distance': 'Controller|Configuration|Fog End Distance', - 'Fog Bottom Height': 'Controller|Configuration|Fog Bottom Height', - 'Fog Max Height': 'Controller|Configuration|Fog Max Height', - 'Noise Texture': 'Controller|Configuration|Noise Texture', - 'Noise Texture First Octave Scale': 'Controller|Configuration|Noise Texture First Octave Scale', - 'Noise Texture First Octave Velocity': 'Controller|Configuration|Noise Texture First Octave Velocity', - 'Noise Texture Second Octave Scale': 'Controller|Configuration|Noise Texture Second Octave Scale', - 'Noise Texture Second Octave Velocity': 'Controller|Configuration|Noise Texture Second Octave Velocity', - 'Octaves Blend Factor': 'Controller|Configuration|Octaves Blend Factor', + 'Fog Start Distance': 'Controller|Configuration|Distance|Fog Start Distance', + 'Fog End Distance': 'Controller|Configuration|Distance|Fog End Distance', + 'Fog Bottom Height': 'Controller|Configuration|Fog Layer|Fog Bottom Height', + 'Fog Max Height': 'Controller|Configuration|Fog Layer|Fog Max Height', + 'Noise Texture': 'Controller|Configuration|Turbulence|Noise Texture', + 'Noise Texture First Octave Scale': 'Controller|Configuration|Turbulence|Noise Texture First Octave Scale', + 'Noise Texture First Octave Velocity': 'Controller|Configuration|Turbulence|Noise Texture First Octave Velocity', + 'Noise Texture Second Octave Scale': 'Controller|Configuration|Turbulence|Noise Texture Second Octave Scale', + 'Noise Texture Second Octave Velocity': 'Controller|Configuration|Turbulence|Noise Texture Second Octave Velocity', + 'Octaves Blend Factor': 'Controller|Configuration|Turbulence|Octaves Blend Factor', 'Enable Turbulence Properties': 'Controller|Configuration|Enable Turbulence Properties', 'Enable Fog Layer': 'Controller|Configuration|Enable Fog Layer', + 'Fog Density': 'Controller|Configuration|Density Control|Fog Density', + 'Fog Density Clamp': 'Controller|Configuration|Density Control|Fog Density Clamp', + 'Fog Mode': 'Controller|Configuration|Fog Mode', } return properties[property] diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DeferredFogAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DeferredFogAdded.py index e842075d02d5..0dbbeb782501 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DeferredFogAdded.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DeferredFogAdded.py @@ -112,6 +112,22 @@ class Tests: deletion_redo = ( "REDO deletion success", "P0: REDO deletion failed") + edit_fog_mode = ( + "Fog mode updated", + "P1: Failed to set the fog mode") + fog_density_min = ( + "Fog Density set to minimum value", + "P1: Fog Density failed to be set to minimum value") + fog_density_clamp_min = ( + "Fog Density Clamp set to minimum value", + "P1: Fog Density Clamp failed to be set to minimum value") + fog_density_max = ( + "Fog Density set to maximum value", + "P1: Fog Density failed to be set to maximum value") + fog_density_clamp_max = ( + "Fog Density Clamp set to maximum value", + "P1: Fog Density Clamp failed to be set to maximum value") + def AtomEditorComponents_DeferredFog_AddedToEntity(): @@ -165,7 +181,7 @@ def AtomEditorComponents_DeferredFog_AddedToEntity(): from editor_python_test_tools.editor_entity_utils import EditorEntity from editor_python_test_tools.utils import Report, Tracer, TestHelper - from Atom.atom_utils.atom_constants import AtomComponentProperties + from Atom.atom_utils.atom_constants import (AtomComponentProperties, FOG_MODES) with Tracer() as error_tracer: # Test setup begins. @@ -229,176 +245,215 @@ def AtomEditorComponents_DeferredFog_AddedToEntity(): AtomComponentProperties.deferred_fog('Enable Deferred Fog'), True) general.idle_wait_frames(1) - # 9. Enable/Disable the Enable Turbulence Properties parameter. - # Enable the Enable Turbulence Properties parameter. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Enable Turbulence Properties'), True) - Report.result(Tests.enable_turbulence_properties_parameter_enabled, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Enable Turbulence Properties')) is True) - - # Disable the Enable Turbulence Properties parameter. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Enable Turbulence Properties'), False) - Report.result(Tests.enable_turbulence_properties_parameter_disabled, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Enable Turbulence Properties')) is False) - - # Re-enable the Enable Turbulence Properties parameter for game mode verification. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Enable Turbulence Properties'), True) - - # 10. Enable/Disable the Enable Fog Layer parameter. - # Enable the Enable Fog Layer parameter. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Enable Fog Layer'), True) - Report.result(Tests.enable_fog_layer_parameter_enabled, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Enable Fog Layer')) is True) - - # Disable the Enable Fog Layer parameter. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Enable Fog Layer'), False) - Report.result(Tests.enable_fog_layer_parameter_disabled, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Enable Fog Layer')) is False) - - # Re-enable the Enable Fog Layer parameter for game mode verification. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Enable Fog Layer'), True) - general.idle_wait_frames(1) - - # 11. Edit the Fog Color parameter. - violet_color_value = math.Vector3(0.498, 0.0, 1.0) - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog Color'), violet_color_value) - fog_color_value = deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog Color')) - Report.result(Tests.edit_fog_color, fog_color_value.IsClose(violet_color_value)) - - # 12. Update the Fog Start Distance parameter to min/max values. - # Update the Fog Start Distance parameter to its minimum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog Start Distance'), 0.0) - Report.result(Tests.fog_start_min, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog Start Distance')) == 0.0) - - # Update the Fog Start Distance parameter to its maximum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog Start Distance'), 5000.0) - Report.result(Tests.fog_start_max, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog Start Distance')) == 5000.0) - - # 13. Update the Fog End Distance parameter to min/max values. - # Update the Fog End Distance parameter to its maximum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog End Distance'), 5000.0) - Report.result(Tests.fog_end_max, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog End Distance')) == 5000.0) - - # Update the Fog End Distance parameter to its minimum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog End Distance'), 0.0) - Report.result(Tests.fog_end_min, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog End Distance')) == 0.0) - - # 14. Update the Fog Bottom Height parameter to min/max values. - # Update the Fog Bottom Height parameter to its maximum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog Bottom Height'), 5000.0) - Report.result(Tests.fog_bottom_height_max, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog Bottom Height')) == 5000.0) - - # Update the Fog Bottom Height parameter to its minimum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog Bottom Height'), -5000.0) - Report.result(Tests.fog_bottom_height_min, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog Bottom Height')) == -5000.0) - - # 15. Update the Fog Max Height parameter to min/max values. - # Update the Fog Max Height parameter to its minimum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog Max Height'), -5000.0) - Report.result(Tests.fog_max_height_min, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog Max Height')) == -5000.0) - - # Update the Fog Max Height parameter to its maximum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Fog Max Height'), 5000.0) - Report.result(Tests.fog_max_height_max, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Fog Max Height')) == 5000.0) - general.idle_wait_frames(1) - - # 16. Edit the Noise Texture parameter. - # This field cannot currently be edited. It will be fixed in a future sprint. - - # Store Noise Texture First/Second Scale & Velocity value: - set_octave = math.Vector2(-100.0, 100.0) - - # 17. Update the Noise Texture First Octave Scale parameter to low/high values. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture First Octave Scale'), set_octave) - get_first_octave_scale = deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture First Octave Scale')) - Report.result(Tests.first_octave_scale, get_first_octave_scale.IsClose(set_octave)) - - # 18. Update the Noise Texture First Octave Velocity parameter to low/high values. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture First Octave Velocity'), set_octave) - get_first_octave_velocity = deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture First Octave Velocity')) - Report.result(Tests.first_octave_velocity, get_first_octave_velocity.IsClose(set_octave)) - - # 19. Update the Noise Texture Second Octave Scale parameter to low/high values. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture Second Octave Scale'), set_octave) - get_second_octave_scale = deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture Second Octave Scale')) - Report.result(Tests.second_octave_scale, get_second_octave_scale.IsClose(set_octave)) - - # 20. Update the Noise Texture Second Octave Velocity parameter to low/high values. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture Second Octave Velocity'), set_octave) - get_second_octave_velocity = deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Noise Texture Second Octave Velocity')) - Report.result(Tests.second_octave_velocity, get_second_octave_velocity.IsClose(set_octave)) - - # 21. Update the Octaves Blend Factor parameter to min/max values. - # Update the Octaves Blend Factor to its minimum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Octaves Blend Factor'), 0.0) - Report.result(Tests.octaves_blend_factor_min, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Octaves Blend Factor')) == 0.0) - - # Update the Octave Blend Factor to its maximum value. - deferred_fog_component.set_component_property_value( - AtomComponentProperties.deferred_fog('Octaves Blend Factor'), 1.0) - Report.result(Tests.octaves_blend_factor_max, - deferred_fog_component.get_component_property_value( - AtomComponentProperties.deferred_fog('Octaves Blend Factor')) == 1.0) - - # 22. Enter/Exit game mode. - TestHelper.enter_game_mode(Tests.enter_game_mode) - general.idle_wait_frames(1) - TestHelper.exit_game_mode(Tests.exit_game_mode) - - # 23. Test IsHidden. - deferred_fog_entity.set_visibility_state(False) - Report.result(Tests.is_hidden, deferred_fog_entity.is_hidden() is True) - - # 24. Test IsVisible. - deferred_fog_entity.set_visibility_state(True) - general.idle_wait_frames(1) - Report.result(Tests.is_visible, deferred_fog_entity.is_visible() is True) + # Cycle through the fog modes + for fog_mode in FOG_MODES.keys(): + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Mode'), FOG_MODES[fog_mode]) + + general.idle_wait_frames(1) + Report.result(Tests.edit_fog_mode, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Mode')) == FOG_MODES[fog_mode]) + + # 9. Enable/Disable the Enable Turbulence Properties parameter. + # Enable the Enable Turbulence Properties parameter. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Enable Turbulence Properties'), True) + Report.result(Tests.enable_turbulence_properties_parameter_enabled, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Enable Turbulence Properties')) is True) + + # Disable the Enable Turbulence Properties parameter. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Enable Turbulence Properties'), False) + Report.result(Tests.enable_turbulence_properties_parameter_disabled, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Enable Turbulence Properties')) is False) + + # Re-enable the Enable Turbulence Properties parameter for game mode verification. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Enable Turbulence Properties'), True) + + # 10. Enable/Disable the Enable Fog Layer parameter. + # Enable the Enable Fog Layer parameter. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Enable Fog Layer'), True) + Report.result(Tests.enable_fog_layer_parameter_enabled, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Enable Fog Layer')) is True) + + # Disable the Enable Fog Layer parameter. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Enable Fog Layer'), False) + Report.result(Tests.enable_fog_layer_parameter_disabled, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Enable Fog Layer')) is False) + + # Re-enable the Enable Fog Layer parameter for game mode verification. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Enable Fog Layer'), True) + general.idle_wait_frames(1) + + # 11. Edit the Fog Color parameter. + violet_color_value = math.Vector3(0.498, 0.0, 1.0) + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Color'), violet_color_value) + fog_color_value = deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Color')) + Report.result(Tests.edit_fog_color, fog_color_value.IsClose(violet_color_value)) + + # 12. Update the Fog Start Distance parameter to min/max values. + # Update the Fog Start Distance parameter to its minimum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Start Distance'), 0.0) + Report.result(Tests.fog_start_min, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Start Distance')) == 0.0) + + # Update the Fog Start Distance parameter to its maximum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Start Distance'), 5000.0) + Report.result(Tests.fog_start_max, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Start Distance')) == 5000.0) + + if FOG_MODES[fog_mode] == FOG_MODES['Linear']: + # 13. Update the Fog End Distance parameter to min/max values. + # Update the Fog End Distance parameter to its maximum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog End Distance'), 5000.0) + Report.result(Tests.fog_end_max, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog End Distance')) == 5000.0) + + # Update the Fog End Distance parameter to its minimum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog End Distance'), 0.0) + Report.result(Tests.fog_end_min, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog End Distance')) == 0.0) + + # 14. Update the Fog Bottom Height parameter to min/max values. + # Update the Fog Bottom Height parameter to its maximum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Bottom Height'), 5000.0) + Report.result(Tests.fog_bottom_height_max, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Bottom Height')) == 5000.0) + + # Update the Fog Bottom Height parameter to its minimum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Bottom Height'), -5000.0) + Report.result(Tests.fog_bottom_height_min, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Bottom Height')) == -5000.0) + + # 15. Update the Fog Max Height parameter to min/max values. + # Update the Fog Max Height parameter to its minimum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Max Height'), -5000.0) + Report.result(Tests.fog_max_height_min, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Max Height')) == -5000.0) + + # Update the Fog Max Height parameter to its maximum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Max Height'), 5000.0) + Report.result(Tests.fog_max_height_max, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Max Height')) == 5000.0) + + # Update the Fog Density Clamp to it's min/max values + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density Clamp'), 1.0) + Report.result(Tests.fog_density_clamp_max, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density Clamp')) == 1.0) + + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density Clamp'), 0.0) + Report.result(Tests.fog_density_clamp_min, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density Clamp')) == 0.0) + + if FOG_MODES[fog_mode] in (FOG_MODES['Exponential'], FOG_MODES['ExponentialSquared']): + # Update the Fog Density to it's min/max values + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density'), 1.0) + Report.result(Tests.fog_density_max, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density')) == 1.0) + + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density'), 0.0) + Report.result(Tests.fog_density_min, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Fog Density')) == 0.0) + + general.idle_wait_frames(1) + + # 16. Edit the Noise Texture parameter. + # This field cannot currently be edited. It will be fixed in a future sprint. + + # Store Noise Texture First/Second Scale & Velocity value: + set_octave = math.Vector2(-100.0, 100.0) + + # 17. Update the Noise Texture First Octave Scale parameter to low/high values. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture First Octave Scale'), set_octave) + get_first_octave_scale = deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture First Octave Scale')) + Report.result(Tests.first_octave_scale, get_first_octave_scale.IsClose(set_octave)) + + # 18. Update the Noise Texture First Octave Velocity parameter to low/high values. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture First Octave Velocity'), set_octave) + get_first_octave_velocity = deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture First Octave Velocity')) + Report.result(Tests.first_octave_velocity, get_first_octave_velocity.IsClose(set_octave)) + + # 19. Update the Noise Texture Second Octave Scale parameter to low/high values. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture Second Octave Scale'), set_octave) + get_second_octave_scale = deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture Second Octave Scale')) + Report.result(Tests.second_octave_scale, get_second_octave_scale.IsClose(set_octave)) + + # 20. Update the Noise Texture Second Octave Velocity parameter to low/high values. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture Second Octave Velocity'), set_octave) + get_second_octave_velocity = deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Noise Texture Second Octave Velocity')) + Report.result(Tests.second_octave_velocity, get_second_octave_velocity.IsClose(set_octave)) + + # 21. Update the Octaves Blend Factor parameter to min/max values. + # Update the Octaves Blend Factor to its minimum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Octaves Blend Factor'), 0.0) + Report.result(Tests.octaves_blend_factor_min, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Octaves Blend Factor')) == 0.0) + + # Update the Octave Blend Factor to its maximum value. + deferred_fog_component.set_component_property_value( + AtomComponentProperties.deferred_fog('Octaves Blend Factor'), 1.0) + Report.result(Tests.octaves_blend_factor_max, + deferred_fog_component.get_component_property_value( + AtomComponentProperties.deferred_fog('Octaves Blend Factor')) == 1.0) + + # 22. Enter/Exit game mode. + TestHelper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + TestHelper.exit_game_mode(Tests.exit_game_mode) + + # 23. Test IsHidden. + deferred_fog_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, deferred_fog_entity.is_hidden() is True) + + # 24. Test IsVisible. + deferred_fog_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, deferred_fog_entity.is_visible() is True) # 25. Delete Deferred Fog entity. deferred_fog_entity.delete() diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/ScreenSpace/DeferredFog.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/ScreenSpace/DeferredFog.azsl index 02b8b8210a31..e2c5e9b60a6f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/ScreenSpace/DeferredFog.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/ScreenSpace/DeferredFog.azsl @@ -29,6 +29,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback float3 m_fogColor; float m_fogStartDistance; // Distance at which the fog starts to appear float m_fogEndDistance; // Distance for complete fog color taking over + float m_fogDensity; + float m_fogDensityClamp; #if ENABLE_FOG_LAYER float m_fogMinHeight; // Minmum and Maximum fog layer heights @@ -79,6 +81,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback option bool o_useNoiseTexture = true; option bool o_enableFogLayer = true; +// "Linear" is a reserved keyword, so we change it to "LinearMode" +option enum class FogMode { LinearMode, ExponentialMode, ExponentialSquaredMode } o_fogMode = FogMode::LinearMode; #if ENABLE_FOG_LAYER float CalculateFogDensity(float3 surfacePosWS, float depthInLayer) @@ -194,7 +198,7 @@ PSOutput MainPS(VSOutput IN) linearDepth *= lerp(1.0, fogDensity, fogDistanceDeviationRatio); // The following line is the linear depth traversing the layer - linearDepth = fogTraversalRelLength * linearDepth - max( 0, PassSrg::m_fogStartDistance - distToFogLayer * linearDepth); + linearDepth = max(0, fogTraversalRelLength * linearDepth - max( 0, PassSrg::m_fogStartDistance - distToFogLayer * linearDepth)); } else #endif // ENABLE_FOG_LAYER @@ -202,9 +206,24 @@ PSOutput MainPS(VSOutput IN) linearDepth = max( 0, linearDepth - PassSrg::m_fogStartDistance ); } - float layerFogAmountWithStartDist = saturate(linearDepth / (PassSrg::m_fogEndDistance - PassSrg::m_fogStartDistance)); + float density = 0.0f; + switch(o_fogMode) + { + case FogMode::LinearMode: + density = saturate(linearDepth / (PassSrg::m_fogEndDistance - PassSrg::m_fogStartDistance)); + break; + case FogMode::ExponentialMode: + density = 1.0 - exp(-linearDepth * PassSrg::m_fogDensity); + break; + case FogMode::ExponentialSquaredMode: + density = 1.0 - exp(-pow(linearDepth * PassSrg::m_fogDensity, 2)); + break; + default: + break; + } - OUT.m_color = float4(PassSrg::m_fogColor, layerFogAmountWithStartDist); + density = clamp(density, 0.0, PassSrg::m_fogDensityClamp); + OUT.m_color = float4(PassSrg::m_fogColor, density); return OUT; } diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogParams.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogParams.inl index 8824c3e2ad04..69807678157f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogParams.inl +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogParams.inl @@ -16,6 +16,10 @@ AZ_GFX_FLOAT_PARAM(FogEndDistance, m_fogEndDistance, 5.0f ) AZ_GFX_FLOAT_PARAM(FogMinHeight, m_fogMinHeight, 0.01f) AZ_GFX_FLOAT_PARAM(FogMaxHeight, m_fogMaxHeight, 1.0f) +AZ_GFX_FLOAT_PARAM(FogDensity, m_fogDensity, 0.33f) +AZ_GFX_FLOAT_PARAM(FogDensityClamp, m_fogDensityClamp, 1.0f) +AZ_GFX_COMMON_PARAM(Render::FogMode, FogMode, m_fogMode, FogMode::Linear) + AZ_GFX_TEXTURE2D_PARAM(NoiseTexture, m_noiseTexture, "textures/cloudnoise_01.jpg.streamingimage") // First noise octave diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h index 58a50016ee89..77010564fddc 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h @@ -10,11 +10,20 @@ #include #include +#include namespace AZ { namespace Render { + AZ_ENUM_CLASS_WITH_UNDERLYING_TYPE( + FogMode, + uint8_t, + (Linear, 0), //!< f = (end - d)/(end - start). "d" represents depth, or the distance from the viewpoint + (Exponential, 1), //!< f = 1/exp(d * density). "density" is an arbitrary fog density that can range from 0.0 to 1.0. + (ExponentialSquared, 2) //!< f = 1/exp((d * density)^2). "density" is an arbitrary fog density that can range from 0.0 to 1.0. + ); + class DeferredFogSettingsInterface { public: diff --git a/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.cpp index de499269d2d6..99bd374de386 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.cpp @@ -28,11 +28,13 @@ namespace AZ { namespace Render { + static const char* const FogModeOptionName{ "o_fogMode" }; AZ_CVAR(bool, r_enableFog, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Enable fog"); DeferredFogPass::DeferredFogPass(const RPI::PassDescriptor& descriptor) : RPI::FullscreenTrianglePass(descriptor) + , m_fogModeOptionName(FogModeOptionName) { } @@ -214,6 +216,21 @@ namespace AZ fogSettings->GetEnableFogLayerShaderOption() ? AZ::Name("true") : AZ::Name("false")); shaderOption.SetValue(AZ::Name("o_useNoiseTexture"), fogSettings->GetUseNoiseTextureShaderOption() ? AZ::Name("true") : AZ::Name("false")); + switch (fogSettings->GetFogMode()) + { + case FogMode::Linear: + shaderOption.SetValue(m_fogModeOptionName, AZ::Name("FogMode::LinearMode")); + break; + case FogMode::Exponential: + shaderOption.SetValue(m_fogModeOptionName, AZ::Name("FogMode::ExponentialMode")); + break; + case FogMode::ExponentialSquared: + shaderOption.SetValue(m_fogModeOptionName, AZ::Name("FogMode::ExponentialSquaredMode")); + break; + default: + AZ_Error("DeferredFogPass", false, "Invalid fog mode %d", fogSettings->GetFogMode()); + break; + } // The following method returns the specified options, as well as fall back values for all // non-specified options. If all were set you can use the method GetShaderVariantKey that is diff --git a/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.h b/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.h index f37f47e5f91f..77d87395c360 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogPass.h @@ -79,6 +79,9 @@ namespace AZ // Shader options for variant generation (texture and layer activation in this case) AZ::RPI::ShaderVariantKey m_ShaderOptions; + + // Fog mode option name + const AZ::Name m_fogModeOptionName; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogBus.h index fb004e63859a..0fbb733e8e69 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogBus.h @@ -9,6 +9,7 @@ #pragma once #include +#include namespace AZ { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogComponentConfig.h index 8e41ba6a2c39..716dc1eaf6d9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/ScreenSpace/DeferredFogComponentConfig.h @@ -72,6 +72,15 @@ namespace AZ return m_enableFogLayerShaderOption; } + bool SupportsFogDensity() + { + return m_fogMode == FogMode::Exponential || m_fogMode == FogMode::ExponentialSquared; + } + bool SupportsFogEnd() + { + return m_fogMode == FogMode::Linear; + } + // Generate Get / Set methods #define AZ_GFX_COMMON_PARAM(ValueType, Name, MemberName, DefaultValue) \ virtual ValueType Get##Name() const { return MemberName; } \ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp index 4c3ebd3d999d..30ee9c91cc49 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp @@ -20,7 +20,7 @@ namespace AZ if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(1); + ->Version(2); if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { @@ -53,9 +53,27 @@ namespace AZ "Enable Deferred Fog.") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(Edit::UIHandlers::CheckBox, &DeferredFogComponentConfig::m_enableFogLayerShaderOption, + "Enable Fog Layer", + "Enable Fog Layer") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + ->DataElement(Edit::UIHandlers::CheckBox, &DeferredFogComponentConfig::m_useNoiseTextureShaderOption, + "Enable Turbulence Properties", + "Enable Turbulence Properties") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::Color, &DeferredFogComponentConfig::m_fogColor, "Fog Color", "The fog color.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + ->DataElement(Edit::UIHandlers::ComboBox, &DeferredFogComponentConfig::m_fogMode, + "Fog Mode", + "Which formula to use for calculating the fog.") + ->Attribute(AZ::Edit::Attributes::EnumValues, AZ::Edit::GetEnumConstantsFromTraits()) + + ->ClassElement(Edit::ClassElements::Group, "Distance") + ->Attribute(Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogStartDistance, "Fog Start Distance", "The distance from the viewer when the fog starts") @@ -66,20 +84,40 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogEndDistance, - "Fog End Distance", "At what distance from the viewer does the fog take over and mask the background scene out") + "Fog End Distance", "At what distance from the viewer does the fog take over and mask the background scene out.") ->Attribute(AZ::Edit::Attributes::Min, &DeferredFogComponentConfig::m_fogStartDistance) ->Attribute(AZ::Edit::Attributes::Max, 5000.0f) ->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f) ->Attribute(AZ::Edit::Attributes::SoftMax, 100.0f) ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::SupportsFogEnd) - // Fog layer properties - ->DataElement(Edit::UIHandlers::CheckBox, - &DeferredFogComponentConfig::m_enableFogLayerShaderOption, - "Enable Fog Layer", - "Enable Fog Layer") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->ClassElement(Edit::ClassElements::Group, "Density Control") + ->Attribute(Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogDensity, + "Fog Density", + "Density of the fog that can range from 0.0 to 1.0") + ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->Attribute(AZ::Edit::Attributes::Max, 1.0f) + ->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f) + ->Attribute(AZ::Edit::Attributes::SoftMax, 1.0f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::SupportsFogDensity) + + ->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogDensityClamp, + "Fog Density Clamp", + "The maximum density that the fog can reach. This enables the sky, horizon, and other bright, distant objects to be visible through dense fog.") + ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->Attribute(AZ::Edit::Attributes::Max, 1.0f) + ->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f) + ->Attribute(AZ::Edit::Attributes::SoftMax, 1.0f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + // Fog layer properties + ->ClassElement(Edit::ClassElements::Group, "Fog Layer") + ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::GetEnableFogLayerShaderOption) ->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogMinHeight, "Fog Bottom Height", "The height at which the fog layer starts") ->Attribute(AZ::Edit::Attributes::Min, -5000.0f) @@ -88,6 +126,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::SoftMax, 1000.0f) ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogMaxHeight, "Fog Max Height", "The height of the fog layer top") ->Attribute(AZ::Edit::Attributes::Min, -5000.0f) @@ -97,12 +136,9 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) // Fog turbulence properties - ->DataElement(Edit::UIHandlers::CheckBox, - &DeferredFogComponentConfig::m_useNoiseTextureShaderOption, - "Enable Turbulence Properties", - "Enable Turbulence Properties") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - + ->ClassElement(Edit::ClassElements::Group, "Turbulence") + ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::GetUseNoiseTextureShaderOption) ->DataElement(AZ::Edit::UIHandlers::LineEdit, &DeferredFogComponentConfig::m_noiseTexture, "Noise Texture", "The noise texture used for creating the fog turbulence") ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)