diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py index 5299e55a2b..54e3d8cb41 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py @@ -20,9 +20,14 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests") @pytest.mark.parametrize("launcher_platform", ['windows_editor']) class TestAutomation(EditorTestSuite): - enable_prefab_system = False + enable_prefab_system = True # this test is intermittently timing out without ever having executed. sandboxing while we investigate cause. @pytest.mark.test_case_id("C36525660") class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module + + # The "Sponza" level is failing with a hard lock 4-12% of the time, needs root causing and fixing. + @pytest.mark.test_case_id("C36529679") + class AtomLevelLoadTest_Editor_Sandbox(EditorSharedTest): + from Atom.tests import hydra_Atom_LevelLoadTest_Sandbox as test_module diff --git a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py index 6525536f96..778f9bd3fb 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py @@ -33,7 +33,9 @@ GLOBAL_ILLUMINATION_QUALITY = { } # Level list used in Editor Level Load Test -LEVEL_LIST = ["hermanubis", "hermanubis_high", "macbeth_shaderballs", "PbrMaterialChart", "ShadowTest", "Sponza"] +# WARNING: "Sponza" level is sandboxed due to an intermittent failure. +LEVEL_LIST = ["hermanubis", "hermanubis_high", "macbeth_shaderballs", "PbrMaterialChart", "ShadowTest"] + class AtomComponentProperties: """ diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_Atom_LevelLoadTest_Sandbox.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_Atom_LevelLoadTest_Sandbox.py new file mode 100644 index 0000000000..6cee7b2840 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_Atom_LevelLoadTest_Sandbox.py @@ -0,0 +1,71 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + + +def Atom_LevelLoadTest(): + """ + Summary: + Loads all graphics levels within the AutomatedTesting project in editor. For each level this script will verify that + the level loads, and can enter/exit gameplay without crashing the editor. + + Test setup: + - Store all available levels in a list. + - Set up a for loop to run all checks for each level. + + Expected Behavior: + Test verifies that each level loads, enters/exits game mode, and reports success for all test actions. + + Test Steps for each level: + 1) Create tuple with level load success and failure messages + 2) Open the level using the python test tools command + 3) Verify level is loaded using a separate command, and report success/failure + 4) Enter gameplay and report result using a tuple + 5) Exit Gameplay and report result using a tuple + 6) Look for errors or asserts. + + :return: None + """ + SANDBOX_LEVEL_LIST = ["Sponza"] + + import azlmbr.legacy.general as general + + from editor_python_test_tools.utils import Report, Tracer, TestHelper + + with Tracer() as error_tracer: + + for level in SANDBOX_LEVEL_LIST: + + # 1. Create tuple with level load success and failure messages + level_check_tuple = (f"loaded {level}", f"failed to load {level}") + + # 2. Open the level using the python test tools command + TestHelper.init_idle() + TestHelper.open_level("Graphics", level) + + # 3. Verify level is loaded using a separate command, and report success/failure + Report.result(level_check_tuple, level == general.get_current_level_name()) + + # 4. Enter gameplay and report result using a tuple + enter_game_mode_tuple = (f"{level} entered gameplay successfully ", f"{level} failed to enter gameplay") + TestHelper.enter_game_mode(enter_game_mode_tuple) + general.idle_wait_frames(1) + + # 5. Exit gameplay and report result using a tuple + exit_game_mode_tuple = (f"{level} exited gameplay successfully ", f"{level} failed to exit gameplay") + TestHelper.exit_game_mode(exit_game_mode_tuple) + + # 6. Look for errors or asserts. + TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0) + for error_info in error_tracer.errors: + Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}") + for assert_info in error_tracer.asserts: + Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}") + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(Atom_LevelLoadTest) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main_Optimized.py index a40b9065d6..3242735345 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main_Optimized.py @@ -54,7 +54,7 @@ class EditorSingleTest_WithFileOverrides(EditorSingleTest): fm._restore_file(f, file_list[f]) -# @pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.") +@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.") @pytest.mark.SUITE_main @pytest.mark.parametrize("launcher_platform", ['windows_editor']) @pytest.mark.parametrize("project", ["AutomatedTesting"]) @@ -113,6 +113,9 @@ class TestAutomationWithPrefabSystemEnabled(EditorTestSuite): class C14861504_RenderMeshAsset_WithNoPxAsset(EditorSharedTest): from .tests.collider import Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx as test_module + + class C4976236_AddPhysxColliderComponent(EditorSharedTest): + from .tests.collider import Collider_AddColliderComponent as test_module @pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.") @@ -346,9 +349,6 @@ class TestAutomation(EditorTestSuite): class C5959809_ForceRegion_RotationalOffset(EditorSharedTest): from .tests.force_region import ForceRegion_RotationalOffset as test_module - class C4976236_AddPhysxColliderComponent(EditorSharedTest): - from .tests.collider import Collider_AddColliderComponent as test_module - class C100000_RigidBody_EnablingGravityWorksPoC(EditorSharedTest): from .tests.rigid_body import RigidBody_EnablingGravityWorksPoC as test_module diff --git a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py index d75328d8f7..d8fa6a30cd 100755 --- a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py @@ -440,13 +440,9 @@ class TestAutomation(TestAutomationBase): from .tests.material import Material_LibraryClearingAssignsDefault as test_module self._run_test(request, workspace, editor, test_module) - @pytest.mark.xfail(reason= - "Test failed due to an error message shown while in game mode: " - "'(Prefab) - Invalid asset found referenced in scene while entering game mode. " - "The asset was stored in an instance of Asset.'") def test_Collider_AddColliderComponent(self, request, workspace, editor, launcher_platform): from .tests.collider import Collider_AddColliderComponent as test_module - self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) + self._run_test(request, workspace, editor, test_module) @pytest.mark.xfail( reason="This will fail due to this issue ATOM-15487.") diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddColliderComponent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddColliderComponent.py index 4172e66962..d03cc7fff5 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddColliderComponent.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddColliderComponent.py @@ -49,9 +49,10 @@ def Collider_AddColliderComponent(): from editor_python_test_tools.utils import Tracer from editor_python_test_tools.asset_utils import Asset - helper.init_idle() + import editor_python_test_tools.hydra_editor_utils as hydra + # 1) Load the level - helper.open_level("Physics", "Base") + hydra.open_base_level() # 2) Create test entity test_entity = EditorEntity.create_editor_entity("TestEntity") diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py index e59282c97b..034930484e 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py @@ -49,9 +49,11 @@ class TestAutomationBase: time_info_str += f"{testcase_name}: (Full:{t} sec, Editor:{editor_t} sec)\n" logger.info(time_info_str) + if cls.asset_processor is not None: + cls.asset_processor.teardown() + # Kill all ly processes - cls.asset_processor.teardown() - cls._kill_ly_processes() + cls._kill_ly_processes(include_asset_processor=True) def _run_test(self, request, workspace, editor, testcase_module, extra_cmdline_args=[], batch_mode=True, autotest_mode=True, use_null_renderer=True, enable_prefab_system=True): @@ -62,14 +64,16 @@ class TestAutomationBase: ######### # Setup # - if self.asset_processor is None: + self._kill_ly_processes(include_asset_processor=True) self.__class__.asset_processor = AssetProcessor(workspace) self.asset_processor.backup_ap_settings() - - self._kill_ly_processes(include_asset_processor=False) - self.asset_processor.start() - self.asset_processor.wait_for_idle() + else: + self._kill_ly_processes(include_asset_processor=False) + + if not self.asset_processor.process_exists(): + self.asset_processor.start() + self.asset_processor.wait_for_idle() def teardown(): if os.path.exists(workspace.paths.editor_log()): diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py index 887bfe2426..58a0b42394 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py @@ -61,6 +61,7 @@ class TestAutomation(TestAutomationBase): from . import Graph_HappyPath_ZoomInZoomOut as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_NodePalette_HappyPath_CanSelectNode(self, request, workspace, editor, launcher_platform): from . import NodePalette_HappyPath_CanSelectNode as test_module self._run_test(request, workspace, editor, test_module) @@ -113,6 +114,7 @@ class TestAutomation(TestAutomationBase): from . import Debugger_HappyPath_TargetMultipleGraphs as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_Debugger_HappyPath_TargetMultipleEntities(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -174,6 +176,7 @@ class TestAutomation(TestAutomationBase): from . import ScriptEvents_ReturnSetType_Successfully as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_NodeCategory_ExpandOnClick(self, request, workspace, editor, launcher_platform): from . import NodeCategory_ExpandOnClick as test_module self._run_test(request, workspace, editor, test_module) @@ -187,6 +190,7 @@ class TestAutomation(TestAutomationBase): from . import VariableManager_UnpinVariableType_Works as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_Node_HappyPath_DuplicateNode(self, request, workspace, editor, launcher_platform): from . import Node_HappyPath_DuplicateNode as test_module self._run_test(request, workspace, editor, test_module) @@ -263,6 +267,7 @@ class TestScriptCanvasTests(object): timeout=60, ) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_VariableManager_Default_CreateDeleteVars(self, request, editor, launcher_platform): var_types = ["Boolean", "Color", "EntityID", "Number", "String", "Transform", "Vector2", "Vector3", "Vector4"] expected_lines = [f"Success: {var_type} variable is created" for var_type in var_types] diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_black.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_black.material index d15aa620c7..04766a23e1 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_black.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_black.material @@ -1,35 +1,25 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "irradiance": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } + "propertyValues": { + "baseColor.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "irradiance.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "opacity.factor": 1.0 } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_green.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_green.material index 579359b085..02440cce7a 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_green.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_green.material @@ -1,35 +1,25 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.0, - 1.0, - 0.0, - 1.0 - ] - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "irradiance": { - "color": [ - 0.0, - 1.0, - 0.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } + "propertyValues": { + "baseColor.color": [ + 0.0, + 1.0, + 0.0, + 1.0 + ], + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "irradiance.color": [ + 0.0, + 1.0, + 0.0, + 1.0 + ], + "opacity.factor": 1.0 } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_arch.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_arch.material index 88d5fc0fc6..e91c35fa8b 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_arch.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_arch.material @@ -1,49 +1,29 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureMap": "Textures/arch_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 1.0, - 0.885053813457489, - 0.801281750202179, - 1.0 - ] - }, - "metallic": { - "textureMap": "Textures/arch_1k_metallic.png" - }, - "normal": { - "textureMap": "Textures/arch_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "Textures/arch_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.050999999046325687, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "Textures/arch_1k_roughness.png" - } + "propertyValues": { + "baseColor.color": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1.0 + ], + "baseColor.textureMap": "Textures/arch_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 1.0, + 0.885053813457489, + 0.801281750202179, + 1.0 + ], + "metallic.textureMap": "Textures/arch_1k_metallic.png", + "normal.textureMap": "Textures/arch_1k_normal.jpg", + "occlusion.diffuseTextureMap": "Textures/arch_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.050999999046325684, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "Textures/arch_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_bricks.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_bricks.material index 7244397ee9..aa23f2e97c 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_bricks.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_bricks.material @@ -1,54 +1,32 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureMap": "Textures/bricks_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "normalMap": "Textures/bricks_1k_normal.jpg", - "roughness": 0.5 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 1.0, - 0.9703211784362793, - 0.9703211784362793, - 1.0 - ] - }, - "metallic": { - "textureMap": "Textures/bricks_1k_metallic.png" - }, - "normal": { - "textureMap": "Textures/bricks_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "Textures/bricks_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.03500000014901161, - "quality": "Medium", - "useTexture": false - }, - "roughness": { - "textureMap": "Textures/bricks_1k_roughness.png" - } + "propertyValues": { + "baseColor.color": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1.0 + ], + "baseColor.textureMap": "Textures/bricks_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.normalMap": "Textures/bricks_1k_normal.jpg", + "clearCoat.roughness": 0.5, + "general.applySpecularAA": true, + "irradiance.color": [ + 1.0, + 0.9703211784362793, + 0.9703211784362793, + 1.0 + ], + "metallic.textureMap": "Textures/bricks_1k_metallic.png", + "normal.textureMap": "Textures/bricks_1k_normal.jpg", + "occlusion.diffuseTextureMap": "Textures/bricks_1k_ao.png", + "opacity.factor": 1.0, + "parallax.algorithm": "ContactRefinement", + "parallax.factor": 0.03500000014901161, + "parallax.quality": "Medium", + "parallax.useTexture": false, + "roughness.textureMap": "Textures/bricks_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_floor.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_floor.material index 8a3f289c26..a49327a710 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_floor.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_floor.material @@ -1,51 +1,31 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureMap": "Textures/floor_1k_basecolor.png" - }, - "clearCoat": { - "enable": true, - "influenceMap": "Textures/floor_1k_ao.png", - "normalMap": "Textures/floor_1k_normal.png", - "roughness": 0.25 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 1.0, - 0.9404135346412659, - 0.8688944578170776, - 1.0 - ] - }, - "normal": { - "textureMap": "Textures/floor_1k_normal.png" - }, - "occlusion": { - "diffuseTextureMap": "Textures/floor_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.012000000104308129, - "pdo": true, - "useTexture": false - }, - "roughness": { - "textureMap": "Textures/floor_1k_roughness.png" - } + "propertyValues": { + "baseColor.color": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1.0 + ], + "baseColor.textureMap": "Textures/floor_1k_basecolor.png", + "clearCoat.enable": true, + "clearCoat.influenceMap": "Textures/floor_1k_ao.png", + "clearCoat.normalMap": "Textures/floor_1k_normal.png", + "clearCoat.roughness": 0.25, + "general.applySpecularAA": true, + "irradiance.color": [ + 1.0, + 0.9404135346412659, + 0.8688944578170776, + 1.0 + ], + "normal.textureMap": "Textures/floor_1k_normal.png", + "occlusion.diffuseTextureMap": "Textures/floor_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.012000000104308128, + "parallax.pdo": true, + "parallax.useTexture": false, + "roughness.textureMap": "Textures/floor_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_roof.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_roof.material index 7bc193978f..4f6b6bae92 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_roof.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_mat_roof.material @@ -1,44 +1,26 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureBlendMode": "Lerp", - "textureMap": "Textures/roof_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "metallic": { - "useTexture": false - }, - "normal": { - "factor": 0.5, - "flipY": true, - "textureMap": "Textures/roof_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "Textures/roof_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.019999999552965165, - "quality": "Medium", - "useTexture": false - }, - "roughness": { - "textureMap": "Textures/roof_1k_roughness.png" - } + "propertyValues": { + "baseColor.color": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1.0 + ], + "baseColor.textureBlendMode": "Lerp", + "baseColor.textureMap": "Textures/roof_1k_basecolor.png", + "general.applySpecularAA": true, + "metallic.useTexture": false, + "normal.factor": 0.5, + "normal.flipY": true, + "normal.textureMap": "Textures/roof_1k_normal.jpg", + "occlusion.diffuseTextureMap": "Textures/roof_1k_ao.png", + "opacity.factor": 1.0, + "parallax.algorithm": "ContactRefinement", + "parallax.factor": 0.019999999552965164, + "parallax.quality": "Medium", + "parallax.useTexture": false, + "roughness.textureMap": "Textures/roof_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_phong5.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_phong5.material index a53cbef4e4..e801b4d095 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_phong5.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_phong5.material @@ -1,35 +1,25 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.0, - 0.0, - 1.0, - 1.0 - ] - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "irradiance": { - "color": [ - 0.0, - 0.0, - 1.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } + "propertyValues": { + "baseColor.color": [ + 0.0, + 0.0, + 1.0, + 1.0 + ], + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "irradiance.color": [ + 0.0, + 0.0, + 1.0, + 1.0 + ], + "opacity.factor": 1.0 } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_red.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_red.material index 6ddb645319..ea364bab34 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_red.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_red.material @@ -1,35 +1,25 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.0, - 0.0, - 1.0 - ] - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "irradiance": { - "color": [ - 1.0, - 0.0, - 0.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } + "propertyValues": { + "baseColor.color": [ + 0.800000011920929, + 0.0, + 0.0, + 1.0 + ], + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "irradiance.color": [ + 1.0, + 0.0, + 0.0, + 1.0 + ], + "opacity.factor": 1.0 } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_white.material b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_white.material index e3d310cd15..0f90de5e13 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_white.material +++ b/AutomatedTesting/Gem/Sponza/Assets/TestData/Test_Sponza_Material_Conversion_white.material @@ -1,19 +1,13 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } + "propertyValues": { + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "opacity.factor": 1.0 } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/lightBlocker_lambert1.material b/AutomatedTesting/Gem/Sponza/Assets/objects/lightBlocker_lambert1.material index 35677a81c6..0f90de5e13 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/lightBlocker_lambert1.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/lightBlocker_lambert1.material @@ -1,19 +1,13 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } + "propertyValues": { + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "opacity.factor": 1.0 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_arch.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_arch.material index 6518091265..21f63885a9 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_arch.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_arch.material @@ -1,40 +1,22 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/arch_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.2663614749908447, - 0.2383916974067688, - 0.18117037415504456, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/arch_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/arch_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.050999999046325684, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/arch_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/arch_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.2663614749908447, + 0.2383916974067688, + 0.18117037415504456, + 1.0 + ], + "normal.textureMap": "../Textures/arch_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/arch_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.050999999046325684, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/arch_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_background.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_background.material index 2fd7ed39cc..7d5edb86e8 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_background.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_background.material @@ -1,45 +1,25 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/background_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "normalMap": "../Textures/background_1k_normal.jpg", - "roughness": 0.4000000059604645 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.19806210696697235, - 0.1746547669172287, - 0.16513313353061676, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/background_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/background_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.03099999949336052, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/background_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/background_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.normalMap": "../Textures/background_1k_normal.jpg", + "clearCoat.roughness": 0.4000000059604645, + "general.applySpecularAA": true, + "irradiance.color": [ + 0.19806210696697235, + 0.1746547669172287, + 0.16513313353061676, + 1.0 + ], + "normal.textureMap": "../Textures/background_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/background_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.03099999949336052, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/background_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_bricks.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_bricks.material index 52fdf9e3a2..9e7a01d573 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_bricks.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_bricks.material @@ -1,45 +1,25 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/bricks_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "normalMap": "../Textures/bricks_1k_normal.jpg", - "roughness": 0.5 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.27467766404151917, - 0.27467766404151917, - 0.270496666431427, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/bricks_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/bricks_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.03500000014901161, - "quality": "Medium", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/bricks_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/bricks_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.normalMap": "../Textures/bricks_1k_normal.jpg", + "clearCoat.roughness": 0.5, + "general.applySpecularAA": true, + "irradiance.color": [ + 0.27467766404151917, + 0.27467766404151917, + 0.270496666431427, + 1.0 + ], + "normal.textureMap": "../Textures/bricks_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/bricks_1k_ao.png", + "opacity.factor": 1.0, + "parallax.algorithm": "ContactRefinement", + "parallax.factor": 0.03500000014901161, + "parallax.quality": "Medium", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/bricks_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_ceiling.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_ceiling.material index 10f5a01a8e..b9bc4e3dcb 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_ceiling.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_ceiling.material @@ -1,36 +1,22 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/ceiling_1k_basecolor.png" - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "irradiance": { - "color": [ - 0.29176774621009827, - 0.27888914942741394, - 0.2501564025878906, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/ceiling_1k_normal.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "../Textures/ceiling_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/ceiling_1k_basecolor.png", + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "irradiance.color": [ + 0.29176774621009827, + 0.27888914942741394, + 0.2501564025878906, + 1.0 + ], + "normal.textureMap": "../Textures/ceiling_1k_normal.png", + "opacity.factor": 1.0, + "roughness.textureMap": "../Textures/ceiling_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_chain.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_chain.material index caf03bd3ce..5b553b5113 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_chain.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_chain.material @@ -1,35 +1,21 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureBlendMode": "Lerp", - "textureMap": "../Textures/chain_basecolor.png" - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "general": { - "doubleSided": true - }, - "metallic": { - "factor": 0.8899999856948853 - }, - "normal": { - "textureMap": "../Textures/chain_normal.jpg" - }, - "opacity": { - "alphaSource": "Split", - "factor": 1.0, - "mode": "Cutout", - "textureMap": "../Textures/chain_alpha.png" - } + "propertyValues": { + "baseColor.textureBlendMode": "Lerp", + "baseColor.textureMap": "../Textures/chain_basecolor.png", + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "general.doubleSided": true, + "metallic.factor": 0.8899999856948853, + "normal.textureMap": "../Textures/chain_normal.jpg", + "opacity.alphaSource": "Split", + "opacity.factor": 1.0, + "opacity.mode": "Cutout", + "opacity.textureMap": "../Textures/chain_alpha.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columna.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columna.material index 15c3fec349..5e8b17d959 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columna.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columna.material @@ -1,45 +1,25 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/columnA_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "normalMap": "../Textures/columnA_1k_normal.jpg", - "roughness": 0.30000001192092896 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 1.0, - 0.8964369893074036, - 0.8264744281768799, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/columnA_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/columnA_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.017000000923871994, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/columnA_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/columnA_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.normalMap": "../Textures/columnA_1k_normal.jpg", + "clearCoat.roughness": 0.30000001192092896, + "general.applySpecularAA": true, + "irradiance.color": [ + 1.0, + 0.8964369893074036, + 0.8264744281768799, + 1.0 + ], + "normal.textureMap": "../Textures/columnA_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/columnA_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.017000000923871994, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/columnA_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnb.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnb.material index e13f96b2bb..4f24f4d61b 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnb.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnb.material @@ -1,45 +1,25 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/columnB_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "normalMap": "../Textures/columnB_1k_normal.jpg", - "roughness": 0.30000001192092896 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.41788357496261597, - 0.40723279118537903, - 0.4286869466304779, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/columnB_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/columnB_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.020999999716877937, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/columnB_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/columnB_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.normalMap": "../Textures/columnB_1k_normal.jpg", + "clearCoat.roughness": 0.30000001192092896, + "general.applySpecularAA": true, + "irradiance.color": [ + 0.41788357496261597, + 0.40723279118537903, + 0.4286869466304779, + 1.0 + ], + "normal.textureMap": "../Textures/columnB_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/columnB_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.020999999716877937, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/columnB_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnc.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnc.material index 479692848a..e7c9401091 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnc.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_columnc.material @@ -1,45 +1,25 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/columnC_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "normalMap": "../Textures/columnC_1k_normal.jpg", - "roughness": 0.30000001192092896 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.32314029335975647, - 0.29176774621009827, - 0.24228274822235107, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/columnC_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/columnC_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.014000000432133675, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/columnC_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/columnC_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.normalMap": "../Textures/columnC_1k_normal.jpg", + "clearCoat.roughness": 0.30000001192092896, + "general.applySpecularAA": true, + "irradiance.color": [ + 0.32314029335975647, + 0.29176774621009827, + 0.24228274822235107, + 1.0 + ], + "normal.textureMap": "../Textures/columnC_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/columnC_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.014000000432133675, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/columnC_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainblue.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainblue.material index 50fd968956..8b2167e4ac 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainblue.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainblue.material @@ -1,52 +1,32 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "color": [ - 1.0, - 1.0, - 1.0, - 1.0 - ], - "textureMap": "../Textures/curtainBlue_1k_basecolor.png" - }, - "emissive": { - "color": [ - 1.0, - 1.0, - 1.0, - 1.0 - ] - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.0, - 0.14901961386203766, - 1.0, - 1.0 - ] - }, - "metallic": { - "textureMap": "../Textures/curtain_metallic.png" - }, - "normal": { - "factor": 0.5, - "textureMap": "../Textures/curtain_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/curtain_ao.png" - }, - "roughness": { - "textureMap": "../Textures/curtain_roughness.png" - }, - "specularF0": { - "enableMultiScatterCompensation": true - } + "propertyValues": { + "baseColor.color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "baseColor.textureMap": "../Textures/curtainBlue_1k_basecolor.png", + "emissive.color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "general.applySpecularAA": true, + "irradiance.color": [ + 0.0, + 0.14901961386203766, + 1.0, + 1.0 + ], + "metallic.textureMap": "../Textures/curtain_metallic.png", + "normal.factor": 0.5, + "normal.textureMap": "../Textures/curtain_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/curtain_ao.png", + "roughness.textureMap": "../Textures/curtain_roughness.png", + "specularF0.enableMultiScatterCompensation": true } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtaingreen.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtaingreen.material index 6e70a42d24..5e6233ab04 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtaingreen.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtaingreen.material @@ -1,38 +1,20 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/curtainGreen_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.0, - 0.15294118225574493, - 0.0, - 1.0 - ] - }, - "metallic": { - "textureMap": "../Textures/curtain_metallic.png" - }, - "normal": { - "factor": 0.5, - "textureMap": "../Textures/curtain_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/curtain_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "../Textures/curtain_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/curtainGreen_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.0, + 0.15294118225574493, + 0.0, + 1.0 + ], + "metallic.textureMap": "../Textures/curtain_metallic.png", + "normal.factor": 0.5, + "normal.textureMap": "../Textures/curtain_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/curtain_ao.png", + "opacity.factor": 1.0, + "roughness.textureMap": "../Textures/curtain_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainred.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainred.material index 8233633310..86122d274f 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainred.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_curtainred.material @@ -1,43 +1,23 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/curtainRed_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.41960784792900085, - 0.003921568859368563, - 0.003921568859368563, - 1.0 - ] - }, - "metallic": { - "textureMap": "../Textures/curtain_metallic.png" - }, - "normal": { - "textureMap": "../Textures/curtain_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/curtain_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "../Textures/curtain_roughness.png" - }, - "uv": { - "center": [ - 16.0, - 0.0 - ] - } + "propertyValues": { + "baseColor.textureMap": "../Textures/curtainRed_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.41960784792900085, + 0.003921568859368563, + 0.003921568859368563, + 1.0 + ], + "metallic.textureMap": "../Textures/curtain_metallic.png", + "normal.textureMap": "../Textures/curtain_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/curtain_ao.png", + "opacity.factor": 1.0, + "roughness.textureMap": "../Textures/curtain_roughness.png", + "uv.center": [ + 16.0, + 0.0 + ] } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_details.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_details.material index b66d8fa679..1a8588e749 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_details.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_details.material @@ -1,39 +1,19 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/details_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "normalMap": "../Textures/details_1k_normal.png", - "roughness": 0.25 - }, - "general": { - "applySpecularAA": true - }, - "metallic": { - "textureMap": "../Textures/details_1k_metallic.png" - }, - "normal": { - "textureMap": "../Textures/details_1k_normal.png" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/details_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.02500000037252903, - "pdo": true, - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/details_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/details_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.normalMap": "../Textures/details_1k_normal.png", + "clearCoat.roughness": 0.25, + "general.applySpecularAA": true, + "metallic.textureMap": "../Textures/details_1k_metallic.png", + "normal.textureMap": "../Textures/details_1k_normal.png", + "occlusion.diffuseTextureMap": "../Textures/details_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.02500000037252903, + "parallax.pdo": true, + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/details_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricblue.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricblue.material index 19ce3a6839..4cb149b1dc 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricblue.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricblue.material @@ -1,39 +1,21 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/fabricBlue_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.0, - 0.15049973130226135, - 1.0, - 1.0 - ], - "factor": 0.30000001192092896 - }, - "metallic": { - "textureMap": "../Textures/fabric_metallic.png" - }, - "normal": { - "factor": 0.5, - "textureMap": "../Textures/fabric_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/fabric_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "../Textures/fabric_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/fabricBlue_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.0, + 0.15049973130226135, + 1.0, + 1.0 + ], + "irradiance.factor": 0.30000001192092896, + "metallic.textureMap": "../Textures/fabric_metallic.png", + "normal.factor": 0.5, + "normal.textureMap": "../Textures/fabric_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/fabric_ao.png", + "opacity.factor": 1.0, + "roughness.textureMap": "../Textures/fabric_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricgreen.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricgreen.material index 94b8270fef..9a6746ba12 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricgreen.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricgreen.material @@ -1,39 +1,21 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/fabricGreen_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.0, - 0.15292592346668243, - 0.0012207217514514923, - 1.0 - ], - "factor": 0.30000001192092896 - }, - "metallic": { - "textureMap": "../Textures/fabric_metallic.png" - }, - "normal": { - "factor": 0.5, - "textureMap": "../Textures/fabric_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/fabric_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "../Textures/fabric_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/fabricGreen_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.0, + 0.15292592346668243, + 0.0012207217514514923, + 1.0 + ], + "irradiance.factor": 0.30000001192092896, + "metallic.textureMap": "../Textures/fabric_metallic.png", + "normal.factor": 0.5, + "normal.textureMap": "../Textures/fabric_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/fabric_ao.png", + "opacity.factor": 1.0, + "roughness.textureMap": "../Textures/fabric_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricred.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricred.material index 7bd2ecddd0..85cd0e1650 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricred.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_fabricred.material @@ -1,39 +1,21 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/fabricRed_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.42040130496025085, - 0.004654001910239458, - 0.0037232013419270515, - 1.0 - ], - "factor": 0.30000001192092896 - }, - "metallic": { - "textureMap": "../Textures/fabric_metallic.png" - }, - "normal": { - "factor": 0.5, - "textureMap": "../Textures/fabric_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/fabric_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "../Textures/fabric_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/fabricRed_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.42040130496025085, + 0.004654001910239458, + 0.0037232013419270515, + 1.0 + ], + "irradiance.factor": 0.30000001192092896, + "metallic.textureMap": "../Textures/fabric_metallic.png", + "normal.factor": 0.5, + "normal.textureMap": "../Textures/fabric_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/fabric_ao.png", + "opacity.factor": 1.0, + "roughness.textureMap": "../Textures/fabric_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_flagpole.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_flagpole.material index aca6c05d29..53f78ac390 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_flagpole.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_flagpole.material @@ -1,46 +1,24 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/flagpole_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 1.0, - 0.6520485281944275, - 0.7122911214828491, - 1.0 - ] - }, - "metallic": { - "textureMap": "../Textures/flagpole_1k_metallic.png" - }, - "normal": { - "textureMap": "../Textures/flagpole_1k_normal.png" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/flagpole_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.014000000432133675, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/flagpole_1k_roughness.png" - }, - "specularF0": { - "enableMultiScatterCompensation": true - } + "propertyValues": { + "baseColor.textureMap": "../Textures/flagpole_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 1.0, + 0.6520485281944275, + 0.7122911214828491, + 1.0 + ], + "metallic.textureMap": "../Textures/flagpole_1k_metallic.png", + "normal.textureMap": "../Textures/flagpole_1k_normal.png", + "occlusion.diffuseTextureMap": "../Textures/flagpole_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.014000000432133675, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/flagpole_1k_roughness.png", + "specularF0.enableMultiScatterCompensation": true } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_floor.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_floor.material index b75143326d..29aed982e7 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_floor.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_floor.material @@ -1,44 +1,24 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/floor_1k_basecolor.png" - }, - "clearCoat": { - "influenceMap": "../Textures/floor_1k_ao.png", - "normalMap": "../Textures/floor_1k_normal.png", - "roughness": 0.25 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 1.0, - 0.9404135346412659, - 0.8688944578170776, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/floor_1k_normal.png" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/floor_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.012000000104308128, - "pdo": true, - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/floor_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/floor_1k_basecolor.png", + "clearCoat.influenceMap": "../Textures/floor_1k_ao.png", + "clearCoat.normalMap": "../Textures/floor_1k_normal.png", + "clearCoat.roughness": 0.25, + "general.applySpecularAA": true, + "irradiance.color": [ + 1.0, + 0.9404135346412659, + 0.8688944578170776, + 1.0 + ], + "normal.textureMap": "../Textures/floor_1k_normal.png", + "occlusion.diffuseTextureMap": "../Textures/floor_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.012000000104308128, + "parallax.pdo": true, + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/floor_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_leaf.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_leaf.material index 51638d6d94..50c2a119ef 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_leaf.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_leaf.material @@ -1,43 +1,25 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/thorn_basecolor.png" - }, - "clearCoat": { - "factor": 0.05000000074505806, - "normalMap": "../Textures/thorn_normal.jpg", - "roughness": 0.10000000149011612 - }, - "general": { - "applySpecularAA": true, - "doubleSided": true - }, - "irradiance": { - "color": [ - 0.46506446599960327, - 1.0, - 0.3944609761238098, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/thorn_normal.jpg" - }, - "opacity": { - "alphaSource": "Split", - "factor": 0.20000000298023224, - "mode": "Cutout", - "textureMap": "../Textures/thorn_alpha.png" - }, - "parallax": { - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/thorn_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/thorn_basecolor.png", + "clearCoat.factor": 0.05000000074505806, + "clearCoat.normalMap": "../Textures/thorn_normal.jpg", + "clearCoat.roughness": 0.10000000149011612, + "general.applySpecularAA": true, + "general.doubleSided": true, + "irradiance.color": [ + 0.46506446599960327, + 1.0, + 0.3944609761238098, + 1.0 + ], + "normal.textureMap": "../Textures/thorn_normal.jpg", + "opacity.alphaSource": "Split", + "opacity.factor": 0.20000000298023224, + "opacity.mode": "Cutout", + "opacity.textureMap": "../Textures/thorn_alpha.png", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/thorn_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_lion.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_lion.material index eee41e9c13..97dbaa7f18 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_lion.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_lion.material @@ -1,36 +1,22 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/lion_1k_basecolor.png" - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "irradiance": { - "color": [ - 0.5583428740501404, - 0.496940553188324, - 0.4125429093837738, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/lion_1k_normal.jpg" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "../Textures/lion_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/lion_1k_basecolor.png", + "emissive.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "irradiance.color": [ + 0.5583428740501404, + 0.496940553188324, + 0.4125429093837738, + 1.0 + ], + "normal.textureMap": "../Textures/lion_1k_normal.jpg", + "opacity.factor": 1.0, + "roughness.textureMap": "../Textures/lion_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_roof.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_roof.material index fec7bb1e34..6416ee2b55 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_roof.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_roof.material @@ -1,47 +1,27 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureBlendMode": "Lerp", - "textureMap": "../Textures/roof_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.29613184928894043, - 0.3324483036994934, - 0.45078203082084656, - 1.0 - ] - }, - "metallic": { - "textureMap": "../Textures/roof_1k_metallic.png", - "useTexture": false - }, - "normal": { - "factor": 0.5, - "flipY": true, - "textureMap": "../Textures/roof_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/roof_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.019999999552965164, - "quality": "Medium", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/roof_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureBlendMode": "Lerp", + "baseColor.textureMap": "../Textures/roof_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.29613184928894043, + 0.3324483036994934, + 0.45078203082084656, + 1.0 + ], + "metallic.textureMap": "../Textures/roof_1k_metallic.png", + "metallic.useTexture": false, + "normal.factor": 0.5, + "normal.flipY": true, + "normal.textureMap": "../Textures/roof_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/roof_1k_ao.png", + "opacity.factor": 1.0, + "parallax.algorithm": "ContactRefinement", + "parallax.factor": 0.019999999552965164, + "parallax.quality": "Medium", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/roof_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vase.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vase.material index da7a9de3a8..4722c4a2ff 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vase.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vase.material @@ -1,46 +1,24 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/vase_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 1.0, - 0.8713664412498474, - 0.6021667718887329, - 1.0 - ] - }, - "metallic": { - "textureMap": "../Textures/vase_1k_metallic.png" - }, - "normal": { - "textureMap": "../Textures/vase_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/vase_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.027000000700354576, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/vase_1k_roughness.png" - }, - "specularF0": { - "enableMultiScatterCompensation": true - } + "propertyValues": { + "baseColor.textureMap": "../Textures/vase_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 1.0, + 0.8713664412498474, + 0.6021667718887329, + 1.0 + ], + "metallic.textureMap": "../Textures/vase_1k_metallic.png", + "normal.textureMap": "../Textures/vase_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/vase_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.027000000700354576, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/vase_1k_roughness.png", + "specularF0.enableMultiScatterCompensation": true } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vasehanging.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vasehanging.material index bda7aad38c..31ac0bd369 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vasehanging.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vasehanging.material @@ -1,43 +1,23 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/vaseHanging_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.765606164932251, - 1.0, - 0.7052567601203918, - 1.0 - ] - }, - "metallic": { - "textureMap": "../Textures/vaseHanging_1k_metallic.png" - }, - "normal": { - "textureMap": "../Textures/vaseHanging_1k_normal.png" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/vaseHanging_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.04600000008940697, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/vaseHanging_1k_roughness.png" - } + "propertyValues": { + "baseColor.textureMap": "../Textures/vaseHanging_1k_basecolor.png", + "general.applySpecularAA": true, + "irradiance.color": [ + 0.765606164932251, + 1.0, + 0.7052567601203918, + 1.0 + ], + "metallic.textureMap": "../Textures/vaseHanging_1k_metallic.png", + "normal.textureMap": "../Textures/vaseHanging_1k_normal.png", + "occlusion.diffuseTextureMap": "../Textures/vaseHanging_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.04600000008940697, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/vaseHanging_1k_roughness.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseplant.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseplant.material index 5546daa0e0..fc92f7beca 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseplant.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseplant.material @@ -1,36 +1,26 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureBlendMode": "Lerp", - "textureMap": "../Textures/vasePlant_1k_basecolor.png" - }, - "general": { - "applySpecularAA": true, - "doubleSided": true - }, - "irradiance": { - "color": [ - 0.09086747467517853, - 0.4111391007900238, - 0.0474097803235054, - 1.0 - ] - }, - "opacity": { - "alphaSource": "Split", - "factor": 0.23999999463558197, - "mode": "Cutout", - "textureMap": "../Textures/vasePlant_1k_alpha.png" - } + "propertyValues": { + "baseColor.color": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1.0 + ], + "baseColor.textureBlendMode": "Lerp", + "baseColor.textureMap": "../Textures/vasePlant_1k_basecolor.png", + "general.applySpecularAA": true, + "general.doubleSided": true, + "irradiance.color": [ + 0.09086747467517853, + 0.4111391007900238, + 0.0474097803235054, + 1.0 + ], + "opacity.alphaSource": "Split", + "opacity.factor": 0.23999999463558197, + "opacity.mode": "Cutout", + "opacity.textureMap": "../Textures/vasePlant_1k_alpha.png" } } \ No newline at end of file diff --git a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseround.material b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseround.material index 268e3ab613..049859e37e 100644 --- a/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseround.material +++ b/AutomatedTesting/Gem/Sponza/Assets/objects/sponza_mat_vaseround.material @@ -1,49 +1,27 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "../Textures/vaseRound_1k_basecolor.png" - }, - "clearCoat": { - "factor": 0.5, - "influenceMap": "../Textures/vaseRound_1k_ao.png", - "normalMap": "../Textures/vaseRound_1k_normal.jpg", - "roughness": 0.25 - }, - "general": { - "applySpecularAA": true - }, - "irradiance": { - "color": [ - 0.46933698654174805, - 0.3824063539505005, - 0.47861447930336, - 1.0 - ] - }, - "normal": { - "textureMap": "../Textures/vaseRound_1k_normal.jpg" - }, - "occlusion": { - "diffuseTextureMap": "../Textures/vaseRound_1k_ao.png" - }, - "opacity": { - "factor": 1.0 - }, - "parallax": { - "factor": 0.019999999552965164, - "pdo": true, - "quality": "High", - "useTexture": false - }, - "roughness": { - "textureMap": "../Textures/vaseRound_1k_roughness.png" - }, - "specularF0": { - "enableMultiScatterCompensation": true - } + "propertyValues": { + "baseColor.textureMap": "../Textures/vaseRound_1k_basecolor.png", + "clearCoat.factor": 0.5, + "clearCoat.influenceMap": "../Textures/vaseRound_1k_ao.png", + "clearCoat.normalMap": "../Textures/vaseRound_1k_normal.jpg", + "clearCoat.roughness": 0.25, + "general.applySpecularAA": true, + "irradiance.color": [ + 0.46933698654174805, + 0.3824063539505005, + 0.47861447930336, + 1.0 + ], + "normal.textureMap": "../Textures/vaseRound_1k_normal.jpg", + "occlusion.diffuseTextureMap": "../Textures/vaseRound_1k_ao.png", + "opacity.factor": 1.0, + "parallax.factor": 0.019999999552965164, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.useTexture": false, + "roughness.textureMap": "../Textures/vaseRound_1k_roughness.png", + "specularF0.enableMultiScatterCompensation": true } } \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic.material index 6af3ceb0c1..7fbdfd2e4e 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic.material @@ -1,32 +1,26 @@ { "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "baseColor": { - "color": [ 1.0, 1.0, 1.0 ], - "factor": 0.75, - "useTexture": false, - "textureMap": "" - }, - "metallic": { - "factor": 0.0, - "useTexture": false, - "textureMap": "" - }, - "roughness": { - "factor": 0.0, - "useTexture": false, - "textureMap": "" - }, - "specularF0": { - "factor": 0.5, - "useTexture": false, - "textureMap": "" - }, - "normal": { - "factor": 1.0, - "useTexture": false, - "textureMap": "" - } + "propertyValues": { + "baseColor.color": [ + 1.0, + 1.0, + 1.0 + ], + "baseColor.factor": 0.75, + "baseColor.textureMap": "", + "baseColor.useTexture": false, + "metallic.factor": 0.0, + "metallic.textureMap": "", + "metallic.useTexture": false, + "normal.factor": 1.0, + "normal.textureMap": "", + "normal.useTexture": false, + "roughness.factor": 0.0, + "roughness.textureMap": "", + "roughness.useTexture": false, + "specularF0.factor": 0.5, + "specularF0.textureMap": "", + "specularF0.useTexture": false } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r00.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r00.material index 541bd83981..0a84ea1a7f 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r00.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r00.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.0 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.0 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r01.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r01.material index 19691258e0..2eca4d2cee 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r01.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r01.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.1 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.10000000149011612 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r02.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r02.material index 46fda2aab1..3bd1791d7c 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r02.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r02.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.2 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.20000000298023224 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r03.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r03.material index 79cf4bf401..15f7e5895d 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r03.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r03.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.3 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.30000001192092896 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r04.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r04.material index 9aabf3e158..e33d6a9e8f 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r04.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r04.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.4 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.4000000059604645 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r05.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r05.material index 8b02f225fc..d7f663fefc 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r05.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r05.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.5 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.5 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r06.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r06.material index 5b089da4bd..7a3be6c791 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r06.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r06.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.6 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.6000000238418579 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r07.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r07.material index 25741cf689..ad59f0bc0a 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r07.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r07.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.7 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.699999988079071 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r08.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r08.material index 04103273f2..ed24021dce 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r08.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r08.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.8 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.800000011920929 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r09.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r09.material index 74eb68da99..34d75d2d03 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r09.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r09.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 0.9 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 0.8999999761581421 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r10.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r10.material index 3533ca6676..d540e239a0 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r10.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m00_r10.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 0.0 - }, - "roughness": { - "factor": 1.0 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 0.0, + "roughness.factor": 1.0 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r00.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r00.material index d2ce0fadc9..b3ac239778 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r00.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r00.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.0 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.0 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r01.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r01.material index 8d96ea6217..fc1b49c65a 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r01.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r01.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.1 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.10000000149011612 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r02.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r02.material index e8feb87283..5058b2f562 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r02.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r02.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.2 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.20000000298023224 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r03.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r03.material index c14591bd52..f1395484c8 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r03.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r03.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.3 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.30000001192092896 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r04.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r04.material index 60a3167f02..87d741f0bc 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r04.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r04.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.4 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.4000000059604645 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r05.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r05.material index d71ff06961..128b1a45f2 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r05.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r05.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.5 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.5 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r06.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r06.material index 6fa8cfe1a6..00c7864af4 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r06.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r06.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.6 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.6000000238418579 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r07.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r07.material index 773cc66f03..74e26c35e4 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r07.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r07.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.7 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.699999988079071 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r08.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r08.material index 6971597d1d..6f8140338c 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r08.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r08.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.8 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.800000011920929 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r09.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r09.material index c2d8cc47bd..bbfaca32a1 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r09.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r09.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.9 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 0.8999999761581421 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r10.material b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r10.material index 906879b0ea..5c375fde88 100644 --- a/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r10.material +++ b/AutomatedTesting/Levels/Graphics/PbrMaterialChart/materials/basic_m10_r10.material @@ -1,13 +1,9 @@ { - "parentMaterial": "./basic.material", "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 1.0 - } + "parentMaterial": "./basic.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.factor": 1.0 } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Materials/DefaultPBR.material b/AutomatedTesting/Materials/DefaultPBR.material index f0990f148c..918af4b939 100644 --- a/AutomatedTesting/Materials/DefaultPBR.material +++ b/AutomatedTesting/Materials/DefaultPBR.material @@ -1,4 +1,4 @@ { "materialType": "Materials/Types/StandardPBR.materialtype", "parentMaterial": "Materials/Presets/PBR/default_grid.material" -} +} \ No newline at end of file diff --git a/AutomatedTesting/Materials/DefaultPBRTransparent.material b/AutomatedTesting/Materials/DefaultPBRTransparent.material index a7000d5371..9a0c3ba360 100644 --- a/AutomatedTesting/Materials/DefaultPBRTransparent.material +++ b/AutomatedTesting/Materials/DefaultPBRTransparent.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "Materials/Presets/PBR/default_grid.material", "materialTypeVersion": 3, - "properties": { - "opacity": { - "mode": "Blended" - } + "parentMaterial": "Materials/Presets/PBR/default_grid.material", + "propertyValues": { + "opacity.mode": "Blended" } } \ No newline at end of file diff --git a/AutomatedTesting/Materials/MinimalBlue.material b/AutomatedTesting/Materials/MinimalBlue.material index 7310a90250..62d4659a96 100644 --- a/AutomatedTesting/Materials/MinimalBlue.material +++ b/AutomatedTesting/Materials/MinimalBlue.material @@ -1,17 +1,13 @@ { - "description": "", - "parentMaterial": "", "materialType": "TestData/Materials/Types/MinimalPBR.materialtype", "materialTypeVersion": 3, - "properties": { - "settings": { - "color": [ - 0.08522164076566696, - 0.11898985505104065, - 1.0, - 1.0 - ], - "roughness": 0.33000001311302185 - } + "propertyValues": { + "settings.color": [ + 0.08522164076566696, + 0.11898985505104065, + 1.0, + 1.0 + ], + "settings.roughness": 0.33000001311302185 } } \ No newline at end of file diff --git a/AutomatedTesting/Materials/UVs.material b/AutomatedTesting/Materials/UVs.material index bd66df622e..4515b7c234 100644 --- a/AutomatedTesting/Materials/UVs.material +++ b/AutomatedTesting/Materials/UVs.material @@ -1,3 +1,3 @@ { "materialType": "UVs.materialtype" -} +} \ No newline at end of file diff --git a/AutomatedTesting/Materials/basic_grey.material b/AutomatedTesting/Materials/basic_grey.material index 6ecc1e029a..740a17b163 100644 --- a/AutomatedTesting/Materials/basic_grey.material +++ b/AutomatedTesting/Materials/basic_grey.material @@ -1,32 +1,26 @@ { "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 1, - "properties": { - "baseColor": { - "color": [ 0.18, 0.18, 0.18 ], - "factor": 1.0, - "useTexture": false, - "textureMap": "" - }, - "metallic": { - "factor": 0.0, - "useTexture": false, - "textureMap": "" - }, - "roughness": { - "factor": 1.0, - "useTexture": false, - "textureMap": "" - }, - "specularF0": { - "factor": 0.5, - "useTexture": false, - "textureMap": "" - }, - "normal": { - "factor": 1.0, - "useTexture": false, - "textureMap": "" - } + "propertyValues": { + "baseColor.color": [ + 0.18000000715255737, + 0.18000000715255737, + 0.18000000715255737 + ], + "baseColor.factor": 1.0, + "baseColor.textureMap": "", + "baseColor.useTexture": false, + "metallic.factor": 0.0, + "metallic.textureMap": "", + "metallic.useTexture": false, + "normal.factor": 1.0, + "normal.textureMap": "", + "normal.useTexture": false, + "roughness.factor": 1.0, + "roughness.textureMap": "", + "roughness.useTexture": false, + "specularF0.factor": 0.5, + "specularF0.textureMap": "", + "specularF0.useTexture": false } -} +} \ No newline at end of file diff --git a/AutomatedTesting/Materials/decal/airship_symbol_decal.material b/AutomatedTesting/Materials/decal/airship_symbol_decal.material index 40060aafeb..f1faca6105 100644 --- a/AutomatedTesting/Materials/decal/airship_symbol_decal.material +++ b/AutomatedTesting/Materials/decal/airship_symbol_decal.material @@ -1,36 +1,20 @@ { "materialType": "Materials/Types/StandardPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "textureMap": "Materials/decal/airship_symbol_decal.tif" - }, - "general": { - "doubleSided": true - }, - "metallic": { - "useTexture": false - }, - "normal": { - "useTexture": false - }, - "opacity": { - "alphaSource": "Split", - "factor": 0.6899999976158142, - "mode": "Cutout", - "textureMap": "Materials/decal/airship_symbol_decal.tif" - }, - "roughness": { - "useTexture": false - }, - "specularF0": { - "useTexture": false - }, - "uv": { - "center": [ - 0.0, - 1.0 - ] - } + "propertyValues": { + "baseColor.textureMap": "Materials/decal/airship_symbol_decal.tif", + "general.doubleSided": true, + "metallic.useTexture": false, + "normal.useTexture": false, + "opacity.alphaSource": "Split", + "opacity.factor": 0.6899999976158142, + "opacity.mode": "Cutout", + "opacity.textureMap": "Materials/decal/airship_symbol_decal.tif", + "roughness.useTexture": false, + "specularF0.useTexture": false, + "uv.center": [ + 0.0, + 1.0 + ] } } \ No newline at end of file diff --git a/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material b/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material index 52c323b454..a918ef45be 100644 --- a/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material +++ b/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material @@ -1,13 +1,9 @@ { - "description": "", "materialType": "Materials/Types/Skin.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "wrinkleLayers": { - "count": 3, - "enable": true, - "showBlendValues": true - } + "propertyValues": { + "wrinkleLayers.count": 3, + "wrinkleLayers.enable": true, + "wrinkleLayers.showBlendValues": true } -} +} \ No newline at end of file diff --git a/Code/Framework/AzCore/AzCore/DOM/DomComparison.cpp b/Code/Framework/AzCore/AzCore/DOM/DomComparison.cpp new file mode 100644 index 0000000000..dc21761670 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomComparison.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AZ::Dom +{ + PatchUndoRedoInfo GenerateHierarchicalDeltaPatch( + const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params) + { + PatchUndoRedoInfo patches; + + auto AddPatch = [&patches](PatchOperation op, PatchOperation inverse) + { + patches.m_forwardPatches.PushBack(AZStd::move(op)); + patches.m_inversePatches.PushFront(AZStd::move(inverse)); + }; + + AZStd::function compareValues; + + struct PendingComparison + { + Path m_path; + const Value& m_before; + const Value& m_after; + + PendingComparison(Path path, const Value& before, const Value& after) + : m_path(AZStd::move(path)) + , m_before(before) + , m_after(after) + { + } + }; + AZStd::queue entriesToCompare; + + AZStd::unordered_set desiredKeys; + auto compareObjects = [&](const Path& path, const Value& before, const Value& after) + { + desiredKeys.clear(); + Path subPath = path; + for (auto it = after.MemberBegin(); it != after.MemberEnd(); ++it) + { + desiredKeys.insert(it->first.GetHash()); + subPath.Push(it->first); + auto beforeIt = before.FindMember(it->first); + if (beforeIt == before.MemberEnd()) + { + AddPatch(PatchOperation::AddOperation(subPath, it->second), PatchOperation::RemoveOperation(subPath)); + } + else + { + entriesToCompare.emplace(subPath, beforeIt->second, it->second); + } + subPath.Pop(); + } + + for (auto it = before.MemberBegin(); it != before.MemberEnd(); ++it) + { + if (!desiredKeys.contains(it->first.GetHash())) + { + subPath.Push(it->first); + AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, it->second)); + subPath.Pop(); + } + } + }; + + auto compareArrays = [&](const Path& path, const Value& before, const Value& after) + { + const size_t beforeSize = before.ArraySize(); + const size_t afterSize = after.ArraySize(); + + // If more than replaceThreshold values differ, do a replace operation instead + if (params.m_replaceThreshold != DeltaPatchGenerationParameters::NoReplace) + { + size_t changedValueCount = 0; + const size_t entriesToEnumerate = AZStd::min(beforeSize, afterSize); + for (size_t i = 0; i < entriesToEnumerate; ++i) + { + if (before[i] != after[i]) + { + ++changedValueCount; + if (changedValueCount >= params.m_replaceThreshold) + { + AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before)); + return; + } + } + } + } + + Path subPath = path; + for (size_t i = 0; i < afterSize; ++i) + { + if (i >= beforeSize) + { + subPath.Push(PathEntry(PathEntry::EndOfArrayIndex)); + AddPatch(PatchOperation::AddOperation(subPath, after[i]), PatchOperation::RemoveOperation(subPath)); + subPath.Pop(); + } + else + { + subPath.Push(PathEntry(i)); + entriesToCompare.emplace(subPath, before[i], after[i]); + subPath.Pop(); + } + } + + if (beforeSize > afterSize) + { + subPath.Push(PathEntry(PathEntry::EndOfArrayIndex)); + for (size_t i = beforeSize; i > afterSize; --i) + { + AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, before[i - 1])); + } + } + }; + + auto compareNodes = [&](const Path& path, const Value& before, const Value& after) + { + if (before.GetNodeName() != after.GetNodeName()) + { + AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before)); + } + else + { + compareObjects(path, before, after); + compareArrays(path, before, after); + } + }; + + compareValues = [&](const Path& path, const Value& before, const Value& after) + { + if (before.GetType() != after.GetType()) + { + AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before)); + } + else if (before == after) + { + // If a shallow comparison succeeds we're pointing to an identical value or container + // and don't need to drill down. + return; + } + else if (before.IsObject()) + { + compareObjects(path, before, after); + } + else if (before.IsArray()) + { + compareArrays(path, before, after); + } + else if (before.IsNode()) + { + compareNodes(path, before, after); + } + else + { + AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before)); + } + }; + + entriesToCompare.emplace(Path(), beforeState, afterState); + while (!entriesToCompare.empty()) + { + PendingComparison& comparison = entriesToCompare.front(); + compareValues(comparison.m_path, comparison.m_before, comparison.m_after); + entriesToCompare.pop(); + } + return patches; + } +} diff --git a/Code/Framework/AzCore/AzCore/DOM/DomComparison.h b/Code/Framework/AzCore/AzCore/DOM/DomComparison.h new file mode 100644 index 0000000000..f882887cba --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomComparison.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace AZ::Dom +{ + //! A set of patches for applying a change and doing the inverse operation. + struct PatchUndoRedoInfo + { + Patch m_forwardPatches; + Patch m_inversePatches; + }; + + //! Parameters for GenerateHierarchicalDeltaPatch. + struct DeltaPatchGenerationParameters + { + static constexpr size_t NoReplace = AZStd::numeric_limits::max(); + static constexpr size_t AlwaysFullReplace = 0; + + //! The threshold of changed values in a node or array which, if exceeded, will cause the generation to create an + //! entire "replace" oepration instead. If set to NoReplace, no replacement will occur. + size_t m_replaceThreshold = 3; + }; + + //! Generates a set of patches such that m_forwardPatches.Apply(beforeState) shall produce a document equivalent to afterState, and + //! a subsequent m_inversePatches.Apply(beforeState) shall produce the original document. This patch generation strategy does a + //! hierarchical comparison and is not guaranteed to create the minimal set of patches required to transform between the two states. + PatchUndoRedoInfo GenerateHierarchicalDeltaPatch(const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params = {}); +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomPatch.cpp b/Code/Framework/AzCore/AzCore/DOM/DomPatch.cpp new file mode 100644 index 0000000000..dc0bff4e7c --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomPatch.cpp @@ -0,0 +1,799 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +namespace AZ::Dom +{ + PatchOperation::PatchOperation(Path destinationPath, Type type, Value value) + : m_domPath(AZStd::move(destinationPath)) + , m_type(type) + , m_value(AZStd::move(value)) + { + } + + PatchOperation::PatchOperation(Path destinationPath, Type type, Path sourcePath) + : m_domPath(AZStd::move(destinationPath)) + , m_type(type) + , m_value(AZStd::move(sourcePath)) + { + } + + PatchOperation::PatchOperation(Path destinationPath, Type type) + : m_domPath(AZStd::move(destinationPath)) + , m_type(type) + { + } + + bool PatchOperation::operator==(const PatchOperation& rhs) const + { + if (m_type != rhs.m_type) + { + return false; + } + + switch (m_type) + { + case Type::Add: + return m_domPath == rhs.m_domPath && Utils::DeepCompareIsEqual(GetValue(), rhs.GetValue()); + case Type::Remove: + return m_domPath == rhs.m_domPath; + case Type::Replace: + return m_domPath == rhs.m_domPath && Utils::DeepCompareIsEqual(GetValue(), rhs.GetValue()); + case Type::Copy: + return m_domPath == rhs.m_domPath && GetSourcePath() == rhs.GetSourcePath(); + case Type::Move: + return m_domPath == rhs.m_domPath && GetSourcePath() == rhs.GetSourcePath(); + case Type::Test: + return m_domPath == rhs.m_domPath && Utils::DeepCompareIsEqual(GetValue(), rhs.GetValue()); + default: + AZ_Assert(false, "PatchOperation::GetDomRepresentation: invalid patch type specified"); + return false; + } + } + + bool PatchOperation::operator!=(const PatchOperation& rhs) const + { + return !operator==(rhs); + } + + PatchOperation::Type PatchOperation::GetType() const + { + return m_type; + } + + void PatchOperation::SetType(Type type) + { + m_type = type; + } + + const Path& PatchOperation::GetDestinationPath() const + { + return m_domPath; + } + + void PatchOperation::SetDestinationPath(Path path) + { + m_domPath = path; + } + + const Value& PatchOperation::GetValue() const + { + return AZStd::get(m_value); + } + + void PatchOperation::SetValue(Value value) + { + m_value = AZStd::move(value); + } + + const Path& PatchOperation::GetSourcePath() const + { + return AZStd::get(m_value); + } + + void PatchOperation::SetSourcePath(Path path) + { + m_value = AZStd::move(path); + } + + AZ::Outcome PatchOperation::Apply(Value rootElement) const + { + PatchOutcome outcome = ApplyInPlace(rootElement); + if (!outcome.IsSuccess()) + { + return AZ::Failure(outcome.TakeError()); + } + return AZ::Success(AZStd::move(rootElement)); + } + + PatchOperation::PatchOutcome PatchOperation::ApplyInPlace(Value& rootElement) const + { + switch (m_type) + { + case Type::Add: + return ApplyAdd(rootElement); + case Type::Remove: + return ApplyRemove(rootElement); + case Type::Replace: + return ApplyReplace(rootElement); + case Type::Copy: + return ApplyCopy(rootElement); + case Type::Move: + return ApplyMove(rootElement); + case Type::Test: + return ApplyTest(rootElement); + } + return AZ::Failure("Unsupported DOM patch operation specified"); + } + + Value PatchOperation::GetDomRepresentation() const + { + Value serializedPatch(Dom::Type::Object); + switch (m_type) + { + case Type::Add: + serializedPatch["op"].SetString("add"); + serializedPatch["path"].CopyFromString(GetDestinationPath().ToString()); + serializedPatch["value"] = GetValue(); + break; + case Type::Remove: + serializedPatch["op"].SetString("remove"); + serializedPatch["path"].CopyFromString(GetDestinationPath().ToString()); + break; + case Type::Replace: + serializedPatch["op"].SetString("replace"); + serializedPatch["path"].CopyFromString(GetDestinationPath().ToString()); + serializedPatch["value"] = GetValue(); + break; + case Type::Copy: + serializedPatch["op"].SetString("copy"); + serializedPatch["from"].CopyFromString(GetSourcePath().ToString()); + serializedPatch["path"].CopyFromString(GetDestinationPath().ToString()); + break; + case Type::Move: + serializedPatch["op"].SetString("move"); + serializedPatch["from"].CopyFromString(GetSourcePath().ToString()); + serializedPatch["path"].CopyFromString(GetDestinationPath().ToString()); + break; + case Type::Test: + serializedPatch["op"].SetString("test"); + serializedPatch["path"].CopyFromString(GetDestinationPath().ToString()); + serializedPatch["value"] = GetValue(); + break; + default: + AZ_Assert(false, "PatchOperation::GetDomRepresentation: invalid patch type specified"); + } + return serializedPatch; + } + + AZ::Outcome PatchOperation::CreateFromDomRepresentation(Value domValue) + { + if (!domValue.IsObject()) + { + return AZ::Failure("PatchOperation failed to load: PatchOperation must be specified as an Object"); + } + + auto loadField = [&](const char* field, AZStd::optional type = {}) -> AZ::Outcome + { + auto it = domValue.FindMember(field); + if (it == domValue.MemberEnd()) + { + return AZ::Failure(AZStd::string::format("PatchOperation failed to load: no \"%s\" specified", field)); + } + + if (type.has_value() && it->second.GetType() != type) + { + return AZ::Failure(AZStd::string::format("PatchOperation failed to load: \"%s\" is invalid", field)); + } + + return AZ::Success(it->second); + }; + + auto opLoad = loadField("op", Dom::Type::String); + if (!opLoad.IsSuccess()) + { + return AZ::Failure(opLoad.TakeError()); + } + AZStd::string_view op = opLoad.GetValue().GetString(); + if (op == "add") + { + auto pathLoad = loadField("path", Dom::Type::String); + if (!pathLoad.IsSuccess()) + { + return AZ::Failure(pathLoad.TakeError()); + } + auto valueLoad = loadField("value"); + if (!valueLoad.IsSuccess()) + { + return AZ::Failure(valueLoad.TakeError()); + } + + return AZ::Success(PatchOperation::AddOperation(Path(pathLoad.GetValue().GetString()), valueLoad.TakeValue())); + } + else if (op == "remove") + { + auto pathLoad = loadField("path", Dom::Type::String); + if (!pathLoad.IsSuccess()) + { + return AZ::Failure(pathLoad.TakeError()); + } + + return AZ::Success(PatchOperation::RemoveOperation(Path(pathLoad.GetValue().GetString()))); + } + else if (op == "replace") + { + auto pathLoad = loadField("path", Dom::Type::String); + if (!pathLoad.IsSuccess()) + { + return AZ::Failure(pathLoad.TakeError()); + } + auto valueLoad = loadField("value"); + if (!valueLoad.IsSuccess()) + { + return AZ::Failure(valueLoad.TakeError()); + } + + return AZ::Success(PatchOperation::ReplaceOperation(Path(pathLoad.GetValue().GetString()), valueLoad.TakeValue())); + } + else if (op == "copy") + { + auto destLoad = loadField("path", Dom::Type::String); + if (!destLoad.IsSuccess()) + { + return AZ::Failure(destLoad.TakeError()); + } + auto sourceLoad = loadField("from", Dom::Type::String); + if (!sourceLoad.IsSuccess()) + { + return AZ::Failure(sourceLoad.TakeError()); + } + + return AZ::Success( + PatchOperation::CopyOperation(Path(destLoad.GetValue().GetString()), Path(sourceLoad.GetValue().GetString()))); + } + else if (op == "move") + { + auto destLoad = loadField("path", Dom::Type::String); + if (!destLoad.IsSuccess()) + { + return AZ::Failure(destLoad.TakeError()); + } + auto sourceLoad = loadField("from", Dom::Type::String); + if (!sourceLoad.IsSuccess()) + { + return AZ::Failure(sourceLoad.TakeError()); + } + + return AZ::Success( + PatchOperation::MoveOperation(Path(destLoad.GetValue().GetString()), Path(sourceLoad.GetValue().GetString()))); + } + else if (op == "test") + { + auto pathLoad = loadField("path", Dom::Type::String); + if (!pathLoad.IsSuccess()) + { + return AZ::Failure(pathLoad.TakeError()); + } + auto valueLoad = loadField("value"); + if (!valueLoad.IsSuccess()) + { + return AZ::Failure(valueLoad.TakeError()); + } + + return AZ::Success(PatchOperation::TestOperation(Path(pathLoad.GetValue().GetString()), valueLoad.TakeValue())); + } + else + { + return AZ::Failure("PatchOperation failed to create DOM representation: invalid \"op\" specified"); + } + } + + AZ::Outcome, AZStd::string> PatchOperation::GetInverse(Value stateBeforeApplication) const + { + switch (m_type) + { + case Type::Add: + { + // Add -> Replace (if value already existed in an object) otherwise + // Add -> Remove + if (m_domPath.Size() > 0 && m_domPath[m_domPath.Size() - 1].IsKey()) + { + const Value* existingValue = stateBeforeApplication.FindChild(m_domPath); + if (existingValue != nullptr) + { + return AZ::Success({PatchOperation::ReplaceOperation(m_domPath, *existingValue)}); + } + } + return AZ::Success({PatchOperation::RemoveOperation(m_domPath)}); + } + case Type::Remove: + { + // Remove -> Add + const Value* existingValue = stateBeforeApplication.FindChild(m_domPath); + if (existingValue == nullptr) + { + AZStd::string errorMessage = "Unable to invert DOM remove patch, source path not found: "; + m_domPath.AppendToString(errorMessage); + return AZ::Failure(AZStd::move(errorMessage)); + } + return AZ::Success({PatchOperation::AddOperation(m_domPath, *existingValue)}); + } + case Type::Replace: + { + // Replace -> Replace (with old value) + const Value* existingValue = stateBeforeApplication.FindChild(m_domPath); + if (existingValue == nullptr) + { + AZStd::string errorMessage = "Unable to invert DOM replace patch, source path not found: "; + m_domPath.AppendToString(errorMessage); + return AZ::Failure(AZStd::move(errorMessage)); + } + return AZ::Success({PatchOperation::ReplaceOperation(m_domPath, *existingValue)}); + } + case Type::Copy: + { + // Copy -> Replace (with old value) + const Value* existingValue = stateBeforeApplication.FindChild(m_domPath); + if (existingValue == nullptr) + { + AZStd::string errorMessage = "Unable to invert DOM copy patch, source path not found: "; + m_domPath.AppendToString(errorMessage); + return AZ::Failure(AZStd::move(errorMessage)); + } + return AZ::Success({PatchOperation::ReplaceOperation(m_domPath, *existingValue)}); + } + case Type::Move: + { + const Value* sourceValue = stateBeforeApplication.FindChild(GetSourcePath()); + if (sourceValue == nullptr) + { + AZStd::string errorMessage = "Unable to invert DOM copy patch, source path not found: "; + m_domPath.AppendToString(errorMessage); + return AZ::Failure(AZStd::move(errorMessage)); + } + + // If there was a value at the destination path, invert with an add / replace + const Value* destinationValue = stateBeforeApplication.FindChild(GetDestinationPath()); + if (destinationValue != nullptr) + { + InversePatches result({PatchOperation::AddOperation(GetSourcePath(), *sourceValue)}); + result.push_back(PatchOperation::ReplaceOperation(GetDestinationPath(), *destinationValue)); + return AZ::Success({ + PatchOperation::AddOperation(GetSourcePath(), *sourceValue), + PatchOperation::ReplaceOperation(GetDestinationPath(), *destinationValue), + }); + } + // Otherwise, just do a move + return AZ::Success({PatchOperation::MoveOperation(GetDestinationPath(), GetSourcePath())}); + } + case Type::Test: + { + // Test -> Test (no change) + // When inverting a sequence of patches, applying them in reverse order should allow the test to continue to succeed + return AZ::Success({*this}); + } + } + return AZ::Failure("Unable to invert DOM patch, unknown type specified"); + } + + AZ::Outcome PatchOperation::LookupPath( + Value& rootElement, const Path& path, ExistenceCheckFlags flags) + { + const bool verifyFullPath = (flags & ExistenceCheckFlags::VerifyFullPath) != ExistenceCheckFlags::DefaultExistenceCheck; + const bool allowEndOfArray = (flags & ExistenceCheckFlags::AllowEndOfArray) != ExistenceCheckFlags::DefaultExistenceCheck; + + Path target = path; + if (target.IsEmpty()) + { + Value wrapper(Dom::Type::Array); + wrapper.ArrayPushBack(rootElement); + return AZ::Success({ wrapper, PathEntry(0) }); + } + + if (verifyFullPath || !allowEndOfArray) + { + for (size_t i = 0; i < path.Size(); ++i) + { + const PathEntry& entry = path[i]; + if (entry.IsEndOfArray() && (!allowEndOfArray || i != path.Size() - 1)) + { + return AZ::Failure("Append to array index (\"-\") specified for path that must already exist"); + } + } + } + + PathEntry destinationIndex = target[target.Size() - 1]; + target.Pop(); + + Value* targetValue = rootElement.FindMutableChild(target); + if (targetValue == nullptr) + { + AZStd::string errorMessage = "Path not found: "; + target.AppendToString(errorMessage); + return AZ::Failure(AZStd::move(errorMessage)); + } + + if (destinationIndex.IsIndex() || destinationIndex.IsEndOfArray()) + { + if (!targetValue->IsArray() && !targetValue->IsNode()) + { + return AZ::Failure("Array index specified for a value that is not an array or node"); + } + + if (destinationIndex.IsIndex() && destinationIndex.GetIndex() >= targetValue->ArraySize()) + { + return AZ::Failure("Array index out bounds"); + } + } + else + { + if (!targetValue->IsObject() && !targetValue->IsNode()) + { + return AZ::Failure("Key specified for a value that is not an object or node"); + } + + if (verifyFullPath) + { + if (auto it = targetValue->FindMember(destinationIndex.GetKey()); it == targetValue->MemberEnd()) + { + return AZ::Failure("Key not found in container"); + } + } + } + + return AZ::Success({ *targetValue, AZStd::move(destinationIndex) }); + } + + PatchOperation::PatchOutcome PatchOperation::ApplyAdd(Value& rootElement) const + { + auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::AllowEndOfArray); + if (!pathLookup.IsSuccess()) + { + return AZ::Failure(pathLookup.TakeError()); + } + const PathContext& context = pathLookup.GetValue(); + const PathEntry& destinationIndex = context.m_key; + Value& targetValue = context.m_value; + + if (destinationIndex.IsIndex() || destinationIndex.IsEndOfArray()) + { + if (destinationIndex.IsEndOfArray()) + { + targetValue.ArrayPushBack(GetValue()); + } + else + { + const size_t index = destinationIndex.GetIndex(); + auto& arrayToChange = targetValue.GetMutableArray(); + arrayToChange.insert(arrayToChange.begin() + index, GetValue()); + } + } + else + { + targetValue[destinationIndex] = GetValue(); + } + return AZ::Success(); + } + + PatchOperation::PatchOutcome PatchOperation::ApplyRemove(Value& rootElement) const + { + auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::VerifyFullPath | ExistenceCheckFlags::AllowEndOfArray); + if (!pathLookup.IsSuccess()) + { + return AZ::Failure(pathLookup.TakeError()); + } + const PathContext& context = pathLookup.GetValue(); + const PathEntry& destinationIndex = context.m_key; + Value& targetValue = context.m_value; + + if (destinationIndex.IsIndex() || destinationIndex.IsEndOfArray()) + { + size_t index = destinationIndex.IsEndOfArray() ? targetValue.ArraySize() - 1 : destinationIndex.GetIndex(); + targetValue.ArrayErase(targetValue.MutableArrayBegin() + index); + } + else + { + auto it = targetValue.FindMutableMember(destinationIndex.GetKey()); + targetValue.EraseMember(it); + } + return AZ::Success(); + } + + PatchOperation::PatchOutcome PatchOperation::ApplyReplace(Value& rootElement) const + { + auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::VerifyFullPath); + if (!pathLookup.IsSuccess()) + { + return AZ::Failure(pathLookup.TakeError()); + } + + rootElement[m_domPath] = GetValue(); + return AZ::Success(); + } + + PatchOperation::PatchOutcome PatchOperation::ApplyCopy(Value& rootElement) const + { + auto sourceLookup = LookupPath(rootElement, GetSourcePath(), ExistenceCheckFlags::VerifyFullPath); + if (!sourceLookup.IsSuccess()) + { + return AZ::Failure(sourceLookup.TakeError()); + } + + auto destLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::AllowEndOfArray); + if (!destLookup.IsSuccess()) + { + return AZ::Failure(destLookup.TakeError()); + } + + rootElement[m_domPath] = rootElement[GetSourcePath()]; + return AZ::Success(); + } + + PatchOperation::PatchOutcome PatchOperation::ApplyMove(Value& rootElement) const + { + auto sourceLookup = LookupPath(rootElement, GetSourcePath(), ExistenceCheckFlags::VerifyFullPath); + if (!sourceLookup.IsSuccess()) + { + return AZ::Failure(sourceLookup.TakeError()); + } + + auto destLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::AllowEndOfArray); + if (!destLookup.IsSuccess()) + { + return AZ::Failure(destLookup.TakeError()); + } + + Value valueToMove = rootElement[GetSourcePath()]; + const PathContext& sourceContext = sourceLookup.GetValue(); + if (sourceContext.m_key.IsEndOfArray()) + { + sourceContext.m_value.ArrayPopBack(); + } + else if (sourceContext.m_key.IsIndex()) + { + sourceContext.m_value.ArrayErase(sourceContext.m_value.MutableArrayBegin() + sourceContext.m_key.GetIndex()); + } + else + { + sourceContext.m_value.EraseMember(sourceContext.m_key.GetKey()); + } + + rootElement[m_domPath] = AZStd::move(valueToMove); + return AZ::Success(); + } + + PatchOperation::PatchOutcome PatchOperation::ApplyTest(Value& rootElement) const + { + auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::VerifyFullPath); + if (!pathLookup.IsSuccess()) + { + return AZ::Failure(pathLookup.TakeError()); + } + + if (!Utils::DeepCompareIsEqual(rootElement[m_domPath], GetValue())) + { + return AZ::Failure("Test failed, values don't match"); + } + + return AZ::Success(); + } + + namespace PatchApplicationStrategy + { + void HaltOnFailure(PatchApplicationState& state) + { + if (!state.m_outcome.IsSuccess()) + { + state.m_shouldContinue = false; + } + } + + void IgnoreFailureAndContinue([[maybe_unused]] PatchApplicationState& state) + { + } + } // namespace PatchApplicationStrategy + + Patch::Patch(AZStd::initializer_list init) + : m_operations(init) + { + } + + bool Patch::operator==(const Patch& rhs) const + { + if (m_operations.size() != rhs.m_operations.size()) + { + return false; + } + + for (size_t i = 0; i < m_operations.size(); ++i) + { + if (m_operations[i] != rhs.m_operations[i]) + { + return false; + } + } + + return true; + } + + bool Patch::operator!=(const Patch& rhs) const + { + return !operator==(rhs); + } + + const Patch::OperationsContainer& Patch::GetOperations() const + { + return m_operations; + } + + void Patch::PushBack(PatchOperation op) + { + m_operations.push_back(AZStd::move(op)); + } + + void Patch::PushFront(PatchOperation op) + { + m_operations.insert(m_operations.begin(), AZStd::move(op)); + } + + void Patch::Pop() + { + m_operations.pop_back(); + } + + void Patch::Clear() + { + m_operations.clear(); + } + + const PatchOperation& Patch::At(size_t index) const + { + return m_operations[index]; + } + + size_t Patch::Size() const + { + return m_operations.size(); + } + + PatchOperation& Patch::operator[](size_t index) + { + return m_operations[index]; + } + + const PatchOperation& Patch::operator[](size_t index) const + { + return m_operations[index]; + } + + auto Patch::begin() -> OperationsContainer::iterator + { + return m_operations.begin(); + } + + auto Patch::end() -> OperationsContainer::iterator + { + return m_operations.end(); + } + + auto Patch::begin() const -> OperationsContainer::const_iterator + { + return m_operations.begin(); + } + + auto Patch::end() const -> OperationsContainer::const_iterator + { + return m_operations.end(); + } + + auto Patch::cbegin() const -> OperationsContainer::const_iterator + { + return m_operations.begin(); + } + + auto Patch::cend() const -> OperationsContainer::const_iterator + { + return m_operations.end(); + } + + size_t Patch::size() const + { + return m_operations.size(); + } + + AZ::Outcome Patch::Apply(Value rootElement, StrategyFunctor strategy) const + { + auto result = ApplyInPlace(rootElement, strategy); + if (!result.IsSuccess()) + { + return AZ::Failure(result.TakeError()); + } + return AZ::Success(AZStd::move(rootElement)); + } + + AZ::Outcome Patch::ApplyInPlace(Value& rootElement, StrategyFunctor strategy) const + { + PatchApplicationState state; + state.m_currentState = &rootElement; + state.m_patch = this; + + for (const PatchOperation& operation : m_operations) + { + state.m_lastOperation = &operation; + state.m_outcome = operation.ApplyInPlace(rootElement); + strategy(state); + if (!state.m_shouldContinue) + { + break; + } + } + return state.m_outcome; + } + + Value Patch::GetDomRepresentation() const + { + Value domValue(Dom::Type::Array); + for (const PatchOperation& operation : m_operations) + { + domValue.ArrayPushBack(operation.GetDomRepresentation()); + } + return domValue; + } + + AZ::Outcome Patch::CreateFromDomRepresentation(Value domValue) + { + if (!domValue.IsArray()) + { + return AZ::Failure("Patch must be an array"); + } + + Patch patch; + for (auto it = domValue.ArrayBegin(); it != domValue.ArrayEnd(); ++it) + { + auto operationLoadResult = PatchOperation::CreateFromDomRepresentation(*it); + if (!operationLoadResult.IsSuccess()) + { + return AZ::Failure(operationLoadResult.TakeError()); + } + patch.PushBack(operationLoadResult.TakeValue()); + } + return AZ::Success(AZStd::move(patch)); + } + + PatchOperation PatchOperation::AddOperation(Path destinationPath, Value value) + { + return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Add, AZStd::move(value)); + } + + PatchOperation PatchOperation::RemoveOperation(Path pathToRemove) + { + return PatchOperation(AZStd::move(pathToRemove), PatchOperation::Type::Remove); + } + + PatchOperation PatchOperation::ReplaceOperation(Path destinationPath, Value value) + { + return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Replace, AZStd::move(value)); + } + + PatchOperation PatchOperation::CopyOperation(Path destinationPath, Path sourcePath) + { + return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Copy, AZStd::move(sourcePath)); + } + + PatchOperation PatchOperation::MoveOperation(Path destinationPath, Path sourcePath) + { + return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Move, AZStd::move(sourcePath)); + } + + PatchOperation PatchOperation::TestOperation(Path testPath, Value value) + { + return PatchOperation(AZStd::move(testPath), PatchOperation::Type::Test, AZStd::move(value)); + } +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomPatch.h b/Code/Framework/AzCore/AzCore/DOM/DomPatch.h new file mode 100644 index 0000000000..2d591a8079 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomPatch.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace AZ::Dom +{ + //! A patch operation that represents an atomic operation for mutating or validating a Value. + //! PatchOperations can be created with helper methods in Patch. /see Patch + class PatchOperation final + { + public: + using PatchOutcome = AZ::Outcome; + + //! The operation to perform. + enum class Type + { + Add, //!< Inserts or replaces the value at DestinationPath with Value + Remove, //!< Removes the entry at DestinationPath + Replace, //!< Replaces the value at DestinationPath with Value + Copy, //!< Copies the contents of SourcePath to DestinationPath + Move, //!< Moves the contents of SourcePath to DestinationPath + Test //!< Ensures the contents of DestinationPath match Value or fails, performs no mutations + }; + + PatchOperation() = default; + PatchOperation(const PatchOperation&) = default; + PatchOperation(PatchOperation&&) = default; + + PatchOperation(Path destionationPath, Type type, Value value); + PatchOperation(Path destionationPath, Type type, Path sourcePath); + PatchOperation(Path path, Type type); + + static PatchOperation AddOperation(Path destinationPath, Value value); + static PatchOperation RemoveOperation(Path pathToRemove); + static PatchOperation ReplaceOperation(Path destinationPath, Value value); + static PatchOperation CopyOperation(Path destinationPath, Path sourcePath); + static PatchOperation MoveOperation(Path destinationPath, Path sourcePath); + static PatchOperation TestOperation(Path testPath, Value value); + + PatchOperation& operator=(const PatchOperation&) = default; + PatchOperation& operator=(PatchOperation&&) = default; + + bool operator==(const PatchOperation& rhs) const; + bool operator!=(const PatchOperation& rhs) const; + + Type GetType() const; + void SetType(Type type); + + const Path& GetDestinationPath() const; + void SetDestinationPath(Path path); + + const Value& GetValue() const; + void SetValue(Value value); + + const Path& GetSourcePath() const; + void SetSourcePath(Path path); + + AZ::Outcome Apply(Value rootElement) const; + PatchOutcome ApplyInPlace(Value& rootElement) const; + + Value GetDomRepresentation() const; + static AZ::Outcome CreateFromDomRepresentation(Value domValue); + + using InversePatches = AZStd::fixed_vector; + AZ::Outcome, AZStd::string> GetInverse(Value stateBeforeApplication) const; + + enum class ExistenceCheckFlags : AZ::u8 + { + DefaultExistenceCheck = 0x0, + VerifyFullPath = 0x1, + AllowEndOfArray = 0x2, + }; + + private: + struct PathContext + { + Value& m_value; + PathEntry m_key; + }; + + static AZ::Outcome LookupPath( + Value& rootElement, const Path& path, ExistenceCheckFlags existenceCheckFlags = ExistenceCheckFlags::DefaultExistenceCheck); + + PatchOutcome ApplyAdd(Value& rootElement) const; + PatchOutcome ApplyRemove(Value& rootElement) const; + PatchOutcome ApplyReplace(Value& rootElement) const; + PatchOutcome ApplyCopy(Value& rootElement) const; + PatchOutcome ApplyMove(Value& rootElement) const; + PatchOutcome ApplyTest(Value& rootElement) const; + + AZStd::variant m_value; + Path m_domPath; + Type m_type; + }; + + AZ_DEFINE_ENUM_BITWISE_OPERATORS(PatchOperation::ExistenceCheckFlags); + + class Patch; + + //! The current state of a Patch application operation. + struct PatchApplicationState + { + //! The outcome of the last operation, may be overridden to produce a different failure outcome. + PatchOperation::PatchOutcome m_outcome; + //! The patch being applied. + const Patch* m_patch = nullptr; + //! The last operation attempted. + const PatchOperation* m_lastOperation = nullptr; + //! The current state of the value being patched, will be returned if the patch operation succeeds. + Value* m_currentState = nullptr; + //! If set to false, the patch operation should halt. + bool m_shouldContinue = true; + }; + + namespace PatchApplicationStrategy + { + //! The default patching strategy. Applies all operations in a patch, but halts if any one operation fails. + void HaltOnFailure(PatchApplicationState& state); + //! Patching strategy that attemps to apply all operations in a patch, but ignores operation failures and continues. + void IgnoreFailureAndContinue(PatchApplicationState& state); + } // namespace PatchApplicationStrategy + + //! A set of operations that can be applied to a Value to produce a new Value. + //! \see PatchOperation + class Patch final + { + public: + using StrategyFunctor = AZStd::function; + using OperationsContainer = AZStd::deque; + + Patch() = default; + Patch(const Patch&) = default; + Patch(Patch&&) = default; + Patch(AZStd::initializer_list init); + + template + Patch(InputIterator first, InputIterator last) + : m_operations(first, last) + { + } + + Patch& operator=(const Patch&) = default; + Patch& operator=(Patch&&) = default; + + bool operator==(const Patch& rhs) const; + bool operator!=(const Patch& rhs) const; + + const OperationsContainer& GetOperations() const; + void PushBack(PatchOperation op); + void PushFront(PatchOperation op); + void Pop(); + void Clear(); + const PatchOperation& At(size_t index) const; + size_t Size() const; + + PatchOperation& operator[](size_t index); + const PatchOperation& operator[](size_t index) const; + + OperationsContainer::iterator begin(); + OperationsContainer::iterator end(); + OperationsContainer::const_iterator begin() const; + OperationsContainer::const_iterator end() const; + OperationsContainer::const_iterator cbegin() const; + OperationsContainer::const_iterator cend() const; + size_t size() const; + + AZ::Outcome Apply(Value rootElement, StrategyFunctor strategy = PatchApplicationStrategy::HaltOnFailure) const; + AZ::Outcome ApplyInPlace(Value& rootElement, StrategyFunctor strategy = PatchApplicationStrategy::HaltOnFailure) const; + + Value GetDomRepresentation() const; + static AZ::Outcome CreateFromDomRepresentation(Value domValue); + + private: + OperationsContainer m_operations; + }; +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomPath.cpp b/Code/Framework/AzCore/AzCore/DOM/DomPath.cpp index bc50a8513c..5f6438518f 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomPath.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomPath.cpp @@ -53,17 +53,20 @@ namespace AZ::Dom bool PathEntry::operator==(size_t value) const { - return IsIndex() && GetIndex() == value; + const size_t* internalValue = AZStd::get_if(&m_value); + return internalValue != nullptr && *internalValue == value; } bool PathEntry::operator==(const AZ::Name& key) const { - return IsKey() && GetKey() == key; + const AZ::Name* internalValue = AZStd::get_if(&m_value); + return internalValue != nullptr && *internalValue == key; } bool PathEntry::operator==(AZStd::string_view key) const { - return IsKey() && GetKey() == AZ::Name(key); + const AZ::Name* internalValue = AZStd::get_if(&m_value); + return internalValue != nullptr && *internalValue == AZ::Name(key); } bool PathEntry::operator!=(const PathEntry& other) const @@ -73,17 +76,17 @@ namespace AZ::Dom bool PathEntry::operator!=(size_t value) const { - return !IsIndex() || GetIndex() != value; + return !operator==(value); } bool PathEntry::operator!=(const AZ::Name& key) const { - return !IsKey() || GetKey() != key; + return !operator==(key); } bool PathEntry::operator!=(AZStd::string_view key) const { - return !IsKey() || GetKey() != AZ::Name(key); + return !operator==(key); } void PathEntry::SetEndOfArray() @@ -243,6 +246,11 @@ namespace AZ::Dom return m_entries.size(); } + bool Path::IsEmpty() const + { + return m_entries.empty(); + } + PathEntry& Path::operator[](size_t index) { return m_entries[index]; @@ -320,13 +328,13 @@ namespace AZ::Dom return size; } - void Path::FormatString(char* stringBuffer, size_t bufferSize) const + size_t Path::FormatString(char* stringBuffer, size_t bufferSize) const { size_t bufferIndex = 0; auto putChar = [&](char c) { - if (bufferIndex == bufferSize) + if (bufferIndex >= bufferSize) { return; } @@ -357,6 +365,11 @@ namespace AZ::Dom for (const PathEntry& entry : m_entries) { + if (bufferIndex >= bufferSize) + { + return bufferIndex; + } + putChar(PathSeparator); if (entry.IsEndOfArray()) { @@ -372,7 +385,10 @@ namespace AZ::Dom } } + size_t bytesWritten = bufferIndex; putChar('\0'); + + return bytesWritten; } AZStd::string Path::ToString() const diff --git a/Code/Framework/AzCore/AzCore/DOM/DomPath.h b/Code/Framework/AzCore/AzCore/DOM/DomPath.h index 39f7c7da98..7a031a2c68 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomPath.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomPath.h @@ -111,6 +111,7 @@ namespace AZ::Dom void Clear(); PathEntry At(size_t index) const; size_t Size() const; + bool IsEmpty() const; PathEntry& operator[](size_t index); const PathEntry& operator[](size_t index) const; @@ -128,10 +129,19 @@ namespace AZ::Dom size_t GetStringLength() const; //! Formats a JSON-pointer style path string into the target buffer. //! This operation will fail if bufferSize < GetStringLength() + 1 - void FormatString(char* stringBuffer, size_t bufferSize) const; + //! \return The number of bytes written, excepting the null terminator. + size_t FormatString(char* stringBuffer, size_t bufferSize) const; //! Returns a JSON-pointer style path string for this path. AZStd::string ToString() const; + void AppendToString(AZStd::string& output) const; + template + void AppendToString(T& output) const + { + const size_t startIndex = output.length(); + output.resize_no_construct(startIndex + FormatString(output.data() + startIndex, output.capacity() - startIndex)); + } + //! Reads a JSON-pointer style path from pathString and replaces this path's contents. //! Paths are accepted in the following forms: //! "/path/to/foo/0" diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp index 6b927b7010..13852ba354 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp @@ -25,6 +25,11 @@ extern "C" { # include # include # include + + // versions of LUA before 5.3.x used to define a union that contained a double, a pointer, and a long + // as L_Umaxalign. Newer versions define those inner types in the macro LUAI_MAXALIGN instead but + // no longer actually declare a union around it. For backward compatibility we define the same one here + union L_Umaxalign { LUAI_MAXALIGN; }; } #include @@ -1687,6 +1692,11 @@ LUA_API const Node* lua_getDummyNode() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// + const char* ScriptDataContext::GetInterpreterVersion() + { + return LUA_VERSION; + } + ////////////////////////////////////////////////////////////////////////// ScriptContext* ScriptDataContext::GetScriptContext() const @@ -4367,7 +4377,7 @@ LUA_API const Node* lua_getDummyNode() lua_pushlightuserdata(m_lua, m_owner); int tableRef = luaL_ref(m_lua, LUA_REGISTRYINDEX); (void)tableRef; - AZ_Assert(tableRef == AZ_LUA_SCRIPT_CONTEXT_REF, "Table referece should match %d !", AZ_LUA_SCRIPT_CONTEXT_REF); + AZ_Assert(tableRef == AZ_LUA_SCRIPT_CONTEXT_REF, "Table reference should match %d but is instead %d!", AZ_LUA_SCRIPT_CONTEXT_REF, tableRef); // create a AZGlobals table, we can use internal unodered_map if it's faster (TODO: test which is faster, or if there is a benefit keeping in la) lua_createtable(m_lua, 0, 1024); // pre allocate some values in the hash diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptContext.h b/Code/Framework/AzCore/AzCore/Script/ScriptContext.h index 9a7b6681f9..c8f08a7772 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptContext.h +++ b/Code/Framework/AzCore/AzCore/Script/ScriptContext.h @@ -212,6 +212,10 @@ namespace AZ ~ScriptDataContext() { Reset(); } + //! Retrieve a string representing the current version of the interpreter. + //! Example of use: To signal incompatibility with previously emitted bytecode, to invalidate + static const char* GetInterpreterVersion(); + ScriptContext* GetScriptContext() const; lua_State* GetNativeContext() const { return m_nativeContext; } diff --git a/Code/Framework/AzCore/AzCore/Script/lua/lua.h b/Code/Framework/AzCore/AzCore/Script/lua/lua.h index 7ec14a5b3d..2f69cc5db1 100644 --- a/Code/Framework/AzCore/AzCore/Script/lua/lua.h +++ b/Code/Framework/AzCore/AzCore/Script/lua/lua.h @@ -14,38 +14,13 @@ extern "C" { # include } -// Currently we support Lua 5.1 and later (we have tested with 5.2) - -#if LUA_VERSION_NUM <= 502 - -inline void lua_pushunsigned(lua_State* l, unsigned int v) -{ - lua_pushnumber(l, static_cast(v)); -} - -inline unsigned int lua_tounsigned(lua_State* l, int idx) -{ - return static_cast(lua_tonumber(l, idx)); -} - -#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) - -inline LUA_API int lua_load(lua_State* L, lua_Reader reader, void* data, const char* chunkname, const char* mode) -{ - (void)mode; - return lua_load(L, reader, data, chunkname); -} - -#define LUA_RIDX_LAST 0 -#define LUA_NUMTAGS 9 - -#endif - -#define AZ_LUA_SCRIPT_CONTEXT_REF LUA_RIDX_LAST + 1 -#define AZ_LUA_GLOBALS_TABLE_REF LUA_RIDX_LAST + 2 -#define AZ_LUA_CLASS_TABLE_REF LUA_RIDX_LAST + 3 -#define AZ_LUA_WEAK_CACHE_TABLE_REF LUA_RIDX_LAST + 4 -#define AZ_LUA_ERROR_HANDLER_FUN_REF LUA_RIDX_LAST + 5 +// Currently we support Lua 5.4.4 and later +// note that Lua 5.x defines LUA_RID_LAST + 1 to be an index of a free-list. +#define AZ_LUA_SCRIPT_CONTEXT_REF LUA_RIDX_LAST + 2 +#define AZ_LUA_GLOBALS_TABLE_REF LUA_RIDX_LAST + 3 +#define AZ_LUA_CLASS_TABLE_REF LUA_RIDX_LAST + 4 +#define AZ_LUA_WEAK_CACHE_TABLE_REF LUA_RIDX_LAST + 5 +#define AZ_LUA_ERROR_HANDLER_FUN_REF LUA_RIDX_LAST + 6 #define AZ_LUA_CLASS_METATABLE_NAME_INDEX 1 // can we always read the name from the behavior class??? #define AZ_LUA_CLASS_METATABLE_BEHAVIOR_CLASS 2 diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index a78120f67a..b7821f1d65 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -116,6 +116,8 @@ set(FILES Debug/TraceReflection.h DOM/DomBackend.cpp DOM/DomBackend.h + DOM/DomPatch.cpp + DOM/DomPatch.h DOM/DomPath.cpp DOM/DomPath.h DOM/DomUtils.cpp @@ -126,6 +128,8 @@ set(FILES DOM/DomValueWriter.h DOM/DomVisitor.cpp DOM/DomVisitor.h + DOM/DomComparison.cpp + DOM/DomComparison.h DOM/Backends/JSON/JsonBackend.h DOM/Backends/JSON/JsonSerializationUtils.cpp DOM/Backends/JSON/JsonSerializationUtils.h diff --git a/Code/Framework/AzCore/Tests/DOM/DomPatchBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomPatchBenchmarks.cpp new file mode 100644 index 0000000000..e44ba3ce67 --- /dev/null +++ b/Code/Framework/AzCore/Tests/DOM/DomPatchBenchmarks.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace AZ::Dom::Benchmark +{ + class DomPatchBenchmark : public Tests::DomBenchmarkFixture + { + public: + void TearDownHarness() override + { + m_before = {}; + m_after = {}; + Tests::DomBenchmarkFixture::TearDownHarness(); + } + + void SimpleReplace(benchmark::State& state, bool deepCopy, bool apply) + { + m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before; + m_after["entries"]["Key0"] = Value("replacement string", true); + + RunBenchmarkInternal(state, apply); + } + + void TopLevelReplace(benchmark::State& state, bool apply) + { + m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + m_after = Value(Type::Object); + m_after["UnrelatedKey"] = Value(42); + + RunBenchmarkInternal(state, apply); + } + + void KeyRemove(benchmark::State& state, bool deepCopy, bool apply) + { + m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before; + m_after["entries"].RemoveMember("Key1"); + + RunBenchmarkInternal(state, apply); + } + + void ArrayAppend(benchmark::State& state, bool deepCopy, bool apply) + { + m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before; + m_after["entries"]["Key2"].ArrayPushBack(Value(0)); + + RunBenchmarkInternal(state, apply); + } + + void ArrayPrepend(benchmark::State& state, bool deepCopy, bool apply) + { + m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before; + auto& arr = m_after["entries"]["Key2"].GetMutableArray(); + arr.insert(arr.begin(), Value(42)); + + RunBenchmarkInternal(state, apply); + } + + private: + void RunBenchmarkInternal(benchmark::State& state, bool apply) + { + if (apply) + { + auto patchInfo = GenerateHierarchicalDeltaPatch(m_before, m_after); + for (auto _ : state) + { + auto patchResult = patchInfo.m_forwardPatches.Apply(m_before); + benchmark::DoNotOptimize(patchResult); + } + } + else + { + for (auto _ : state) + { + auto patchInfo = GenerateHierarchicalDeltaPatch(m_before, m_after); + benchmark::DoNotOptimize(patchInfo); + } + } + + state.SetItemsProcessed(state.iterations()); + } + + Value m_before; + Value m_after; + }; + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_ShallowCopy)(benchmark::State& state) + { + SimpleReplace(state, false, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_ShallowCopy) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_DeepCopy)(benchmark::State& state) + { + SimpleReplace(state, true, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_DeepCopy) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_TopLevelReplace)(benchmark::State& state) + { + TopLevelReplace(state, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_TopLevelReplace) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_ShallowCopy)(benchmark::State& state) + { + KeyRemove(state, false, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_ShallowCopy) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_DeepCopy)(benchmark::State& state) + { + KeyRemove(state, true, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_DeepCopy) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_ShallowCopy)(benchmark::State& state) + { + ArrayAppend(state, false, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_ShallowCopy) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_DeepCopy)(benchmark::State& state) + { + ArrayAppend(state, true, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_DeepCopy) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_ArrayPrepend)(benchmark::State& state) + { + ArrayPrepend(state, true, false); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_ArrayPrepend) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_SimpleReplace)(benchmark::State& state) + { + SimpleReplace(state, true, true); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_SimpleReplace) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_TopLevelReplace)(benchmark::State& state) + { + TopLevelReplace(state, true); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_TopLevelReplace) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_KeyRemove)(benchmark::State& state) + { + KeyRemove(state, true, true); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_KeyRemove) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_ArrayAppend)(benchmark::State& state) + { + ArrayAppend(state, true, true); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_ArrayAppend) + + BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_ArrayPrepend)(benchmark::State& state) + { + ArrayPrepend(state, true, true); + } + DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_ArrayPrepend) +} // namespace AZ::Dom::Benchmark diff --git a/Code/Framework/AzCore/Tests/DOM/DomPatchTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomPatchTests.cpp new file mode 100644 index 0000000000..b60c09330f --- /dev/null +++ b/Code/Framework/AzCore/Tests/DOM/DomPatchTests.cpp @@ -0,0 +1,563 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AZ::Dom::Tests +{ + class DomPatchTests : public DomTestFixture + { + public: + void SetUp() override + { + DomTestFixture::SetUp(); + + m_dataset = Value(Type::Object); + m_dataset["arr"].SetArray(); + + m_dataset["node"].SetNode("SomeNode"); + m_dataset["node"]["int"] = 5; + m_dataset["node"]["null"] = Value(); + + for (int i = 0; i < 5; ++i) + { + m_dataset["arr"].ArrayPushBack(Value(i)); + m_dataset["node"].ArrayPushBack(Value(i * 2)); + } + + m_dataset["obj"].SetObject(); + m_dataset["obj"]["foo"] = true; + m_dataset["obj"]["bar"] = false; + + m_deltaDataset = m_dataset; + } + + void TearDown() override + { + m_dataset = m_deltaDataset = Value(); + + DomTestFixture::TearDown(); + } + + PatchUndoRedoInfo GenerateAndVerifyDelta() + { + PatchUndoRedoInfo info = GenerateHierarchicalDeltaPatch(m_dataset, m_deltaDataset); + + auto result = info.m_forwardPatches.Apply(m_dataset); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue(), m_deltaDataset)); + + result = info.m_inversePatches.Apply(result.GetValue()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue(), m_dataset)); + + // Verify serialization of the patches + auto VerifySerialization = [](const Patch& patch) + { + Value serializedPatch = patch.GetDomRepresentation(); + auto deserializePatchResult = Patch::CreateFromDomRepresentation(serializedPatch); + EXPECT_TRUE(deserializePatchResult.IsSuccess()); + EXPECT_EQ(deserializePatchResult.GetValue(), patch); + }; + VerifySerialization(info.m_forwardPatches); + VerifySerialization(info.m_inversePatches); + + return info; + } + + Value m_dataset; + Value m_deltaDataset; + }; + + TEST_F(DomPatchTests, AddOperation_InsertInObject_Succeeds) + { + Path p("/obj/baz"); + PatchOperation op = PatchOperation::AddOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()[p].GetInt64(), 42); + } + + TEST_F(DomPatchTests, AddOperation_ReplaceInObject_Succeeds) + { + Path p("/obj/foo"); + PatchOperation op = PatchOperation::AddOperation(p, Value(false)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()[p].GetBool(), false); + } + + TEST_F(DomPatchTests, AddOperation_InsertObjectKeyInArray_Fails) + { + Path p("/arr/key"); + PatchOperation op = PatchOperation::AddOperation(p, Value(999)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, AddOperation_AppendInArray_Succeeds) + { + Path p("/arr/-"); + PatchOperation op = PatchOperation::AddOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()["arr"][5].GetInt64(), 42); + } + + TEST_F(DomPatchTests, AddOperation_InsertKeyInNode_Succeeds) + { + Path p("/node/attr"); + PatchOperation op = PatchOperation::AddOperation(p, Value(500)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()[p].GetInt64(), 500); + } + + TEST_F(DomPatchTests, AddOperation_ReplaceIndexInNode_Succeeds) + { + Path p("/node/0"); + PatchOperation op = PatchOperation::AddOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()[p].GetInt64(), 42); + } + + TEST_F(DomPatchTests, AddOperation_AppendInNode_Succeeds) + { + Path p("/node/-"); + PatchOperation op = PatchOperation::AddOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()["node"][5].GetInt64(), 42); + } + + TEST_F(DomPatchTests, AddOperation_InvalidPath_Fails) + { + Path p("/non/existent/path"); + PatchOperation op = PatchOperation::AddOperation(p, Value(0)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, RemoveOperation_RemoveKeyFromObject_Succeeds) + { + Path p("/obj/foo"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_FALSE(result.GetValue()["obj"].HasMember("foo")); + } + + TEST_F(DomPatchTests, RemoveOperation_RemoveIndexFromArray_Succeeds) + { + Path p("/arr/0"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()["arr"].ArraySize(), 4); + EXPECT_EQ(result.GetValue()["arr"][0].GetInt64(), 1); + } + + TEST_F(DomPatchTests, RemoveOperation_PopArray_Succeeds) + { + Path p("/arr/-"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + EXPECT_EQ(result.GetValue()["arr"].ArraySize(), 4); + } + + TEST_F(DomPatchTests, RemoveOperation_RemoveKeyFromNode_Succeeds) + { + Path p("/node/int"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_FALSE(result.GetValue()["node"].HasMember("int")); + } + + TEST_F(DomPatchTests, RemoveOperation_RemoveIndexFromNode_Succeeds) + { + Path p("/node/1"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()["node"].ArraySize(), 4); + EXPECT_EQ(result.GetValue()["node"][1].GetInt64(), 4); + } + + TEST_F(DomPatchTests, RemoveOperation_PopIndexFromNode_Succeeds) + { + Path p("/node/-"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()["node"].ArraySize(), 4); + } + + TEST_F(DomPatchTests, RemoveOperation_RemoveKeyFromArray_Fails) + { + Path p("/arr/foo"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, RemoveOperation_InvalidPath_Fails) + { + Path p("/non/existent/path"); + PatchOperation op = PatchOperation::RemoveOperation(p); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, ReplaceOperation_InsertInObject_Fails) + { + Path p("/obj/baz"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, ReplaceOperation_ReplaceInObject_Succeeds) + { + Path p("/obj/foo"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(false)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()[p].GetBool(), false); + } + + TEST_F(DomPatchTests, ReplaceOperation_InsertObjectKeyInArray_Fails) + { + Path p("/arr/key"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(999)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, ReplaceOperation_AppendInArray_Fails) + { + Path p("/arr/-"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, ReplaceOperation_InsertKeyInNode_Fails) + { + Path p("/node/attr"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(500)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, ReplaceOperation_ReplaceIndexInNode_Succeeds) + { + Path p("/node/0"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetValue()[p].GetInt64(), 42); + } + + TEST_F(DomPatchTests, ReplaceOperation_AppendInNode_Fails) + { + Path p("/node/-"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, ReplaceOperation_InvalidPath_Fails) + { + Path p("/non/existent/path"); + PatchOperation op = PatchOperation::ReplaceOperation(p, Value(0)); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, CopyOperation_ArrayToObject_Succeeds) + { + Path dest("/obj/arr"); + Path src("/arr"); + PatchOperation op = PatchOperation::CopyOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest])); + EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue()[src], result.GetValue()[dest])); + } + + TEST_F(DomPatchTests, CopyOperation_ObjectToArrayInRange_Succeeds) + { + Path dest("/arr/0"); + Path src("/obj"); + PatchOperation op = PatchOperation::CopyOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest])); + EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue()[src], result.GetValue()[dest])); + } + + TEST_F(DomPatchTests, CopyOperation_ObjectToArrayOutOfRange_Fails) + { + Path dest("/arr/5"); + Path src("/obj"); + PatchOperation op = PatchOperation::CopyOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, CopyOperation_ObjectToNodeChildInRange_Succeeds) + { + Path dest("/node/0"); + Path src("/obj"); + PatchOperation op = PatchOperation::CopyOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest])); + EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue()[src], result.GetValue()[dest])); + } + + TEST_F(DomPatchTests, CopyOperation_ObjectToNodeChildOutOfRange_Fails) + { + Path dest("/node/5"); + Path src("/obj"); + PatchOperation op = PatchOperation::CopyOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, CopyOperation_InvalidSourcePath_Fails) + { + Path dest("/node/0"); + Path src("/invalid/path"); + PatchOperation op = PatchOperation::CopyOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, CopyOperation_InvalidDestinationPath_Fails) + { + Path dest("/invalid/path"); + Path src("/arr/0"); + PatchOperation op = PatchOperation::CopyOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, MoveOperation_ArrayToObject_Succeeds) + { + Path dest("/obj/arr"); + Path src("/arr"); + PatchOperation op = PatchOperation::MoveOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest])); + EXPECT_FALSE(result.GetValue().HasMember("arr")); + } + + TEST_F(DomPatchTests, MoveOperation_ObjectToArrayInRange_Succeeds) + { + Path dest("/arr/0"); + Path src("/obj"); + PatchOperation op = PatchOperation::MoveOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest])); + EXPECT_FALSE(result.GetValue().HasMember("obj")); + } + + TEST_F(DomPatchTests, MoveOperation_ObjectToArrayOutOfRange_Fails) + { + Path dest("/arr/5"); + Path src("/obj"); + PatchOperation op = PatchOperation::MoveOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, MoveOperation_ObjectToNodeChildInRange_Succeeds) + { + Path dest("/node/0"); + Path src("/obj"); + PatchOperation op = PatchOperation::MoveOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest])); + EXPECT_FALSE(result.GetValue().HasMember("obj")); + } + + TEST_F(DomPatchTests, MoveOperation_ObjectToNodeChildOutOfRange_Fails) + { + Path dest("/node/5"); + Path src("/obj"); + PatchOperation op = PatchOperation::MoveOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, MoveOperation_InvalidSourcePath_Fails) + { + Path dest("/node/0"); + Path src("/invalid/path"); + PatchOperation op = PatchOperation::MoveOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, MoveOperation_InvalidDestinationPath_Fails) + { + Path dest("/invalid/path"); + Path src("/arr/0"); + PatchOperation op = PatchOperation::MoveOperation(dest, src); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, TestOperation_TestCorrectValue_Succeeds) + { + Path path("/arr/1"); + Value value(1); + PatchOperation op = PatchOperation::TestOperation(path, value); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, TestOperation_TestIncorrectValue_Fails) + { + Path path("/arr/1"); + Value value(55); + PatchOperation op = PatchOperation::TestOperation(path, value); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, TestOperation_TestCorrectComplexValue_Succeeds) + { + Path path; + Value value = m_dataset; + PatchOperation op = PatchOperation::TestOperation(path, value); + auto result = op.Apply(m_dataset); + ASSERT_TRUE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, TestOperation_TestIncorrectComplexValue_Fails) + { + Path path; + Value value = m_dataset; + value["arr"][4] = 9; + PatchOperation op = PatchOperation::TestOperation(path, value); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, TestOperation_TestInvalidPath_Fails) + { + Path path("/invalid/path"); + Value value; + PatchOperation op = PatchOperation::TestOperation(path, value); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, TestOperation_TestInsertArrayPath_Fails) + { + Path path("/arr/-"); + Value value(4); + PatchOperation op = PatchOperation::TestOperation(path, value); + auto result = op.Apply(m_dataset); + ASSERT_FALSE(result.IsSuccess()); + } + + TEST_F(DomPatchTests, TestPatch_ReplaceArrayValue) + { + m_deltaDataset["arr"][0] = 5; + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_AppendArrayValue) + { + m_deltaDataset["arr"].ArrayPushBack(Value(7)); + auto result = GenerateAndVerifyDelta(); + + // Ensure the generated patch uses the array append operation + ASSERT_EQ(result.m_forwardPatches.Size(), 1); + EXPECT_TRUE(result.m_forwardPatches[0].GetDestinationPath()[1].IsEndOfArray()); + } + + TEST_F(DomPatchTests, TestPatch_AppendArrayValues) + { + m_deltaDataset["arr"].ArrayPushBack(Value(7)); + m_deltaDataset["arr"].ArrayPushBack(Value(8)); + m_deltaDataset["arr"].ArrayPushBack(Value(9)); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_InsertArrayValue) + { + auto& arr = m_deltaDataset["arr"].GetMutableArray(); + arr.insert(arr.begin(), Value(42)); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_InsertObjectKey) + { + m_deltaDataset["obj"]["newKey"].CopyFromString("test"); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_DeleteObjectKey) + { + m_deltaDataset["obj"].RemoveMember("foo"); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_AppendNodeValues) + { + m_deltaDataset["node"].ArrayPushBack(Value(7)); + m_deltaDataset["node"].ArrayPushBack(Value(8)); + m_deltaDataset["node"].ArrayPushBack(Value(9)); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_InsertNodeValue) + { + auto& node = m_deltaDataset["node"].GetMutableNode(); + node.GetChildren().insert(node.GetChildren().begin(), Value(42)); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_InsertNodeKey) + { + m_deltaDataset["node"]["newKey"].CopyFromString("test"); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_DeleteNodeKey) + { + m_deltaDataset["node"].RemoveMember("int"); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_RenameNode) + { + m_deltaDataset["node"].SetNodeName("RenamedNode"); + GenerateAndVerifyDelta(); + } + + TEST_F(DomPatchTests, TestPatch_ReplaceRoot) + { + m_deltaDataset = Value(Type::Array); + m_deltaDataset.ArrayPushBack(Value(2)); + m_deltaDataset.ArrayPushBack(Value(4)); + m_deltaDataset.ArrayPushBack(Value(6)); + GenerateAndVerifyDelta(); + } +} // namespace AZ::Dom::Tests diff --git a/Code/Framework/AzCore/Tests/DOM/DomPathBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomPathBenchmarks.cpp index 624b24cd20..4741900aa1 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomPathBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomPathBenchmarks.cpp @@ -96,4 +96,25 @@ namespace AZ::Dom::Benchmark state.SetItemsProcessed(3 * state.iterations()); } BENCHMARK_REGISTER_F(DomPathBenchmark, DomPathEntry_IsEndOfArray); + + BENCHMARK_DEFINE_F(DomPathBenchmark, DomPathEntry_Comparison)(benchmark::State& state) + { + PathEntry name("name"); + PathEntry index(0); + PathEntry endOfArray; + endOfArray.SetEndOfArray(); + + for (auto _ : state) + { + benchmark::DoNotOptimize(name == name); + benchmark::DoNotOptimize(name == index); + benchmark::DoNotOptimize(name == endOfArray); + benchmark::DoNotOptimize(index == index); + benchmark::DoNotOptimize(index == endOfArray); + benchmark::DoNotOptimize(endOfArray == endOfArray); + } + + state.SetItemsProcessed(6 * state.iterations()); + } + BENCHMARK_REGISTER_F(DomPathBenchmark, DomPathEntry_Comparison); } diff --git a/Code/Framework/AzCore/Tests/DOM/DomPathTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomPathTests.cpp index 54bff9f29b..5f3aa946b2 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomPathTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomPathTests.cpp @@ -174,4 +174,23 @@ namespace AZ::Dom::Tests p.AppendToString(s); EXPECT_EQ(s, "/foo/0/foo/0"); } + + TEST_F(DomPathTests, MixedPath_AppendToFixedString) + { + Path p("/foo/0"); + + { + AZStd::fixed_string<7> s; + p.AppendToString(s); + EXPECT_EQ(s, "/foo/0"); + } + + { + AZStd::fixed_string<9> s; + p.AppendToString(s); + EXPECT_EQ(s, "/foo/0"); + p.AppendToString(s); + EXPECT_EQ(s, "/foo/0/fo"); + } + } } // namespace AZ::Dom::Tests diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index a8d0f57723..b07cd32ec1 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -224,6 +224,8 @@ set(FILES DOM/DomJsonBenchmarks.cpp DOM/DomPathTests.cpp DOM/DomPathBenchmarks.cpp + DOM/DomPatchTests.cpp + DOM/DomPatchBenchmarks.cpp DOM/DomValueTests.cpp DOM/DomValueBenchmarks.cpp ) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index 62c6518d4c..800464a336 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -292,7 +292,7 @@ namespace AzToolsFramework::Prefab return false; } - const InstanceOptionalConstReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId); + InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId); if (!instance.has_value()) { return false; @@ -308,7 +308,7 @@ namespace AzToolsFramework::Prefab return false; } - InstanceOptionalConstReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId); + InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId); while (instance.has_value()) { if (instance->get().GetAbsoluteInstanceAliasPath() == m_rootAliasFocusPath) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp index 567ccc3619..dcb17d02b4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp @@ -235,10 +235,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils if (!asset->GetId().IsValid()) { - AZ_Error( - "Prefab", false, - "Invalid asset found referenced in scene while entering game mode. The asset was stored in an instance of %s.", - classData->m_name); + // Invalid asset found referenced in scene while entering game mode. return false; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp index 866080a83f..4896a5af49 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp @@ -7,6 +7,7 @@ */ #include +#include #include @@ -117,9 +118,16 @@ namespace AzToolsFramework { } - bool EditorEntityUiHandlerBase::OnEntityDoubleClick([[maybe_unused]] AZ::EntityId entityId) const + bool EditorEntityUiHandlerBase::OnOutlinerItemDoubleClick([[maybe_unused]] const QModelIndex& index) const { return false; } + AZ::EntityId EditorEntityUiHandlerBase::GetEntityIdFromIndex(const QModelIndex& index) + { + QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName); + + return AZ::EntityId(firstColumnIndex.data(EntityOutlinerListModel::EntityIdRole).value()); + } + } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h index 96d393efa1..948c26d710 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h @@ -21,7 +21,6 @@ class QTreeView; namespace AzToolsFramework { //! Defines a handler that can customize entity UI appearance and behavior in the Entity Outliner. - //! This class is meant to be abstract, entities do not have a handler by default. class EditorEntityUiHandlerBase { protected: @@ -33,7 +32,7 @@ namespace AzToolsFramework public: EditorEntityUiHandlerId GetHandlerId(); - // # Entity Outliner + // # Entity Outliner Item //! Returns the item info string that is appended to the item name in the Outliner. virtual QString GenerateItemInfoString(AZ::EntityId entityId) const; @@ -41,10 +40,12 @@ namespace AzToolsFramework virtual QString GenerateItemTooltip(AZ::EntityId entityId) const; //! Returns the item icon pixmap to display in the Outliner. virtual QIcon GenerateItemIcon(AZ::EntityId entityId) const; - //! Returns whether the element's lock and visibility state should be accessible in the Outliner - virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const; //! Returns whether the element's name should be editable virtual bool CanRename(AZ::EntityId entityId) const; + //! Returns whether the element's lock and visibility state should be accessible in the Outliner + virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const; + + // Qt-specific painting functions //! Paints the background of the item in the Outliner. virtual void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; @@ -54,24 +55,27 @@ namespace AzToolsFramework //! Paints the background of the descendant branches of the item in the Outliner. virtual void PaintDescendantBranchBackground(QPainter* painter, const QTreeView* view, const QRect& rect, const QModelIndex& index, const QModelIndex& descendantIndex) const; - //! Paints visual elements on the foreground of the item in the Outliner. virtual void PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; //! Paints visual elements on the foreground of the descendants of the item in the Outliner. virtual void PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QModelIndex& descendantIndex) const; + // Outliner-specific interactions + //! Triggered when the entity is clicked in the Outliner. //! @return True if the click has been handled and should not be propagated, false otherwise. virtual bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const; + //! Triggered when the entity is double-clicked in the Outliner. + //! @return True if the double-click has been handled and should not be propagated, false otherwise. + virtual bool OnOutlinerItemDoubleClick(const QModelIndex& index) const; //! Triggered when an entity's children are expanded in the Outliner. virtual void OnOutlinerItemExpand(const QModelIndex& index) const; //! Triggered when an entity's children are collapsed in the Outliner. virtual void OnOutlinerItemCollapse(const QModelIndex& index) const; - //! Triggered when the entity is double clicked in the Outliner or in the Viewport. - //! @return True if the double click has been handled and should not be propagated, false otherwise. - virtual bool OnEntityDoubleClick(AZ::EntityId entityId) const; + protected: + static AZ::EntityId GetEntityIdFromIndex(const QModelIndex& index); private: EditorEntityUiHandlerId m_handlerId = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index 52b688543a..f4855cb715 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -945,7 +945,7 @@ namespace AzToolsFramework { if (AZ::EntityId entityId = GetEntityIdFromIndex(index); auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId)) { - entityUiHandler->OnEntityDoubleClick(entityId); + entityUiHandler->OnOutlinerItemDoubleClick(index); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp index b34bbff298..9c5c478a2f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp @@ -33,7 +33,7 @@ namespace AzToolsFramework } } - QIcon LevelRootUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const + QIcon LevelRootUiHandler::GenerateItemIcon([[maybe_unused]] AZ::EntityId entityId) const { return QIcon(m_levelRootIconPath); } @@ -62,17 +62,18 @@ namespace AzToolsFramework return infoString; } - bool LevelRootUiHandler::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const + bool LevelRootUiHandler::CanToggleLockVisibility([[maybe_unused]] AZ::EntityId entityId) const { return false; } - bool LevelRootUiHandler::CanRename(AZ::EntityId /*entityId*/) const + bool LevelRootUiHandler::CanRename([[maybe_unused]] AZ::EntityId entityId) const { return false; } - void LevelRootUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const + void LevelRootUiHandler::PaintItemBackground( + QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const { if (!painter) { @@ -94,8 +95,10 @@ namespace AzToolsFramework painter->restore(); } - bool LevelRootUiHandler::OnEntityDoubleClick(AZ::EntityId entityId) const + bool LevelRootUiHandler::OnOutlinerItemDoubleClick(const QModelIndex& index) const { + AZ::EntityId entityId = GetEntityIdFromIndex(index); + if (auto prefabFocusPublicInterface = AZ::Interface::Get(); !prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h index 3f7f56670e..a43aa0606a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h @@ -33,7 +33,7 @@ namespace AzToolsFramework bool CanToggleLockVisibility(AZ::EntityId entityId) const override; bool CanRename(AZ::EntityId entityId) const override; void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - bool OnEntityDoubleClick(AZ::EntityId entityId) const override; + bool OnOutlinerItemDoubleClick(const QModelIndex& index) const override; private: Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp index 69d6ae82ca..f3579c223c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp @@ -99,7 +99,7 @@ namespace AzToolsFramework return; } - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const bool isFirstColumn = index.column() == EntityOutlinerListModel::ColumnName; const bool isLastColumn = index.column() == EntityOutlinerListModel::ColumnLockToggle; QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName); @@ -183,7 +183,7 @@ namespace AzToolsFramework return; } - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const QTreeView* outlinerTreeView(qobject_cast(option.widget)); const int ancestorLeft = outlinerTreeView->visualRect(index).left() + (m_prefabBorderThickness / 2) - 1; @@ -283,7 +283,7 @@ namespace AzToolsFramework void PrefabUiHandler::PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const { - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const QPoint offset = QPoint(-18, 3); QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName); const int iconSize = 16; @@ -385,7 +385,7 @@ namespace AzToolsFramework bool PrefabUiHandler::OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const { - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const QPoint offset = QPoint(-18, 3); if (m_prefabFocusPublicInterface->IsOwningPrefabInFocusHierarchy(entityId)) @@ -411,7 +411,7 @@ namespace AzToolsFramework void PrefabUiHandler::OnOutlinerItemCollapse(const QModelIndex& index) const { - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { @@ -420,8 +420,10 @@ namespace AzToolsFramework } } - bool PrefabUiHandler::OnEntityDoubleClick(AZ::EntityId entityId) const + bool PrefabUiHandler::OnOutlinerItemDoubleClick(const QModelIndex& index) const { + AZ::EntityId entityId = GetEntityIdFromIndex(index); + if (!m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { // Focus on this prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h index a1c624f85a..7166629cf3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h @@ -43,8 +43,8 @@ namespace AzToolsFramework const QModelIndex& index, const QModelIndex& descendantIndex) const override; bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + bool OnOutlinerItemDoubleClick(const QModelIndex& index) const override; void OnOutlinerItemCollapse(const QModelIndex& index) const override; - bool OnEntityDoubleClick(AZ::EntityId entityId) const override; protected: Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr; diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp index 0ad61b924b..483db4076e 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp @@ -15,7 +15,7 @@ namespace UnitTest // When no containers are in the way, the function will just return the entityId of the entity that was clicked. // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -29,7 +29,7 @@ namespace UnitTest m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -47,7 +47,7 @@ namespace UnitTest m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -65,7 +65,7 @@ namespace UnitTest m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -85,7 +85,7 @@ namespace UnitTest m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp index 90becfa46f..374b85c01d 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -93,10 +94,13 @@ namespace UnitTest entity->CreateComponent(); entity->Activate(); - // Move the CarEntity so it's out of the way. - AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, WorldCarEntityPosition); + // Move the City so that it is in view + AZ::TransformBus::Event(m_entityMap[CityEntityName], &AZ::TransformBus::Events::SetWorldTranslation, s_worldCityEntityPosition); - // Setup the camera so the Car entity is in view. + // Move the CarEntity so that it's not overlapping with the rest + AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, s_worldCarEntityPosition); + + // Setup the camera so the entities is in view. AzFramework::SetCameraTransform( m_cameraState, AZ::Transform::CreateFromQuaternionAndTranslation( @@ -113,4 +117,5 @@ namespace UnitTest return entity->GetId(); } + } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h index 0cf1be6ffd..88cc5ac921 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h @@ -8,7 +8,6 @@ #pragma once -#include #include #include @@ -38,9 +37,6 @@ namespace UnitTest AzToolsFramework::EntityIdList GetSelectedEntities(); AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull(); - AzFramework::CameraState m_cameraState; - - inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f); inline static const char* CityEntityName = "City"; inline static const char* StreetEntityName = "Street"; @@ -49,7 +45,11 @@ namespace UnitTest inline static const char* Passenger1EntityName = "Passenger1"; inline static const char* Passenger2EntityName = "Passenger2"; - inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); + AzFramework::CameraState m_cameraState; + + inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f); + inline static AZ::Vector3 s_worldCityEntityPosition = AZ::Vector3(5.0f, 10.0f, 0.0f); + inline static AZ::Vector3 s_worldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); }; } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h index fe1de9b122..5dc323dd8c 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h @@ -45,5 +45,20 @@ namespace UnitTest // Click the entity in the viewport m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); } + + void BoxSelectOnViewport() + { + // Calculate the position in screen space of where to begin and end the box select action + const auto beginningPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(-10.0f, 15.0f, 5.0f), m_cameraState); + const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(10.0f, 15.0f, -5.0f), m_cameraState); + + // Perform a box select in the viewport + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) + ->MousePosition(beginningPositionWorldBoxSelect) + ->MouseLButtonDown() + ->MousePosition(endingPositionWorldBoxSelect) + ->MouseLButtonUp(); + } }; } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp index 1efcb15b30..ee338539a8 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp @@ -13,7 +13,7 @@ namespace UnitTest TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnLevel) { // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -27,7 +27,7 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -41,7 +41,7 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -55,7 +55,7 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -68,10 +68,71 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); EXPECT_EQ(selectedEntitiesAfter.size(), 0); } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnLevel) + { + // Do a box select that includes all entities in the fixture + BoxSelectOnViewport(); + + // Entities are selected + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, + UnorderedElementsAre( + m_entityMap[CityEntityName], + m_entityMap[StreetEntityName], + m_entityMap[CarEntityName], + m_entityMap[Passenger1EntityName], + m_entityMap[SportsCarEntityName], + m_entityMap[Passenger2EntityName] + ) + ); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnChild) + { + // Set the focus on the Passenger1 Entity (child of the entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); + + // Do a box select that includes all entities in the fixture + BoxSelectOnViewport(); + + // Entities are selected + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, + UnorderedElementsAre( + m_entityMap[StreetEntityName], + m_entityMap[CarEntityName], + m_entityMap[Passenger1EntityName], + m_entityMap[SportsCarEntityName], + m_entityMap[Passenger2EntityName] + ) + ); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnLeaf) + { + // Set the focus on the Passenger1 Entity (child of the entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]); + + // Do a box select that includes all entities in the fixture + BoxSelectOnViewport(); + + // Entities are selected + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, + UnorderedElementsAre( + m_entityMap[Passenger1EntityName] + ) + ); + } + } // namespace UnitTest diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/ImageProcessingDefines.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageProcessingDefines.h similarity index 96% rename from Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/ImageProcessingDefines.h rename to Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageProcessingDefines.h index 7c35a0634e..38f6e4a488 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/ImageProcessingDefines.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/ImageProcessingDefines.h @@ -49,8 +49,7 @@ namespace ImageProcessingAtom static const unsigned int s_MinReduceLevel = 0; static const unsigned int s_MaxReduceLevel = 5; - static const int s_TotalSupportedImageExtensions = 10; - static const char* s_SupportedImageExtensions[s_TotalSupportedImageExtensions] = { + static const char* s_SupportedImageExtensions[] = { "*.tif", "*.tiff", "*.png", @@ -62,6 +61,7 @@ namespace ImageProcessingAtom "*.dds", "*.exr" }; + static constexpr int s_TotalSupportedImageExtensions = AZ_ARRAY_SIZE(s_SupportedImageExtensions); enum class RGBWeight : AZ::u32 { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h index 443b91bc07..65fc0aa2a7 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h @@ -8,12 +8,12 @@ #pragma once -#include #include #include #include #include #include +#include #include #include diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h index 77f804b646..fbfc95ac46 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/MipmapSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/MipmapSettings.h index c9abc82b09..c5fa48e10f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/MipmapSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/MipmapSettings.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include #include diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PlatformSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PlatformSettings.h index 10f76db1dd..014b2c7cfb 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PlatformSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PlatformSettings.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h index 348fff989d..c0228cef79 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h @@ -11,9 +11,9 @@ #include #include -#include #include #include +#include #include namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h index 24a2f07bfb..1767b5d9e8 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include #include diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h index 6920ae0cc1..ae4217764d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h index ba3d21191f..a59c3471b3 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h @@ -10,10 +10,10 @@ #include -#include #include #include #include +#include #include #include diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.h index ac15d47806..2a5aef9902 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvertJob.h @@ -8,10 +8,10 @@ #pragma once -#include #include #include #include +#include #include namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp index 91b0952a06..f73446653f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake index a6fe09bfa6..3f7cb0a79d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake @@ -13,6 +13,7 @@ set(FILES Include/Atom/ImageProcessing/ImageProcessingEditorBus.h Include/Atom/ImageProcessing/PixelFormats.h Include/Atom/ImageProcessing/ImageObject.h + Include/Atom/ImageProcessing/ImageProcessingDefines.h ../Assets/Editor/Resources.qrc ../Assets/Editor/Backward.png ../Assets/Editor/Forward.png @@ -28,7 +29,6 @@ set(FILES Source/BuilderSettings/BuilderSettings.h Source/BuilderSettings/CubemapSettings.cpp Source/BuilderSettings/CubemapSettings.h - Source/BuilderSettings/ImageProcessingDefines.h Source/BuilderSettings/MipmapSettings.cpp Source/BuilderSettings/MipmapSettings.h Source/BuilderSettings/PlatformSettings.h diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessingatom_headers_files.cmake b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessingatom_headers_files.cmake index c2c5a11c4c..51864a8442 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessingatom_headers_files.cmake +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessingatom_headers_files.cmake @@ -7,4 +7,5 @@ # set(FILES + Include/Atom/ImageProcessing/ImageProcessingDefines.h ) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli new file mode 100644 index 0000000000..a1318bf383 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli @@ -0,0 +1,142 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#ifdef SHADOWS +#include +#endif + +#ifndef MULTILAYER +#define MULTILAYER 0 +#endif + +#ifndef ENABLE_ALPHA_CLIP +#define ENABLE_ALPHA_CLIP 0 +#endif + +#ifndef SHADOWS +#define SHADOWS 0 +#endif + +struct VSInput +{ + float3 m_position : POSITION; + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; + + // only used for parallax depth calculation + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + +#if MULTILAYER + // This gets set automatically by the system at runtime only if it's available. + // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. + // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). + // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. + float4 m_optional_blendMask : COLOR0; +#endif +}; + +struct VSDepthOutput +{ + // "centroid" is needed for SV_Depth to compile + precise linear centroid float4 m_position : SV_Position; + float2 m_uv[UvSetCount] : UV1; + + // only used for parallax depth calculation + float3 m_normal : NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + +#if MULTILAYER + float3 m_blendMask : UV3; +#endif +}; + +VSDepthOutput MainVS(VSInput IN) +{ + VSDepthOutput OUT; + + float4x4 objectToWorld = GetObjectToWorld(); + float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); + + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); + + float2 uvs[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformUvs(uvs, OUT.m_uv); + + if(ShouldHandleParallaxInDepthShaders()) + { + OUT.m_worldPosition = worldPosition.xyz; + + float3x3 objectToWorldIT = GetNormalToWorld(); + ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); + } + +#if MULTILAYER + if(o_blendMask_isBound) + { + OUT.m_blendMask = IN.m_optional_blendMask.rgb; + } + else + { + OUT.m_blendMask = float3(0,0,0); + } +#endif + + return OUT; +} + +struct PSDepthOutput +{ + precise float m_depth : SV_Depth; +}; + +PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + PSDepthOutput OUT; + + OUT.m_depth = IN.m_position.z; + + if(ShouldHandleParallaxInDepthShaders()) + { + float3 tangents[UvSetCount] = { IN.m_tangent, IN.m_tangent }; + float3 bitangents[UvSetCount] = { IN.m_bitangent, IN.m_bitangent }; + + for (int i = 0; i != UvSetCount; ++i) + { + EvaluateTangentFrame( + IN.m_normal, + IN.m_worldPosition, + isFrontFace, + IN.m_uv[i], + i, + IN.m_tangent, + IN.m_bitangent, + tangents[i], + bitangents[i]); + } + +#if MULTILAYER + MultilayerSetPixelDepth(IN.m_blendMask, IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); +#else + SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); +#endif + +#if SHADOWS + OUT.m_depth += PdoShadowMapBias; +#endif + } + +#if ENABLE_ALPHA_CLIP + GetAlphaAndClip(IN.m_uv); +#endif + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl index 08642decc0..eb220faec6 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -8,88 +8,13 @@ #include "./EnhancedPBR_Common.azsli" #include -#include -#include -#include "MaterialInputs/AlphaInput.azsli" -#include "MaterialInputs/ParallaxInput.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" -struct VSInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VSDepthOutput -{ - precise linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VSDepthOutput MainVS(VSInput IN) -{ - VSDepthOutput OUT; - - float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); - - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - return OUT; -} - -struct PSDepthOutput -{ - precise float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - } - - // Clip Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#define ENABLE_ALPHA_CLIP 1 +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 8458ca11a2..640ada8bd8 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -10,21 +10,6 @@ // SRGs #include -#include - -// Pass Output -#include - -// Utility -#include -#include - -// Custom Surface & Lighting -#include - -// Decals -#include - // ---------- Material Parameters ---------- @@ -49,397 +34,13 @@ COMMON_OPTIONS_DETAIL_MAPS() #include "MaterialInputs/TransmissionInput.azsli" -// ---------- Vertex Shader ---------- - -struct VSInput -{ - // Base fields (required by the template azsli file)... - float3 m_position : POSITION; - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; -}; - -struct VSOutput -{ - // Base fields (required by the template azsli file)... - precise linear centroid float4 m_position : SV_Position; - float3 m_normal: NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV5; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv[UvSetCount] : UV1; - float2 m_detailUv[UvSetCount] : UV3; -}; - -#include - -VSOutput EnhancedPbr_ForwardPassVS(VSInput IN) -{ - VSOutput OUT; - - float3 worldPosition = mul(ObjectSrg::GetWorldMatrix(), float4(IN.m_position, 1.0)).xyz; - - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - // As seen above our standard practice is to only transform the first UV as that's the one we expect to be used for - // tiling. But for detail maps you could actually use either UV stream for tiling. There is no concern about applying - // the same transform to both UV sets because the detail map feature forces the same UV set to be used for all detail maps. - // Note we might be able to combine these into a single UV similar to what Skin.materialtype does, - // but we would need to address how it works with the parallax code below that indexes into the m_detailUV array. - OUT.m_detailUv[0] = mul(MaterialSrg::m_detailUvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_detailUv[1] = mul(MaterialSrg::m_detailUvMatrix, float3(IN.m_uv1, 1.0)).xy; - - // Shadow coords will be calculated in the pixel shader in this case - bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; - - VertexHelper(IN, OUT, worldPosition, skipShadowCoords); - - return OUT; -} - - -// ---------- Pixel Shader ---------- - -PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth) -{ - const float3 vertexNormal = normalize(IN.m_normal); - - // ------- Tangents & Bitangets ------- - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture) || o_detail_normal_useTexture) - { - PrepareGeneratedTangent(vertexNormal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - } - - // ------- Depth & Parallax ------- - - depth = IN.m_position.z; - - bool displacementIsClipped = false; - - // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scatteirng is enabled - if(ShouldHandleParallax()) - { - // GetParallaxInput applies an tangent offset to the UV. We want to apply the same offset to the detailUv (note: this needs to be tested with content) - // The math is: offset = newUv - oldUv; detailUv += offset; - // This is the same as: detailUv -= oldUv; detailUv += newUv; - IN.m_detailUv[MaterialSrg::m_parallaxUvIndex] -= IN.m_uv[MaterialSrg::m_parallaxUvIndex]; - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(vertexNormal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, IN.m_position.w, displacementIsClipped); - - // Apply second part of the offset to the detail UV (see comment above) - IN.m_detailUv[MaterialSrg::m_parallaxUvIndex] -= IN.m_uv[MaterialSrg::m_parallaxUvIndex]; - - // Adjust directional light shadow coorinates for parallax correction - if(o_parallax_enablePixelDepthOffset) - { - const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; - if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) - { - DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); - } - } - } - - Surface surface; - surface.position = IN.m_worldPosition; - - // ------- Alpha & Clip ------- - - float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUv = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = GetAlphaInputAndClip(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUv, opacityUv, MaterialSrg::m_sampler, MaterialSrg::m_opacityFactor, o_opacity_source); - - // ------- Detail Layer Setup ------- - - const float2 detailUv = IN.m_detailUv[MaterialSrg::m_detail_allMapsUvIndex]; - - // When the detail maps and the detail blend mask are on the same UV, they both use the transformed detail UVs because they are 'attached' to each other - const float2 detailBlendMaskUv = (MaterialSrg::m_detail_blendMask_uvIndex == MaterialSrg::m_detail_allMapsUvIndex) ? - IN.m_detailUv[MaterialSrg::m_detail_blendMask_uvIndex] : - IN.m_uv[MaterialSrg::m_detail_blendMask_uvIndex]; - - const float detailLayerBlendFactor = GetDetailLayerBlendFactor( - MaterialSrg::m_detail_blendMask_texture, - MaterialSrg::m_sampler, - detailBlendMaskUv, - o_detail_blendMask_useTexture, - MaterialSrg::m_detail_blendFactor); - - // ------- Normal ------- - - float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex]; - float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. - float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor; - surface.vertexNormal = vertexNormal; - surface.normal = GetDetailedNormalInputWS( - isFrontFace, IN.m_normal, - tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture, - tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, detailUv, detailLayerNormalFactor, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY, MaterialSrg::m_detailUvMatrix, o_detail_normal_useTexture); - - //--------------------- Base Color ---------------------- - - // [GFX TODO][ATOM-1761] Figure out how we want our base material to expect channels to be encoded, and apply that to the way we pack alpha. - - float detailLayerBaseColorFactor = MaterialSrg::m_detail_baseColor_factor * detailLayerBlendFactor; - - float3 baseColor = GetDetailedBaseColorInput( - MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, o_baseColor_useTexture, MaterialSrg::m_baseColor, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, - MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, detailUv, o_detail_baseColor_useTexture, detailLayerBaseColorFactor); - - if(o_parallax_highlightClipping && displacementIsClipped) - { - ApplyParallaxClippingHighlight(baseColor); - } - - // ------- Metallic ------- - - float metallic = 0; - if(!o_enableSubsurfaceScattering) // If subsurface scattering is enabled skip texture lookup for metallic, as this quantity won't be used anyway - { - float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex]; - metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); - } - - // ------- Specular ------- - - float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex]; - float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); - - // ------- Roughness ------- - - float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex]; - surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, - MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); - surface.CalculateRoughnessA(); - - // ------- Subsurface ------- - - float2 subsurfaceUv = IN.m_uv[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex]; - float surfaceScatteringFactor = GetSubsurfaceInput(MaterialSrg::m_subsurfaceScatteringInfluenceMap, MaterialSrg::m_sampler, subsurfaceUv, MaterialSrg::m_subsurfaceScatteringFactor); - - // ------- Transmission ------- - - float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex]; - float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness); - surface.transmission.tint = transmissionTintThickness.rgb; - surface.transmission.thickness = transmissionTintThickness.w; - surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams; - surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance; - - // ------- Anisotropy ------- - - if (o_enableAnisotropy) - { - // Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI] - const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI; - const float anisotropyFactor = MaterialSrg::m_anisotropicFactor; - surface.anisotropy.Init(surface.normal, IN.m_tangent, IN.m_bitangent, anisotropyAngle, anisotropyFactor, surface.roughnessA); - } - - // ------- Lighting Data ------- - - LightingData lightingData; - - // Light iterator - lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); - lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); - - // Directional light shadow coordinates - lightingData.shadowCoords = IN.m_shadowCoords; - - // ------- Emissive ------- - - float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex]; - lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); - - // ------- Occlusion ------- - - lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); - lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); - - // ------- Thin Object Light Transmission ------- - - // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection - lightingData.shrinkFactor = surface.transmission.transmissionParams.x; - - // Angle offset for subsurface scattering through thin objects - lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y; - - // Attenuation applied to hide artifacts due to low-res shadow maps - lightingData.distanceAttenuation = surface.transmission.transmissionParams.z; - - // ------- Clearcoat ------- - - // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags - if(o_clearCoat_feature_enabled) - { - if(o_clearCoat_enabled) - { - float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, - MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, - MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, - uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], - MaterialSrg::m_sampler, isFrontFace, - surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); - } - - // manipulate base layer f0 if clear coat is enabled - // modify base layer's normal incidence reflectance - // for the derivation of the following equation please refer to: - // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification - float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); - surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); - } - - // Diffuse and Specular response (used in IBL calculations) - lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); - lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; - - if(o_clearCoat_feature_enabled) - { - // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 - lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); - } - - // ------- Multiscatter ------- - - lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); - - // ------- Lighting Calculation ------- - - // Apply Decals - ApplyDecals(lightingData.tileIterator, surface); - - // Apply Direct Lighting - ApplyDirectLighting(surface, lightingData); - - // Apply Image Based Lighting (IBL) - ApplyIBL(surface, lightingData); - - // Finalize Lighting - lightingData.FinalizeLighting(surface.transmission.tint); - - PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); - - // ------- Opacity ------- - - if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) - { - // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. - // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface - // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor - // values close to 1.0, that indicates the absence of a surface entirely, so this effect should - // not apply. - float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; - alpha = lerp(fresnelAlpha, alpha, MaterialSrg::m_opacityAffectsSpecularFactor); - } - - // Note: lightingOutput rendertargets are not always used as named, particularly m_diffuseColor (target 0) and - // m_specularColor (target 1). Comments below describe the differences when appropriate. - - if (o_opacity_mode == OpacityMode::Blended) - { - // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when - // specular is being added to diffuse just because we're calling render target 0 "diffuse". - - // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular - // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. - // It's done this way because surface transparency doesn't really change specular response (eg, glass). - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_diffuseColor.w = alpha; - } - else if (o_opacity_mode == OpacityMode::TintedTransparent) - { - // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting - // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength - // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, - // absorption, and interior color to be specified. - // - // The technique uses dual source blending to allow two separate sources to be part of the blending equation - // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and - // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). - // - // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then - // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_specularColor.rgb = baseColor * (1.0 - alpha); - } - else - { - // Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961 - uint factorAndQuality = dot(round(float2(saturate(surfaceScatteringFactor), MaterialSrg::m_subsurfaceScatteringQuality) * 255), float2(256, 1)); - lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0); - lightingOutput.m_scatterDistance = MaterialSrg::m_scatterDistance; - } - - return lightingOutput; -} - -ForwardPassOutputWithDepth EnhancedPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutputWithDepth OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); - - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; - OUT.m_scatterDistance = lightingOutput.m_scatterDistance; - OUT.m_depth = depth; - return OUT; -} - -[earlydepthstencil] -ForwardPassOutput EnhancedPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutput OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); - - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; - OUT.m_scatterDistance = lightingOutput.m_scatterDistance; - - return OUT; -} +#include "MaterialFunctions/EvaluateEnhancedSurface.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/EnhancedParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" +#include "MaterialFunctions/StandardTransformDetailUvs.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" + +#include "EnhancedSurface_ForwardPass.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl index 0f2457fcd8..be350a3ce7 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl @@ -16,85 +16,13 @@ #include "MaterialInputs/AlphaInput.azsli" #include "MaterialInputs/ParallaxInput.azsli" -struct VertexInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VertexOutput -{ - float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VertexOutput MainVS(VertexInput IN) -{ - const float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - VertexOutput OUT; - - const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - - OUT.m_depth += PdoShadowMapBias; - } - - // Clip Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#define SHADOWS 1 +#define ENABLE_ALPHA_CLIP 1 +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsli new file mode 100644 index 0000000000..8bc9802443 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsli @@ -0,0 +1,317 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +// SRGs +#include + +// Pass Output +#include + +// Utility +#include + +// Custom Surface & Lighting +#include + +// Decals +#include + +// ---------- Vertex Shader ---------- + +struct VSInput +{ + // Base fields (required by the template azsli file)... + float3 m_position : POSITION; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; +}; + +struct VSOutput +{ + // Base fields (required by the template azsli file)... + precise linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV5; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv[UvSetCount] : UV1; + float2 m_detailUv[UvSetCount] : UV3; +}; + +VSOutput EnhancedPbr_ForwardPassVS(VSInput IN) +{ + VSOutput OUT; + + float4x4 objectToWorld = GetObjectToWorld(); + float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); + OUT.m_worldPosition = worldPosition.xyz; + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); + + float2 uv[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformUvs(uv, OUT.m_uv); + + float2 detailUv[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformDetailUvs(detailUv, OUT.m_detailUv); + + // Shadow coords will be calculated in the pixel shader in this case + bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; + + float3x3 objectToWorldIT = GetNormalToWorld(); + ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); + + // directional light shadow + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && !skipShadowCoords && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords( + shadowIndex, + worldPosition, + OUT.m_normal, + OUT.m_shadowCoords); + } + + return OUT; +} + + +// ---------- Pixel Shader ---------- + +PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth) +{ + const float3 vertexNormal = normalize(IN.m_normal); + + // ------- Tangents & Bitangets ------- + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + + if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture) || o_detail_normal_useTexture) + { + for (int i = 0; i != UvSetCount; ++i) + { + EvaluateTangentFrame( + IN.m_normal, + IN.m_worldPosition, + isFrontFace, + IN.m_uv[i], + i, + IN.m_tangent, + IN.m_bitangent, + tangents[i], + bitangents[i]); + } + } + + // ------- Depth & Parallax ------- + + depth = IN.m_position.z; + + bool displacementIsClipped = false; + + // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scatteirng is enabled + if(ShouldHandleParallax()) + { + EnhancedSetPixelDepth( + IN.m_worldPosition, + IN.m_normal, + tangents, + bitangents, + IN.m_uv, + isFrontFace, + IN.m_detailUv, + IN.m_position.w, + depth, + displacementIsClipped); + + // Adjust directional light shadow coorinates for parallax correction + if(o_parallax_enablePixelDepthOffset) + { + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); + } + } + } + + SurfaceSettings surfaceSettings; + Surface surface; + surface.vertexNormal = vertexNormal; + surface.position = IN.m_worldPosition; + + // ------- Alpha & Clip ------- + // TODO: this often invokes a separate sample of the base color texture which is wasteful + float alpha = GetAlphaAndClip(IN.m_uv); + + EvaluateEnhancedSurface(IN.m_normal, IN.m_uv, IN.m_detailUv, tangents, bitangents, isFrontFace, displacementIsClipped, surface, surfaceSettings); + + // ------- Lighting Data ------- + + LightingData lightingData; + + // Light iterator + lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); + lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); + + // Directional light shadow coordinates + lightingData.shadowCoords = IN.m_shadowCoords; + + lightingData.emissiveLighting = surface.emissiveLighting; + lightingData.diffuseAmbientOcclusion = surface.diffuseAmbientOcclusion; + lightingData.specularOcclusion = surface.specularOcclusion; + + // Diffuse and Specular response (used in IBL calculations) + lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); + lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; + + // ------- Thin Object Light Transmission ------- + + // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection + lightingData.shrinkFactor = surface.transmission.transmissionParams.x; + + // Angle offset for subsurface scattering through thin objects + lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y; + + // Attenuation applied to hide artifacts due to low-res shadow maps + lightingData.distanceAttenuation = surface.transmission.transmissionParams.z; + + if(o_clearCoat_feature_enabled) + { + // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 + lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); + } + + // ------- Multiscatter ------- + + lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); + + // ------- Lighting Calculation ------- + + // Apply Decals + ApplyDecals(lightingData.tileIterator, surface); + + // Apply Direct Lighting + ApplyDirectLighting(surface, lightingData); + + // Apply Image Based Lighting (IBL) + ApplyIBL(surface, lightingData); + + // Finalize Lighting + lightingData.FinalizeLighting(surface.transmission.tint); + + PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); + + // ------- Opacity ------- + + if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) + { + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; + alpha = lerp(fresnelAlpha, alpha, surfaceSettings.opacityAffectsSpecularFactor); + } + + // Note: lightingOutput rendertargets are not always used as named, particularly m_diffuseColor (target 0) and + // m_specularColor (target 1). Comments below describe the differences when appropriate. + + if (o_opacity_mode == OpacityMode::Blended) + { + // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when + // specular is being added to diffuse just because we're calling render target 0 "diffuse". + + // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular + // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. + // It's done this way because surface transparency doesn't really change specular response (eg, glass). + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_diffuseColor.w = alpha; + } + else if (o_opacity_mode == OpacityMode::TintedTransparent) + { + // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting + // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength + // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, + // absorption, and interior color to be specified. + // + // The technique uses dual source blending to allow two separate sources to be part of the blending equation + // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and + // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). + // + // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then + // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_specularColor.rgb = surface.baseColor * (1.0 - alpha); + } + else + { + // Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961 + uint factorAndQuality = dot(round(float2(saturate(surface.subsurfaceScatteringFactor), surfaceSettings.subsurfaceScatteringQuality) * 255), float2(256, 1)); + lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0); + lightingOutput.m_scatterDistance = surfaceSettings.scatterDistance; + } + + return lightingOutput; +} + +ForwardPassOutputWithDepth EnhancedPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutputWithDepth OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; + OUT.m_scatterDistance = lightingOutput.m_scatterDistance; + OUT.m_depth = depth; + return OUT; +} + +[earlydepthstencil] +ForwardPassOutput EnhancedPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutput OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; + OUT.m_scatterDistance = lightingOutput.m_scatterDistance; + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli new file mode 100644 index 0000000000..449c789d01 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli @@ -0,0 +1,41 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include "../MaterialInputs/ParallaxInput.azsli" +#include + + void EnhancedSetPixelDepth( + float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + float2 uvs[UvSetCount], + bool isFrontFace, + inout float2 detailUv[UvSetCount], + inout float depthCS, + out float depth, + out bool isClipped) +{ + // GetParallaxInput applies an tangent offset to the UV. We want to apply the same offset to the detailUv (note: this needs to be tested with content) + // The math is: offset = newUv - oldUv; detailUv += offset; + // This is the same as: detailUv -= oldUv; detailUv += newUv; + detailUv[MaterialSrg::m_parallaxUvIndex] -= uvs[MaterialSrg::m_parallaxUvIndex]; + + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depth, depthCS, isClipped); + + // Apply second part of the offset to the detail UV (see comment above) + detailUv[MaterialSrg::m_parallaxUvIndex] -= uvs[MaterialSrg::m_parallaxUvIndex]; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli new file mode 100644 index 0000000000..d1cb52004a --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli @@ -0,0 +1,149 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +void EvaluateEnhancedSurface( + float3 normal, + float2 uvs[UvSetCount], + float2 detailUvs[UvSetCount], + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + bool isFrontFace, + bool displacementIsClipped, + inout Surface surface, + out SurfaceSettings surfaceSettings) +{ + // ------- Detail Layer Setup ------- + + const float2 detailUv = detailUvs[MaterialSrg::m_detail_allMapsUvIndex]; + + // When the detail maps and the detail blend mask are on the same UV, they both use the transformed detail UVs because they are 'attached' to each other + const float2 detailBlendMaskUv = (MaterialSrg::m_detail_blendMask_uvIndex == MaterialSrg::m_detail_allMapsUvIndex) ? + detailUvs[MaterialSrg::m_detail_blendMask_uvIndex] : + uvs[MaterialSrg::m_detail_blendMask_uvIndex]; + + const float detailLayerBlendFactor = GetDetailLayerBlendFactor( + MaterialSrg::m_detail_blendMask_texture, + MaterialSrg::m_sampler, + detailBlendMaskUv, + o_detail_blendMask_useTexture, + MaterialSrg::m_detail_blendFactor); + + // ------- Normal ------- + + float2 normalUv = uvs[MaterialSrg::m_normalMapUvIndex]; + float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. + float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor; + surface.normal = GetDetailedNormalInputWS( + isFrontFace, normal, + tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture, + tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, detailUv, detailLayerNormalFactor, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY, MaterialSrg::m_detailUvMatrix, o_detail_normal_useTexture); + + //--------------------- Base Color ---------------------- + + // [GFX TODO][ATOM-1761] Figure out how we want our base material to expect channels to be encoded, and apply that to the way we pack alpha. + + float detailLayerBaseColorFactor = MaterialSrg::m_detail_baseColor_factor * detailLayerBlendFactor; + float2 baseColorUv = uvs[MaterialSrg::m_baseColorMapUvIndex]; + + float3 baseColor = GetDetailedBaseColorInput( + MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, o_baseColor_useTexture, MaterialSrg::m_baseColor, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, + MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, detailUv, o_detail_baseColor_useTexture, detailLayerBaseColorFactor); + + if(o_parallax_highlightClipping && displacementIsClipped) + { + ApplyParallaxClippingHighlight(baseColor); + } + + // ------- Metallic ------- + + float metallic = 0; + if(!o_enableSubsurfaceScattering) // If subsurface scattering is enabled skip texture lookup for metallic, as this quantity won't be used anyway + { + float2 metallicUv = uvs[MaterialSrg::m_metallicMapUvIndex]; + metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + } + + // ------- Specular ------- + + float2 specularUv = uvs[MaterialSrg::m_specularF0MapUvIndex]; + float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); + + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); + + // ------- Roughness ------- + + float2 roughnessUv = uvs[MaterialSrg::m_roughnessMapUvIndex]; + surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, + MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); + surface.CalculateRoughnessA(); + + // ------- Subsurface ------- + + float2 subsurfaceUv = uvs[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex]; + surface.subsurfaceScatteringFactor = GetSubsurfaceInput(MaterialSrg::m_subsurfaceScatteringInfluenceMap, MaterialSrg::m_sampler, subsurfaceUv, MaterialSrg::m_subsurfaceScatteringFactor); + surfaceSettings.subsurfaceScatteringQuality = MaterialSrg::m_subsurfaceScatteringQuality; + surfaceSettings.scatterDistance = MaterialSrg::m_scatterDistance; + + // ------- Transmission ------- + + float2 transmissionUv = uvs[MaterialSrg::m_transmissionThicknessMapUvIndex]; + float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness); + surface.transmission.tint = transmissionTintThickness.rgb; + surface.transmission.thickness = transmissionTintThickness.w; + surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams; + surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance; + + // ------- Anisotropy ------- + + if (o_enableAnisotropy) + { + // Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI] + const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI; + const float anisotropyFactor = MaterialSrg::m_anisotropicFactor; + surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA); + } + + // ------- Emissive ------- + + float2 emissiveUv = uvs[MaterialSrg::m_emissiveMapUvIndex]; + surface.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); + + // ------- Occlusion ------- + + surface.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvs[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + surface.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, uvs[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + + // ------- Clearcoat ------- + + // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags + if(o_clearCoat_feature_enabled) + { + if(o_clearCoat_enabled) + { + float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, uvs[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, + MaterialSrg::m_clearCoatRoughnessMap, uvs[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, + MaterialSrg::m_clearCoatNormalMap, uvs[MaterialSrg::m_clearCoatNormalMapUvIndex], normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, + uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], + MaterialSrg::m_sampler, isFrontFace, + surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); + } + + // manipulate base layer f0 if clear coat is enabled + // modify base layer's normal incidence reflectance + // for the derivation of the following equation please refer to: + // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification + float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); + surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); + } + + surfaceSettings.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli new file mode 100644 index 0000000000..da24bb3937 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli @@ -0,0 +1,95 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +void EvaluateStandardSurface( + float3 normal, + float2 uv[UvSetCount], + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + bool isFrontFace, + bool displacementIsClipped, + inout Surface surface, + out SurfaceSettings surfaceSettings) +{ + // ------- Normal ------- + + float2 normalUv = uv[MaterialSrg::m_normalMapUvIndex]; + float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. + surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, normal, + tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor); + + // ------- Base Color ------- + + float2 baseColorUv = uv[MaterialSrg::m_baseColorMapUvIndex]; + float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); + float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); + + if(o_parallax_highlightClipping && displacementIsClipped) + { + ApplyParallaxClippingHighlight(baseColor); + } + + // ------- Metallic ------- + + float2 metallicUv = uv[MaterialSrg::m_metallicMapUvIndex]; + float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + + // ------- Specular ------- + + float2 specularUv = uv[MaterialSrg::m_specularF0MapUvIndex]; + float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); + + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); + + // ------- Roughness ------- + + float2 roughnessUv = uv[MaterialSrg::m_roughnessMapUvIndex]; + surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, + MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); + surface.CalculateRoughnessA(); + + // ------- Emissive ------- + + float2 emissiveUv = uv[MaterialSrg::m_emissiveMapUvIndex]; + surface.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); + + // ------- Occlusion ------- + + surface.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + surface.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + + // ------- Clearcoat ------- + + // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags + if(o_clearCoat_feature_enabled) + { + if(o_clearCoat_enabled) + { + float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, + MaterialSrg::m_clearCoatRoughnessMap, uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, + MaterialSrg::m_clearCoatNormalMap, uv[MaterialSrg::m_clearCoatNormalMapUvIndex], normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, + uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], + MaterialSrg::m_sampler, isFrontFace, + surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); + } + + // manipulate base layer f0 if clear coat is enabled + // modify base layer's normal incidence reflectance + // for the derivation of the following equation please refer to: + // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification + float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); + surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); + } + + // ------- Opacity ------- + surfaceSettings.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli new file mode 100644 index 0000000000..0045d18e47 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli @@ -0,0 +1,33 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +// The built-in tangent frame evaluation forwards the tangent frame interpolanted from the vertex +// data streams for UV-index 0. For UV-index 1, the tangent frame is computed from UV surface gradients. +void EvaluateTangentFrame( + float3 normal, + float3 worldPosition, + bool isFrontFace, + float2 uv, + int uvIndex, + // The input tangent and bitangent vectors are optional and used to forward data from interpolants + float3 IN_tangent, + float3 IN_bitangent, + out float3 OUT_tangent, + out float3 OUT_bitangent) +{ + if (DrawSrg::GetTangentAtUv(uvIndex) == 0) + { + OUT_tangent = IN_tangent; + OUT_bitangent = IN_bitangent; + } + else + { + SurfaceGradientNormalMapping_Init(normal, worldPosition, !isFrontFace); + SurfaceGradientNormalMapping_GenerateTB(uv, OUT_tangent, OUT_bitangent); + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli new file mode 100644 index 0000000000..3f8b87c942 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli @@ -0,0 +1,35 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include "../MaterialInputs/ParallaxInput.azsli" +#include + + void MultilayerSetPixelDepth( + float3 blendMask, + float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + float2 uvs[UvSetCount], + bool isFrontFace, + out float depth) +{ + s_blendMaskFromVertexStream = blendMask; + + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + float parallaxOverallOffset = MaterialSrg::m_displacementMax; + float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin; + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + parallaxOverallFactor, parallaxOverallOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depth); +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli new file mode 100644 index 0000000000..645e3a4c2d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli @@ -0,0 +1,51 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include "../MaterialInputs/ParallaxInput.azsli" +#include + + void SetPixelDepth( + inout float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + inout float2 uvs[UvSetCount], + bool isFrontFace, + inout float depthNDC) +{ + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depthNDC); +} + + void SetPixelDepth( + inout float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + inout float2 uvs[UvSetCount], + bool isFrontFace, + inout float depthCS, + inout float depthNDC, + out bool isClipped) +{ + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depthNDC, depthCS, isClipped); +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli new file mode 100644 index 0000000000..c588b4423b --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli @@ -0,0 +1,19 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "../MaterialInputs/AlphaInput.azsli" + +float GetAlphaAndClip(float2 uvs[UvSetCount]) +{ + // Alpha + float2 baseColorUV = uvs[MaterialSrg::m_baseColorMapUvIndex]; + float2 opacityUV = uvs[MaterialSrg::m_opacityMapUvIndex]; + float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); + CheckClipping(alpha, MaterialSrg::m_opacityFactor); + return MaterialSrg::m_opacityFactor * alpha; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli similarity index 56% rename from Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.azsl rename to Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli index 02e9e93ba2..f55f1b2078 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli @@ -6,8 +6,7 @@ * */ -// NOTE: This file is a temporary workaround until .shader files can #define macros for their .azsl files - -#define QUALITY_LOW_END 1 - -#include "StandardPBR_ForwardPass.azsl" +float3x3 GetNormalToWorld() +{ + return ObjectSrg::GetWorldMatrixInverseTranspose(); +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli new file mode 100644 index 0000000000..f02677658d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli @@ -0,0 +1,12 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +float4x4 GetObjectToWorld() +{ + return ObjectSrg::GetWorldMatrix(); +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli new file mode 100644 index 0000000000..e6bb26ddc5 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli @@ -0,0 +1,18 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +void TransformDetailUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount]) +{ + // Our standard practice is to only transform the first UV as that's the one we expect to be used for + // tiling. But for detail maps you could actually use either UV stream for tiling. There is no concern about applying + // the same transform to both UV sets because the detail map feature forces the same UV set to be used for all detail maps. + // Note we might be able to combine these into a single UV similar to what Skin.materialtype does, + // but we would need to address how it works with the parallax code below that indexes into the m_detailUV array. + OUT[0] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[0], 1.0)).xy; + OUT[1] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[1], 1.0)).xy; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli new file mode 100644 index 0000000000..39d77c7a93 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli @@ -0,0 +1,14 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +void TransformUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount]) +{ + // By design, only UV0 is allowed to apply transforms. + OUT[0] = mul(MaterialSrg::m_uvMatrix, float3(IN[0], 1.0)).xy; + OUT[1] = IN[1]; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/README.md b/Gems/Atom/Feature/Common/Assets/Materials/Types/README.md new file mode 100644 index 0000000000..e176f6d7dc --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/README.md @@ -0,0 +1,98 @@ +# Upcoming material system changes + +Currently, `.materialtype` files specify a set of shaders for each pass in the rendering pipeline. +For example, the `StandardPBR.materialtype` asset specifies the following shaders: + +```json +[ + { + "file": "./StandardPBR_ForwardPass.shader", + "tag": "ForwardPass" + }, + { + "file": "./StandardPBR_ForwardPass_EDS.shader", + "tag": "ForwardPass_EDS" + }, + { + "file": "./StandardPBR_LowEndForward.shader", + "tag": "LowEndForward" + }, + { + "file": "./StandardPBR_LowEndForward_EDS.shader", + "tag": "LowEndForward_EDS" + }, + { + "file": "Shaders/Shadow/Shadowmap.shader", + "tag": "Shadowmap" + }, + { + "file": "./StandardPBR_Shadowmap_WithPS.shader", + "tag": "Shadowmap_WithPS" + }, + { + "file": "Shaders/Depth/DepthPass.shader", + "tag": "DepthPass" + }, + { + "file": "./StandardPBR_DepthPass_WithPS.shader", + "tag": "DepthPass_WithPS" + }, + { + "file": "Shaders/MotionVector/MeshMotionVector.shader", + "tag": "MeshMotionVector" + }, + { + "file": "Shaders/Depth/DepthPassTransparentMin.shader", + "tag": "DepthPassTransparentMin" + }, + { + "file": "Shaders/Depth/DepthPassTransparentMax.shader", + "tag": "DepthPassTransparentMax" + } +] +``` + +**This will be changing in a future release** to a material type description that specifies shader snippets (aka material functions) +instead of explicit shaders. + +## Why is it changing? + +There are two primary reasons to move to a different scheme. + +1. Material types are strongly coupled to the rendering pipeline. If a user wants to change the pipeline, or the engine wants to use, for example, a custom pipeline for mobile, or VR, this isn't possible today without cloning existing material types and changing the shader array. +2. The material canvas work that has been prioritized to allow artist-driven material customization benefits from a more modular construction of materials. For example, we'd like to apply a "wind graph" and mix and match that with a "foliage graph" to describe the appearance of some foliage. The current material type description couples all the geometric passes with the material and lighting passes, which makes this sort of decomposition difficult. + +## What is it changing to? + +The best way to understand how this is changing is to inspect the current structure of `EnhancedPBR_ForwardPass.azsl` and `StandardPBR_ForwardPass.azsl`. +These shaders start with a number of includes to specify the SRG as follows: + +```hlsl +#include "StandardPBR_Common.azsli" +#include +``` + +Later, it includes a number of material functions, for example: + +```hlsl +#include "MaterialFunctions/EvaluateStandardSurface.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +``` + +The material function headers define functions that may later be overridden using material graphs. + +Finally, in the case of the standard surface shader, it includes an implementation file: + +```hlsl +#include "StandardSurface_ForwardPass.azsli" +``` + +This file, if you inspect it, _makes no reference to `MaterialSrg`_, and furthermore, does not include files needed to implement any of the material functions. +In other words, the structure of the standard pbr forward shader is such that it can be assembled with different components, specifing the SRG, material functions, and implementation. + +In the future, a material pipeline abstraction will allow the `materialtype` asset to specify _only_ the material function files, and the tuple of `materialtype` and `materialpipeline` will allow the material builder to assemble the shader on behalf of the user. The final piece to the puzzle is that (again, in the future), material canvas (in active development) can produce material functions to replace the built-in ones. diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl index 7875457489..0f000fba98 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl @@ -21,104 +21,12 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "./StandardMultilayerPBR_Common.azsli" -struct VSInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/MultilayerParallaxDepth.azsli" - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // This gets set automatically by the system at runtime only if it's available. - // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. - // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). - // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. - float4 m_optional_blendMask : COLOR0; -}; - -struct VSDepthOutput -{ - precise linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_blendMask : UV3; -}; - -VSDepthOutput MainVS(VSInput IN) -{ - VSDepthOutput OUT; - - float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); - - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); - - // By design, only UV0 is allowed to apply transforms. - // Note there are additional UV transforms that happen for each layer, but we defer that step to the pixel shader to avoid bloating the vertex output buffer. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - if(o_blendMask_isBound) - { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendMask = float3(0,0,0); - } - - return OUT; -} - -struct PSDepthOutput -{ - precise float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - s_blendMaskFromVertexStream = IN.m_blendMask; - - float depth; - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - float parallaxOverallOffset = MaterialSrg::m_displacementMax; - float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin; - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], parallaxOverallFactor, parallaxOverallOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth); - - OUT.m_depth = depth; - } - - return OUT; -} +#define MULTILAYER 1 +#define ENABLE_ALPHA_CLIP 0 +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 3617b7fb04..48d3cb4739 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -451,8 +451,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Combine Albedo, roughness, specular, roughness --------- float3 baseColor = BlendLayers(lightingInputLayer1.m_baseColor, lightingInputLayer2.m_baseColor, lightingInputLayer3.m_baseColor, blendWeights); - float3 specularF0Factor = BlendLayers(lightingInputLayer1.m_specularF0Factor, lightingInputLayer2.m_specularF0Factor, lightingInputLayer3.m_specularF0Factor, blendWeights); - float3 metallic = BlendLayers(lightingInputLayer1.m_metallic, lightingInputLayer2.m_metallic, lightingInputLayer3.m_metallic, blendWeights); + float specularF0Factor = BlendLayers(lightingInputLayer1.m_specularF0Factor, lightingInputLayer2.m_specularF0Factor, lightingInputLayer3.m_specularF0Factor, blendWeights); + float metallic = BlendLayers(lightingInputLayer1.m_metallic, lightingInputLayer2.m_metallic, lightingInputLayer3.m_metallic, blendWeights); if(o_parallax_highlightClipping && displacementIsClipped) { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl index 45d8ed94b3..9d64916444 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ - + #include #include #include @@ -21,103 +21,13 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "StandardMultilayerPBR_Common.azsli" -struct VertexInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/MultilayerParallaxDepth.azsli" - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // This gets set automatically by the system at runtime only if it's available. - // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. - // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). - // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. - float4 m_optional_blendMask : COLOR0; -}; - -struct VertexOutput -{ - float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_blendMask : UV3; -}; - -VertexOutput MainVS(VertexInput IN) -{ - const float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - VertexOutput OUT; - - const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - - // By design, only UV0 is allowed to apply transforms. - // Note there are additional UV transforms that happen for each layer, but we defer that step to the pixel shader to avoid bloating the vertex output buffer. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - if(o_blendMask_isBound) - { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendMask = float3(0,0,0); - } - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - s_blendMaskFromVertexStream = IN.m_blendMask; - - float depthNDC; - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - float parallaxOverallOffset = MaterialSrg::m_displacementMax; - float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin; - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], parallaxOverallFactor, parallaxOverallOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC); - - OUT.m_depth = depthNDC; - } - - return OUT; -} +#define MULTILAYER 1 +#define ENABLE_ALPHA_CLIP 0 +#define SHADOWS 1 +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl index 04fd104407..b848ba03ba 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl @@ -8,91 +8,13 @@ #include "./StandardPBR_Common.azsli" #include -#include -#include -#include "MaterialInputs/AlphaInput.azsli" -#include "MaterialInputs/ParallaxInput.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" -struct VSInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VSDepthOutput -{ - // "centroid" is needed for SV_Depth to compile - precise linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VSDepthOutput MainVS(VSInput IN) -{ - VSDepthOutput OUT; - - float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); - - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - return OUT; -} - -struct PSDepthOutput -{ - precise float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - } - - // Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#define ENABLE_ALPHA_CLIP 1 +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index b99ea734af..4240c291da 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -10,23 +10,7 @@ #include "StandardPBR_Common.azsli" -// SRGs #include -#include - -// Pass Output -#include - -// Utility -#include -#include - -// Custom Surface & Lighting -#include - -// Decals -#include - // ---------- Material Parameters ---------- @@ -43,320 +27,12 @@ COMMON_OPTIONS_EMISSIVE() // Alpha #include "MaterialInputs/AlphaInput.azsli" -// ---------- Vertex Shader ---------- - -struct VSInput -{ - // Base fields (required by the template azsli file)... - float3 m_position : POSITION; - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; -}; - -struct VSOutput -{ - // Base fields (required by the template azsli file)... - // "centroid" is needed for SV_Depth to compile - precise linear centroid float4 m_position : SV_Position; - float3 m_normal: NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV3; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv[UvSetCount] : UV1; -}; - -#include - -VSOutput StandardPbr_ForwardPassVS(VSInput IN) -{ - VSOutput OUT; - - float3 worldPosition = mul(ObjectSrg::GetWorldMatrix(), float4(IN.m_position, 1.0)).xyz; - - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - // Shadow coords will be calculated in the pixel shader in this case - bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; - - VertexHelper(IN, OUT, worldPosition, skipShadowCoords); - - return OUT; -} - - -// ---------- Pixel Shader ---------- - -PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) -{ - const float3 vertexNormal = normalize(IN.m_normal); - - // ------- Tangents & Bitangets ------- - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - if (ShouldHandleParallax() || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture)) - { - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - } - - // ------- Depth & Parallax ------- - - depthNDC = IN.m_position.z; - - bool displacementIsClipped = false; - - if(ShouldHandleParallax()) - { - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC, IN.m_position.w, displacementIsClipped); - - // Adjust directional light shadow coordinates for parallax correction - if(o_parallax_enablePixelDepthOffset) - { - const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; - if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) - { - DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); - } - } - } - - Surface surface; - surface.position = IN.m_worldPosition.xyz; - - // ------- Alpha & Clip ------- - - float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUv = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = GetAlphaInputAndClip(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUv, opacityUv, MaterialSrg::m_sampler, MaterialSrg::m_opacityFactor, o_opacity_source); - - // ------- Normal ------- - - float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex]; - float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. - surface.vertexNormal = vertexNormal; - surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, IN.m_normal, - tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor); - - // ------- Base Color ------- - - float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); - float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); - - if(o_parallax_highlightClipping && displacementIsClipped) - { - ApplyParallaxClippingHighlight(baseColor); - } - - // ------- Metallic ------- - - float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex]; - float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); - - // ------- Specular ------- - - float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex]; - float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); - - // ------- Roughness ------- - - float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex]; - surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, - MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); - surface.CalculateRoughnessA(); - - // ------- Lighting Data ------- - - LightingData lightingData; - - // Light iterator - lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); - lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); - - // Directional light shadow coordinates - lightingData.shadowCoords = IN.m_shadowCoords; - - // ------- Emissive ------- - - float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex]; - lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); - - // ------- Occlusion ------- - - lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); - lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); - - // ------- Clearcoat ------- - - // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags - if(o_clearCoat_feature_enabled) - { - if(o_clearCoat_enabled) - { - float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, - MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, - MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, - uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], - MaterialSrg::m_sampler, isFrontFace, - surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); - } - - // manipulate base layer f0 if clear coat is enabled - // modify base layer's normal incidence reflectance - // for the derivation of the following equation please refer to: - // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification - float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); - surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); - } - - // Diffuse and Specular response (used in IBL calculations) - lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); - lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; - - if(o_clearCoat_feature_enabled) - { - // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 - lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); - } - - // ------- Multiscatter ------- - - lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); - - // ------- Lighting Calculation ------- - - // Apply Decals - ApplyDecals(lightingData.tileIterator, surface); - - // Apply Direct Lighting - ApplyDirectLighting(surface, lightingData); - - // Apply Image Based Lighting (IBL) - ApplyIBL(surface, lightingData); - - // Finalize Lighting - lightingData.FinalizeLighting(); - - PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); - - // ------- Opacity ------- - - if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) - { - // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. - // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface - // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor - // values close to 1.0, that indicates the absence of a surface entirely, so this effect should - // not apply. - float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; - alpha = lerp(fresnelAlpha, alpha, MaterialSrg::m_opacityAffectsSpecularFactor); - } - - if (o_opacity_mode == OpacityMode::Blended) - { - // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when - // specular is being added to diffuse just because we're calling render target 0 "diffuse". - - // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular - // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. - // It's done this way because surface transparency doesn't really change specular response (eg, glass). - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_diffuseColor.w = alpha; - } - else if (o_opacity_mode == OpacityMode::TintedTransparent) - { - // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting - // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength - // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, - // absorption, and interior color to be specified. - // - // The technique uses dual source blending to allow two separate sources to be part of the blending equation - // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and - // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). - // - // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then - // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_specularColor.rgb = baseColor * (1.0 - alpha); - } - else - { - lightingOutput.m_diffuseColor.w = -1; // Disable subsurface scattering - } - - return lightingOutput; -} - -ForwardPassOutputWithDepth StandardPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutputWithDepth OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); - -#ifdef UNIFIED_FORWARD_OUTPUT - OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; - OUT.m_color.a = lightingOutput.m_diffuseColor.a; - OUT.m_depth = depth; -#else - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; - OUT.m_depth = depth; -#endif - return OUT; -} - -[earlydepthstencil] -ForwardPassOutput StandardPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutput OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); - -#ifdef UNIFIED_FORWARD_OUTPUT - OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; - OUT.m_color.a = lightingOutput.m_diffuseColor.a; -#else - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; -#endif - return OUT; -} +#include "MaterialFunctions/EvaluateStandardSurface.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" + +#include "StandardSurface_ForwardPass.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader index 44139608ca..511749c6ae 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader @@ -5,7 +5,9 @@ // DrawListTag. If your pipeline doesn't have a "lowEndForward" DrawListTag, no draw items // for this shader will be created. - "Source" : "./StandardPBR_LowEndForward.azsl", + "Source" : "./StandardPBR_ForwardPass.azsl", + + "Definitions": [ "QUALITY_LOW_END=1" ], "DepthStencilState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader index 9faa1d3698..6dc4004b07 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader @@ -5,7 +5,9 @@ // DrawListTag. If your pipeline doesn't have a "lowEndForward" DrawListTag, no draw items // for this shader will be created. - "Source" : "./StandardPBR_LowEndForward.azsl", + "Source" : "./StandardPBR_ForwardPass.azsl", + + "Definitions": [ "QUALITY_LOW_END=1" ], "DepthStencilState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl index 02f1cd0389..634d23daa1 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl @@ -9,93 +9,17 @@ #include #include "StandardPBR_Common.azsli" #include -#include -#include -#include #include "MaterialInputs/AlphaInput.azsli" #include "MaterialInputs/ParallaxInput.azsli" -struct VertexInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VertexOutput -{ - // "centroid" is needed for SV_Depth to compile - linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VertexOutput MainVS(VertexInput IN) -{ - const float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - VertexOutput OUT; - - const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - - OUT.m_depth += PdoShadowMapBias; - } - - // Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#define SHADOWS 1 +#define ENABLE_ALPHA_CLIP 1 +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsli new file mode 100644 index 0000000000..5f89fc704b --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsli @@ -0,0 +1,306 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +// Pass Output +#include + +// Utility +#include +#include + +// Custom Surface & Lighting +#include + +// Decals +#include + + +// ---------- Vertex Shader ---------- + +struct VSInput +{ + // Base fields (required by the template azsli file)... + float3 m_position : POSITION; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; +}; + +struct VSOutput +{ + // Base fields (required by the template azsli file)... + // "centroid" is needed for SV_Depth to compile + precise linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV3; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv[UvSetCount] : UV1; +}; + +#include + +VSOutput StandardPbr_ForwardPassVS(VSInput IN) +{ + VSOutput OUT; + + float4x4 objectToWorld = GetObjectToWorld(); + float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); + OUT.m_worldPosition = worldPosition.xyz; + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); + + float2 uvs[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformUvs(uvs, OUT.m_uv); + + // Shadow coords will be calculated in the pixel shader in this case + bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; + + float3x3 objectToWorldIT = GetNormalToWorld(); + ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); + + // directional light shadow + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && !skipShadowCoords && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords( + shadowIndex, + worldPosition, + OUT.m_normal, + OUT.m_shadowCoords); + } + + return OUT; +} + + +// ---------- Pixel Shader ---------- + +PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) +{ + const float3 vertexNormal = normalize(IN.m_normal); + + // ------- Tangents & Bitangents ------- + float3 tangents[UvSetCount] = { IN.m_tangent, IN.m_tangent }; + float3 bitangents[UvSetCount] = { IN.m_bitangent, IN.m_bitangent }; + + if (ShouldHandleParallax() || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture)) + { + for (int i = 0; i != UvSetCount; ++i) + { + EvaluateTangentFrame( + IN.m_normal, + IN.m_worldPosition, + isFrontFace, + IN.m_uv[i], + i, + IN.m_tangent, + IN.m_bitangent, + tangents[i], + bitangents[i]); + } + } + + // ------- Depth & Parallax ------- + + depthNDC = IN.m_position.z; + bool displacementIsClipped = false; + + if(ShouldHandleParallax()) + { + SetPixelDepth( + IN.m_worldPosition, + IN.m_normal, + tangents, + bitangents, + IN.m_uv, + isFrontFace, + IN.m_position.w, + depthNDC, + displacementIsClipped); + + // Adjust directional light shadow coordinates for parallax correction + if(o_parallax_enablePixelDepthOffset) + { + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); + } + } + } + + SurfaceSettings surfaceSettings; + Surface surface; + surface.vertexNormal = vertexNormal; + surface.position = IN.m_worldPosition.xyz; + + // ------- Alpha & Clip ------- + // TODO: this often invokes a separate sample of the base color texture which is wasteful + float alpha = GetAlphaAndClip(IN.m_uv); + + EvaluateStandardSurface(IN.m_normal, IN.m_uv, tangents, bitangents, isFrontFace, displacementIsClipped, surface, surfaceSettings); + + // ------- Lighting Data ------- + + LightingData lightingData; + + // Light iterator + lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); + lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); + + // Directional light shadow coordinates + lightingData.shadowCoords = IN.m_shadowCoords; + + // Surface lighting properties + lightingData.emissiveLighting = surface.emissiveLighting; + lightingData.diffuseAmbientOcclusion = surface.diffuseAmbientOcclusion; + lightingData.specularOcclusion = surface.specularOcclusion; + + // Diffuse and Specular response (used in IBL calculations) + lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); + lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; + + if(o_clearCoat_feature_enabled) + { + // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 + lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); + } + + // ------- Multiscatter ------- + + lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); + + // ------- Lighting Calculation ------- + + // Apply Decals + ApplyDecals(lightingData.tileIterator, surface); + + // Apply Direct Lighting + ApplyDirectLighting(surface, lightingData); + + // Apply Image Based Lighting (IBL) + ApplyIBL(surface, lightingData); + + // Finalize Lighting + lightingData.FinalizeLighting(); + + PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); + + // ------- Opacity ------- + + if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) + { + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; + alpha = lerp(fresnelAlpha, alpha, surfaceSettings.opacityAffectsSpecularFactor); + } + + if (o_opacity_mode == OpacityMode::Blended) + { + // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when + // specular is being added to diffuse just because we're calling render target 0 "diffuse". + + // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular + // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. + // It's done this way because surface transparency doesn't really change specular response (eg, glass). + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_diffuseColor.w = alpha; + } + else if (o_opacity_mode == OpacityMode::TintedTransparent) + { + // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting + // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength + // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, + // absorption, and interior color to be specified. + // + // The technique uses dual source blending to allow two separate sources to be part of the blending equation + // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and + // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). + // + // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then + // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_specularColor.rgb = surface.baseColor * (1.0 - alpha); + } + else + { + lightingOutput.m_diffuseColor.w = -1; // Disable subsurface scattering + } + + return lightingOutput; +} + +ForwardPassOutputWithDepth StandardPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutputWithDepth OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + +#ifdef UNIFIED_FORWARD_OUTPUT + OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; + OUT.m_color.a = lightingOutput.m_diffuseColor.a; + OUT.m_depth = depth; +#else + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; + OUT.m_depth = depth; +#endif + return OUT; +} + +[earlydepthstencil] +ForwardPassOutput StandardPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutput OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + +#ifdef UNIFIED_FORWARD_OUTPUT + OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; + OUT.m_color.a = lightingOutput.m_diffuseColor.a; +#else + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; +#endif + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli index eb8c33cdce..961fbd49f9 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli @@ -13,6 +13,21 @@ #include #include +// This data varies across different surfaces, but is uniform within a surface +class SurfaceSettings +{ + //! Subsurface scattering parameters + float subsurfaceScatteringQuality; + float3 scatterDistance; + + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float opacityAffectsSpecularFactor; +}; + class Surface { AnisotropicSurfaceData anisotropy; @@ -24,11 +39,19 @@ class Surface float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space float3 vertexNormal; //!< Vertex normal in world-space - float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value - float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 baseColor; //!< Surface base color + float metallic; //!< Surface metallic property float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance + float subsurfaceScatteringFactor; + + //! Surface lighting inputs + float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value + float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 emissiveLighting; //!< Emissive lighting + float diffuseAmbientOcclusion; //!< Diffuse ambient occlusion factor - [0, 1] :: [Dark, Bright] + float specularOcclusion; //!< Specular occlusion factor - [0, 1] :: [Dark, Bright] //! Applies specular anti-aliasing to roughnessA2 void ApplySpecularAA(); @@ -76,12 +99,13 @@ void Surface::CalculateRoughnessA() } } -void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic) +void Surface::SetAlbedoAndSpecularF0(float3 newBaseColor, float specularF0Factor, float newMetallic) { + baseColor = newBaseColor; + metallic = newMetallic; float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor; // Compute albedo and specularF0 based on metalness albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic); specularF0 = lerp(dielectricSpecularF0, baseColor, metallic); } - diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli index cf4edba923..9a8d5cfd54 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli @@ -8,11 +8,21 @@ #pragma once -#include #include #include #include +// This data varies across different surfaces, but is uniform within a surface +class SurfaceSettings +{ + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float opacityAffectsSpecularFactor; +}; + class Surface { @@ -25,19 +35,33 @@ class Surface precise float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space float3 vertexNormal; //!< Vertex normal in world-space - float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value - float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 baseColor; //!< Surface base color + float metallic; //!< Surface metallic property float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float opacityAffectsSpecularFactor; + + //! Surface lighting data + float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value + float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 emissiveLighting; //!< Emissive lighting + float diffuseAmbientOcclusion; //!< Diffuse ambient occlusion factor - [0, 1] :: [Dark, Bright] + float specularOcclusion; //!< Specular occlusion factor - [0, 1] :: [Dark, Bright] + //! Applies specular anti-aliasing to roughnessA2 void ApplySpecularAA(); //! Calculates roughnessA and roughnessA2 after roughness has been set void CalculateRoughnessA(); - //! Sets albedo and specularF0 using metallic workflow + //! Sets albedo, base color, specularF0, and metallic properties using metallic workflow void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic); }; @@ -75,12 +99,14 @@ void Surface::CalculateRoughnessA() } } -void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic) +void Surface::SetAlbedoAndSpecularF0(float3 newBaseColor, float specularF0Factor, float newMetallic) { + baseColor = newBaseColor; + metallic = newMetallic; + float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor; // Compute albedo and specularF0 based on metalness albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic); specularF0 = lerp(dielectricSpecularF0, baseColor, metallic); } - diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index e6ad71bde3..00d437acd1 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -10,12 +10,24 @@ set(FILES Materials/Special/ShadowCatcher.azsl Materials/Special/ShadowCatcher.materialtype Materials/Special/ShadowCatcher.shader + Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli + Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli + Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli + Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli + Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli + Materials/Types/MaterialFunctions/ParallaxDepth.azsli + Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli + Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli + Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli + Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli + Materials/Types/MaterialFunctions/StandardTransformUvs.azsli Materials/Types/BasePBR.materialtype Materials/Types/BasePBR_Common.azsli Materials/Types/BasePBR_ForwardPass.azsl Materials/Types/BasePBR_ForwardPass.shader Materials/Types/BasePBR_LowEndForward.azsl Materials/Types/BasePBR_LowEndForward.shader + Materials/Types/DepthPass_WithPS.azsli Materials/Types/EnhancedPBR.materialtype Materials/Types/EnhancedPBR_Common.azsli Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -26,6 +38,7 @@ set(FILES Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl Materials/Types/EnhancedPBR_Shadowmap_WithPS.shader Materials/Types/EnhancedPBR_SubsurfaceState.lua + Materials/Types/EnhancedSurface_ForwardPass.azsli Materials/Types/Skin.azsl Materials/Types/Skin.materialtype Materials/Types/Skin.shader @@ -56,7 +69,6 @@ set(FILES Materials/Types/StandardPBR_ForwardPass_EDS.shader Materials/Types/StandardPBR_HandleOpacityDoubleSided.lua Materials/Types/StandardPBR_HandleOpacityMode.lua - Materials/Types/StandardPBR_LowEndForward.azsl Materials/Types/StandardPBR_LowEndForward.shader Materials/Types/StandardPBR_LowEndForward_EDS.shader Materials/Types/StandardPBR_Metallic.lua @@ -65,6 +77,7 @@ set(FILES Materials/Types/StandardPBR_ShaderEnable.lua Materials/Types/StandardPBR_Shadowmap_WithPS.azsl Materials/Types/StandardPBR_Shadowmap_WithPS.shader + Materials/Types/StandardSurface_ForwardPass.azsli Materials/Types/MaterialInputs/AlphaInput.azsli Materials/Types/MaterialInputs/BaseColorInput.azsli Materials/Types/MaterialInputs/ClearCoatInput.azsli diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h index 98220fae15..9622b5aa40 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h @@ -100,7 +100,8 @@ namespace AZ //! Sets all of the the disk data for the provided LightHandle. virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0; - + //! Get a read only copy of a disk lights data, useful for debug rendering + virtual const DiskLightData& GetDiskData(LightHandle handle) const = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp index 168a7ea00a..9c626fccd8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -255,6 +255,13 @@ namespace AZ UpdateShadow(handle); } + const DiskLightData& DiskLightFeatureProcessor::GetDiskData(LightHandle handle) const + { + AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::GetDiskData()."); + + return m_diskLightData.GetData(handle.GetIndex()); + } + const Data::Instance DiskLightFeatureProcessor::GetLightBuffer()const { return m_lightBufferHandler.GetBuffer(); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index bafddacc65..d742b1fbc0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -58,6 +58,7 @@ namespace AZ void SetEsmExponent(LightHandle handle, float esmExponent) override; void SetDiskData(LightHandle handle, const DiskLightData& data) override; + const DiskLightData& GetDiskData(LightHandle handle) const override; const Data::Instance GetLightBuffer()const; uint32_t GetLightCount()const; diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp index d5096d7a0b..680ad5f690 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp @@ -82,9 +82,8 @@ namespace AZ // The source data for generating material asset sourceData.m_materialType = GetMaterialTypePath(); - auto handleTexture = [&materialData, &sourceData]( - const char* propertyTextureGroup, SceneAPI::DataTypes::IMaterialData::TextureMapType textureType) { - MaterialSourceData::PropertyMap& properties = sourceData.m_properties[propertyTextureGroup]; + auto handleTexture = [&materialData, &sourceData](const char* propertyTextureGroup, SceneAPI::DataTypes::IMaterialData::TextureMapType textureType) + { const AZStd::string& texturePath = materialData.GetTexture(textureType); // Check to see if the image asset exists. If not, skip this texture map and just disable it. @@ -101,7 +100,7 @@ namespace AZ if (assetFound) { - properties["textureMap"].m_value = texturePath; + sourceData.SetPropertyValue(MaterialPropertyId{propertyTextureGroup, "textureMap"}, texturePath); } else if (!texturePath.empty()) { @@ -120,7 +119,7 @@ namespace AZ { anyPBRInUse = true; handleTexture("baseColor", SceneAPI::DataTypes::IMaterialData::TextureMapType::BaseColor); - sourceData.m_properties["baseColor"]["textureBlendMode"].m_value = AZStd::string("Lerp"); + sourceData.SetPropertyValue(Name{"baseColor.textureBlendMode"}, AZStd::string("Lerp")); } else { @@ -135,10 +134,10 @@ namespace AZ if (baseColor.has_value()) { anyPBRInUse = true; - sourceData.m_properties["baseColor"]["color"].m_value = toColor(baseColor.value()); + sourceData.SetPropertyValue(Name{"baseColor.color"}, toColor(baseColor.value())); } - sourceData.m_properties["opacity"]["factor"].m_value = materialData.GetOpacity(); + sourceData.SetPropertyValue(Name{"opacity.factor"}, materialData.GetOpacity()); auto applyOptionalPropertiesFunc = [&sourceData, &anyPBRInUse](const auto& propertyGroup, const auto& propertyName, const auto& propertyOptional) { @@ -147,7 +146,7 @@ namespace AZ if (propertyOptional.has_value()) { anyPBRInUse = true; - sourceData.m_properties[propertyGroup][propertyName].m_value = propertyOptional.value(); + sourceData.SetPropertyValue(MaterialPropertyId{propertyGroup, propertyName}, propertyOptional.value()); } }; @@ -160,7 +159,7 @@ namespace AZ applyOptionalPropertiesFunc("roughness", "useTexture", materialData.GetUseRoughnessMap()); handleTexture("emissive", SceneAPI::DataTypes::IMaterialData::TextureMapType::Emissive); - sourceData.m_properties["emissive"]["color"].m_value = toColor(materialData.GetEmissiveColor()); + sourceData.SetPropertyValue(Name{"emissive.color"}, toColor(materialData.GetEmissiveColor())); applyOptionalPropertiesFunc("emissive", "intensity", materialData.GetEmissiveIntensity()); applyOptionalPropertiesFunc("emissive", "useTexture", materialData.GetUseEmissiveMap()); @@ -171,7 +170,7 @@ namespace AZ { // If it doesn't have the useColorMap property, then it's a non-PBR material and the baseColor // texture needs to be set to the diffuse color. - sourceData.m_properties["baseColor"]["color"].m_value = toColor(materialData.GetDiffuseColor()); + sourceData.SetPropertyValue(Name{"baseColor.color"}, toColor(materialData.GetDiffuseColor())); } return true; } diff --git a/Gems/Atom/RHI/Code/Tests/PipelineState.h b/Gems/Atom/RHI/Code/Tests/PipelineState.h index 7f7303d0b9..29e2099097 100644 --- a/Gems/Atom/RHI/Code/Tests/PipelineState.h +++ b/Gems/Atom/RHI/Code/Tests/PipelineState.h @@ -23,7 +23,7 @@ namespace UnitTest AZStd::unordered_map m_pipelineStates; private: - AZ::RHI::ResultCode InitInternal(AZ::RHI::Device&, const RHI::PipelineLibraryDescriptor&) override { return AZ::RHI::ResultCode::Success; } + AZ::RHI::ResultCode InitInternal(AZ::RHI::Device&, const AZ::RHI::PipelineLibraryDescriptor&) override { return AZ::RHI::ResultCode::Success; } void ShutdownInternal() override; AZ::RHI::ResultCode MergeIntoInternal(AZStd::span) override; AZ::RHI::ConstPtr GetSerializedDataInternal() const override { return nullptr; } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 0a9371f722..8819cbc78b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -59,24 +59,25 @@ namespace AZ uint32_t m_materialTypeVersion = 0; //!< The version of the material type that was used to configure this material - struct Property - { - AZ_TYPE_INFO(AZ::RPI::MaterialSourceData::Property, "{8D613464-3750-4122-AFFE-9238010D5AFC}"); - - MaterialPropertyValue m_value; - }; - - using PropertyMap = AZStd::map; - using PropertyGroupMap = AZStd::map; - - PropertyGroupMap m_properties; - enum class ApplyVersionUpdatesResult { Failed, NoUpdates, UpdatesApplied }; + + //! If the data was loaded from an old format file (i.e. where "properties" was a tree with property values nested under groups), + //! this converts to the new format where properties are stored in a flat list. + void ConvertToNewDataFormat(); + + // Note that even though we use an unordered map, the JSON serialization system is nice enough to sort the data when saving to JSON. + using PropertyValueMap = AZStd::unordered_map; + + void SetPropertyValue(const Name& propertyId, const MaterialPropertyValue& value); + const MaterialPropertyValue& GetPropertyValue(const Name& propertyId) const; + const PropertyValueMap& GetPropertyValues() const; + bool HasPropertyValue(const Name& propertyId) const; + void RemovePropertyValue(const Name& propertyId); //! Creates a MaterialAsset from the MaterialSourceData content. //! @param assetId ID for the MaterialAsset @@ -103,8 +104,16 @@ namespace AZ AZStd::unordered_set* sourceDependencies = nullptr) const; private: + void ApplyPropertiesToAssetCreator( AZ::RPI::MaterialAssetCreator& materialAssetCreator, const AZStd::string_view& materialSourceFilePath) const; + + // @deprecated: Don't use "properties" in JSON, use "propertyValues" instead. + using PropertyGroupMap = AZStd::unordered_map; + PropertyGroupMap m_propertiesOld; + + PropertyValueMap m_propertyValues; + MaterialPropertyValue m_invalidValue; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h index 79c73495e0..23219cfa89 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h @@ -216,11 +216,11 @@ namespace AZ //! This field is unused, and has been replaced by MaterialTypeSourceData::m_version below. It is kept for legacy file compatibility to suppress warnings and errors. uint32_t m_versionOld = 0; - //! [Deprecated] Use m_propertyGroups instead + //! @deprecated: Use m_propertyGroups instead //! List of groups that will contain the available properties AZStd::vector m_groupsOld; - //! [Deprecated] Use m_propertyGroups instead + //! @deprecated: Use m_propertyGroups instead AZStd::map> m_propertiesOld; //! Collection of all available user-facing properties diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h index 2fb55e5f40..f6c10e003e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h @@ -24,6 +24,7 @@ namespace AZ namespace RPI { + class MaterialSourceData; class MaterialTypeSourceData; namespace MaterialUtils @@ -48,11 +49,14 @@ namespace AZ //! @return if resolving is successful. An error will be reported if it fails. bool ResolveMaterialPropertyEnumValue(const MaterialPropertyDescriptor* propertyDescriptor, const AZ::Name& enumName, MaterialPropertyValue& outResolvedValue); - //! Load material type from a json file. If the file path is relative, the loaded json document must be provided. + //! Load a material type from a json file. If the file path is relative, the loaded json document must be provided. //! Otherwise, it will use the passed in document first if not null, or load the json document from the path. //! @param filePath a relative path if document is provided, an absolute path if document is not provided. //! @param document the loaded json document. AZ::Outcome LoadMaterialTypeSourceData(const AZStd::string& filePath, const rapidjson::Value* document = nullptr); + + //! Load a material from a json file. + AZ::Outcome LoadMaterialSourceData(const AZStd::string& filePath, const rapidjson::Value* document = nullptr, bool warningsAsErrors = false); //! Utility function for custom JSON serializers to report results as "Skipped" when encountering keys that aren't recognized //! as part of the custom format. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h index 29b127407e..b3e898c4dd 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h @@ -184,8 +184,8 @@ namespace AZ virtual void DrawDisk(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0; //! Draw a cone. - //! @param center The center of the base circle. - //! @param direction The direction vector. The tip of the cone will point along this vector. + //! @param center The center of the cone base. + //! @param direction The direction vector. This is the vector from the center of the base to the point at the tip. //! @param radius The radius. //! @param height The height of the cone (the distance from the base center to the tip). //! @param color The color to draw the cone. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h index 546089ab1e..6516407265 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h @@ -60,6 +60,11 @@ namespace AZ //! Same as above. Provided as a convenience when all arguments of the 'numthreads' attributes should be assigned to RHI::DispatchDirect::m_threadsPerGroup* variables. AZ::Outcome GetComputeShaderNumThreads(const Data::Asset& shaderAsset, RHI::DispatchDirect& dispatchDirect); + //! Get single image pixel value from raw image data + //! This assumes the imageData is not empty + template + T GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex = 0); + //! Get single image pixel value for specified mip and slice template T GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index d55f202c03..bb0330e7b6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -52,7 +52,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 117; // new material type file format + materialBuilderDescriptor.m_version = 119; // new material file format materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); @@ -129,38 +129,6 @@ namespace AZ } } - template - AZ::Outcome LoadSourceData(const rapidjson::Value& value, const AZStd::string& filePath) - { - MaterialSourceDataT material; - - JsonDeserializerSettings settings; - - JsonReportingHelper reportingHelper; - reportingHelper.Attach(settings); - - // This is required by some custom material serializers to support relative path references. - JsonFileLoadContext fileLoadContext; - fileLoadContext.PushFilePath(filePath); - settings.m_metadata.Add(fileLoadContext); - - JsonSerialization::Load(material, value, settings); - - if (reportingHelper.ErrorsReported()) - { - return AZ::Failure(); - } - else if (reportingHelper.WarningsReported()) - { - AZ_Error(MaterialBuilderName, false, "Warnings reported while loading '%s'", filePath.c_str()); - return AZ::Failure(); - } - else - { - return AZ::Success(AZStd::move(material)); - } - } - void MaterialBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const { if (m_isShuttingDown) @@ -295,7 +263,7 @@ namespace AZ AZ::Data::Asset MaterialBuilder::CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) const { - auto material = LoadSourceData(json, materialSourceFilePath); + auto material = MaterialUtils::LoadMaterialSourceData(materialSourceFilePath, &json, true); if (!material.IsSuccess()) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp index cb345e1d93..07d8c919d0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp @@ -47,61 +47,61 @@ namespace AZ { namespace JSR = JsonSerializationResult; - AZ_Assert(azrtti_typeid() == outputValueTypeId, + AZ_Assert(azrtti_typeid() == outputValueTypeId, "Unable to deserialize material property value to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - MaterialSourceData::Property* property = reinterpret_cast(outputValue); + MaterialPropertyValue* property = reinterpret_cast(outputValue); AZ_Assert(property, "Output value for JsonMaterialPropertyValueSerializer can't be null."); JSR::ResultCode result(JSR::Tasks::ReadField); if (inputValue.IsBool()) { - result.Combine(LoadVariant(property->m_value, false, inputValue, context)); + result.Combine(LoadVariant(*property, false, inputValue, context)); } else if (inputValue.IsInt() || inputValue.IsInt64()) { - result.Combine(LoadVariant(property->m_value, 0, inputValue, context)); + result.Combine(LoadVariant(*property, 0, inputValue, context)); } else if (inputValue.IsUint() || inputValue.IsUint64()) { - result.Combine(LoadVariant(property->m_value, 0u, inputValue, context)); + result.Combine(LoadVariant(*property, 0u, inputValue, context)); } else if (inputValue.IsFloat() || inputValue.IsDouble()) { - result.Combine(LoadVariant(property->m_value, 0.0f, inputValue, context)); + result.Combine(LoadVariant(*property, 0.0f, inputValue, context)); } else if (inputValue.IsArray() && inputValue.Size() == 4) { - result.Combine(LoadVariant(property->m_value, Vector4{0.0f, 0.0f, 0.0f, 0.0f}, inputValue, context)); + result.Combine(LoadVariant(*property, Vector4{0.0f, 0.0f, 0.0f, 0.0f}, inputValue, context)); } else if (inputValue.IsArray() && inputValue.Size() == 3) { - result.Combine(LoadVariant(property->m_value, Vector3{0.0f, 0.0f, 0.0f}, inputValue, context)); + result.Combine(LoadVariant(*property, Vector3{0.0f, 0.0f, 0.0f}, inputValue, context)); } else if (inputValue.IsArray() && inputValue.Size() == 2) { - result.Combine(LoadVariant(property->m_value, Vector2{0.0f, 0.0f}, inputValue, context)); + result.Combine(LoadVariant(*property, Vector2{0.0f, 0.0f}, inputValue, context)); } else if (inputValue.IsObject()) { - JsonSerializationResult::ResultCode resultCode = LoadVariant(property->m_value, Color::CreateZero(), inputValue, context); + JsonSerializationResult::ResultCode resultCode = LoadVariant(*property, Color::CreateZero(), inputValue, context); if(resultCode.GetProcessing() != JsonSerializationResult::Processing::Completed) { - resultCode = LoadVariant(property->m_value, Vector4::CreateZero(), inputValue, context); + resultCode = LoadVariant(*property, Vector4::CreateZero(), inputValue, context); } if(resultCode.GetProcessing() != JsonSerializationResult::Processing::Completed) { - resultCode = LoadVariant(property->m_value, Vector3::CreateZero(), inputValue, context); + resultCode = LoadVariant(*property, Vector3::CreateZero(), inputValue, context); } if(resultCode.GetProcessing() != JsonSerializationResult::Processing::Completed) { - resultCode = LoadVariant(property->m_value, Vector2::CreateZero(), inputValue, context); + resultCode = LoadVariant(*property, Vector2::CreateZero(), inputValue, context); } if(resultCode.GetProcessing() == JsonSerializationResult::Processing::Completed) @@ -115,7 +115,7 @@ namespace AZ } else if (inputValue.IsString()) { - result.Combine(LoadVariant(property->m_value, AZStd::string{}, inputValue, context)); + result.Combine(LoadVariant(*property, AZStd::string{}, inputValue, context)); } else { @@ -137,51 +137,51 @@ namespace AZ { namespace JSR = JsonSerializationResult; - AZ_Assert(azrtti_typeid() == valueTypeId, + AZ_Assert(azrtti_typeid() == valueTypeId, "Unable to serialize material property value to json because the provided type is %s", valueTypeId.ToString().c_str()); AZ_UNUSED(valueTypeId); - const MaterialSourceData::Property* property = reinterpret_cast(inputValue); + const MaterialPropertyValue* property = reinterpret_cast(inputValue); AZ_Assert(property, "Input value for JsonMaterialPropertyValueSerializer can't be null."); JSR::ResultCode result(JSR::Tasks::WriteValue); - if (property->m_value.Is()) + if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } - else if (property->m_value.Is()) + else if (property->Is()) { - result.Combine(ContinueStoring(outputValue, &property->m_value.GetValue(), nullptr, azrtti_typeid(), context)); + result.Combine(ContinueStoring(outputValue, &property->GetValue(), nullptr, azrtti_typeid(), context)); } if (result.GetProcessing() == JsonSerializationResult::Processing::Completed) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index ae7889aa93..fe6ec415a3 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -44,7 +44,7 @@ namespace AZ { if (JsonRegistrationContext* jsonContext = azrtti_cast(context)) { - jsonContext->Serializer()->HandlesType(); + jsonContext->Serializer()->HandlesType(); } else if (auto* serializeContext = azrtti_cast(context)) { @@ -54,15 +54,12 @@ namespace AZ ->Field("materialType", &MaterialSourceData::m_materialType) ->Field("materialTypeVersion", &MaterialSourceData::m_materialTypeVersion) ->Field("parentMaterial", &MaterialSourceData::m_parentMaterial) - ->Field("properties", &MaterialSourceData::m_properties) + ->Field("properties", &MaterialSourceData::m_propertiesOld) + ->Field("propertyValues", &MaterialSourceData::m_propertyValues) ; - serializeContext->RegisterGenericType(); + serializeContext->RegisterGenericType(); serializeContext->RegisterGenericType(); - - serializeContext->Class() - ->Version(1) - ; } } @@ -77,6 +74,55 @@ namespace AZ } } + void MaterialSourceData::SetPropertyValue(const Name& propertyId, const MaterialPropertyValue& value) + { + if (!propertyId.IsEmpty()) + { + m_propertyValues[propertyId] = value; + } + } + + const MaterialPropertyValue& MaterialSourceData::GetPropertyValue(const Name& propertyId) const + { + auto iter = m_propertyValues.find(propertyId); + if (iter == m_propertyValues.end()) + { + return m_invalidValue; + } + else + { + return iter->second; + } + } + + void MaterialSourceData::RemovePropertyValue(const Name& propertyId) + { + m_propertyValues.erase(propertyId); + } + + const MaterialSourceData::PropertyValueMap& MaterialSourceData::GetPropertyValues() const + { + return m_propertyValues; + } + + bool MaterialSourceData::HasPropertyValue(const Name& propertyId) const + { + return m_propertyValues.find(propertyId) != m_propertyValues.end(); + } + + void MaterialSourceData::ConvertToNewDataFormat() + { + for (const auto& [groupName, propertyList] : m_propertiesOld) + { + for (const auto& [propertyName, propertyValue] : propertyList) + { + SetPropertyValue(MaterialPropertyId{groupName, propertyName}, propertyValue); + } + } + + m_propertiesOld.clear(); + } + Outcome> MaterialSourceData::CreateMaterialAsset( Data::AssetId assetId, AZStd::string_view materialSourceFilePath, MaterialAssetProcessingMode processingMode, bool elevateWarnings) const { @@ -254,12 +300,14 @@ namespace AZ return Failure(); } - MaterialSourceData parentSourceData; - if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentSourceAbsPath, parentSourceData)) + auto loadParentResult = MaterialUtils::LoadMaterialSourceData(parentSourceAbsPath); + if (!loadParentResult) { AZ_Error("MaterialSourceData", false, "Failed to load MaterialSourceData for parent material: '%s'.", parentSourceAbsPath.c_str()); return Failure(); } + + MaterialSourceData parentSourceData = loadParentResult.TakeValue(); // Make sure that all materials in the hierarchy share the same material type const auto parentTypeAssetId = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); @@ -318,30 +366,29 @@ namespace AZ void MaterialSourceData::ApplyPropertiesToAssetCreator( AZ::RPI::MaterialAssetCreator& materialAssetCreator, const AZStd::string_view& materialSourceFilePath) const { - for (auto& group : m_properties) + for (auto& [propertyId, propertyValue] : m_propertyValues) { - for (auto& property : group.second) + if (!propertyValue.IsValid()) + { + materialAssetCreator.ReportWarning("Source data for material property value is invalid."); + } + else { - MaterialPropertyId propertyId{ group.first, property.first }; - if (!property.second.m_value.IsValid()) - { - materialAssetCreator.ReportWarning("Source data for material property value is invalid."); - } // If the source value type is a string, there are two possible property types: Image and Enum. If there is a "." in // the string (for the extension) we assume it's an Image and look up the referenced Asset. Otherwise, we can assume // it's an Enum value and just preserve the original string. - else if (property.second.m_value.Is() && AzFramework::StringFunc::Contains(property.second.m_value.GetValue(), ".")) + if (propertyValue.Is() && AzFramework::StringFunc::Contains(propertyValue.GetValue(), ".")) { Data::Asset imageAsset; MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference( - imageAsset, materialSourceFilePath, property.second.m_value.GetValue()); + imageAsset, materialSourceFilePath, propertyValue.GetValue()); if (result == MaterialUtils::GetImageAssetResult::Missing) { materialAssetCreator.ReportWarning( "Material property '%s': Could not find the image '%s'", propertyId.GetCStr(), - property.second.m_value.GetValue().data()); + propertyValue.GetValue().data()); } imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); @@ -349,7 +396,7 @@ namespace AZ } else { - materialAssetCreator.SetPropertyValue(propertyId, property.second.m_value); + materialAssetCreator.SetPropertyValue(propertyId, propertyValue); } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp index b9a5754732..23976cf357 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -100,9 +100,9 @@ namespace AZ serializeContext->Class() ->Version(3) // Added propertyGroups - ->Field("version", &PropertyLayout::m_versionOld) //< Deprecated, preserved for backward compatibility, replaced by MaterialTypeSourceData::version - ->Field("groups", &PropertyLayout::m_groupsOld) //< Deprecated, preserved for backward compatibility, replaced by propertyGroups - ->Field("properties", &PropertyLayout::m_propertiesOld) //< Deprecated, preserved for backward compatibility, replaced by propertyGroups + ->Field("version", &PropertyLayout::m_versionOld) //< @deprecated: preserved for backward compatibility, replaced by MaterialTypeSourceData::version + ->Field("groups", &PropertyLayout::m_groupsOld) //< @deprecated: preserved for backward compatibility, replaced by propertyGroups + ->Field("properties", &PropertyLayout::m_propertiesOld) //< @deprecated: preserved for backward compatibility, replaced by propertyGroups ->Field("propertyGroups", &PropertyLayout::m_propertyGroups) ; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index b03771173f..3855a0a222 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +83,7 @@ namespace AZ loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(filePath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!loadOutcome.IsSuccess()) { - AZ_Error("AZ::RPI::JsonUtils", false, "%s", loadOutcome.GetError().c_str()); + AZ_Error("MaterialUtils", false, "%s", loadOutcome.GetError().c_str()); return AZ::Failure(); } @@ -114,6 +115,46 @@ namespace AZ return AZ::Success(AZStd::move(materialType)); } } + + AZ::Outcome LoadMaterialSourceData(const AZStd::string& filePath, const rapidjson::Value* document, bool warningsAsErrors) + { + AZ::Outcome loadOutcome; + if (document == nullptr) + { + loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(filePath, AZ::RPI::JsonUtils::DefaultMaxFileSize); + if (!loadOutcome.IsSuccess()) + { + AZ_Error("MaterialUtils", false, "%s", loadOutcome.GetError().c_str()); + return AZ::Failure(); + } + + document = &loadOutcome.GetValue(); + } + + MaterialSourceData material; + + JsonDeserializerSettings settings; + + JsonReportingHelper reportingHelper; + reportingHelper.Attach(settings); + + JsonSerialization::Load(material, *document, settings); + material.ConvertToNewDataFormat(); + + if (reportingHelper.ErrorsReported()) + { + return AZ::Failure(); + } + else if (warningsAsErrors && reportingHelper.WarningsReported()) + { + AZ_Error("MaterialUtils", false, "Warnings reported while loading '%s'", filePath.c_str()); + return AZ::Failure(); + } + else + { + return AZ::Success(AZStd::move(material)); + } + } void CheckForUnrecognizedJsonFields(const AZStd::string_view* acceptedFieldNames, uint32_t acceptedFieldNameCount, const rapidjson::Value& object, JsonDeserializerContext& context, JsonSerializationResult::ResultCode &result) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp index e13db253f3..8a6cc80cfe 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp @@ -133,7 +133,8 @@ namespace AZ case AZ::RHI::Format::R16G16_UNORM: case AZ::RHI::Format::R16G16B16A16_UNORM: { - return mem[index] / static_cast(std::numeric_limits::max()); + auto actualMem = reinterpret_cast(mem); + return actualMem[index] / static_cast(std::numeric_limits::max()); } case AZ::RHI::Format::R16_SNORM: case AZ::RHI::Format::R16G16_SNORM: @@ -231,16 +232,12 @@ namespace AZ } } - template - T GetSubImagePixelValueInternal(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + size_t GetImageDataIndex(const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) { - AZStd::array values{ aznumeric_cast(0) }; + auto width = imageDescriptor.m_size.m_width; + const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); - auto topLeft = AZStd::make_pair(x, y); - auto bottomRight = AZStd::make_pair(x + 1, y + 1); - GetSubImagePixelValues(imageAsset, topLeft, bottomRight, AZStd::span(values), componentIndex, mip, slice); - - return values[0]; + return (y * width + x) * numComponents + componentIndex; } } @@ -446,22 +443,60 @@ namespace AZ return GetComputeShaderNumThreads(shaderAsset, &dispatchDirect.m_threadsPerGroupX, &dispatchDirect.m_threadsPerGroupY, &dispatchDirect.m_threadsPerGroupZ); } + template<> + float GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) + { + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); + return Internal::RetrieveFloatValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + + template<> + AZ::u32 GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) + { + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); + return Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + + template<> + AZ::s32 GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) + { + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); + return Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + + template + T GetSubImagePixelValueInternal(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + if (!imageAsset.IsReady()) + { + return aznumeric_cast(0); + } + + auto imageData = imageAsset->GetSubImageData(mip, slice); + if (imageData.empty()) + { + return aznumeric_cast(0); + } + + return GetImageDataPixelValue(imageData, imageAsset->GetImageDescriptor(), x, y, componentIndex); + } + template<> float GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + return GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); } template<> AZ::u32 GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + return GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); } template<> AZ::s32 GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + return GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); } bool GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) @@ -477,17 +512,14 @@ namespace AZ return false; } - const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); - const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format) / numComponents; + const AZ::RHI::ImageDescriptor& imageDescriptor = imageAsset->GetImageDescriptor(); size_t outValuesIndex = 0; for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) { for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) { - size_t imageDataIndex = (y * width + x) * pixelSize + componentIndex; + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); auto& outValue = outValues[outValuesIndex++]; outValue = Internal::RetrieveFloatValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); @@ -510,17 +542,14 @@ namespace AZ return false; } - const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); - const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format) / numComponents; + const AZ::RHI::ImageDescriptor& imageDescriptor = imageAsset->GetImageDescriptor(); size_t outValuesIndex = 0; for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) { for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) { - size_t imageDataIndex = (y * width + x) * pixelSize + componentIndex; + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); auto& outValue = outValues[outValuesIndex++]; outValue = Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); @@ -543,17 +572,14 @@ namespace AZ return false; } - const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); - const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format) / numComponents; + const AZ::RHI::ImageDescriptor& imageDescriptor = imageAsset->GetImageDescriptor(); size_t outValuesIndex = 0; for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) { for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) { - size_t imageDataIndex = (y * width + x) * pixelSize + componentIndex; + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); auto& outValue = outValues[outValuesIndex++]; outValue = Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index 2bd257d55b..7676772389 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -86,7 +86,7 @@ namespace UnitTest RPITestFixture::TearDown(); } - + Data::Asset CreateTestMaterialTypeAsset(Data::AssetId assetId) { const char* materialTypeJson = R"( @@ -146,21 +146,21 @@ namespace UnitTest } )"; - MaterialTypeSourceData materialTypeSourceData; LoadTestDataFromJson(materialTypeSourceData, materialTypeJson); return materialTypeSourceData.CreateMaterialTypeAsset(assetId).TakeValue(); } }; - void AddPropertyGroup(MaterialSourceData& material, AZStd::string_view groupName) + void AddPropertyGroup(MaterialSourceData&, AZStd::string_view) { - material.m_properties.insert(groupName); + // Old function, left blank intentionally } - void AddProperty(MaterialSourceData& material, AZStd::string_view groupName, AZStd::string_view propertyName, const MaterialPropertyValue& anyValue) + void AddProperty(MaterialSourceData& material, AZStd::string_view groupName, AZStd::string_view propertyName, const MaterialPropertyValue& value) { - material.m_properties[groupName][propertyName].m_value = anyValue; + MaterialPropertyId id{groupName, propertyName}; + material.SetPropertyValue(id, value); } TEST_F(MaterialSourceDataTests, CreateMaterialAsset_BasicProperties) @@ -357,82 +357,63 @@ namespace UnitTest return fixupType(a.GetTypeId()) == fixupType(targetTypeId) && fixupType(b.GetTypeId()) == fixupType(targetTypeId); } - void CheckEqual(MaterialSourceData& a, MaterialSourceData& b) + void CheckEqual(const MaterialSourceData& a, const MaterialSourceData& b) { - EXPECT_STREQ(a.m_materialType.data(), b.m_materialType.data()); - EXPECT_STREQ(a.m_description.data(), b.m_description.data()); - EXPECT_STREQ(a.m_parentMaterial.data(), b.m_parentMaterial.data()); + EXPECT_STREQ(a.m_materialType.c_str(), b.m_materialType.c_str()); + EXPECT_STREQ(a.m_description.c_str(), b.m_description.c_str()); + EXPECT_STREQ(a.m_parentMaterial.c_str(), b.m_parentMaterial.c_str()); EXPECT_EQ(a.m_materialTypeVersion, b.m_materialTypeVersion); - EXPECT_EQ(a.m_properties.size(), b.m_properties.size()); - for (auto& groupA : a.m_properties) - { - AZStd::string groupName = groupA.first; + EXPECT_EQ(a.GetPropertyValues().size(), b.GetPropertyValues().size()); - auto groupIterB = b.m_properties.find(groupName); - if (groupIterB == b.m_properties.end()) + for (auto& [propertyId, propertyValue] : a.GetPropertyValues()) + { + if (!b.HasPropertyValue(propertyId)) { - EXPECT_TRUE(false) << "groupB[" << groupName.c_str() << "] not found"; + EXPECT_TRUE(false) << "Property '" << propertyId.GetCStr() << "' not found in material B"; continue; } - auto& groupB = *groupIterB; + auto& propertyA = propertyValue; + auto& propertyB = b.GetPropertyValue(propertyId); - EXPECT_EQ(groupA.second.size(), groupB.second.size()) << " for group[" << groupName.c_str() << "]"; - - for (auto& propertyIterA : groupA.second) - { - AZStd::string propertyName = propertyIterA.first; - - auto propertyIterB = groupB.second.find(propertyName); - if (propertyIterB == groupB.second.end()) - { - EXPECT_TRUE(false) << "groupB[" << groupName.c_str() << "][" << propertyName.c_str() << "] not found"; - continue; - } - - auto& propertyA = propertyIterA.second; - auto& propertyB = propertyIterB->second; - - AZStd::string propertyReference = AZStd::string::format(" for property '%s.%s'", groupName.c_str(), propertyName.c_str()); + AZStd::string propertyReference = AZStd::string::format(" for property '%s'", propertyId.GetCStr()); - // We allow some types like Vector4 and Color or Int and UInt to be interchangeable since they serialize the same and can be converted when the MaterialAsset is finalized. + // We allow some types like Vector4 and Color or Int and UInt to be interchangeable since they serialize the same and can be converted when the MaterialAsset is finalized. - if (AreTypesCompatible(propertyA.m_value, propertyB.m_value)) - { - EXPECT_EQ(propertyA.m_value.GetValue(), propertyB.m_value.GetValue()) << propertyReference.c_str(); - } - else if (AreTypesCompatible(propertyA.m_value, propertyB.m_value)) - { - EXPECT_EQ(GetAsInt(propertyA.m_value), GetAsInt(propertyB.m_value)) << propertyReference.c_str(); - } - else if (AreTypesCompatible(propertyA.m_value, propertyB.m_value)) - { - EXPECT_NEAR(propertyA.m_value.GetValue(), propertyB.m_value.GetValue(), 0.01) << propertyReference.c_str(); - } - else if (AreTypesCompatible(propertyA.m_value, propertyB.m_value)) - { - EXPECT_TRUE(propertyA.m_value.GetValue().IsClose(propertyB.m_value.GetValue())) << propertyReference.c_str(); - } - else if (AreTypesCompatible(propertyA.m_value, propertyB.m_value)) - { - EXPECT_TRUE(propertyA.m_value.GetValue().IsClose(propertyB.m_value.GetValue())) << propertyReference.c_str(); - } - else if (AreTypesCompatible(propertyA.m_value, propertyB.m_value)) - { - EXPECT_TRUE(GetAsVector4(propertyA.m_value).IsClose(GetAsVector4(propertyB.m_value))) << propertyReference.c_str(); - } - else if (AreTypesCompatible(propertyA.m_value, propertyB.m_value)) - { - EXPECT_STREQ(propertyA.m_value.GetValue().c_str(), propertyB.m_value.GetValue().c_str()) << propertyReference.c_str(); - } - else - { - ADD_FAILURE(); - } + if (AreTypesCompatible(propertyA, propertyB)) + { + EXPECT_EQ(propertyA.GetValue(), propertyB.GetValue()) << propertyReference.c_str(); + } + else if (AreTypesCompatible(propertyA, propertyB)) + { + EXPECT_EQ(GetAsInt(propertyA), GetAsInt(propertyB)) << propertyReference.c_str(); + } + else if (AreTypesCompatible(propertyA, propertyB)) + { + EXPECT_NEAR(propertyA.GetValue(), propertyB.GetValue(), 0.01) << propertyReference.c_str(); + } + else if (AreTypesCompatible(propertyA, propertyB)) + { + EXPECT_TRUE(propertyA.GetValue().IsClose(propertyB.GetValue())) << propertyReference.c_str(); + } + else if (AreTypesCompatible(propertyA, propertyB)) + { + EXPECT_TRUE(propertyA.GetValue().IsClose(propertyB.GetValue())) << propertyReference.c_str(); + } + else if (AreTypesCompatible(propertyA, propertyB)) + { + EXPECT_TRUE(GetAsVector4(propertyA).IsClose(GetAsVector4(propertyB))) << propertyReference.c_str(); + } + else if (AreTypesCompatible(propertyA, propertyB)) + { + EXPECT_STREQ(propertyA.GetValue().c_str(), propertyB.GetValue().c_str()) << propertyReference.c_str(); + } + else + { + ADD_FAILURE(); } } - } TEST_F(MaterialSourceDataTests, TestJsonRoundTrip) @@ -465,6 +446,88 @@ namespace UnitTest CheckEqual(sourceDataOriginal, sourceDataCopy); } + + TEST_F(MaterialSourceDataTests, TestLoadLegacyFormat) + { + const AZStd::string inputJson = R"( + { + "materialType": "test.materialtype", // Doesn't matter, this isn't loaded + "properties": { + "groupA": { + "myBool": true, + "myInt": 5, + "myFloat": 0.5 + }, + "groupB": { + "myFloat2": [0.1, 0.2], + "myFloat3": [0.3, 0.4, 0.5], + "myFloat4": [0.6, 0.7, 0.8, 0.9], + "myString": "Hello" + } + } + } + )"; + + MaterialSourceData material; + LoadTestDataFromJson(material, inputJson); + material.ConvertToNewDataFormat(); + + MaterialSourceData expectedMaterial; + expectedMaterial.m_materialType = "test.materialtype"; + expectedMaterial.SetPropertyValue(Name{"groupA.myBool"}, true); + expectedMaterial.SetPropertyValue(Name{"groupA.myInt"}, 5); + expectedMaterial.SetPropertyValue(Name{"groupA.myFloat"}, 0.5f); + expectedMaterial.SetPropertyValue(Name{"groupB.myFloat2"}, Vector2(0.1f, 0.2f)); + expectedMaterial.SetPropertyValue(Name{"groupB.myFloat3"}, Vector3(0.3f, 0.4f, 0.5f)); + expectedMaterial.SetPropertyValue(Name{"groupB.myFloat4"}, Vector4(0.6f, 0.7f, 0.8f, 0.9f)); + expectedMaterial.SetPropertyValue(Name{"groupB.myString"}, AZStd::string{"Hello"}); + + CheckEqual(expectedMaterial, material); + } + + TEST_F(MaterialSourceDataTests, TestPropertyValues) + { + MaterialSourceData material; + + Name foo{"foo"}; + Name bar{"bar"}; + Name baz{"baz"}; + + EXPECT_EQ(0, material.GetPropertyValues().size()); + EXPECT_FALSE(material.HasPropertyValue(foo)); + EXPECT_FALSE(material.HasPropertyValue(bar)); + EXPECT_FALSE(material.HasPropertyValue(baz)); + EXPECT_FALSE(material.GetPropertyValue(foo).IsValid()); + EXPECT_FALSE(material.GetPropertyValue(bar).IsValid()); + EXPECT_FALSE(material.GetPropertyValue(baz).IsValid()); + + material.SetPropertyValue(Name{"foo"}, 2); + material.SetPropertyValue(Name{"bar"}, true); + material.SetPropertyValue(Name{"baz"}, 0.5f); + + EXPECT_EQ(3, material.GetPropertyValues().size()); + EXPECT_TRUE(material.HasPropertyValue(foo)); + EXPECT_TRUE(material.HasPropertyValue(bar)); + EXPECT_TRUE(material.HasPropertyValue(baz)); + EXPECT_TRUE(material.GetPropertyValue(foo).IsValid()); + EXPECT_TRUE(material.GetPropertyValue(bar).IsValid()); + EXPECT_TRUE(material.GetPropertyValue(baz).IsValid()); + EXPECT_EQ(material.GetPropertyValue(foo).GetValue(), 2); + EXPECT_EQ(material.GetPropertyValue(bar).GetValue(), true); + EXPECT_EQ(material.GetPropertyValue(baz).GetValue(), 0.5f); + + material.RemovePropertyValue(bar); + + EXPECT_EQ(2, material.GetPropertyValues().size()); + EXPECT_TRUE(material.HasPropertyValue(foo)); + EXPECT_FALSE(material.HasPropertyValue(bar)); + EXPECT_TRUE(material.HasPropertyValue(baz)); + EXPECT_TRUE(material.GetPropertyValue(foo).IsValid()); + EXPECT_FALSE(material.GetPropertyValue(bar).IsValid()); + EXPECT_TRUE(material.GetPropertyValue(baz).IsValid()); + EXPECT_EQ(material.GetPropertyValue(foo).GetValue(), 2); + EXPECT_EQ(material.GetPropertyValue(baz).GetValue(), 0.5f); + } TEST_F(MaterialSourceDataTests, Load_MaterialTypeAfterPropertyList) { @@ -487,21 +550,14 @@ namespace UnitTest } )"; - const char* materialTypeFilePath = "@exefolder@/Temp/simpleMaterialType.materialtype"; - - AZ::IO::FileIOStream file; - EXPECT_TRUE(file.Open(materialTypeFilePath, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath)); - file.Write(simpleMaterialTypeJson.size(), simpleMaterialTypeJson.data()); - file.Close(); + AZ::Utils::WriteFile(simpleMaterialTypeJson, "@exefolder@/Temp/simpleMaterialType.materialtype"); // It shouldn't matter whether the materialType field appears before the property value list. This allows for the possibility // that customer scripts generate material data and happen to use an unexpected order. const AZStd::string inputJson = R"( { - "properties": { - "general": { - "testValue": 1.2 - } + "propertyValues": { + "general.testValue": 1.2 }, "materialType": "@exefolder@/Temp/simpleMaterialType.materialtype" } @@ -513,7 +569,7 @@ namespace UnitTest EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask()); EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing()); - float testValue = material.m_properties["general"]["testValue"].m_value.GetValue(); + float testValue = material.GetPropertyValue(Name{"general.testValue"}).GetValue(); EXPECT_FLOAT_EQ(1.2f, testValue); } @@ -522,10 +578,8 @@ namespace UnitTest const AZStd::string inputJson = R"( { "materialTypeVersion": 1, - "properties": { - "baseColor": { - "color": [1.0,1.0,1.0] - } + "propertyValues": { + "baseColor.color": [1.0,1.0,1.0] } } )"; @@ -561,10 +615,8 @@ namespace UnitTest { "materialType": "DoesNotExist.materialtype", "materialTypeVersion": 1, - "properties": { - "baseColor": { - "color": [1.0,1.0,1.0] - } + "propertyValues": { + "baseColor.color": [1.0,1.0,1.0] } } )"; @@ -900,10 +952,8 @@ namespace UnitTest const AZStd::string inputJson = AZStd::string::format(R"( { "materialType": "@exefolder@/Temp/test.materialtype", - "properties": { - "%s": { - "%s": %s - } + "propertyValues": { + "%s.%s": %s } } )", groupName, propertyName, jsonValue); @@ -965,7 +1015,239 @@ namespace UnitTest CheckEndToEndDataTypeResolution("MyFloat4", "{\"y\":0.2, \"x\":0.1, \"Z\":0.3}", Vector4{0.1f, 0.2f, 0.3f, 0.0f}); CheckEndToEndDataTypeResolution("MyFloat4", "{\"y\":0.2, \"W\":0.4, \"x\":0.1, \"Z\":0.3}", Vector4{0.1f, 0.2f, 0.3f, 0.4f}); } + + TEST_F(MaterialSourceDataTests, CreateMaterialAssetFromSourceData_MultiLevelDataInheritance) + { + // Note the data being tested here is based on CreateMaterialAsset_MultiLevelDataInheritance() + + const AZStd::string simpleMaterialTypeJson = R"( + { + "propertyLayout": { + "propertyGroups": + [ + { + "name": "general", + "properties": [ + { + "name": "MyFloat", + "type": "Float" + }, + { + "name": "MyFloat2", + "type": "Vector2" + }, + { + "name": "MyColor", + "type": "Color" + } + ] + } + ] + } + } + )"; + + AZ::Utils::WriteFile(simpleMaterialTypeJson, "@exefolder@/Temp/test.materialtype"); + + const AZStd::string material1Json = R"( + { + "materialType": "@exefolder@/Temp/test.materialtype", + "propertyValues": { + "general.MyFloat": 1.5, + "general.MyColor": [0.1, 0.2, 0.3, 0.4] + } + } + )"; + + AZ::Utils::WriteFile(material1Json, "@exefolder@/Temp/m1.material"); + + const AZStd::string material2Json = R"( + { + "materialType": "@exefolder@/Temp/test.materialtype", + "parentMaterial": "@exefolder@/Temp/m1.material", + "propertyValues": { + "general.MyFloat2": [4.1, 4.2], + "general.MyColor": [0.15, 0.25, 0.35, 0.45] + } + } + )"; + + AZ::Utils::WriteFile(material2Json, "@exefolder@/Temp/m2.material"); + + const AZStd::string material3Json = R"( + { + "materialType": "@exefolder@/Temp/test.materialtype", + "parentMaterial": "@exefolder@/Temp/m2.material", + "propertyValues": { + "general.MyFloat": 3.5 + } + } + )"; + + AZ::Utils::WriteFile(material3Json, "@exefolder@/Temp/m3.material"); + + MaterialSourceData sourceDataLevel1 = MaterialUtils::LoadMaterialSourceData("@exefolder@/Temp/m1.material").TakeValue(); + MaterialSourceData sourceDataLevel2 = MaterialUtils::LoadMaterialSourceData("@exefolder@/Temp/m2.material").TakeValue(); + MaterialSourceData sourceDataLevel3 = MaterialUtils::LoadMaterialSourceData("@exefolder@/Temp/m3.material").TakeValue(); + + auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAssetFromSourceData(Uuid::CreateRandom()); + ASSERT_TRUE(materialAssetLevel1.IsSuccess()); + EXPECT_TRUE(materialAssetLevel1.GetValue()->WasPreFinalized()); + + auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAssetFromSourceData(Uuid::CreateRandom()); + ASSERT_TRUE(materialAssetLevel2.IsSuccess()); + EXPECT_TRUE(materialAssetLevel2.GetValue()->WasPreFinalized()); + + auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAssetFromSourceData(Uuid::CreateRandom()); + ASSERT_TRUE(materialAssetLevel3.IsSuccess()); + EXPECT_TRUE(materialAssetLevel3.GetValue()->WasPreFinalized()); + + auto layout = materialAssetLevel1.GetValue()->GetMaterialPropertiesLayout(); + MaterialPropertyIndex myFloat = layout->FindPropertyIndex(Name("general.MyFloat")); + MaterialPropertyIndex myFloat2 = layout->FindPropertyIndex(Name("general.MyFloat2")); + MaterialPropertyIndex myColor = layout->FindPropertyIndex(Name("general.MyColor")); + + AZStd::span properties; + + // Check level 1 properties + properties = materialAssetLevel1.GetValue()->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 1.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(0.0f, 0.0f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.1f, 0.2f, 0.3f, 0.4f)); + + // Check level 2 properties + properties = materialAssetLevel2.GetValue()->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 1.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); + + // Check level 3 properties + properties = materialAssetLevel3.GetValue()->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 3.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); + } + TEST_F(MaterialSourceDataTests, CreateMaterialAssetFromSourceData_MultiLevelDataInheritance_OldFormat) + { + // This test is the same as CreateMaterialAssetFromSourceData_MultiLevelDataInheritance except it uses the old format + // where material property values in the .material file were nested, with properties listed under a group object, + // rather than using a flat list of property values. + // Basically, we are making sure that MaterialSourceData::ConvertToNewDataFormat() is getting called. + + const AZStd::string simpleMaterialTypeJson = R"( + { + "propertyLayout": { + "propertyGroups": + [ + { + "name": "general", + "properties": [ + { + "name": "MyFloat", + "type": "Float" + }, + { + "name": "MyFloat2", + "type": "Vector2" + }, + { + "name": "MyColor", + "type": "Color" + } + ] + } + ] + } + } + )"; + + AZ::Utils::WriteFile(simpleMaterialTypeJson, "@exefolder@/Temp/test.materialtype"); + + const AZStd::string material1Json = R"( + { + "materialType": "@exefolder@/Temp/test.materialtype", + "properties": { + "general": { + "MyFloat": 1.5, + "MyColor": [0.1, 0.2, 0.3, 0.4] + } + } + } + )"; + + AZ::Utils::WriteFile(material1Json, "@exefolder@/Temp/m1.material"); + + const AZStd::string material2Json = R"( + { + "materialType": "@exefolder@/Temp/test.materialtype", + "parentMaterial": "@exefolder@/Temp/m1.material", + "properties": { + "general": { + "MyFloat2": [4.1, 4.2], + "MyColor": [0.15, 0.25, 0.35, 0.45] + } + } + } + )"; + + AZ::Utils::WriteFile(material2Json, "@exefolder@/Temp/m2.material"); + + const AZStd::string material3Json = R"( + { + "materialType": "@exefolder@/Temp/test.materialtype", + "parentMaterial": "@exefolder@/Temp/m2.material", + "properties": { + "general": { + "MyFloat": 3.5 + } + } + } + )"; + + AZ::Utils::WriteFile(material3Json, "@exefolder@/Temp/m3.material"); + + MaterialSourceData sourceDataLevel1 = MaterialUtils::LoadMaterialSourceData("@exefolder@/Temp/m1.material").TakeValue(); + MaterialSourceData sourceDataLevel2 = MaterialUtils::LoadMaterialSourceData("@exefolder@/Temp/m2.material").TakeValue(); + MaterialSourceData sourceDataLevel3 = MaterialUtils::LoadMaterialSourceData("@exefolder@/Temp/m3.material").TakeValue(); + + auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAssetFromSourceData(Uuid::CreateRandom()); + EXPECT_TRUE(materialAssetLevel1.IsSuccess()); + EXPECT_TRUE(materialAssetLevel1.GetValue()->WasPreFinalized()); + + auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAssetFromSourceData(Uuid::CreateRandom()); + EXPECT_TRUE(materialAssetLevel2.IsSuccess()); + EXPECT_TRUE(materialAssetLevel2.GetValue()->WasPreFinalized()); + + auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAssetFromSourceData(Uuid::CreateRandom()); + EXPECT_TRUE(materialAssetLevel3.IsSuccess()); + EXPECT_TRUE(materialAssetLevel3.GetValue()->WasPreFinalized()); + + auto layout = materialAssetLevel1.GetValue()->GetMaterialPropertiesLayout(); + MaterialPropertyIndex myFloat = layout->FindPropertyIndex(Name("general.MyFloat")); + MaterialPropertyIndex myFloat2 = layout->FindPropertyIndex(Name("general.MyFloat2")); + MaterialPropertyIndex myColor = layout->FindPropertyIndex(Name("general.MyColor")); + + AZStd::span properties; + + // Check level 1 properties + properties = materialAssetLevel1.GetValue()->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 1.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(0.0f, 0.0f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.1f, 0.2f, 0.3f, 0.4f)); + + // Check level 2 properties + properties = materialAssetLevel2.GetValue()->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 1.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); + + // Check level 3 properties + properties = materialAssetLevel3.GetValue()->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 3.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); + } } diff --git a/Gems/Atom/TestData/TestData/Materials/AutoBrick/Brick.material b/Gems/Atom/TestData/TestData/Materials/AutoBrick/Brick.material index 061510d4c2..4312a91ffe 100644 --- a/Gems/Atom/TestData/TestData/Materials/AutoBrick/Brick.material +++ b/Gems/Atom/TestData/TestData/Materials/AutoBrick/Brick.material @@ -1,30 +1,24 @@ { - "description": "", "materialType": "TestData/Materials/Types/AutoBrick.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "appearance": { - "ao": 0.5252525210380554, - "brickColor": [ - 0.3013504147529602, - 0.0032501716632395984, - 0.0032501716632395984, - 1.0 - ], - "brickColorBleed": 0.5050504803657532, - "brickColorNoise": 0.20202019810676576, - "lineColor": [ - 0.08339055627584458, - 0.07264820486307144, - 0.05905241519212723, - 1.0 - ], - "lineColorNoise": 0.35353541374206545 - }, - "shape": { - "brickWidth": 0.16660000383853913, - "lineDepth": 0.005454500205814838 - } + "propertyValues": { + "appearance.ao": 0.5252525210380554, + "appearance.brickColor": [ + 0.3013504147529602, + 0.0032501716632395983, + 0.0032501716632395983, + 1.0 + ], + "appearance.brickColorBleed": 0.5050504803657532, + "appearance.brickColorNoise": 0.20202019810676575, + "appearance.lineColor": [ + 0.08339055627584457, + 0.07264820486307144, + 0.05905241519212723, + 1.0 + ], + "appearance.lineColorNoise": 0.35353541374206543, + "shape.brickWidth": 0.16660000383853912, + "shape.lineDepth": 0.005454500205814838 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/AutoBrick/Tile.material b/Gems/Atom/TestData/TestData/Materials/AutoBrick/Tile.material index b81ff4110b..c4fbe58477 100644 --- a/Gems/Atom/TestData/TestData/Materials/AutoBrick/Tile.material +++ b/Gems/Atom/TestData/TestData/Materials/AutoBrick/Tile.material @@ -1,33 +1,27 @@ { - "description": "", "materialType": "TestData/Materials/Types/AutoBrick.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "appearance": { - "ao": 0.010100999847054482, - "brickColor": [ - 0.4612802267074585, - 0.6926985383033752, - 0.6798046827316284, - 1.0 - ], - "brickColorBleed": 0.5050504803657532, - "brickColorNoise": 0.05000000074505806, - "lineColor": [ - 1.0, - 1.0, - 1.0, - 1.0 - ], - "lineColorNoise": 0.0 - }, - "shape": { - "brickHeight": 0.16660000383853913, - "brickOffset": 0.0, - "brickWidth": 0.16660000383853913, - "lineDepth": 0.0012121000327169896, - "lineWidth": 0.01030299998819828 - } + "propertyValues": { + "appearance.ao": 0.010100999847054482, + "appearance.brickColor": [ + 0.4612802267074585, + 0.6926985383033752, + 0.6798046827316284, + 1.0 + ], + "appearance.brickColorBleed": 0.5050504803657532, + "appearance.brickColorNoise": 0.05000000074505806, + "appearance.lineColor": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "appearance.lineColorNoise": 0.0, + "shape.brickHeight": 0.16660000383853912, + "shape.brickOffset": 0.0, + "shape.brickWidth": 0.16660000383853912, + "shape.lineDepth": 0.0012121000327169895, + "shape.lineWidth": 0.01030299998819828 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material index 1e140b9cf7..4348318fbd 100644 --- a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material +++ b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material @@ -1,33 +1,18 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "Materials/Presets/PBR/default_grid.material", "materialTypeVersion": 3, - "properties": { - "occlusion": { - "diffuseTextureMap": "TestData/Textures/cc0/Rock030_2K_AmbientOcclusion.jpg" - }, - "baseColor": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" - }, - "metallic": { - "useTexture": false - }, - "normal": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" - }, - "parallax": { - "algorithm": "POM", - "factor": 0.03, - "quality": "High", - "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg", - "pdo": true - }, - "roughness": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg" - }, - "specularF0": { - "useTexture": false - } + "parentMaterial": "Materials/Presets/PBR/default_grid.material", + "propertyValues": { + "baseColor.textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg", + "metallic.useTexture": false, + "normal.textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg", + "occlusion.diffuseTextureMap": "TestData/Textures/cc0/Rock030_2K_AmbientOcclusion.jpg", + "parallax.algorithm": "POM", + "parallax.factor": 0.029999999329447746, + "parallax.pdo": true, + "parallax.quality": "High", + "parallax.textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg", + "roughness.textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg", + "specularF0.useTexture": false } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_hermanubis_regression_test.material b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_hermanubis_regression_test.material index be607e7721..f5f52bbf7e 100644 --- a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_hermanubis_regression_test.material +++ b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/001_hermanubis_regression_test.material @@ -1,55 +1,43 @@ { - "description": "", "materialType": "Materials/Types/Skin.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.1277027577161789, - 0.174273282289505, - 0.29372090101242068, - 1.0 - ], - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", - "useTexture": false - }, - "detailLayerGroup": { - "baseColorDetailBlend": 0.4300000071525574, - "baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", - "enableBaseColor": true, - "enableDetailLayer": true, - "enableNormals": true, - "normalDetailFlipY": true, - "normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", - "normalDetailStrength": 0.25999999046325686, - "textureMapUv": "Tiled" - }, - "detailUV": { - "scale": 5.0 - }, - "normal": { - "flipY": true, - "textureMap": "Objects/Hermanubis/Hermanubis_Normal.png" - }, - "subsurfaceScattering": { - "enableSubsurfaceScattering": true, - "influenceMap": "Objects/Hermanubis/Hermanubis_thickness.tif", - "scatterDistance": 15.0, - "subsurfaceScatterFactor": 0.4300000071525574, - "thicknessMap": "Objects/Hermanubis/Hermanubis_thickness.tif", - "transmissionAttenuation": 15.0, - "transmissionDistortion": 0.3499999940395355, - "transmissionMode": "ThickObject", - "transmissionPower": 16.399999618530275, - "transmissionScale": 0.10000000149011612, - "transmissionTint": [ - 1.0, - 0.3182879388332367, - 0.16388189792633058, - 1.0 - ], - "useInfluenceMap": false - } + "propertyValues": { + "baseColor.color": [ + 0.1277027577161789, + 0.174273282289505, + 0.29372090101242065, + 1.0 + ], + "baseColor.textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", + "baseColor.useTexture": false, + "detailLayerGroup.baseColorDetailBlend": 0.4300000071525574, + "detailLayerGroup.baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", + "detailLayerGroup.enableBaseColor": true, + "detailLayerGroup.enableDetailLayer": true, + "detailLayerGroup.enableNormals": true, + "detailLayerGroup.normalDetailFlipY": true, + "detailLayerGroup.normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", + "detailLayerGroup.normalDetailStrength": 0.25999999046325684, + "detailLayerGroup.textureMapUv": "Tiled", + "detailUV.scale": 5.0, + "normal.flipY": true, + "normal.textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", + "subsurfaceScattering.enableSubsurfaceScattering": true, + "subsurfaceScattering.influenceMap": "Objects/Hermanubis/Hermanubis_thickness.tif", + "subsurfaceScattering.scatterDistance": 15.0, + "subsurfaceScattering.subsurfaceScatterFactor": 0.4300000071525574, + "subsurfaceScattering.thicknessMap": "Objects/Hermanubis/Hermanubis_thickness.tif", + "subsurfaceScattering.transmissionAttenuation": 15.0, + "subsurfaceScattering.transmissionDistortion": 0.3499999940395355, + "subsurfaceScattering.transmissionMode": "ThickObject", + "subsurfaceScattering.transmissionPower": 16.399999618530273, + "subsurfaceScattering.transmissionScale": 0.10000000149011612, + "subsurfaceScattering.transmissionTint": [ + 1.0, + 0.3182879388332367, + 0.16388189792633057, + 1.0 + ], + "subsurfaceScattering.useInfluenceMap": false } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material index 4222108b5e..3e3fe338c5 100644 --- a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material +++ b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material @@ -1,63 +1,49 @@ { - "description": "", "materialType": "Materials/Types/Skin.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.2847791314125061, - 0.45421531796455386, - 0.9392080307006836, - 1.0 - ], - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png" - }, - "detailLayerGroup": { - "baseColorDetailBlend": 0.4300000071525574, - "baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", - "enableBaseColor": true, - "enableDetailLayer": true, - "enableNormals": true, - "normalDetailFlipY": true, - "normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", - "normalDetailStrength": 1.5, - "textureMapUv": "Tiled" - }, - "detailUV": { - "scale": 5.0 - }, - "normal": { - "flipY": true, - "textureMap": "Objects/Hermanubis/Hermanubis_Normal.png" - }, - "subsurfaceScattering": { - "enableSubsurfaceScattering": true, - "influenceMap": "TestData/Textures/checker8x8_gray_512.png", - "scatterDistance": 15.0, - "subsurfaceScatterFactor": 0.4300000071525574, - "thicknessMap": "Objects/Hermanubis/Hermanubis_thickness.tif", - "transmissionAttenuation": 15.0, - "transmissionDistortion": 0.3499999940395355, - "transmissionMode": "ThickObject", - "transmissionPower": 16.399999618530275, - "transmissionScale": 0.10000000149011612, - "transmissionTint": [ - 1.0, - 0.3182879388332367, - 0.16388189792633058, - 1.0 - ] - }, - "wrinkleLayers": { - "baseColorMap1": "TestData/Textures/cc0/Lava004_1K_Color.jpg", - "baseColorMap3": "TestData/Textures/checker8x8_gray_512.png", - "count": 3, - "enable": true, - "enableBaseColor": true, - "enableNormal": true, - "normalMap1": "TestData/Textures/cc0/Lava004_1K_Normal.jpg", - "normalMap2": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png" - } + "propertyValues": { + "baseColor.color": [ + 0.2847791314125061, + 0.45421531796455383, + 0.9392080307006836, + 1.0 + ], + "baseColor.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png", + "detailLayerGroup.baseColorDetailBlend": 0.4300000071525574, + "detailLayerGroup.baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", + "detailLayerGroup.enableBaseColor": true, + "detailLayerGroup.enableDetailLayer": true, + "detailLayerGroup.enableNormals": true, + "detailLayerGroup.normalDetailFlipY": true, + "detailLayerGroup.normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", + "detailLayerGroup.normalDetailStrength": 1.5, + "detailLayerGroup.textureMapUv": "Tiled", + "detailUV.scale": 5.0, + "normal.flipY": true, + "normal.textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", + "subsurfaceScattering.enableSubsurfaceScattering": true, + "subsurfaceScattering.influenceMap": "TestData/Textures/checker8x8_gray_512.png", + "subsurfaceScattering.scatterDistance": 15.0, + "subsurfaceScattering.subsurfaceScatterFactor": 0.4300000071525574, + "subsurfaceScattering.thicknessMap": "Objects/Hermanubis/Hermanubis_thickness.tif", + "subsurfaceScattering.transmissionAttenuation": 15.0, + "subsurfaceScattering.transmissionDistortion": 0.3499999940395355, + "subsurfaceScattering.transmissionMode": "ThickObject", + "subsurfaceScattering.transmissionPower": 16.399999618530273, + "subsurfaceScattering.transmissionScale": 0.10000000149011612, + "subsurfaceScattering.transmissionTint": [ + 1.0, + 0.3182879388332367, + 0.16388189792633057, + 1.0 + ], + "wrinkleLayers.baseColorMap1": "TestData/Textures/cc0/Lava004_1K_Color.jpg", + "wrinkleLayers.baseColorMap3": "TestData/Textures/checker8x8_gray_512.png", + "wrinkleLayers.count": 3, + "wrinkleLayers.enable": true, + "wrinkleLayers.enableBaseColor": true, + "wrinkleLayers.enableNormal": true, + "wrinkleLayers.normalMap1": "TestData/Textures/cc0/Lava004_1K_Normal.jpg", + "wrinkleLayers.normalMap2": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index f683ad052d..29c5cd2cbe 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -1,156 +1,96 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "blend": { - "enableLayer2": true, - "enableLayer3": true - }, - "layer1_baseColor": { - "color": [ - 0.3495536744594574, - 0.2659952640533447, - 0.12039368599653244, - 1.0 - ], - "textureMap": "TestData/Textures/cc0/bark1_col.jpg" - }, - "layer1_emissive": { - "color": [ - 0.8521705865859985, - 0.029510948807001115, - 0.029510948807001115, - 1.0 - ], - "intensity": 0.8199999928474426 - }, - "layer1_normal": { - "factor": 0.4444443881511688, - "flipY": true, - "textureMap": "TestData/Textures/cc0/bark1_norm.jpg" - }, - "layer1_occlusion": { - "diffuseFactor": 1.6399999856948853, - "diffuseTextureMap": "TestData/Textures/cc0/bark1_disp.jpg" - }, - "layer1_parallax": { - "factor": 0.02500000037252903, - "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" - }, - "layer1_roughness": { - "lowerBound": 0.010100999847054482, - "textureMap": "TestData/Textures/cc0/bark1_roughness.jpg" - }, - "layer1_specularF0": { - "factor": 0.5099999904632568, - "textureMap": "TestData/Textures/checker8x8_512.png" - }, - "layer1_uv": { - "center": [ - 0.75, - 0.75 - ], - "offsetU": 0.5, - "offsetV": 0.25 - }, - "layer2_baseColor": { - "textureMap": "TestData/Textures/cc0/Lava004_1K_Color.jpg" - }, - "layer2_clearCoat": { - "enable": true, - "influenceMap": "TestData/Textures/checker8x8_512.png", - "normalMap": "TestData/Objects/cube/cube_norm.tif", - "normalStrength": 0.5400000214576721, - "roughness": 0.10000000149011612 - }, - "layer2_emissive": { - "enable": true, - "intensity": 2.140000104904175, - "textureMap": "TestData/Textures/cc0/Lava004_1K_Emission.jpg" - }, - "layer2_normal": { - "flipY": true, - "textureMap": "TestData/Textures/cc0/Lava004_1K_Normal.jpg" - }, - "layer2_occlusion": { - "specularFactor": 2.0, - "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" - }, - "layer2_parallax": { - "factor": 0.01600000075995922, - "textureMap": "TestData/Textures/cc0/Lava004_1K_Displacement.jpg" - }, - "layer2_roughness": { - "textureMap": "TestData/Textures/cc0/Lava004_1K_Roughness.jpg" - }, - "layer2_uv": { - "center": [ - 0.0, - 0.0 - ], - "offsetU": 0.5, - "offsetV": 0.25 - }, - "layer3_baseColor": { - "color": [ - 0.6315556764602661, - 1.0, - 0.9451438188552856, - 1.0 - ], - "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Color.jpg" - }, - "layer3_clearCoat": { - "influenceMap": "TestData/Textures/checker8x8_512.png" - }, - "layer3_emissive": { - "intensity": -0.9399999976158142 - }, - "layer3_metallic": { - "factor": 1.0, - "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Metalness.jpg" - }, - "layer3_normal": { - "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Normal.jpg" - }, - "layer3_occlusion": { - "diffuseFactor": 1.0399999618530274, - "diffuseTextureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" - }, - "layer3_parallax": { - "factor": 0.004999999888241291, - "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" - }, - "layer3_roughness": { - "lowerBound": 0.07999999821186066, - "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Roughness.jpg", - "upperBound": 0.75 - }, - "layer3_specularF0": { - "factor": 0.47474750876426699 - }, - "layer3_uv": { - "center": [ - 0.0, - 0.0 - ], - "offsetU": 0.11999999731779099, - "rotateDegrees": -57.599998474121097 - }, - "parallax": { - "quality": "Medium" - }, - "uv": { - "center": [ - 0.10000000149011612, - 0.20000000298023225 - ], - "offsetU": 0.23000000417232514, - "offsetV": -0.23999999463558198, - "rotateDegrees": 39.599998474121097, - "scale": 1.100000023841858 - } + "propertyValues": { + "blend.enableLayer2": true, + "blend.enableLayer3": true, + "layer1_baseColor.color": [ + 0.3495536744594574, + 0.2659952640533447, + 0.12039368599653244, + 1.0 + ], + "layer1_baseColor.textureMap": "TestData/Textures/cc0/bark1_col.jpg", + "layer1_emissive.color": [ + 0.8521705865859985, + 0.029510948807001114, + 0.029510948807001114, + 1.0 + ], + "layer1_emissive.intensity": 0.8199999928474426, + "layer1_normal.factor": 0.4444443881511688, + "layer1_normal.flipY": true, + "layer1_normal.textureMap": "TestData/Textures/cc0/bark1_norm.jpg", + "layer1_occlusion.diffuseFactor": 1.6399999856948853, + "layer1_occlusion.diffuseTextureMap": "TestData/Textures/cc0/bark1_disp.jpg", + "layer1_parallax.factor": 0.02500000037252903, + "layer1_parallax.textureMap": "TestData/Textures/cc0/bark1_disp.jpg", + "layer1_roughness.lowerBound": 0.010100999847054482, + "layer1_roughness.textureMap": "TestData/Textures/cc0/bark1_roughness.jpg", + "layer1_specularF0.factor": 0.5099999904632568, + "layer1_specularF0.textureMap": "TestData/Textures/checker8x8_512.png", + "layer1_uv.center": [ + 0.75, + 0.75 + ], + "layer1_uv.offsetU": 0.5, + "layer1_uv.offsetV": 0.25, + "layer2_baseColor.textureMap": "TestData/Textures/cc0/Lava004_1K_Color.jpg", + "layer2_clearCoat.enable": true, + "layer2_clearCoat.influenceMap": "TestData/Textures/checker8x8_512.png", + "layer2_clearCoat.normalMap": "TestData/Objects/cube/cube_norm.tif", + "layer2_clearCoat.normalStrength": 0.5400000214576721, + "layer2_clearCoat.roughness": 0.10000000149011612, + "layer2_emissive.enable": true, + "layer2_emissive.intensity": 2.140000104904175, + "layer2_emissive.textureMap": "TestData/Textures/cc0/Lava004_1K_Emission.jpg", + "layer2_normal.flipY": true, + "layer2_normal.textureMap": "TestData/Textures/cc0/Lava004_1K_Normal.jpg", + "layer2_occlusion.specularFactor": 2.0, + "layer2_occlusion.specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg", + "layer2_parallax.factor": 0.01600000075995922, + "layer2_parallax.textureMap": "TestData/Textures/cc0/Lava004_1K_Displacement.jpg", + "layer2_roughness.textureMap": "TestData/Textures/cc0/Lava004_1K_Roughness.jpg", + "layer2_uv.center": [ + 0.0, + 0.0 + ], + "layer2_uv.offsetU": 0.5, + "layer2_uv.offsetV": 0.25, + "layer3_baseColor.color": [ + 0.6315556764602661, + 1.0, + 0.9451438188552856, + 1.0 + ], + "layer3_baseColor.textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Color.jpg", + "layer3_clearCoat.influenceMap": "TestData/Textures/checker8x8_512.png", + "layer3_emissive.intensity": -0.9399999976158142, + "layer3_metallic.factor": 1.0, + "layer3_metallic.textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Metalness.jpg", + "layer3_normal.textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Normal.jpg", + "layer3_occlusion.diffuseFactor": 1.0399999618530273, + "layer3_occlusion.diffuseTextureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg", + "layer3_parallax.factor": 0.004999999888241291, + "layer3_parallax.textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg", + "layer3_roughness.lowerBound": 0.07999999821186066, + "layer3_roughness.textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Roughness.jpg", + "layer3_roughness.upperBound": 0.75, + "layer3_specularF0.factor": 0.47474750876426697, + "layer3_uv.center": [ + 0.0, + 0.0 + ], + "layer3_uv.offsetU": 0.11999999731779099, + "layer3_uv.rotateDegrees": -57.599998474121094, + "parallax.quality": "Medium", + "uv.center": [ + 0.10000000149011612, + 0.20000000298023224 + ], + "uv.offsetU": 0.23000000417232513, + "uv.offsetV": -0.23999999463558197, + "uv.rotateDegrees": 39.599998474121094, + "uv.scale": 1.100000023841858 } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer2Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer2Off.material index 042f31f3ec..9318469c74 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer2Off.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer2Off.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "enableLayer2": false - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material", + "propertyValues": { + "blend.enableLayer2": false } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer3Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer3Off.material index 59fc168a6c..e6d2da09cc 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer3Off.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures_Layer3Off.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "enableLayer3": false - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material", + "propertyValues": { + "blend.enableLayer3": false } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material index a1d3c288ea..cd244f5273 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material @@ -1,55 +1,29 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "blend": { - "enableLayer2": true, - "enableLayer3": true - }, - "layer1_baseColor": { - "textureMap": "TestData/Textures/cc0/bark1_col.jpg" - }, - "layer1_normal": { - "textureMap": "TestData/Textures/cc0/bark1_norm.jpg" - }, - "layer1_parallax": { - "factor": 0.03999999910593033, - "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" - }, - "layer1_roughness": { - "textureMap": "TestData/Textures/cc0/bark1_roughness.jpg" - }, - "layer2_baseColor": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" - }, - "layer2_clearCoat": { - "normalStrength": 0.0 - }, - "layer2_normal": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" - }, - "layer2_parallax": { - "factor": 0.05299999937415123, - "offset": -0.024000000208616258, - "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" - }, - "layer2_roughness": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg" - }, - "layer3_baseColor": { - "color": [ - 0.4298008680343628, - 0.4298008680343628, - 0.4298008680343628, - 1.0 - ], - "textureMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg" - }, - "parallax": { - "pdo": true, - "quality": "Medium" - } + "propertyValues": { + "blend.enableLayer2": true, + "blend.enableLayer3": true, + "layer1_baseColor.textureMap": "TestData/Textures/cc0/bark1_col.jpg", + "layer1_normal.textureMap": "TestData/Textures/cc0/bark1_norm.jpg", + "layer1_parallax.factor": 0.03999999910593033, + "layer1_parallax.textureMap": "TestData/Textures/cc0/bark1_disp.jpg", + "layer1_roughness.textureMap": "TestData/Textures/cc0/bark1_roughness.jpg", + "layer2_baseColor.textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg", + "layer2_clearCoat.normalStrength": 0.0, + "layer2_normal.textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg", + "layer2_parallax.factor": 0.05299999937415123, + "layer2_parallax.offset": -0.024000000208616257, + "layer2_parallax.textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg", + "layer2_roughness.textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg", + "layer3_baseColor.color": [ + 0.4298008680343628, + 0.4298008680343628, + 0.4298008680343628, + 1.0 + ], + "layer3_baseColor.textureMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", + "parallax.pdo": true, + "parallax.quality": "Medium" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material index b7be8ab18f..9e831e6412 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "debugDrawMode": "BlendMask" - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", + "propertyValues": { + "blend.debugDrawMode": "BlendMask" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material index 99a9c9f382..69877b3025 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "debugDrawMode": "FinalBlendWeights" - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", + "propertyValues": { + "blend.debugDrawMode": "FinalBlendWeights" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material index 6dbee69845..04c921a955 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "debugDrawMode": "Displacement" - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", + "propertyValues": { + "blend.debugDrawMode": "Displacement" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material index b53df9a505..3a55475bcd 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material @@ -1,14 +1,9 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "blendSource": "BlendMaskVertexColors" - }, - "parallax": { - "quality": "Medium" - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", + "propertyValues": { + "blend.blendSource": "BlendMaskVertexColors", + "parallax.quality": "Medium" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material index f313080cce..9bc96f315f 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -1,81 +1,43 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "blend": { - "blendSource": "Displacement", - "displacementBlendDistance": 0.008999999612569809, - "enableLayer2": true, - "enableLayer3": true - }, - "layer1_baseColor": { - "textureMap": "TestData/Textures/cc0/Ground033_1K_Color.jpg" - }, - "layer1_normal": { - "textureMap": "TestData/Textures/cc0/Ground033_1K_Normal.jpg" - }, - "layer1_occlusion": { - "diffuseTextureMap": "TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg" - }, - "layer1_parallax": { - "factor": 0.017000000923871995, - "offset": -0.006000000052154064, - "textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg" - }, - "layer1_roughness": { - "textureMap": "TestData/Textures/cc0/Ground033_1K_Roughness.jpg" - }, - "layer2_baseColor": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" - }, - "layer2_normal": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" - }, - "layer2_occlusion": { - "diffuseTextureMap": "TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg" - }, - "layer2_parallax": { - "factor": 0.03099999949336052, - "offset": 0.0020000000949949028, - "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" - }, - "layer2_roughness": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg" - }, - "layer2_uv": { - "center": [ - 0.0, - 0.0 - ], - "offsetU": 0.1599999964237213, - "offsetV": 0.07999999821186066, - "rotateDegrees": 90.0 - }, - "layer3_baseColor": { - "textureMap": "TestData/Textures/cc0/Rocks002_1K_Color.jpg" - }, - "layer3_normal": { - "textureMap": "TestData/Textures/cc0/Rocks002_1K_Normal.jpg" - }, - "layer3_parallax": { - "factor": 0.027000000700354577, - "textureMap": "TestData/Textures/cc0/Rocks002_1K_Displacement.jpg" - }, - "layer3_roughness": { - "textureMap": "TestData/Textures/cc0/Rocks002_1K_Roughness.jpg" - }, - "layer3_uv": { - "center": [ - 0.0, - 0.0 - ], - "scale": 3.4999988079071047 - }, - "parallax": { - "algorithm": "Relief", - "pdo": true - } + "propertyValues": { + "blend.blendSource": "Displacement", + "blend.displacementBlendDistance": 0.008999999612569809, + "blend.enableLayer2": true, + "blend.enableLayer3": true, + "layer1_baseColor.textureMap": "TestData/Textures/cc0/Ground033_1K_Color.jpg", + "layer1_normal.textureMap": "TestData/Textures/cc0/Ground033_1K_Normal.jpg", + "layer1_occlusion.diffuseTextureMap": "TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg", + "layer1_parallax.factor": 0.017000000923871994, + "layer1_parallax.offset": -0.006000000052154064, + "layer1_parallax.textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg", + "layer1_roughness.textureMap": "TestData/Textures/cc0/Ground033_1K_Roughness.jpg", + "layer2_baseColor.textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg", + "layer2_normal.textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg", + "layer2_occlusion.diffuseTextureMap": "TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg", + "layer2_parallax.factor": 0.03099999949336052, + "layer2_parallax.offset": 0.0020000000949949026, + "layer2_parallax.textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg", + "layer2_roughness.textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg", + "layer2_uv.center": [ + 0.0, + 0.0 + ], + "layer2_uv.offsetU": 0.1599999964237213, + "layer2_uv.offsetV": 0.07999999821186066, + "layer2_uv.rotateDegrees": 90.0, + "layer3_baseColor.textureMap": "TestData/Textures/cc0/Rocks002_1K_Color.jpg", + "layer3_normal.textureMap": "TestData/Textures/cc0/Rocks002_1K_Normal.jpg", + "layer3_parallax.factor": 0.027000000700354576, + "layer3_parallax.textureMap": "TestData/Textures/cc0/Rocks002_1K_Displacement.jpg", + "layer3_roughness.textureMap": "TestData/Textures/cc0/Rocks002_1K_Roughness.jpg", + "layer3_uv.center": [ + 0.0, + 0.0 + ], + "layer3_uv.scale": 3.4999988079071045, + "parallax.algorithm": "Relief", + "parallax.pdo": true } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material index 6f64bcd49f..984fd93cdf 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "enableLayer2": false - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyValues": { + "blend.enableLayer2": false } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material index 8b32223c82..491d2ffd89 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "enableLayer3": false - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyValues": { + "blend.enableLayer3": false } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material index 023316c5f6..2b91cf8e17 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material @@ -1,14 +1,9 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "blendSource": "Displacement_With_BlendMaskTexture" - }, - "layer1_parallax": { - "offset": -0.004000000189989805 - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyValues": { + "blend.blendSource": "Displacement_With_BlendMaskTexture", + "layer1_parallax.offset": -0.004000000189989805 } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material index d88802d4de..89b72f810b 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material @@ -1,23 +1,14 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "displacementBlendDistance": 0.0010000000474974514 - }, - "layer1_parallax": { - "offset": -0.00800000037997961, - "textureMap": "" - }, - "layer2_parallax": { - "offset": -0.00800000037997961, - "textureMap": "" - }, - "layer3_parallax": { - "offset": -0.00800000037997961, - "textureMap": "" - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", + "propertyValues": { + "blend.displacementBlendDistance": 0.0010000000474974513, + "layer1_parallax.offset": -0.00800000037997961, + "layer1_parallax.textureMap": "", + "layer2_parallax.offset": -0.00800000037997961, + "layer2_parallax.textureMap": "", + "layer3_parallax.offset": -0.00800000037997961, + "layer3_parallax.textureMap": "" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material index 9ba4d20a9a..a431f63112 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material @@ -1,20 +1,13 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", "materialTypeVersion": 3, - "properties": { - "layer1_parallax": { - "offset": -0.03200000151991844, - "textureMap": "" - }, - "layer2_parallax": { - "offset": -0.00800000037997961, - "textureMap": "" - }, - "layer3_parallax": { - "offset": -0.00800000037997961, - "textureMap": "" - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", + "propertyValues": { + "layer1_parallax.offset": -0.03200000151991844, + "layer1_parallax.textureMap": "", + "layer2_parallax.offset": -0.00800000037997961, + "layer2_parallax.textureMap": "", + "layer3_parallax.offset": -0.00800000037997961, + "layer3_parallax.textureMap": "" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material index 51219aa180..3a4e16b85e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material @@ -1,15 +1,10 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", "materialTypeVersion": 3, - "properties": { - "blend": { - "blendSource": "Displacement_With_BlendMaskVertexColors", - "displacementBlendDistance": 0.02387000061571598 - }, - "parallax": { - "enable": false - } + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyValues": { + "blend.blendSource": "Displacement_With_BlendMaskVertexColors", + "blend.displacementBlendDistance": 0.02387000061571598, + "parallax.enable": false } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/001_DefaultWhite.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/001_DefaultWhite.material index 164b73c892..5b5e902752 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/001_DefaultWhite.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/001_DefaultWhite.material @@ -1,6 +1,4 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3 } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLerp.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLerp.material index 29329a03a2..c2d6cafb1b 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLerp.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLerp.material @@ -1,19 +1,15 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.2541542649269104, - 0.5271076560020447, - 0.8388037085533142, - 1.0 - ], - "factor": 0.75, - "textureBlendMode": "Lerp", - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_hp_bc.png" - } + "propertyValues": { + "baseColor.color": [ + 0.2541542649269104, + 0.5271076560020447, + 0.8388037085533142, + 1.0 + ], + "baseColor.factor": 0.75, + "baseColor.textureBlendMode": "Lerp", + "baseColor.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_hp_bc.png" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLinearLight.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLinearLight.material index 46a8fd70ef..ecad50b541 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLinearLight.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorLinearLight.material @@ -1,19 +1,15 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.2541542649269104, - 0.5271076560020447, - 0.8388037085533142, - 1.0 - ], - "factor": 0.75, - "textureBlendMode": "LinearLight", - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_hp_bc.png" - } + "propertyValues": { + "baseColor.color": [ + 0.2541542649269104, + 0.5271076560020447, + 0.8388037085533142, + 1.0 + ], + "baseColor.factor": 0.75, + "baseColor.textureBlendMode": "LinearLight", + "baseColor.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_hp_bc.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorMultiply.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorMultiply.material index 7abf4ca40c..c76bb9ff90 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorMultiply.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/002_BaseColorMultiply.material @@ -1,18 +1,14 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.2541542649269104, - 0.5271076560020447, - 0.8388037085533142, - 1.0 - ], - "factor": 0.75, - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_hp_bc.png" - } + "propertyValues": { + "baseColor.color": [ + 0.2541542649269104, + 0.5271076560020447, + 0.8388037085533142, + 1.0 + ], + "baseColor.factor": 0.75, + "baseColor.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_hp_bc.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalMatte.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalMatte.material index 73ad13e27b..dabedfeb19 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalMatte.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalMatte.material @@ -1,22 +1,14 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5, - 0.5, - 0.5, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.33 - } + "propertyValues": { + "baseColor.color": [ + 0.5, + 0.5, + 0.5, + 1.0 + ], + "metallic.factor": 1.0, + "roughness.factor": 0.33000001311302185 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalPolished.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalPolished.material index 9dea40d6ec..4dfbb4804d 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalPolished.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/003_MetalPolished.material @@ -1,22 +1,14 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5, - 0.5, - 0.5, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.1 - } + "propertyValues": { + "baseColor.color": [ + 0.5, + 0.5, + 0.5, + 1.0 + ], + "metallic.factor": 1.0, + "roughness.factor": 0.10000000149011612 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/004_MetalMap.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/004_MetalMap.material index d20e354a53..5c5f7a4bc7 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/004_MetalMap.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/004_MetalMap.material @@ -1,23 +1,15 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5093766450881958, - 0.5093766450881958, - 0.5093766450881958, - 1.0 - ] - }, - "metallic": { - "factor": 1.0, - "textureMap": "TestData/Textures/checker8x8_gray_512.png" - }, - "roughness": { - "factor": 0.5 - } + "propertyValues": { + "baseColor.color": [ + 0.5093766450881958, + 0.5093766450881958, + 0.5093766450881958, + 1.0 + ], + "metallic.factor": 1.0, + "metallic.textureMap": "TestData/Textures/checker8x8_gray_512.png", + "roughness.factor": 0.5 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/005_RoughnessMap.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/005_RoughnessMap.material index 283c6ac60b..1cc5d49f0e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/005_RoughnessMap.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/005_RoughnessMap.material @@ -1,25 +1,17 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5093766450881958, - 0.5093766450881958, - 0.5093766450881958, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.5353534817695618, - "upperBound": 0.20202019810676576, - "lowerBound": 0.6464645862579346, - "textureMap": "TestData/Textures/checker8x8_gray_512.png" - } + "propertyValues": { + "baseColor.color": [ + 0.5093766450881958, + 0.5093766450881958, + 0.5093766450881958, + 1.0 + ], + "metallic.factor": 1.0, + "roughness.factor": 0.5353534817695618, + "roughness.lowerBound": 0.6464645862579346, + "roughness.textureMap": "TestData/Textures/checker8x8_gray_512.png", + "roughness.upperBound": 0.20202019810676575 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/006_SpecularF0Map.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/006_SpecularF0Map.material index 11228e2199..23361702c3 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/006_SpecularF0Map.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/006_SpecularF0Map.material @@ -1,22 +1,14 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.3330281674861908, - 0.3330281674861908, - 0.3330281674861908, - 1.0 - ] - }, - "roughness": { - "factor": 0.0 - }, - "specularF0": { - "textureMap": "TestData/Textures/checker8x8_gray_512.png" - } + "propertyValues": { + "baseColor.color": [ + 0.3330281674861908, + 0.3330281674861908, + 0.3330281674861908, + 1.0 + ], + "roughness.factor": 0.0, + "specularF0.textureMap": "TestData/Textures/checker8x8_gray_512.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOff.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOff.material index 3b9779aac1..26d5f1e9e6 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOff.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOff.material @@ -1,26 +1,16 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.9764705896377564, - 0.7098039388656616, - 0.125490203499794, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 1.0 - }, - "specularF0": { - "enableMultiScatterCompensation": false, - "factor": 1.0 - } + "propertyValues": { + "baseColor.color": [ + 0.9764705896377563, + 0.7098039388656616, + 0.125490203499794, + 1.0 + ], + "metallic.factor": 1.0, + "roughness.factor": 1.0, + "specularF0.enableMultiScatterCompensation": false, + "specularF0.factor": 1.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOn.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOn.material index dbbcdc631d..7d7d323b7a 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOn.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/007_MultiscatteringCompensationOn.material @@ -1,26 +1,16 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.9764705896377564, - 0.7098039388656616, - 0.125490203499794, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "roughness": { - "factor": 1.0 - }, - "specularF0": { - "enableMultiScatterCompensation": true, - "factor": 1.0 - } + "propertyValues": { + "baseColor.color": [ + 0.9764705896377563, + 0.7098039388656616, + 0.125490203499794, + 1.0 + ], + "metallic.factor": 1.0, + "roughness.factor": 1.0, + "specularF0.enableMultiScatterCompensation": true, + "specularF0.factor": 1.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap.material index 4b2842a594..973c6132e7 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap.material @@ -1,21 +1,15 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5521476864814758, - 0.5521476864814758, - 0.5521476864814758, - 1.0 - ] - }, - "normal": { - "factor": 0.75, - "flipY": true, - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png" - } + "propertyValues": { + "baseColor.color": [ + 0.5521476864814758, + 0.5521476864814758, + 0.5521476864814758, + 1.0 + ], + "normal.factor": 0.75, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap_Bevels.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap_Bevels.material index aec3bbf478..1326ed4317 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap_Bevels.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/008_NormalMap_Bevels.material @@ -1,12 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "normal": { - "factor": 0.30000001192092898, - "textureMap": "TestData/Objects/cube/cube_norm.tif" - } + "propertyValues": { + "normal.factor": 0.30000001192092896, + "normal.textureMap": "TestData/Objects/cube/cube_norm.tif" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended.material index 1528403868..42534744a6 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended.material @@ -1,23 +1,17 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5906767249107361, - 1.0, - 0.11703670024871826, - 1.0 - ], - "textureMap": "Textures/Default/default_basecolor.tif" - }, - "opacity": { - "alphaSource": "Split", - "factor": 0.75, - "mode": "Blended", - "textureMap": "TestData/Textures/checker8x8_gray_512.png" - } + "propertyValues": { + "baseColor.color": [ + 0.5906767249107361, + 1.0, + 0.11703670024871826, + 1.0 + ], + "baseColor.textureMap": "Textures/Default/default_basecolor.tif", + "opacity.alphaSource": "Split", + "opacity.factor": 0.75, + "opacity.mode": "Blended", + "opacity.textureMap": "TestData/Textures/checker8x8_gray_512.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended_Alpha_Affects_Specular.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended_Alpha_Affects_Specular.material index 20f5ccf098..960a1a42cf 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended_Alpha_Affects_Specular.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended_Alpha_Affects_Specular.material @@ -1,24 +1,18 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5906767249107361, - 1.0, - 0.11703670024871826, - 1.0 - ], - "textureMap": "Textures/Default/default_basecolor.tif" - }, - "opacity": { - "alphaSource": "Split", - "factor": 0.75, - "mode": "Blended", - "textureMap": "TestData/Textures/checker8x8_gray_512.png", - "alphaAffectsSpecular": 1.0 - } + "propertyValues": { + "baseColor.color": [ + 0.5906767249107361, + 1.0, + 0.11703670024871826, + 1.0 + ], + "baseColor.textureMap": "Textures/Default/default_basecolor.tif", + "opacity.alphaAffectsSpecular": 1.0, + "opacity.alphaSource": "Split", + "opacity.factor": 0.75, + "opacity.mode": "Blended", + "opacity.textureMap": "TestData/Textures/checker8x8_gray_512.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_PackedAlpha_DoubleSided.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_PackedAlpha_DoubleSided.material index d8683681c4..9acd51694f 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_PackedAlpha_DoubleSided.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_PackedAlpha_DoubleSided.material @@ -1,16 +1,10 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "TestData/Textures/Foliage_Leaves_0_BaseColor.dds" - }, - "opacity": { - "doubleSided": true, - "mode": "Cutout", - "textureMap": "TestData/Textures/checker8x8_512.png" - } + "propertyValues": { + "baseColor.textureMap": "TestData/Textures/Foliage_Leaves_0_BaseColor.dds", + "opacity.doubleSided": true, + "opacity.mode": "Cutout", + "opacity.textureMap": "TestData/Textures/checker8x8_512.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_DoubleSided.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_DoubleSided.material index 8e8dad46d8..cad29a9f77 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_DoubleSided.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_DoubleSided.material @@ -1,14 +1,10 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "opacity": { - "alphaSource": "Split", - "doubleSided": true, - "mode": "Cutout", - "textureMap": "TestData/Textures/checker8x8_512.png" - } + "propertyValues": { + "opacity.alphaSource": "Split", + "opacity.doubleSided": true, + "opacity.mode": "Cutout", + "opacity.textureMap": "TestData/Textures/checker8x8_512.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_SingleSided.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_SingleSided.material index 2d9b4c514b..9429e31fb6 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_SingleSided.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Cutout_SplitAlpha_SingleSided.material @@ -1,13 +1,9 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "opacity": { - "alphaSource": "Split", - "mode": "Cutout", - "textureMap": "TestData/Textures/checker8x8_512.png" - } + "propertyValues": { + "opacity.alphaSource": "Split", + "opacity.mode": "Cutout", + "opacity.textureMap": "TestData/Textures/checker8x8_512.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Opaque_DoubleSided.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Opaque_DoubleSided.material index f7ac93a7ac..835e19a4f3 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Opaque_DoubleSided.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Opaque_DoubleSided.material @@ -1,14 +1,8 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "Textures/Default/checker_uv_basecolor.png" - }, - "general": { - "doubleSided": true - } + "propertyValues": { + "baseColor.textureMap": "Textures/Default/checker_uv_basecolor.png", + "general.doubleSided": true } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material index 9d36d0a7e6..a9e60e7f5e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material @@ -1,23 +1,17 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.5906767249107361, - 1.0, - 0.11703670024871826, - 1.0 - ], - "textureMap": "Textures/Default/default_basecolor.tif" - }, - "opacity": { - "alphaSource": "Split", - "factor": 0.75, - "mode": "TintedTransparent", - "textureMap": "TestData/Textures/checker8x8_gray_512.png" - } + "propertyValues": { + "baseColor.color": [ + 0.5906767249107361, + 1.0, + 0.11703670024871826, + 1.0 + ], + "baseColor.textureMap": "Textures/Default/default_basecolor.tif", + "opacity.alphaSource": "Split", + "opacity.factor": 0.75, + "opacity.mode": "TintedTransparent", + "opacity.textureMap": "TestData/Textures/checker8x8_gray_512.png" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material index a7fe0d1d4d..8ccf39096a 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material @@ -1,12 +1,9 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "010_OcclusionBase.material", "materialTypeVersion": 3, - "properties": { - "occlusion": { - "diffuseFactor": 2.0, - "diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg" - } + "parentMaterial": "010_OcclusionBase.material", + "propertyValues": { + "occlusion.diffuseFactor": 2.0, + "occlusion.diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material index 1f9c94db47..b2b2b90363 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material @@ -1,14 +1,11 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "010_OcclusionBase.material", "materialTypeVersion": 3, - "properties": { - "occlusion": { - "diffuseFactor": 2.0, - "diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg", - "specularFactor": 2.0, - "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" - } + "parentMaterial": "010_OcclusionBase.material", + "propertyValues": { + "occlusion.diffuseFactor": 2.0, + "occlusion.diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg", + "occlusion.specularFactor": 2.0, + "occlusion.specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material index 534305b68a..170576e20e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material @@ -1,25 +1,15 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.06784161180257797, - 0.2073090672492981, - 0.29570457339286806, - 1.0 - ] - }, - "clearCoat": { - "enable": true - }, - "normal": { - "textureMap": "TestData/Textures/cc0/Tiles009_1K_Normal.jpg" - }, - "roughness": { - "factor": 0.0 - } + "propertyValues": { + "baseColor.color": [ + 0.06784161180257797, + 0.2073090672492981, + 0.29570457339286804, + 1.0 + ], + "clearCoat.enable": true, + "normal.textureMap": "TestData/Textures/cc0/Tiles009_1K_Normal.jpg", + "roughness.factor": 0.0 } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material index 6403bc5c14..f69a316c59 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material @@ -1,12 +1,9 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "010_OcclusionBase.material", "materialTypeVersion": 3, - "properties": { - "occlusion": { - "specularFactor": 2.0, - "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" - } + "parentMaterial": "010_OcclusionBase.material", + "propertyValues": { + "occlusion.specularFactor": 2.0, + "occlusion.specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/011_Emissive.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/011_Emissive.material index dc42c0d6b5..7c640b573d 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/011_Emissive.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/011_Emissive.material @@ -1,21 +1,16 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "Textures/Default/default_basecolor.tif" - }, - "emissive": { - "color": [ - 0.003936827648431063, - 1.0, - 0.0, - 1.0 - ], - "enable": true, - "intensity": 3.0, - "textureMap": "TestData/Textures/checker8x8_gray_512.png" - } + "propertyValues": { + "baseColor.textureMap": "Textures/Default/default_basecolor.tif", + "emissive.color": [ + 0.003936827648431063, + 1.0, + 0.0, + 1.0 + ], + "emissive.enable": true, + "emissive.intensity": 3.0, + "emissive.textureMap": "TestData/Textures/checker8x8_gray_512.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material index fee4a30f77..35f91d0eb1 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material @@ -1,16 +1,11 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png" - }, - "parallax": { - "algorithm": "POM", - "factor": 0.02500000037252903, - "quality": "High", - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png" - } + "propertyValues": { + "baseColor.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png", + "parallax.algorithm": "POM", + "parallax.factor": 0.02500000037252903, + "parallax.quality": "High", + "parallax.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material index d69b75285e..bf6907fbd5 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material @@ -1,28 +1,18 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png" - }, - "opacity": { - "alphaSource": "Split", - "mode": "Cutout", - "textureMap": "TestData/Textures/checker8x8_512.png" - }, - "parallax": { - "factor": 0.10000000149011612, - "quality": "High", - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png" - }, - "uv": { - "center": [ - 0.0, - 0.0 - ], - "scale": 0.5 - } + "propertyValues": { + "baseColor.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png", + "opacity.alphaSource": "Split", + "opacity.mode": "Cutout", + "opacity.textureMap": "TestData/Textures/checker8x8_512.png", + "parallax.factor": 0.10000000149011612, + "parallax.quality": "High", + "parallax.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png", + "uv.center": [ + 0.0, + 0.0 + ], + "uv.scale": 0.5 } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_Off.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_Off.material index a1da93acbb..c266799f26 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_Off.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_Off.material @@ -1,17 +1,10 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", "materialTypeVersion": 3, - "properties": { - "metallic": { - "factor": 1.0 - }, - "normal": { - "flipY": true, - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png" - }, - "roughness": { - "factor": 0.13131310045719148 - } + "propertyValues": { + "metallic.factor": 1.0, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png", + "roughness.factor": 0.13131310045719147 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_On.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_On.material index 07018e9140..a2d33da506 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_On.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/013_SpecularAA_On.material @@ -1,20 +1,11 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", "materialTypeVersion": 3, - "properties": { - "general": { - "applySpecularAA": true - }, - "metallic": { - "factor": 1.0 - }, - "normal": { - "flipY": true, - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png" - }, - "roughness": { - "factor": 0.13131310045719148 - } + "propertyValues": { + "general.applySpecularAA": true, + "metallic.factor": 1.0, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png", + "roughness.factor": 0.13131310045719147 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat.material index e02a8b5fc2..2f60fcc9b2 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat.material @@ -1,27 +1,17 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 1.0, - 0.34190890192985537, - 0.0009155413135886192, - 1.0 - ], - "textureMap": "TestData/Textures/checker8x8_512.png" - }, - "clearCoat": { - "enable": true, - "influenceMap": "TestData/Textures/checker8x8_512.png" - }, - "metallic": { - "factor": 0.5 - }, - "roughness": { - "factor": 0.5 - } + "propertyValues": { + "baseColor.color": [ + 1.0, + 0.34190890192985535, + 0.0009155413135886192, + 1.0 + ], + "baseColor.textureMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.enable": true, + "clearCoat.influenceMap": "TestData/Textures/checker8x8_512.png", + "metallic.factor": 0.5, + "roughness.factor": 0.5 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap.material index 56d8515305..0fb6e22664 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap.material @@ -1,31 +1,21 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 1.0, - 0.34190890192985537, - 0.0009155413135886192, - 1.0 - ], - "textureMap": "TestData/Textures/checker8x8_512.png" - }, - "clearCoat": { - "enable": true, - "influenceMap": "TestData/Textures/checker8x8_512.png", - "normalMap": "TestData/Textures/test_dome_normal.tiff", - "roughnessMap": "TestData/Textures/checker8x8_512.png", - "useInfluenceMap": false, - "useRoughnessMap": false - }, - "metallic": { - "factor": 0.5 - }, - "roughness": { - "factor": 0.5 - } + "propertyValues": { + "baseColor.color": [ + 1.0, + 0.34190890192985535, + 0.0009155413135886192, + 1.0 + ], + "baseColor.textureMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.enable": true, + "clearCoat.influenceMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.normalMap": "TestData/Textures/test_dome_normal.tiff", + "clearCoat.roughnessMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.useInfluenceMap": false, + "clearCoat.useRoughnessMap": false, + "metallic.factor": 0.5, + "roughness.factor": 0.5 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap_2ndUv.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap_2ndUv.material index e7575d8bd6..f76ef83485 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap_2ndUv.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_NormalMap_2ndUv.material @@ -1,35 +1,25 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 1.0, - 0.34190890192985537, - 0.0009155413135886192, - 1.0 - ], - "textureMap": "TestData/Textures/checker8x8_512.png", - "textureMapUv": "Unwrapped" - }, - "clearCoat": { - "enable": true, - "influenceMap": "TestData/Textures/checker8x8_512.png", - "influenceMapUv": "Unwrapped", - "normalMap": "TestData/Textures/test_dome_normal.tiff", - "normalMapUv": "Unwrapped", - "roughnessMap": "TestData/Textures/checker8x8_512.png", - "roughnessMapUv": "Unwrapped", - "useInfluenceMap": false, - "useRoughnessMap": false - }, - "metallic": { - "factor": 0.5 - }, - "roughness": { - "factor": 0.5 - } + "propertyValues": { + "baseColor.color": [ + 1.0, + 0.34190890192985535, + 0.0009155413135886192, + 1.0 + ], + "baseColor.textureMap": "TestData/Textures/checker8x8_512.png", + "baseColor.textureMapUv": "Unwrapped", + "clearCoat.enable": true, + "clearCoat.influenceMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.influenceMapUv": "Unwrapped", + "clearCoat.normalMap": "TestData/Textures/test_dome_normal.tiff", + "clearCoat.normalMapUv": "Unwrapped", + "clearCoat.roughnessMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.roughnessMapUv": "Unwrapped", + "clearCoat.useInfluenceMap": false, + "clearCoat.useRoughnessMap": false, + "metallic.factor": 0.5, + "roughness.factor": 0.5 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_RoughnessMap.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_RoughnessMap.material index 3ccbfeacc1..62e15fe2c5 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_RoughnessMap.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/014_ClearCoat_RoughnessMap.material @@ -1,30 +1,20 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 1.0, - 0.34190890192985537, - 0.0009155413135886192, - 1.0 - ], - "textureMap": "TestData/Textures/checker8x8_512.png" - }, - "clearCoat": { - "enable": true, - "influenceMap": "TestData/Textures/checker8x8_512.png", - "roughness": 0.5050504803657532, - "roughnessMap": "TestData/Textures/checker8x8_512.png", - "useInfluenceMap": false - }, - "metallic": { - "factor": 0.5 - }, - "roughness": { - "factor": 0.5 - } + "propertyValues": { + "baseColor.color": [ + 1.0, + 0.34190890192985535, + 0.0009155413135886192, + 1.0 + ], + "baseColor.textureMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.enable": true, + "clearCoat.influenceMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.roughness": 0.5050504803657532, + "clearCoat.roughnessMap": "TestData/Textures/checker8x8_512.png", + "clearCoat.useInfluenceMap": false, + "metallic.factor": 0.5, + "roughness.factor": 0.5 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering.material index fb3621f056..3f189f5ff5 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering.material @@ -1,20 +1,16 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "subsurfaceScattering": { - "enableSubsurfaceScattering": true, - "influenceMap": "TestData/Textures/checker8x8_512.png", - "scatterColor": [ - 1.0, - 0.20000000298023225, - 0.07058823853731156, - 1.0 - ], - "scatterDistance": 40.0, - "subsurfaceScatterFactor": 1.0 - } + "propertyValues": { + "subsurfaceScattering.enableSubsurfaceScattering": true, + "subsurfaceScattering.influenceMap": "TestData/Textures/checker8x8_512.png", + "subsurfaceScattering.scatterColor": [ + 1.0, + 0.20000000298023224, + 0.07058823853731155, + 1.0 + ], + "subsurfaceScattering.scatterDistance": 40.0, + "subsurfaceScattering.subsurfaceScatterFactor": 1.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material index eff175be77..5a2373d5eb 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material @@ -1,15 +1,11 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "subsurfaceScattering": { - "enableSubsurfaceScattering": true, - "scatterDistance": 64.6464614868164, - "subsurfaceScatterFactor": 1.0, - "thicknessMap": "TestData/Textures/checker8x8_512.png", - "transmissionMode": "ThickObject" - } + "propertyValues": { + "subsurfaceScattering.enableSubsurfaceScattering": true, + "subsurfaceScattering.scatterDistance": 64.6464614868164, + "subsurfaceScattering.subsurfaceScatterFactor": 1.0, + "subsurfaceScattering.thicknessMap": "TestData/Textures/checker8x8_512.png", + "subsurfaceScattering.transmissionMode": "ThickObject" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission_Thin.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission_Thin.material index ee9bb1f4a5..c8a1401d17 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission_Thin.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission_Thin.material @@ -1,29 +1,21 @@ { - "description": "", - "parentMaterial": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", "materialTypeVersion": 4, - "properties": { - "baseColor": { - "color": [ - 0.027664607390761375, - 0.1926604062318802, - 0.013916227966547012, - 1.0 - ] - }, - "general": { - "doubleSided": true - }, - "subsurfaceScattering": { - "thickness": 0.20000000298023224, - "transmissionMode": "ThinObject", - "transmissionTint": [ - 0.009140154346823692, - 0.19806210696697235, - 0.01095597818493843, - 1.0 - ] - } + "propertyValues": { + "baseColor.color": [ + 0.027664607390761375, + 0.1926604062318802, + 0.013916227966547012, + 1.0 + ], + "general.doubleSided": true, + "subsurfaceScattering.thickness": 0.20000000298023224, + "subsurfaceScattering.transmissionMode": "ThinObject", + "subsurfaceScattering.transmissionTint": [ + 0.009140154346823692, + 0.19806210696697235, + 0.01095597818493843, + 1.0 + ] } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material index d88c1f151f..8e68176843 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "occlusion": { - "diffuseTextureMap": "TestData/Objects/cube/cube_diff.tif" - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "occlusion.diffuseTextureMap": "TestData/Objects/cube/cube_diff.tif" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_BaseColor.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_BaseColor.material index 89bd1005a5..565f3bf8e0 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_BaseColor.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_BaseColor.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "TestData/Objects/cube/cube_diff.tif" - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "baseColor.textureMap": "TestData/Objects/cube/cube_diff.tif" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Emissive.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Emissive.material index 564de16cc2..a053737973 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Emissive.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Emissive.material @@ -1,22 +1,17 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "emissive": { - "enable": true, - "intensity": 2.0, - "textureMap": "TestData/Objects/cube/cube_diff.tif", - "useTexture": true - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "baseColor.color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "emissive.enable": true, + "emissive.intensity": 2.0, + "emissive.textureMap": "TestData/Objects/cube/cube_diff.tif", + "emissive.useTexture": true } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Metallic.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Metallic.material index 0eff6198dd..17a13d79cf 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Metallic.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Metallic.material @@ -1,15 +1,10 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "metallic": { - "factor": 1.0, - "textureMap": "TestData/Objects/cube/cube_diff.tif" - }, - "roughness": { - "factor": 0.0 - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "metallic.factor": 1.0, + "metallic.textureMap": "TestData/Objects/cube/cube_diff.tif", + "roughness.factor": 0.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal.material index e50c669114..bbdc3c62ec 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal.material @@ -1,11 +1,8 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "normal": { - "textureMap": "TestData/Objects/cube/cube_diff.tif" - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "normal.textureMap": "TestData/Objects/cube/cube_diff.tif" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate20.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate20.material index 0b3d678bdd..b0e6a0a498 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate20.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate20.material @@ -1,20 +1,14 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "normal": { - "factor": 0.15000000596046449, - "flipY": true, - "textureMap": "TestData/Textures/test_dome_normal.tiff" - }, - "uv": { - "center": [ - 0.5, - 0.5 - ], - "rotateDegrees": 20.0 - } + "propertyValues": { + "normal.factor": 0.15000000596046448, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/test_dome_normal.tiff", + "uv.center": [ + 0.5, + 0.5 + ], + "uv.rotateDegrees": 20.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate90.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate90.material index 4a7ade8b30..0e72deebbc 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate90.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_Rotate90.material @@ -1,20 +1,14 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "normal": { - "factor": 0.15000000596046449, - "flipY": true, - "textureMap": "TestData/Textures/test_dome_normal.tiff" - }, - "uv": { - "center": [ - 0.5, - 0.5 - ], - "rotateDegrees": 90.0 - } + "propertyValues": { + "normal.factor": 0.15000000596046448, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/test_dome_normal.tiff", + "uv.center": [ + 0.5, + 0.5 + ], + "uv.rotateDegrees": 90.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyU.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyU.material index c0477ac5cf..7d87e24938 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyU.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyU.material @@ -1,20 +1,14 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "normal": { - "factor": 0.15000000596046449, - "flipY": true, - "textureMap": "TestData/Textures/test_dome_normal.tiff" - }, - "uv": { - "center": [ - 0.5, - 0.5 - ], - "tileU": 2.0 - } + "propertyValues": { + "normal.factor": 0.15000000596046448, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/test_dome_normal.tiff", + "uv.center": [ + 0.5, + 0.5 + ], + "uv.tileU": 2.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyV.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyV.material index b088a0c090..a589741097 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyV.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleOnlyV.material @@ -1,20 +1,14 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "normal": { - "factor": 0.15000000596046449, - "flipY": true, - "textureMap": "TestData/Textures/test_dome_normal.tiff" - }, - "uv": { - "center": [ - 0.5, - 0.5 - ], - "tileV": 2.0 - } + "propertyValues": { + "normal.factor": 0.15000000596046448, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/test_dome_normal.tiff", + "uv.center": [ + 0.5, + 0.5 + ], + "uv.tileV": 2.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleUniform.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleUniform.material index c7c3fac87f..6d687bfc45 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleUniform.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_ScaleUniform.material @@ -1,20 +1,14 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "normal": { - "factor": 0.15000000596046449, - "flipY": true, - "textureMap": "TestData/Textures/test_dome_normal.tiff" - }, - "uv": { - "center": [ - 0.5, - 0.5 - ], - "scale": 3.0 - } + "propertyValues": { + "normal.factor": 0.15000000596046448, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/test_dome_normal.tiff", + "uv.center": [ + 0.5, + 0.5 + ], + "uv.scale": 3.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_TransformAll.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_TransformAll.material index 849e926031..2e916fbb33 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_TransformAll.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Normal_Dome_TransformAll.material @@ -1,25 +1,19 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "normal": { - "factor": 0.15000000596046449, - "flipY": true, - "textureMap": "TestData/Textures/test_dome_normal.tiff" - }, - "uv": { - "center": [ - 0.25, - 0.5 - ], - "offsetU": 0.3737373948097229, - "offsetV": -0.4545454978942871, - "rotateDegrees": 110.0, - "scale": 2.0, - "tileU": 0.5, - "tileV": 1.5 - } + "propertyValues": { + "normal.factor": 0.15000000596046448, + "normal.flipY": true, + "normal.textureMap": "TestData/Textures/test_dome_normal.tiff", + "uv.center": [ + 0.25, + 0.5 + ], + "uv.offsetU": 0.3737373948097229, + "uv.offsetV": -0.4545454978942871, + "uv.rotateDegrees": 110.0, + "uv.scale": 2.0, + "uv.tileU": 0.5, + "uv.tileV": 1.5 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Opacity.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Opacity.material index b203ec5318..ec056b8459 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Opacity.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Opacity.material @@ -1,14 +1,11 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "opacity": { - "alphaSource": "Split", - "factor": 0.9, - "mode": "Cutout", - "textureMap": "TestData/Objects/cube/cube_diff.tif" - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "opacity.alphaSource": "Split", + "opacity.factor": 0.8999999761581421, + "opacity.mode": "Cutout", + "opacity.textureMap": "TestData/Objects/cube/cube_diff.tif" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material index ad2e27063b..2e0eadb40f 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material @@ -1,36 +1,25 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardPbrTestCases/UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "TestData/Objects/cube/cube_diff.tif" - }, - "metallic": { - "factor": 1.0, - "textureMap": "TestData/Textures/checker8x8_512.png" - }, - "parallax": { - "algorithm": "POM", - "factor": 0.10000000149011612, - "quality": "High", - "textureMap": "TestData/Objects/cube/cube_diff.tif" - }, - "roughness": { - "textureMap": "TestData/Textures/checker8x8_flip_512.png" - }, - "uv": { - "center": [ - 0.25, - 0.5 - ], - "offsetU": -0.6767677068710327, - "offsetV": 0.19191919267177583, - "rotateDegrees": 63.6363639831543, - "scale": 0.800000011920929, - "tileU": 0.699999988079071, - "tileV": 1.5 - } + "parentMaterial": "TestData/Materials/StandardPbrTestCases/UvTilingBase.material", + "propertyValues": { + "baseColor.textureMap": "TestData/Objects/cube/cube_diff.tif", + "metallic.factor": 1.0, + "metallic.textureMap": "TestData/Textures/checker8x8_512.png", + "parallax.algorithm": "POM", + "parallax.factor": 0.10000000149011612, + "parallax.quality": "High", + "parallax.textureMap": "TestData/Objects/cube/cube_diff.tif", + "roughness.textureMap": "TestData/Textures/checker8x8_flip_512.png", + "uv.center": [ + 0.25, + 0.5 + ], + "uv.offsetU": -0.6767677068710327, + "uv.offsetV": 0.19191919267177582, + "uv.rotateDegrees": 63.6363639831543, + "uv.scale": 0.800000011920929, + "uv.tileU": 0.699999988079071, + "uv.tileV": 1.5 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material index 75646e5191..9e368f8be0 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material @@ -1,36 +1,25 @@ { - "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardPbrTestCases/UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "TestData/Objects/cube/cube_diff.tif" - }, - "metallic": { - "factor": 1.0, - "textureMap": "TestData/Textures/checker8x8_512.png" - }, - "parallax": { - "algorithm": "POM", - "factor": 0.05000000074505806, - "quality": "High", - "textureMap": "TestData/Objects/cube/cube_diff.tif" - }, - "roughness": { - "textureMap": "TestData/Textures/checker8x8_flip_512.png" - }, - "uv": { - "center": [ - 0.5, - 0.25 - ], - "offsetU": 1.0, - "offsetV": -1.0, - "rotateDegrees": 90.0, - "scale": 1.2000000476837159, - "tileU": 0.699999988079071, - "tileV": 1.7999999523162842 - } + "parentMaterial": "TestData/Materials/StandardPbrTestCases/UvTilingBase.material", + "propertyValues": { + "baseColor.textureMap": "TestData/Objects/cube/cube_diff.tif", + "metallic.factor": 1.0, + "metallic.textureMap": "TestData/Textures/checker8x8_512.png", + "parallax.algorithm": "POM", + "parallax.factor": 0.05000000074505806, + "parallax.quality": "High", + "parallax.textureMap": "TestData/Objects/cube/cube_diff.tif", + "roughness.textureMap": "TestData/Textures/checker8x8_flip_512.png", + "uv.center": [ + 0.5, + 0.25 + ], + "uv.offsetU": 1.0, + "uv.offsetV": -1.0, + "uv.rotateDegrees": 90.0, + "uv.scale": 1.2000000476837158, + "uv.tileU": 0.699999988079071, + "uv.tileV": 1.7999999523162842 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Roughness.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Roughness.material index 49ff9555f1..35a7dc6ad4 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Roughness.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Roughness.material @@ -1,14 +1,9 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "metallic": { - "factor": 1.0 - }, - "roughness": { - "textureMap": "TestData/Objects/cube/cube_diff.tif" - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "metallic.factor": 1.0, + "roughness.textureMap": "TestData/Objects/cube/cube_diff.tif" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_SpecularF0.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_SpecularF0.material index a750e30d80..43b0aacde4 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_SpecularF0.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_SpecularF0.material @@ -1,23 +1,16 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.11546501517295838, - 0.11546501517295838, - 0.11546501517295838, - 1.0 - ] - }, - "roughness": { - "factor": 0.0 - }, - "specularF0": { - "factor": 1.0, - "textureMap": "TestData/Objects/cube/cube_diff.tif" - } + "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", + "propertyValues": { + "baseColor.color": [ + 0.11546501517295837, + 0.11546501517295837, + 0.11546501517295837, + 1.0 + ], + "roughness.factor": 0.0, + "specularF0.factor": 1.0, + "specularF0.textureMap": "TestData/Objects/cube/cube_diff.tif" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material index 30959fc972..a299d17479 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material @@ -1,31 +1,19 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", - "textureMapUv": "Unwrapped" - }, - "detailUV": { - "center": [ - 0.0, - 0.0 - ] - }, - "metallic": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_Metallic.png", - "textureMapUv": "Unwrapped" - }, - "normal": { - "flipY": true, - "textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", - "textureMapUv": "Unwrapped" - }, - "roughness": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_Roughness.png", - "textureMapUv": "Unwrapped" - } + "propertyValues": { + "baseColor.textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", + "baseColor.textureMapUv": "Unwrapped", + "detailUV.center": [ + 0.0, + 0.0 + ], + "metallic.textureMap": "Objects/Hermanubis/Hermanubis_bronze_Metallic.png", + "metallic.textureMapUv": "Unwrapped", + "normal.flipY": true, + "normal.textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", + "normal.textureMapUv": "Unwrapped", + "roughness.textureMap": "Objects/Hermanubis/Hermanubis_bronze_Roughness.png", + "roughness.textureMapUv": "Unwrapped" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material index 2cb14b490e..4f1247d7c0 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material @@ -1,42 +1,28 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", - "textureMapUv": "Unwrapped" - }, - "detailLayerGroup": { - "baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", - "blendDetailMask": "Objects/Hermanubis/Hermanubis_ao.tif", - "blendDetailMaskUv": "Unwrapped", - "enableBaseColor": true, - "enableDetailLayer": true, - "enableNormals": true, - "normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", - "normalDetailStrength": 1.5 - }, - "detailUV": { - "center": [ - 0.0, - 0.0 - ], - "scale": 10.0 - }, - "metallic": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_Metallic.png", - "textureMapUv": "Unwrapped" - }, - "normal": { - "flipY": true, - "textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", - "textureMapUv": "Unwrapped" - }, - "roughness": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_Roughness.png", - "textureMapUv": "Unwrapped" - } + "propertyValues": { + "baseColor.textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", + "baseColor.textureMapUv": "Unwrapped", + "detailLayerGroup.baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", + "detailLayerGroup.blendDetailMask": "Objects/Hermanubis/Hermanubis_ao.tif", + "detailLayerGroup.blendDetailMaskUv": "Unwrapped", + "detailLayerGroup.enableBaseColor": true, + "detailLayerGroup.enableDetailLayer": true, + "detailLayerGroup.enableNormals": true, + "detailLayerGroup.normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", + "detailLayerGroup.normalDetailStrength": 1.5, + "detailUV.center": [ + 0.0, + 0.0 + ], + "detailUV.scale": 10.0, + "metallic.textureMap": "Objects/Hermanubis/Hermanubis_bronze_Metallic.png", + "metallic.textureMapUv": "Unwrapped", + "normal.flipY": true, + "normal.textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", + "normal.textureMapUv": "Unwrapped", + "roughness.textureMap": "Objects/Hermanubis/Hermanubis_bronze_Roughness.png", + "roughness.textureMapUv": "Unwrapped" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColor.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColor.material index 826ae2d737..ff3e4d63b8 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColor.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColor.material @@ -1,17 +1,12 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material", "materialTypeVersion": 3, - "properties": { - "detailLayerGroup": { - "baseColorDetailBlend": 0.800000011920929, - "baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", - "enableBaseColor": true, - "enableDetailLayer": true - }, - "detailUV": { - "scale": 20.0 - } + "parentMaterial": "TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material", + "propertyValues": { + "detailLayerGroup.baseColorDetailBlend": 0.800000011920929, + "detailLayerGroup.baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", + "detailLayerGroup.enableBaseColor": true, + "detailLayerGroup.enableDetailLayer": true, + "detailUV.scale": 20.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColorWithMask.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColorWithMask.material index 1c2214a031..09cc883efd 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColorWithMask.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColorWithMask.material @@ -1,13 +1,10 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColor.material", "materialTypeVersion": 3, - "properties": { - "detailLayerGroup": { - "baseColorDetailBlend": 1.0, - "blendDetailMask": "TestData/Textures/checker8x8_flip_512.png", - "blendDetailMaskUv": "Unwrapped" - } + "parentMaterial": "TestData/Materials/StandardPbrTestCases/103_DetailMaps_BaseColor.material", + "propertyValues": { + "detailLayerGroup.baseColorDetailBlend": 1.0, + "detailLayerGroup.blendDetailMask": "TestData/Textures/checker8x8_flip_512.png", + "detailLayerGroup.blendDetailMaskUv": "Unwrapped" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_Normal.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_Normal.material index 9a80cfaaa0..81de9e0bce 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_Normal.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_Normal.material @@ -1,18 +1,13 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material", "materialTypeVersion": 3, - "properties": { - "detailLayerGroup": { - "enableDetailLayer": true, - "enableNormals": true, - "normalDetailFlipY": true, - "normalDetailMap": "TestData/Textures/test_dome_normal.tiff", - "normalDetailStrength": 0.30000001192092898 - }, - "detailUV": { - "scale": 40.0 - } + "parentMaterial": "TestData/Materials/StandardPbrTestCases/101_DetailMaps_BaseNoDetailMaps.material", + "propertyValues": { + "detailLayerGroup.enableDetailLayer": true, + "detailLayerGroup.enableNormals": true, + "detailLayerGroup.normalDetailFlipY": true, + "detailLayerGroup.normalDetailMap": "TestData/Textures/test_dome_normal.tiff", + "detailLayerGroup.normalDetailStrength": 0.30000001192092896, + "detailUV.scale": 40.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_NormalWithMask.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_NormalWithMask.material index 0ee81633ae..477da12807 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_NormalWithMask.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/104_DetailMaps_NormalWithMask.material @@ -1,12 +1,9 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "TestData/Materials/StandardPbrTestCases/104_DetailMaps_Normal.material", "materialTypeVersion": 3, - "properties": { - "detailLayerGroup": { - "blendDetailMask": "TestData/Textures/checker8x8_gray_512.png", - "blendDetailMaskUv": "Unwrapped" - } + "parentMaterial": "TestData/Materials/StandardPbrTestCases/104_DetailMaps_Normal.material", + "propertyValues": { + "detailLayerGroup.blendDetailMask": "TestData/Textures/checker8x8_gray_512.png", + "detailLayerGroup.blendDetailMaskUv": "Unwrapped" } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material index b2747ead21..d9c7a42c41 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material @@ -1,41 +1,27 @@ { - "description": "", "materialType": "Materials/Types/EnhancedPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "baseColor": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", - "textureMapUv": "Unwrapped" - }, - "detailLayerGroup": { - "baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", - "blendDetailMask": "TestData/Textures/checker2x2_128.png", - "enableBaseColor": true, - "enableDetailLayer": true, - "enableNormals": true, - "normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", - "normalDetailStrength": 1.5 - }, - "detailUV": { - "center": [ - 0.0, - 0.0 - ], - "scale": 10.0 - }, - "metallic": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_Metallic.png", - "textureMapUv": "Unwrapped" - }, - "normal": { - "flipY": true, - "textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", - "textureMapUv": "Unwrapped" - }, - "roughness": { - "textureMap": "Objects/Hermanubis/Hermanubis_bronze_Roughness.png", - "textureMapUv": "Unwrapped" - } + "propertyValues": { + "baseColor.textureMap": "Objects/Hermanubis/Hermanubis_bronze_BaseColor.png", + "baseColor.textureMapUv": "Unwrapped", + "detailLayerGroup.baseColorDetailMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg", + "detailLayerGroup.blendDetailMask": "TestData/Textures/checker2x2_128.png", + "detailLayerGroup.enableBaseColor": true, + "detailLayerGroup.enableDetailLayer": true, + "detailLayerGroup.enableNormals": true, + "detailLayerGroup.normalDetailMap": "TestData/Textures/cc0/Concrete019_1K_Normal.jpg", + "detailLayerGroup.normalDetailStrength": 1.5, + "detailUV.center": [ + 0.0, + 0.0 + ], + "detailUV.scale": 10.0, + "metallic.textureMap": "Objects/Hermanubis/Hermanubis_bronze_Metallic.png", + "metallic.textureMapUv": "Unwrapped", + "normal.flipY": true, + "normal.textureMap": "Objects/Hermanubis/Hermanubis_Normal.png", + "normal.textureMapUv": "Unwrapped", + "roughness.textureMap": "Objects/Hermanubis/Hermanubis_bronze_Roughness.png", + "roughness.textureMapUv": "Unwrapped" } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/UvTilingBase.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/UvTilingBase.material index be607db929..6927d51ecf 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/UvTilingBase.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/UvTilingBase.material @@ -1,20 +1,16 @@ { - "description": "", "materialType": "Materials\\Types\\StandardPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "uv": { - "center": [ - 0.5, - 0.5 - ], - "offsetU": 0.10000000149011612, - "offsetV": 0.15000000596046449, - "rotateDegrees": 38.181819915771487, - "scale": 1.5, - "tileU": 0.5, - "tileV": 2.0 - } + "propertyValues": { + "uv.center": [ + 0.5, + 0.5 + ], + "uv.offsetU": 0.10000000149011612, + "uv.offsetV": 0.15000000596046448, + "uv.rotateDegrees": 38.181819915771484, + "uv.scale": 1.5, + "uv.tileU": 0.5, + "uv.tileV": 2.0 } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl index 140fc57961..71c1621f7f 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl @@ -68,8 +68,10 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN) surface.CalculateRoughnessA(); // Albedo, SpecularF0 - const float specularF0Factor = 0.5f; - surface.SetAlbedoAndSpecularF0(MinimalPBRSrg::m_baseColor, specularF0Factor, MinimalPBRSrg::m_metallic); + float3 baseColor = MinimalPBRSrg::m_baseColor; + float metallic = MinimalPBRSrg::m_metallic; + float specularF0Factor = 0.5f; + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); // Clear Coat surface.clearCoat.InitializeToZero(); diff --git a/Gems/Atom/TestData/TestData/Objects/ModelHotReload/DisplayVertexColor.material b/Gems/Atom/TestData/TestData/Objects/ModelHotReload/DisplayVertexColor.material index 8a2f45260a..669efe2339 100644 --- a/Gems/Atom/TestData/TestData/Objects/ModelHotReload/DisplayVertexColor.material +++ b/Gems/Atom/TestData/TestData/Objects/ModelHotReload/DisplayVertexColor.material @@ -1,18 +1,12 @@ { - "description": "", "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", - "parentMaterial": "", "materialTypeVersion": 3, - "properties": { - "blend": { - "blendSource": "BlendMaskVertexColors", - "debugDrawMode": "FinalBlendWeights", - "enableLayer2": true, - "enableLayer3": true, - "textureMap": "" - }, - "parallax": { - "enable": false - } + "propertyValues": { + "blend.blendSource": "BlendMaskVertexColors", + "blend.debugDrawMode": "FinalBlendWeights", + "blend.enableLayer2": true, + "blend.enableLayer3": true, + "blend.textureMap": "", + "parallax.enable": false } -} +} \ No newline at end of file diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h deleted file mode 100644 index 9b4c1d77fe..0000000000 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include -#include -#include -#endif - -namespace AtomToolsFramework -{ - struct AtomToolsDocumentSystemSettings - : public AZ::UserSettings - { - AZ_RTTI(AtomToolsDocumentSystemSettings, "{9E576D4F-A74A-4326-9135-C07284D0A3B9}", AZ::UserSettings); - AZ_CLASS_ALLOCATOR(AtomToolsDocumentSystemSettings, AZ::SystemAllocator, 0); - - static void Reflect(AZ::ReflectContext* context); - - bool m_showReloadDocumentPrompt = true; - }; -} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 150b06cabd..4ba1d04b71 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -189,8 +189,9 @@ namespace AtomToolsFramework AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast( &AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); + const bool enableSourceControl = GetSettingOrDefault("/O3DE/AtomToolsFramework/Application/EnableSourceControl", true); AzToolsFramework::SourceControlConnectionRequestBus::Broadcast( - &AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true); + &AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, enableSourceControl); if (!AZ::RPI::RPISystemInterface::Get()->IsInitialized()) { diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp index 4270cb87fe..8394efa46f 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -103,8 +104,12 @@ namespace AtomToolsFramework { const AZStd::vector entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); - const int multiSelectPromptThreshold = 10; - if (entries.size() >= multiSelectPromptThreshold) + const bool promptToOpenMultipleFiles = + GetSettingOrDefault("/O3DE/AtomToolsFramework/AssetBrowser/PromptToOpenMultipleFiles", true); + const AZ::u64 promptToOpenMultipleFilesThreshold = + GetSettingOrDefault("/O3DE/AtomToolsFramework/AssetBrowser/PromptToOpenMultipleFilesThreshold", 10); + + if (promptToOpenMultipleFiles && promptToOpenMultipleFilesThreshold <= entries.size()) { QMessageBox::StandardButton result = QMessageBox::question( QApplication::activeWindow(), diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index c05bb56391..329bc1b1b3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -35,8 +34,6 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::Reflect(AZ::ReflectContext* context) { - AtomToolsDocumentSystemSettings::Reflect(context); - if (AZ::SerializeContext* serialize = azrtti_cast(context)) { serialize->Class() @@ -113,7 +110,6 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::Activate() { m_documentMap.clear(); - m_settings = AZ::UserSettings::CreateFind(AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL); AtomToolsDocumentSystemRequestBus::Handler::BusConnect(); AtomToolsDocumentNotificationBus::Handler::BusConnect(); } @@ -178,6 +174,17 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::ReopenDocuments() { + const bool enableHotReload = GetSettingOrDefault("/O3DE/AtomToolsFramework/DocumentSystem/EnableHotReload", true); + if (!enableHotReload) + { + m_documentIdsWithDependencyChanges.clear(); + m_documentIdsWithExternalChanges.clear(); + m_queueReopenDocuments = false; + } + + const bool enableHotReloadPrompts = + GetSettingOrDefault("/O3DE/AtomToolsFramework/DocumentSystem/EnableHotReloadPrompts", true); + for (const AZ::Uuid& documentId : m_documentIdsWithExternalChanges) { m_documentIdsWithDependencyChanges.erase(documentId); @@ -185,7 +192,7 @@ namespace AtomToolsFramework AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); - if (m_settings->m_showReloadDocumentPrompt && + if (enableHotReloadPrompts && (QMessageBox::question(QApplication::activeWindow(), QString("Document was externally modified"), QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), @@ -212,7 +219,7 @@ namespace AtomToolsFramework AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); - if (m_settings->m_showReloadDocumentPrompt && + if (enableHotReloadPrompts && (QMessageBox::question(QApplication::activeWindow(), QString("Document dependencies have changed"), QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h index 5c7454e5c7..5eb531ef25 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h @@ -15,7 +15,6 @@ #include #include #include -#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -79,7 +78,6 @@ namespace AtomToolsFramework AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); - AZStd::intrusive_ptr m_settings; AZStd::function m_documentCreator; AZStd::unordered_map> m_documentMap; AZStd::unordered_set m_documentIdsWithExternalChanges; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp deleted file mode 100644 index 94af43e524..0000000000 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include -#include - -namespace AtomToolsFramework -{ - void AtomToolsDocumentSystemSettings::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("showReloadDocumentPrompt", &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt) - ; - - if (auto editContext = serializeContext->GetEditContext()) - { - editContext->Class( - "AtomToolsDocumentSystemSettings", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "") - ; - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class("AtomToolsDocumentSystemSettings") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "atomtools") - ->Constructor() - ->Constructor() - ->Property("showReloadDocumentPrompt", BehaviorValueProperty(&AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt)) - ; - } - } -} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index b7f9882e92..041e6e1807 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -17,7 +17,6 @@ set(FILES Include/AtomToolsFramework/Document/AtomToolsDocument.h Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h - Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -54,7 +53,6 @@ set(FILES Source/Document/AtomToolsDocument.cpp Source/Document/AtomToolsDocumentApplication.cpp Source/Document/AtomToolsDocumentMainWindow.cpp - Source/Document/AtomToolsDocumentSystemSettings.cpp Source/Document/AtomToolsDocumentSystemComponent.cpp Source/Document/AtomToolsDocumentSystemComponent.h Source/DynamicProperty/DynamicProperty.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 2c1ff5cad3..8db8ee1eeb 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -353,8 +353,8 @@ namespace MaterialEditor } // TODO: Support populating the Material Editor with nested property groups, not just the top level. - const AZStd::string groupName = propertyId.GetStringView().substr(0, propertyId.GetStringView().size() - propertyDefinition->GetName().size() - 1); - sourceData.m_properties[groupName][propertyDefinition->GetName()].m_value = propertyValue; + AZStd::string_view groupName = propertyId.GetStringView().substr(0, propertyId.GetStringView().size() - propertyDefinition->GetName().size() - 1); + sourceData.SetPropertyValue(AZ::RPI::MaterialPropertyId{groupName, propertyDefinition->GetName()}, propertyValue); } } return true; @@ -438,12 +438,15 @@ namespace MaterialEditor if (!m_materialSourceData.m_parentMaterial.empty()) { AZ::RPI::MaterialSourceData parentMaterialSourceData; - if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_materialSourceData.m_parentMaterial, parentMaterialSourceData)) + auto loadResult = AZ::RPI::MaterialUtils::LoadMaterialSourceData(m_materialSourceData.m_parentMaterial); + if (!loadResult) { AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); return OpenFailed(); } + parentMaterialSourceData = loadResult.TakeValue(); + const auto parentMaterialAssetIdResult = AZ::RPI::AssetUtils::MakeAssetId(m_materialSourceData.m_parentMaterial, 0); if (!parentMaterialAssetIdResult) { @@ -670,13 +673,15 @@ namespace MaterialEditor bool MaterialDocument::LoadMaterialSourceData() { - // Load the material source data so that we can check properties and create a material asset from it - if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, m_materialSourceData)) + auto loadResult = AZ::RPI::MaterialUtils::LoadMaterialSourceData(m_absolutePath); + if (!loadResult) { AZ_Error("MaterialDocument", false, "Material source data could not be loaded: '%s'.", m_absolutePath.c_str()); return false; } + m_materialSourceData = loadResult.TakeValue(); + // We always need the absolute path for the material type and parent material to load source data and resolving // relative paths when saving. This will convert and store them as absolute paths for use within the document. if (!m_materialSourceData.m_parentMaterial.empty()) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp index 357dfc37e0..8bf4191432 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp @@ -14,8 +14,6 @@ namespace MaterialEditor SettingsWidget::SettingsWidget(QWidget* parent) : AtomToolsFramework::InspectorWidget(parent) { - m_documentSystemSettings = AZ::UserSettings::CreateFind( - AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL); } SettingsWidget::~SettingsWidget() @@ -26,23 +24,9 @@ namespace MaterialEditor void SettingsWidget::Populate() { AddGroupsBegin(); - AddDocumentSystemSettingsGroup(); AddGroupsEnd(); } - void SettingsWidget::AddDocumentSystemSettingsGroup() - { - const AZStd::string groupName = "documentSystemSettings"; - const AZStd::string groupDisplayName = "Document System Settings"; - const AZStd::string groupDescription = "Document System Settings"; - - const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); - AddGroup( - groupName, groupDisplayName, groupDescription, - new AtomToolsFramework::InspectorPropertyGroupWidget( - m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), nullptr, this, saveStateKey)); - } - void SettingsWidget::Reset() { AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h index 2642d9d55e..9a222b39c1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h @@ -9,7 +9,6 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include #include #endif @@ -30,11 +29,7 @@ namespace MaterialEditor void Populate(); private: - void AddDocumentSystemSettingsGroup(); - // AtomToolsFramework::InspectorRequestBus::Handler overrides... void Reset() override; - - AZStd::intrusive_ptr m_documentSystemSettings; }; } // namespace MaterialEditor diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp index dde9644c50..52e22645ca 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp @@ -149,8 +149,8 @@ namespace AZ } // TODO: Support populating the Material Editor with nested property groups, not just the top level. - const AZStd::string groupName = propertyId.GetStringView().substr(0, propertyId.GetStringView().size() - propertyDefinition->GetName().size() - 1); - exportData.m_properties[groupName][propertyDefinition->GetName()].m_value = propertyValue; + AZStd::string_view groupName = propertyId.GetStringView().substr(0, propertyId.GetStringView().size() - propertyDefinition->GetName().size() - 1); + exportData.SetPropertyValue(RPI::MaterialPropertyId{groupName, propertyDefinition->GetName()}, propertyValue); return true; }); diff --git a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp index 0be51909f4..dc1f7d11cc 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -219,15 +220,15 @@ namespace EditorPythonBindings void PythonLogSymbolsComponent::LogClassWithName(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass, const AZStd::string className) { - Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); - if (fileHandle.IsValid()) + auto fileHandle = OpenModuleAt(moduleName); + if (fileHandle->IsValid()) { // Behavior Class types with member methods and properties AZStd::string buffer; AzFramework::StringFunc::Append(buffer, "class "); AzFramework::StringFunc::Append(buffer, className.data()); AzFramework::StringFunc::Append(buffer, ":\n"); - AZ::IO::FileIOBase::GetInstance()->Write(fileHandle, buffer.c_str(), buffer.size()); + AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size()); buffer.clear(); if (behaviorClass->m_methods.empty() && behaviorClass->m_properties.empty()) @@ -235,7 +236,7 @@ namespace EditorPythonBindings AZStd::string body{ " # behavior class type with no methods or properties \n" }; Internal::Indent(1, body); AzFramework::StringFunc::Append(body, "pass\n\n"); - AZ::IO::FileIOBase::GetInstance()->Write(fileHandle, body.c_str(), body.size()); + AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, body.c_str(), body.size()); } else { @@ -244,7 +245,7 @@ namespace EditorPythonBindings AZ::BehaviorProperty* property = properyEntry.second; AZStd::string propertyName{ properyEntry.first }; Scope::FetchScriptName(property->m_attributes, propertyName); - WriteProperty(fileHandle, 1, propertyName, *property, behaviorClass); + WriteProperty(*fileHandle, 1, propertyName, *property, behaviorClass); } for (const auto& methodEntry : behaviorClass->m_methods) @@ -254,7 +255,7 @@ namespace EditorPythonBindings { AZStd::string baseMethodName{ methodEntry.first }; Scope::FetchScriptName(method->m_attributes, baseMethodName); - WriteMethod(fileHandle, baseMethodName, *method, behaviorClass); + WriteMethod(*fileHandle, baseMethodName, *method, behaviorClass); } } } @@ -264,14 +265,13 @@ namespace EditorPythonBindings void PythonLogSymbolsComponent::LogClassMethod( const AZStd::string moduleName, const AZStd::string globalMethodName, - const AZ::BehaviorClass* behaviorClass, + [[maybe_unused]] const AZ::BehaviorClass* behaviorClass, const AZ::BehaviorMethod* behaviorMethod) { - AZ_UNUSED(behaviorClass); - Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); - if (fileHandle.IsValid()) + auto fileHandle = OpenModuleAt(moduleName); + if (fileHandle->IsValid()) { - WriteMethod(fileHandle, globalMethodName, *behaviorMethod, nullptr); + WriteMethod(*fileHandle, globalMethodName, *behaviorMethod, nullptr); } } @@ -282,8 +282,8 @@ namespace EditorPythonBindings return; } - Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); - if (fileHandle.IsValid()) + auto fileHandle = OpenModuleAt(moduleName); + if (fileHandle->IsValid()) { AZStd::string buffer; @@ -314,7 +314,7 @@ namespace EditorPythonBindings } AzFramework::StringFunc::Append(buffer, " -> Any:\n"); - AZ::IO::FileIOBase::GetInstance()->Write(fileHandle, buffer.c_str(), buffer.size()); + AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size()); buffer.clear(); auto eventInfoBuilder = [this](const AZ::BehaviorMethod* behaviorMethod, AZStd::string& inOutStrBuffer, [[maybe_unused]] TypeMap& typeCache) @@ -398,7 +398,7 @@ namespace EditorPythonBindings Internal::Indent(1, buffer); AzFramework::StringFunc::Append(buffer, "pass\n\n"); - AZ::IO::FileIOBase::GetInstance()->Write(fileHandle, buffer.c_str(), buffer.size()); + AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size()); // can the EBus create & destroy a handler? if (behaviorEBus->m_createHandler && behaviorEBus->m_destroyHandler) @@ -409,17 +409,17 @@ namespace EditorPythonBindings AzFramework::StringFunc::Append(buffer, "Handler() -> None:\n"); Internal::Indent(1, buffer); AzFramework::StringFunc::Append(buffer, "pass\n\n"); - AZ::IO::FileIOBase::GetInstance()->Write(fileHandle, buffer.c_str(), buffer.size()); + AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size()); } } } void PythonLogSymbolsComponent::LogGlobalMethod(const AZStd::string moduleName, const AZStd::string methodName, const AZ::BehaviorMethod* behaviorMethod) { - Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); - if (fileHandle.IsValid()) + auto fileHandle = OpenModuleAt(moduleName); + if (fileHandle->IsValid()) { - WriteMethod(fileHandle, methodName, *behaviorMethod, nullptr); + WriteMethod(*fileHandle, methodName, *behaviorMethod, nullptr); } auto functionMapIt = m_globalFunctionMap.find(moduleName); @@ -448,14 +448,14 @@ namespace EditorPythonBindings return; } - Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); - if (fileHandle.IsValid()) + auto fileHandle = OpenModuleAt(moduleName); + if (fileHandle->IsValid()) { AZStd::string buffer; // add header AZ::u64 filesize = 0; - AZ::IO::FileIOBase::GetInstance()->Size(fileHandle, filesize); + AZ::IO::FileIOBase::GetInstance()->Size(fileHandle->m_handle, filesize); if (filesize == 0) { AzFramework::StringFunc::Append(buffer, "class property():\n"); @@ -483,14 +483,14 @@ namespace EditorPythonBindings } AzFramework::StringFunc::Append(buffer, "\n"); - AZ::IO::FileIOBase::GetInstance()->Write(fileHandle, buffer.c_str(), buffer.size()); + AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size()); } } void PythonLogSymbolsComponent::Finalize() { - Internal::FileHandle fileHandle(OpenInitFileAt("azlmbr.bus")); - if (fileHandle) + auto fileHandle = OpenInitFileAt("azlmbr.bus"); + if (fileHandle->IsValid()) { AZStd::string buffer; AzFramework::StringFunc::Append(buffer, "# Bus dispatch types:\n"); @@ -499,9 +499,9 @@ namespace EditorPythonBindings AzFramework::StringFunc::Append(buffer, "Event: Final[int] = 1\n"); AzFramework::StringFunc::Append(buffer, "QueueBroadcast: Final[int] = 2\n"); AzFramework::StringFunc::Append(buffer, "QueueEvent: Final[int] = 3\n"); - AZ::IO::FileIOBase::GetInstance()->Write(fileHandle, buffer.c_str(), buffer.size()); + AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size()); } - fileHandle.Close(); + fileHandle->Close(); } void PythonLogSymbolsComponent::GetModuleList(AZStd::vector& moduleList) const @@ -689,11 +689,11 @@ namespace EditorPythonBindings return pythonType; } - AZ::IO::HandleType PythonLogSymbolsComponent::OpenInitFileAt(AZStd::string_view moduleName) + PythonLogSymbolsComponent::FileHandlePtr PythonLogSymbolsComponent::OpenInitFileAt(AZStd::string_view moduleName) { if (m_basePath.empty()) { - return AZ::IO::InvalidHandle; + return AZStd::make_shared(AZ::IO::InvalidHandle); } // creates the __init__.py file in this path @@ -708,20 +708,19 @@ namespace EditorPythonBindings AZ::IO::OpenMode openMode = AZ::IO::OpenMode::ModeText | AZ::IO::OpenMode::ModeWrite; AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; AZ::IO::Result result = AZ::IO::FileIOBase::GetInstance()->Open(initFile.c_str(), openMode, fileHandle); - AZ_Warning("python", result, "Could not open %s to write Python symbols.", initFile.c_str()); if (result) { - return fileHandle; + return AZStd::make_shared(fileHandle); } - return AZ::IO::InvalidHandle; + return AZStd::make_shared(AZ::IO::InvalidHandle); } - AZ::IO::HandleType PythonLogSymbolsComponent::OpenModuleAt(AZStd::string_view moduleName) + PythonLogSymbolsComponent::FileHandlePtr PythonLogSymbolsComponent::OpenModuleAt(AZStd::string_view moduleName) { if (m_basePath.empty()) { - return AZ::IO::InvalidHandle; + return AZStd::make_shared(AZ::IO::InvalidHandle); } bool resetFile = false; @@ -769,12 +768,11 @@ namespace EditorPythonBindings AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; AZ::IO::Result result = AZ::IO::FileIOBase::GetInstance()->Open(modulePath.c_str(), openMode, fileHandle); - AZ_Warning("python", result, "Could not open %s to write Python module symbols.", modulePath.c_str()); if (result) { - return fileHandle; + return AZStd::make_shared(fileHandle); } - return AZ::IO::InvalidHandle; + return AZStd::make_shared(AZ::IO::InvalidHandle); } } diff --git a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h index 5fbd1c3f37..7e89a41cd5 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h +++ b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h @@ -27,6 +27,11 @@ namespace AZ namespace EditorPythonBindings { + namespace Internal + { + struct FileHandle; + } + //! Exports Python symbols to the log folder for Python script developers to include into their local projects class PythonLogSymbolsComponent : public AZ::Component @@ -77,11 +82,13 @@ namespace EditorPythonBindings AZStd::string_view FetchPythonTypeAndTraits(const AZ::TypeId& typeId, AZ::u32 traits); private: + using ModuleSet = AZStd::unordered_set; using GlobalFunctionEntry = AZStd::pair; using GlobalFunctionList = AZStd::vector; using GlobalFunctionMap = AZStd::unordered_map; using TypeMap = AZStd::unordered_map; + using FileHandlePtr = AZStd::shared_ptr; AZStd::string m_basePath; ModuleSet m_moduleSet; @@ -92,8 +99,8 @@ namespace EditorPythonBindings AZStd::string FetchMapType(const AZ::TypeId& typeId); AZStd::string FetchOutcomeType(const AZ::TypeId& typeId); AZStd::string TypeNameFallback(const AZ::TypeId& typeId); - AZ::IO::HandleType OpenInitFileAt(AZStd::string_view moduleName); - AZ::IO::HandleType OpenModuleAt(AZStd::string_view moduleName); + FileHandlePtr OpenInitFileAt(AZStd::string_view moduleName); + FileHandlePtr OpenModuleAt(AZStd::string_view moduleName); void WriteMethod(AZ::IO::HandleType handle, AZStd::string_view methodName, const AZ::BehaviorMethod& behaviorMethod, const AZ::BehaviorClass* behaviorClass); void WriteProperty(AZ::IO::HandleType handle, int level, AZStd::string_view propertyName, const AZ::BehaviorProperty& property, const AZ::BehaviorClass* behaviorClass); }; diff --git a/Gems/FastNoise/Code/Tests/FastNoiseTest.cpp b/Gems/FastNoise/Code/Tests/FastNoiseTest.cpp index 1ac5e8ddca..e82409d599 100644 --- a/Gems/FastNoise/Code/Tests/FastNoiseTest.cpp +++ b/Gems/FastNoise/Code/Tests/FastNoiseTest.cpp @@ -102,7 +102,7 @@ TEST_F(FastNoiseTest, FastNoise_VerifyGetValueAndGetValuesMatch) noiseEntity->Activate(); // Create a gradient sampler and run through a series of points to see if they match expectations. - UnitTest::GradientSignalTestHelpers::CompareGetValueAndGetValues(noiseEntity->GetId(), shapeHalfBounds); + UnitTest::GradientSignalTestHelpers::CompareGetValueAndGetValues(noiseEntity->GetId(), -shapeHalfBounds, shapeHalfBounds); } // This uses custom test / benchmark hooks so that we can load LmbrCentral and GradientSignal Gems. diff --git a/Gems/GradientSignal/Code/CMakeLists.txt b/Gems/GradientSignal/Code/CMakeLists.txt index d2d8f8c696..febf7d9cd4 100644 --- a/Gems/GradientSignal/Code/CMakeLists.txt +++ b/Gems/GradientSignal/Code/CMakeLists.txt @@ -17,9 +17,12 @@ ly_add_target( PUBLIC Include BUILD_DEPENDENCIES + PRIVATE + AZ::AtomCore PUBLIC AZ::AzCore AZ::AzFramework + Gem::Atom_RPI.Public Gem::SurfaceData Gem::ImageProcessingAtom.Headers Gem::LmbrCentral diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h index 044e9d91b1..7ec1c785e5 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h @@ -8,8 +8,11 @@ #pragma once +#include #include #include +#include +#include #include #include #include @@ -25,6 +28,19 @@ namespace LmbrCentral namespace GradientSignal { + // Custom JSON serializer for ImageGradientConfig to handle version conversion + class JsonImageGradientConfigSerializer + : public AZ::BaseJsonSerializer + { + public: + AZ_RTTI(GradientSignal::JsonImageGradientConfigSerializer, "{C5B982C8-2E81-45C3-8932-B6F54B28F493}", AZ::BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + AZ::JsonSerializationResult::Result Load( + void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + AZ::JsonDeserializerContext& context) override; + }; + class ImageGradientConfig : public AZ::ComponentConfig { @@ -32,7 +48,7 @@ namespace GradientSignal AZ_CLASS_ALLOCATOR(ImageGradientConfig, AZ::SystemAllocator, 0); AZ_RTTI(ImageGradientConfig, "{1BDB5DA4-A4A8-452B-BE6D-6BD451D4E7CD}", AZ::ComponentConfig); static void Reflect(AZ::ReflectContext* context); - AZ::Data::Asset m_imageAsset = { AZ::Data::AssetLoadBehavior::QueueLoad }; + AZ::Data::Asset m_imageAsset = { AZ::Data::AssetLoadBehavior::QueueLoad }; float m_tilingX = 1.0f; float m_tilingY = 1.0f; }; @@ -82,6 +98,8 @@ namespace GradientSignal void SetupDependencies(); + void GetSubImageData(); + // ImageGradientRequestBus overrides... AZStd::string GetImageAssetPath() const override; void SetImageAssetPath(const AZStd::string& assetPath) override; @@ -97,5 +115,6 @@ namespace GradientSignal LmbrCentral::DependencyMonitor m_dependencyMonitor; mutable AZStd::shared_mutex m_imageMutex; GradientTransform m_gradientTransform; + AZStd::span m_imageData; }; } diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h b/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h index 4ffab0b4b4..500251d924 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace AZ { @@ -61,6 +62,6 @@ namespace GradientSignal } }; - float GetValueFromImageAsset(const AZ::Data::Asset& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue); + float GetValueFromImageAsset(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue); } // namespace GradientSignal diff --git a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp index 3639d5c6df..0bf914fea3 100644 --- a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -18,16 +19,103 @@ namespace GradientSignal { + AZ::JsonSerializationResult::Result JsonImageGradientConfigSerializer::Load( + void* outputValue, [[maybe_unused]] const AZ::Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, AZ::JsonDeserializerContext& context) + { + // We can distinguish between version 1 and 2 by the presence of the "ImageAsset" field, + // which is only in version 1. + // For version 2, we don't need to do any special processing, so just let the base class + // load the JSON if we don't find the "ImageAsset" field. + rapidjson::Value::ConstMemberIterator itr = inputValue.FindMember("ImageAsset"); + if (itr == inputValue.MemberEnd()) + { + return AZ::BaseJsonSerializer::Load(outputValue, outputValueTypeId, inputValue, context); + } + + namespace JSR = AZ::JsonSerializationResult; + + auto configInstance = reinterpret_cast(outputValue); + AZ_Assert(configInstance, "Output value for JsonImageGradientConfigSerializer can't be null."); + + JSR::ResultCode result(JSR::Tasks::ReadField); + + result.Combine(ContinueLoadingFromJsonObjectField( + &configInstance->m_tilingX, azrtti_typeidm_tilingX)>(), inputValue, "TilingX", context)); + + result.Combine(ContinueLoadingFromJsonObjectField( + &configInstance->m_tilingY, azrtti_typeidm_tilingY)>(), inputValue, "TilingY", context)); + + // Version 1 stored a custom GradientSignal::ImageAsset as the image asset. + // In Version 2, we changed the image asset to use the generic AZ::RPI::StreamingImageAsset, + // so they are both AZ::Data::Asset but reference different types. + // Using the assetHint, which will be something like "my_test_image.gradimage", + // we need to find the valid streaming image asset product from the same source, + // which will be something like "my_test_image.png.streamingimage" + AZStd::string assetHint; + AZ::Data::AssetId fixedAssetId; + auto it = itr->value.FindMember("assetHint"); + if (it != itr->value.MemberEnd()) + { + AZ::ScopedContextPath subPath(context, "assetHint"); + result.Combine(ContinueLoading(&assetHint, azrtti_typeid(), it->value, context)); + + if (assetHint.ends_with(".gradimage")) + { + // We don't know what image format the original source was, so we need to loop through + // all the supported image extensions to check if they have a valid corresponding + // streaming image asset + for (auto& supportedImageExtension : ImageProcessingAtom::s_SupportedImageExtensions) + { + AZStd::string imageExtension(supportedImageExtension); + + // The image extensions are stored with a wildcard (e.g. *.png) so we need to strip that off first + AZ::StringFunc::Replace(imageExtension, "*", ""); + + // Form potential streaming image path (e.g. my_test_image.png.streamingimage) + AZStd::string potentialStreamingImagePath(assetHint); + AZ::StringFunc::Replace(potentialStreamingImagePath, ".gradimage", ""); + potentialStreamingImagePath += imageExtension + ".streamingimage"; + + // Check if there is a valid streaming image asset for this path + AZ::Data::AssetCatalogRequestBus::BroadcastResult(fixedAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, potentialStreamingImagePath.c_str(), azrtti_typeid>(), false); + if (fixedAssetId.IsValid()) + { + break; + } + } + } + } + + // Replace the old gradimage with new AssetId for streaming image asset + if (fixedAssetId.IsValid()) + { + configInstance->m_imageAsset = AZ::Data::AssetManager::Instance().GetAsset(fixedAssetId, AZ::Data::AssetLoadBehavior::QueueLoad); + } + + return context.Report(result, + result.GetProcessing() != JSR::Processing::Halted ? + "Successfully loaded ImageGradientConfig information." : + "Failed to load ImageGradientConfig information."); + } + + AZ_CLASS_ALLOCATOR_IMPL(JsonImageGradientConfigSerializer, AZ::SystemAllocator, 0); + void ImageGradientConfig::Reflect(AZ::ReflectContext* context) { + if (auto jsonContext = azrtti_cast(context)) + { + jsonContext->Serializer()->HandlesType(); + } + AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) { serialize->Class() - ->Version(1) - ->Field("ImageAsset", &ImageGradientConfig::m_imageAsset) + ->Version(2) ->Field("TilingX", &ImageGradientConfig::m_tilingX) ->Field("TilingY", &ImageGradientConfig::m_tilingY) + ->Field("StreamingImageAsset", &ImageGradientConfig::m_imageAsset) ; AZ::EditContext* edit = serialize->GetEditContext(); @@ -127,6 +215,16 @@ namespace GradientSignal m_dependencyMonitor.ConnectDependency(m_configuration.m_imageAsset.GetId()); } + void ImageGradientComponent::GetSubImageData() + { + if (!m_configuration.m_imageAsset || !m_configuration.m_imageAsset.IsReady()) + { + return; + } + + m_imageData = m_configuration.m_imageAsset->GetSubImageData(0, 0); + } + void ImageGradientComponent::Activate() { // This will immediately call OnGradientTransformChanged and initialize m_gradientTransform. @@ -136,10 +234,13 @@ namespace GradientSignal ImageGradientRequestBus::Handler::BusConnect(GetEntityId()); GradientRequestBus::Handler::BusConnect(GetEntityId()); - AZ::Data::AssetBus::Handler::BusConnect(m_configuration.m_imageAsset.GetId()); - AZStd::unique_lock imageLock(m_imageMutex); + // Invoke the QueueLoad before connecting to the AssetBus, so that + // if the asset is already ready, then OnAssetReady will be triggered immediately + m_imageData = AZStd::span(); m_configuration.m_imageAsset.QueueLoad(); + + AZ::Data::AssetBus::Handler::BusConnect(m_configuration.m_imageAsset.GetId()); } void ImageGradientComponent::Deactivate() @@ -179,18 +280,24 @@ namespace GradientSignal { AZStd::unique_lock imageLock(m_imageMutex); m_configuration.m_imageAsset = asset; + + GetSubImageData(); } void ImageGradientComponent::OnAssetMoved(AZ::Data::Asset asset, [[maybe_unused]] void* oldDataPointer) { AZStd::unique_lock imageLock(m_imageMutex); m_configuration.m_imageAsset = asset; + + GetSubImageData(); } void ImageGradientComponent::OnAssetReloaded(AZ::Data::Asset asset) { AZStd::unique_lock imageLock(m_imageMutex); m_configuration.m_imageAsset = asset; + + GetSubImageData(); } void ImageGradientComponent::OnGradientTransformChanged(const GradientTransform& newTransform) @@ -204,6 +311,12 @@ namespace GradientSignal AZ::Vector3 uvw = sampleParams.m_position; bool wasPointRejected = false; + // Return immediately if our cached image data hasn't been retrieved yet + if (m_imageData.empty()) + { + return 0.0f; + } + { AZStd::shared_lock imageLock(m_imageMutex); @@ -212,7 +325,7 @@ namespace GradientSignal if (!wasPointRejected) { return GetValueFromImageAsset( - m_configuration.m_imageAsset, uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); + m_imageData, m_configuration.m_imageAsset->GetImageDescriptor(), uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); } } @@ -227,6 +340,12 @@ namespace GradientSignal return; } + // Return immediately if our cached image data hasn't been retrieved yet + if (m_imageData.empty()) + { + return; + } + AZ::Vector3 uvw; bool wasPointRejected = false; @@ -239,7 +358,7 @@ namespace GradientSignal if (!wasPointRejected) { outValues[index] = GetValueFromImageAsset( - m_configuration.m_imageAsset, uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); + m_imageData, m_configuration.m_imageAsset->GetImageDescriptor(), uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); } else { @@ -265,7 +384,11 @@ namespace GradientSignal { AZStd::unique_lock imageLock(m_imageMutex); - m_configuration.m_imageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(assetId, azrtti_typeid(), m_configuration.m_imageAsset.GetAutoLoadBehavior()); + + // Clear our cached image data + m_imageData = AZStd::span(); + + m_configuration.m_imageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(assetId, azrtti_typeid(), m_configuration.m_imageAsset.GetAutoLoadBehavior()); } SetupDependencies(); diff --git a/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp b/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp index e318e0fdf6..692576b3b3 100644 --- a/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace GradientSignal { @@ -61,6 +62,12 @@ namespace GradientSignal void EditorGradientSurfaceDataComponent::Deactivate() { + // Make sure any previews for this entity aren't currently trying to refresh. Otherwise, the preview job could call + // back into our FilterFunc lambda below after the entity has already been destroyed. + AZ::EntityId canceledEntity; + GradientSignal::GradientPreviewRequestBus::EventResult( + canceledEntity, GetEntityId(), &GradientSignal::GradientPreviewRequestBus::Events::CancelRefresh); + // If the preview shouldn't be active, use an invalid entityId m_gradientEntityId = AZ::EntityId(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); diff --git a/Gems/GradientSignal/Code/Source/ImageAsset.cpp b/Gems/GradientSignal/Code/Source/ImageAsset.cpp index 7e5667a5be..05ad13d193 100644 --- a/Gems/GradientSignal/Code/Source/ImageAsset.cpp +++ b/Gems/GradientSignal/Code/Source/ImageAsset.cpp @@ -15,84 +15,10 @@ #include #include +#include #include #include -namespace -{ - template - float RetrieveValue(const AZ::u8* mem, size_t index) - { - AZ_Assert(false, "Unimplemented!"); - return 0.0f; - } - - template <> - float RetrieveValue([[maybe_unused]] const AZ::u8* mem, [[maybe_unused]] size_t index) - { - return 0.0f; - } - - template <> - float RetrieveValue(const AZ::u8* mem, size_t index) - { - return mem[index] / static_cast(std::numeric_limits::max()); - } - - template <> - float RetrieveValue(const AZ::u8* mem, size_t index) - { - // 16 bits per channel - auto actualMem = reinterpret_cast(mem); - actualMem += index; - - return *actualMem / static_cast(std::numeric_limits::max()); - } - - template <> - float RetrieveValue(const AZ::u8* mem, size_t index) - { - // 32 bits per channel - auto actualMem = reinterpret_cast(mem); - actualMem += index; - - return *actualMem / static_cast(std::numeric_limits::max()); - } - - template <> - float RetrieveValue(const AZ::u8* mem, size_t index) - { - // 32 bits per channel - auto actualMem = reinterpret_cast(mem); - actualMem += index; - - return *actualMem; - } - - float RetrieveValue(const AZ::u8* mem, size_t index, ImageProcessingAtom::EPixelFormat format) - { - using namespace ImageProcessingAtom; - - switch (format) - { - case ePixelFormat_R8: - return RetrieveValue(mem, index); - - case ePixelFormat_R16: - return RetrieveValue(mem, index); - - case ePixelFormat_R32: - return RetrieveValue(mem, index); - - case ePixelFormat_R32F: - return RetrieveValue(mem, index); - - default: - return RetrieveValue(mem, index); - } - } -} - namespace GradientSignal { void ImageAsset::Reflect(AZ::ReflectContext* context) @@ -152,17 +78,14 @@ namespace GradientSignal return true; } - float GetValueFromImageAsset(const AZ::Data::Asset& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue) + float GetValueFromImageAsset(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue) { - if (imageAsset.IsReady()) + if (!imageData.empty()) { - const auto& image = imageAsset.Get(); - AZStd::size_t imageSize = image->m_imageWidth * image->m_imageHeight * - static_cast(image->m_bytesPerPixel); - - if (image->m_imageWidth > 0 && - image->m_imageHeight > 0 && - image->m_imageData.size() == imageSize) + auto width = imageDescriptor.m_size.m_width; + auto height = imageDescriptor.m_size.m_height; + + if (width > 0 && height > 0) { // When "rasterizing" from uvs, a range of 0-1 has slightly different meanings depending on the sampler state. // For repeating states (Unbounded/None, Repeat), a uv value of 1 should wrap around back to our 0th pixel. @@ -185,8 +108,8 @@ namespace GradientSignal // A 16x16 pixel image and tilingX = tilingY = 1 maps the uv range of 0-1 to 0-16 pixels. // A 16x16 pixel image and tilingX = tilingY = 1.5 maps the uv range of 0-1 to 0-24 pixels. - const AZ::Vector3 tiledDimensions((image->m_imageWidth * tilingX), - (image->m_imageHeight * tilingY), + const AZ::Vector3 tiledDimensions((width * tilingX), + (height * tilingY), 0.0f); // Convert from uv space back to pixel space @@ -195,13 +118,13 @@ namespace GradientSignal // UVs outside the 0-1 range are treated as infinitely tiling, so that we behave the same as the // other gradient generators. As mentioned above, if clamping is desired, we expect it to be applied // outside of this function. - size_t x = static_cast(pixelLookup.GetX()) % image->m_imageWidth; - size_t y = static_cast(pixelLookup.GetY()) % image->m_imageHeight; + auto x = aznumeric_cast(pixelLookup.GetX()) % width; + auto y = aznumeric_cast(pixelLookup.GetY()) % height; // Flip the y because images are stored in reverse of our world axes - size_t index = ((image->m_imageHeight - 1) - y) * image->m_imageWidth + x; + y = (height - 1) - y; - return RetrieveValue(image->m_imageData.data(), index, image->m_imageFormat); + return AZ::RPI::GetImageDataPixelValue(imageData, imageDescriptor, x, y); } } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp index 6ffb4a31c4..d8194dcc9a 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalBenchmarks.cpp @@ -140,27 +140,18 @@ namespace UnitTest BENCHMARK_DEFINE_F(GradientGetValues, BM_SurfaceAltitudeGradient)(benchmark::State& state) { - auto mockSurfaceDataSystem = - CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds))); - auto entity = BuildTestSurfaceAltitudeGradient(TestShapeHalfBounds); GradientSignalTestHelpers::RunGetValueOrGetValuesBenchmark(state, entity->GetId()); } BENCHMARK_DEFINE_F(GradientGetValues, BM_SurfaceMaskGradient)(benchmark::State& state) { - auto mockSurfaceDataSystem = - CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds))); - auto entity = BuildTestSurfaceMaskGradient(TestShapeHalfBounds); GradientSignalTestHelpers::RunGetValueOrGetValuesBenchmark(state, entity->GetId()); } BENCHMARK_DEFINE_F(GradientGetValues, BM_SurfaceSlopeGradient)(benchmark::State& state) { - auto mockSurfaceDataSystem = - CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds))); - auto entity = BuildTestSurfaceSlopeGradient(TestShapeHalfBounds); GradientSignalTestHelpers::RunGetValueOrGetValuesBenchmark(state, entity->GetId()); } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp index f0ad53ee64..e217dbb103 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp @@ -24,31 +24,33 @@ namespace UnitTest TEST_F(GradientSignalGetValuesTestsFixture, ImageGradientComponent_VerifyGetValueAndGetValuesMatch) { auto entity = BuildTestImageGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, PerlinGradientComponent_VerifyGetValueAndGetValuesMatch) { auto entity = BuildTestPerlinGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, RandomGradientComponent_VerifyGetValueAndGetValuesMatch) { auto entity = BuildTestRandomGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, ConstantGradientComponent_VerifyGetValueAndGetValuesMatch) { auto entity = BuildTestConstantGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, ShapeAreaFalloffGradientComponent_VerifyGetValueAndGetValuesMatch) { auto entity = BuildTestShapeAreaFalloffGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + + // Use a query range larger than our shape to ensure that we're getting falloff values within our query bounds. + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), -TestShapeHalfBounds, TestShapeHalfBounds * 3.0f); } TEST_F(GradientSignalGetValuesTestsFixture, DitherGradientComponent_VerifyGetValueAndGetValuesMatch) @@ -56,21 +58,21 @@ namespace UnitTest auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto entity = BuildTestDitherGradient(TestShapeHalfBounds, baseEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, InvertGradientComponent_VerifyGetValueAndGetValuesMatch) { auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto entity = BuildTestInvertGradient(TestShapeHalfBounds, baseEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, LevelsGradientComponent_VerifyGetValueAndGetValuesMatch) { auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto entity = BuildTestLevelsGradient(TestShapeHalfBounds, baseEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, MixedGradientComponent_VerifyGetValueAndGetValuesMatch) @@ -78,62 +80,53 @@ namespace UnitTest auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto mixedEntity = BuildTestConstantGradient(TestShapeHalfBounds); auto entity = BuildTestMixedGradient(TestShapeHalfBounds, baseEntity->GetId(), mixedEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, PosterizeGradientComponent_VerifyGetValueAndGetValuesMatch) { auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto entity = BuildTestPosterizeGradient(TestShapeHalfBounds, baseEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, ReferenceGradientComponent_VerifyGetValueAndGetValuesMatch) { auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto entity = BuildTestReferenceGradient(TestShapeHalfBounds, baseEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, SmoothStepGradientComponent_VerifyGetValueAndGetValuesMatch) { auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto entity = BuildTestSmoothStepGradient(TestShapeHalfBounds, baseEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, ThresholdGradientComponent_VerifyGetValueAndGetValuesMatch) { auto baseEntity = BuildTestRandomGradient(TestShapeHalfBounds); auto entity = BuildTestThresholdGradient(TestShapeHalfBounds, baseEntity->GetId()); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, SurfaceAltitudeGradientComponent_VerifyGetValueAndGetValuesMatch) { - auto mockSurfaceDataSystem = - CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds))); - auto entity = BuildTestSurfaceAltitudeGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, SurfaceMaskGradientComponent_VerifyGetValueAndGetValuesMatch) { - auto mockSurfaceDataSystem = - CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds))); - auto entity = BuildTestSurfaceMaskGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } TEST_F(GradientSignalGetValuesTestsFixture, SurfaceSlopeGradientComponent_VerifyGetValueAndGetValuesMatch) { - auto mockSurfaceDataSystem = - CreateMockSurfaceDataSystem(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-TestShapeHalfBounds), AZ::Vector3(TestShapeHalfBounds))); - auto entity = BuildTestSurfaceSlopeGradient(TestShapeHalfBounds); - GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), TestShapeHalfBounds); + GradientSignalTestHelpers::CompareGetValueAndGetValues(entity->GetId(), 0.0f, TestShapeHalfBounds * 2.0f); } } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp index 8ec190000d..c6656d589e 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -88,7 +89,7 @@ namespace UnitTest // Create the Image Gradient Component. GradientSignal::ImageGradientConfig config; - config.m_imageAsset = ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset( + config.m_imageAsset = UnitTest::CreateSpecificPixelImageAsset( test.m_imageSize, test.m_imageSize, static_cast(test.m_pixel.GetX()), static_cast(test.m_pixel.GetY())); config.m_tilingX = test.m_tiling; config.m_tilingY = test.m_tiling; @@ -379,7 +380,7 @@ namespace UnitTest // Create an ImageGradient with a 3x3 asset with the center pixel set. GradientSignal::ImageGradientConfig gradientConfig; - gradientConfig.m_imageAsset = ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset(3, 3, 1, 1); + gradientConfig.m_imageAsset = UnitTest::CreateSpecificPixelImageAsset(3, 3, 1, 1); entity->CreateComponent(gradientConfig); // Create the test GradientTransform diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp index 6f90c5022f..2e602e8c80 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp @@ -65,7 +65,11 @@ namespace UnitTest float slopeMin, float slopeMax, GradientSignal::SurfaceSlopeGradientConfig::RampType rampType, float falloffMidpoint, float falloffRange, float falloffStrength) { - MockSurfaceDataSystem mockSurfaceDataSystem; + auto surfaceEntity = CreateEntity(); + auto mockSurface = surfaceEntity->CreateComponent(); + mockSurface->m_bounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(aznumeric_cast(dataSize))); + mockSurface->m_tags.emplace_back("test_mask"); + AzFramework::SurfaceData::SurfacePoint point; // Fill our mock surface with the correct normal value for each point based on our test angle set. @@ -75,9 +79,10 @@ namespace UnitTest { float angle = AZ::DegToRad(inputAngles[(y * dataSize) + x]); point.m_normal = AZ::Vector3(sinf(angle), 0.0f, cosf(angle)); - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(static_cast(x), static_cast(y))] = { { point } }; + mockSurface->m_surfacePoints[AZStd::make_pair(static_cast(x), static_cast(y))] = { { point } }; } } + ActivateEntity(surfaceEntity.get()); GradientSignal::SurfaceSlopeGradientConfig config; config.m_slopeMin = slopeMin; @@ -538,11 +543,14 @@ namespace UnitTest mockShapeComponentHandler.m_GetEncompassingAabb = AZ::Aabb::CreateFromMinMax(AZ::Vector3::CreateZero(), AZ::Vector3(10.0f)); // Set a different altitude for each point we're going to test. We'll use 0, 2, 5, 10 to test various points along the range. - MockSurfaceDataSystem mockSurfaceDataSystem; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(0.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3::CreateZero() } }; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(1.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 2.0f), AZ::Vector3::CreateZero() } }; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(0.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 5.0f), AZ::Vector3::CreateZero() } }; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(1.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 10.0f), AZ::Vector3::CreateZero() } }; + auto surfaceEntity = CreateEntity(); + auto mockSurface = surfaceEntity->CreateComponent(); + mockSurface->m_bounds = mockShapeComponentHandler.m_GetEncompassingAabb; + mockSurface->m_surfacePoints[AZStd::make_pair(0.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(1.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 2.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(0.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 5.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(1.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 10.0f), AZ::Vector3::CreateZero() } }; + ActivateEntity(surfaceEntity.get()); // We set the min/max to values other than 0-10 to help validate that they aren't used in the case of the pinned shape. GradientSignal::SurfaceAltitudeGradientConfig config; @@ -572,11 +580,14 @@ namespace UnitTest auto entityShape = CreateEntity(); // Set a different altitude for each point we're going to test. We'll use 0, 2, 5, 10 to test various points along the range. - MockSurfaceDataSystem mockSurfaceDataSystem; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(0.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3::CreateZero() } }; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(1.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 2.0f), AZ::Vector3::CreateZero() } }; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(0.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 5.0f), AZ::Vector3::CreateZero() } }; - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(1.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 10.0f), AZ::Vector3::CreateZero() } }; + auto surfaceEntity = CreateEntity(); + auto mockSurface = surfaceEntity->CreateComponent(); + mockSurface->m_bounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(1.0f)); + mockSurface->m_surfacePoints[AZStd::make_pair(0.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(1.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, 2.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(0.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 5.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(1.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 10.0f), AZ::Vector3::CreateZero() } }; + ActivateEntity(surfaceEntity.get()); // We set the min/max to 0-10, but don't set a shape. GradientSignal::SurfaceAltitudeGradientConfig config; @@ -603,9 +614,6 @@ namespace UnitTest auto entityShape = CreateEntity(); - // Don't set any points. - MockSurfaceDataSystem mockSurfaceDataSystem; - // We set the min/max to -5 - 15 so that a height of 0 would produce a non-zero value. GradientSignal::SurfaceAltitudeGradientConfig config; config.m_altitudeMin = -5.0f; @@ -631,16 +639,18 @@ namespace UnitTest auto entityShape = CreateEntity(); - MockSurfaceDataSystem mockSurfaceDataSystem; - + auto surfaceEntity = CreateEntity(); + auto mockSurface = surfaceEntity->CreateComponent(); + mockSurface->m_bounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(1.0f)); // Altitude value below min - should result in 0.0f. - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(0.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, -10.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(0.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, -10.0f), AZ::Vector3::CreateZero() } }; // Altitude value at exactly min - should result in 0.0f. - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(1.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, -5.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(1.0f, 0.0f)] = { { AZ::Vector3(0.0f, 0.0f, -5.0f), AZ::Vector3::CreateZero() } }; // Altitude value at exactly max - should result in 1.0f. - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(0.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 15.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(0.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 15.0f), AZ::Vector3::CreateZero() } }; // Altitude value above max - should result in 1.0f. - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(1.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 20.0f), AZ::Vector3::CreateZero() } }; + mockSurface->m_surfacePoints[AZStd::make_pair(1.0f, 1.0f)] = { { AZ::Vector3(0.0f, 0.0f, 20.0f), AZ::Vector3::CreateZero() } }; + ActivateEntity(surfaceEntity.get()); // We set the min/max to -5 - 15. By using a range without 0 at either end, and not having 0 as the midpoint, // it should be easier to verify that we're successfully clamping to 0 and 1. @@ -667,7 +677,11 @@ namespace UnitTest 0.5f, 1.0f, }; - MockSurfaceDataSystem mockSurfaceDataSystem; + auto surfaceEntity = CreateEntity(); + auto mockSurface = surfaceEntity->CreateComponent(); + mockSurface->m_bounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(aznumeric_cast(dataSize))); + mockSurface->m_tags.emplace_back("test_mask"); + AzFramework::SurfaceData::SurfacePoint point; // Fill our mock surface with the test_mask set and the expected gradient value at each point. @@ -677,9 +691,10 @@ namespace UnitTest { point.m_surfaceTags.clear(); point.m_surfaceTags.emplace_back(AZ_CRC_CE("test_mask"), expectedOutput[(y * dataSize) + x]); - mockSurfaceDataSystem.m_GetSurfacePoints[AZStd::make_pair(static_cast(x), static_cast(y))] = { { point } }; + mockSurface->m_surfacePoints[AZStd::make_pair(static_cast(x), static_cast(y))] = { { point } }; } } + ActivateEntity(surfaceEntity.get()); GradientSignal::SurfaceMaskGradientConfig config; config.m_surfaceTagList.push_back(AZ_CRC("test_mask", 0x7a16e9ff)); @@ -706,8 +721,6 @@ namespace UnitTest 0.0f, 0.0f, }; - MockSurfaceDataSystem mockSurfaceDataSystem; - GradientSignal::SurfaceMaskGradientConfig config; config.m_surfaceTagList.push_back(AZ_CRC("test_mask", 0x7a16e9ff)); diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp index 9f4346e09e..4ab4c76d56 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp @@ -67,9 +67,6 @@ namespace UnitTest const AzFramework::SurfaceData::SurfacePoint& input, const AzFramework::SurfaceData::SurfacePoint& expectedOutput) { - // This lets our component register with surfaceData successfully. - MockSurfaceDataSystem mockSurfaceDataSystem; - // Create a mock shape entity in case our gradient test uses shape constraints. // The mock shape is a cube that goes from -0.5 to 0.5 in space. auto mockShapeEntity = CreateTestEntity(0.5f); @@ -105,7 +102,9 @@ namespace UnitTest ActivateEntity(entity.get()); // Get our registered modifier handle (and verify that it's valid) - auto modifierHandle = mockSurfaceDataSystem.GetSurfaceModifierHandle(entity->GetId()); + SurfaceData::SurfaceDataRegistryHandle modifierHandle = SurfaceData::InvalidSurfaceDataRegistryHandle; + SurfaceData::SurfaceDataSystemRequestBus::BroadcastResult( + modifierHandle, &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfaceDataModifierHandle, entity->GetId()); EXPECT_TRUE(modifierHandle != SurfaceData::InvalidSurfaceDataRegistryHandle); // Call ModifySurfacePoints and verify the results diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp index 402438ee88..8d5ada5214 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp @@ -8,11 +8,17 @@ #include +#include +#include +#include #include #include #include #include +#include +#include +#include // Base gradient components #include @@ -40,7 +46,7 @@ namespace UnitTest { void GradientSignalTestEnvironment::AddGemsAndComponents() { - AddDynamicModulePaths({ "LmbrCentral" }); + AddDynamicModulePaths({ "LmbrCentral", "SurfaceData" }); AddComponentDescriptors({ AzFramework::TransformComponent::CreateDescriptor(), @@ -65,52 +71,26 @@ namespace UnitTest GradientSignal::ThresholdGradientComponent::CreateDescriptor(), MockShapeComponent::CreateDescriptor(), + MockSurfaceProviderComponent::CreateDescriptor(), }); } void GradientSignalBaseFixture::SetupCoreSystems() { - m_mockHandler = new UnitTest::ImageAssetMockAssetHandler(); - AZ::Data::AssetManager::Instance().RegisterHandler(m_mockHandler, azrtti_typeid()); + // Using the AZ::RPI::MakeAssetHandler will both create the asset handlers, + // and register them with the AssetManager + m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler()); + m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler()); } void GradientSignalBaseFixture::TearDownCoreSystems() { - AZ::Data::AssetManager::Instance().UnregisterHandler(m_mockHandler); - delete m_mockHandler; // delete after removing from the asset manager + // This will delete the asset handlers, which will unregister themselves on deletion + m_assetHandlers.clear(); AzFramework::LegacyAssetEventBus::ClearQueuedEvents(); } - AZStd::unique_ptr GradientSignalBaseFixture::CreateMockSurfaceDataSystem(const AZ::Aabb& spawnerBox) - { - AzFramework::SurfaceData::SurfacePoint point; - AZStd::unique_ptr mockSurfaceDataSystem = AZStd::make_unique(); - - // Give the mock surface data a bunch of fake point values to return. - for (float y = spawnerBox.GetMin().GetY(); y < spawnerBox.GetMax().GetY(); y+= 1.0f) - { - for (float x = spawnerBox.GetMin().GetX(); x < spawnerBox.GetMax().GetX(); x += 1.0f) - { - // Use our x distance into the spawnerBox as an arbitrary percentage value that we'll use to calculate - // our other arbitrary values below. - float arbitraryPercentage = AZStd::abs(x / spawnerBox.GetExtents().GetX()); - - // Create a position that's between min and max Z of the box. - point.m_position = AZ::Vector3(x, y, AZ::Lerp(spawnerBox.GetMin().GetZ(), spawnerBox.GetMax().GetZ(), arbitraryPercentage)); - // Create an arbitrary normal value. - point.m_normal = point.m_position.GetNormalized(); - // Create an arbitrary surface value. - point.m_surfaceTags.clear(); - point.m_surfaceTags.emplace_back(AZ_CRC_CE("test_mask"), arbitraryPercentage); - - mockSurfaceDataSystem->m_GetSurfacePoints[AZStd::make_pair(x, y)] = { { point } }; - } - } - - return mockSurfaceDataSystem; - } - AZStd::unique_ptr GradientSignalBaseFixture::CreateTestEntity(float shapeHalfBounds) { // Create the base entity @@ -120,7 +100,7 @@ namespace UnitTest auto boxComponent = testEntity->CreateComponent(LmbrCentral::AxisAlignedBoxShapeComponentTypeId); boxComponent->SetConfiguration(boxConfig); - // Create a transform that locates our gradient in the center of our desired mock Shape. + // Create a transform that locates our gradient in the center of our desired Shape. auto transform = testEntity->CreateComponent(); transform->SetLocalTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds))); transform->SetWorldTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds))); @@ -128,6 +108,23 @@ namespace UnitTest return testEntity; } + AZStd::unique_ptr GradientSignalBaseFixture::CreateTestSphereEntity(float shapeRadius) + { + // Create the base entity + AZStd::unique_ptr testEntity = CreateEntity(); + + LmbrCentral::SphereShapeConfig sphereConfig(shapeRadius); + auto sphereComponent = testEntity->CreateComponent(LmbrCentral::SphereShapeComponentTypeId); + sphereComponent->SetConfiguration(sphereConfig); + + // Create a transform that locates our gradient in the center of our desired Shape. + auto transform = testEntity->CreateComponent(); + transform->SetLocalTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeRadius))); + transform->SetWorldTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeRadius))); + + return testEntity; + } + AZStd::unique_ptr GradientSignalBaseFixture::BuildTestConstantGradient(float shapeHalfBounds) { // Create a Constant Gradient Component with arbitrary parameters. @@ -147,7 +144,7 @@ namespace UnitTest GradientSignal::ImageGradientConfig config; const uint32_t imageSize = 4096; const int32_t imageSeed = 12345; - config.m_imageAsset = ImageAssetMockAssetHandler::CreateImageAsset(imageSize, imageSize, imageSeed); + config.m_imageAsset = UnitTest::CreateImageAsset(imageSize, imageSize, imageSeed); config.m_tilingX = 1.0f; config.m_tilingY = 1.0f; entity->CreateComponent(config); @@ -349,12 +346,18 @@ namespace UnitTest AZStd::unique_ptr GradientSignalBaseFixture::BuildTestSurfaceAltitudeGradient(float shapeHalfBounds) { // Create a Surface Altitude Gradient Component with arbitrary parameters. - auto entity = CreateTestEntity(shapeHalfBounds); + auto entity = CreateTestSphereEntity(shapeHalfBounds); GradientSignal::SurfaceAltitudeGradientConfig config; config.m_altitudeMin = -5.0f; - config.m_altitudeMax = 15.0f; + config.m_altitudeMax = 15.0f + (shapeHalfBounds * 2.0f); entity->CreateComponent(config); + // Create a SurfaceDataShape component to provide surface points from this component. + SurfaceData::SurfaceDataShapeConfig shapeConfig; + shapeConfig.m_providerTags.emplace_back("test_mask"); + auto surfaceShapeComponent = entity->CreateComponent(azrtti_typeid()); + surfaceShapeComponent->SetConfiguration(shapeConfig); + ActivateEntity(entity.get()); return entity; } @@ -362,11 +365,17 @@ namespace UnitTest AZStd::unique_ptr GradientSignalBaseFixture::BuildTestSurfaceMaskGradient(float shapeHalfBounds) { // Create a Surface Mask Gradient Component with arbitrary parameters. - auto entity = CreateTestEntity(shapeHalfBounds); + auto entity = CreateTestSphereEntity(shapeHalfBounds); GradientSignal::SurfaceMaskGradientConfig config; config.m_surfaceTagList.push_back(AZ_CRC_CE("test_mask")); entity->CreateComponent(config); + // Create a SurfaceDataShape component to provide surface points from this component. + SurfaceData::SurfaceDataShapeConfig shapeConfig; + shapeConfig.m_providerTags.emplace_back("test_mask"); + auto surfaceShapeComponent = entity->CreateComponent(azrtti_typeid()); + surfaceShapeComponent->SetConfiguration(shapeConfig); + ActivateEntity(entity.get()); return entity; } @@ -374,7 +383,7 @@ namespace UnitTest AZStd::unique_ptr GradientSignalBaseFixture::BuildTestSurfaceSlopeGradient(float shapeHalfBounds) { // Create a Surface Slope Gradient Component with arbitrary parameters. - auto entity = CreateTestEntity(shapeHalfBounds); + auto entity = CreateTestSphereEntity(shapeHalfBounds); GradientSignal::SurfaceSlopeGradientConfig config; config.m_slopeMin = 5.0f; config.m_slopeMax = 50.0f; @@ -384,6 +393,12 @@ namespace UnitTest config.m_smoothStep.m_falloffStrength = 0.25f; entity->CreateComponent(config); + // Create a SurfaceDataShape component to provide surface points from this component. + SurfaceData::SurfaceDataShapeConfig shapeConfig; + shapeConfig.m_providerTags.emplace_back("test_mask"); + auto surfaceShapeComponent = entity->CreateComponent(azrtti_typeid()); + surfaceShapeComponent->SetConfiguration(shapeConfig); + ActivateEntity(entity.get()); return entity; } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h index 5fda88ea27..c45af43ad9 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h @@ -9,6 +9,7 @@ #include #include +#include #include namespace UnitTest @@ -60,14 +61,14 @@ namespace UnitTest entity->Activate(); } - // Create a mock SurfaceDataSystem that will respond to requests for surface points with mock responses for points inside - // the given input box. - AZStd::unique_ptr CreateMockSurfaceDataSystem(const AZ::Aabb& spawnerBox); - - // Create an entity with a mock shape and a transform. It won't be activated yet though, because we expect a gradient component + // Create an entity with a box shape and a transform. It won't be activated yet though, because we expect a gradient component // to also get added to it first before activation. AZStd::unique_ptr CreateTestEntity(float shapeHalfBounds); + // Create an entity with a sphere shape and a transform. It won't be activated yet though, because we expect a gradient component + // to also get added to it first before activation. + AZStd::unique_ptr CreateTestSphereEntity(float shapeRadius); + // Create and activate an entity with a gradient component of the requested type, initialized with test data. AZStd::unique_ptr BuildTestConstantGradient(float shapeHalfBounds); AZStd::unique_ptr BuildTestImageGradient(float shapeHalfBounds); @@ -89,7 +90,7 @@ namespace UnitTest AZStd::unique_ptr BuildTestSurfaceMaskGradient(float shapeHalfBounds); AZStd::unique_ptr BuildTestSurfaceSlopeGradient(float shapeHalfBounds); - UnitTest::ImageAssetMockAssetHandler* m_mockHandler = nullptr; + AZ::RPI::AssetHandlerPtrList m_assetHandlers; }; struct GradientSignalTest diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.cpp index 46cc3475e8..d3c537ea1d 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.cpp @@ -8,16 +8,194 @@ #include +#include +#include #include #include namespace UnitTest { - void GradientSignalTestHelpers::CompareGetValueAndGetValues(AZ::EntityId gradientEntityId, float shapeHalfBounds) + AZ::RHI::ImageSubresourceLayout BuildSubImageLayout(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize) + { + AZ::RHI::ImageSubresourceLayout layout; + layout.m_size = AZ::RHI::Size{ width, height, 1 }; + layout.m_rowCount = width; + layout.m_bytesPerRow = width * pixelSize; + layout.m_bytesPerImage = width * height * pixelSize; + return layout; + } + + AZStd::vector BuildBasicImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed) + { + const size_t imageSize = width * height * pixelSize; + + AZStd::vector image; + image.reserve(imageSize); + + size_t value = 0; + AZStd::hash_combine(value, seed); + + for (AZ::u32 x = 0; x < width; ++x) + { + for (AZ::u32 y = 0; y < height; ++y) + { + AZStd::hash_combine(value, x); + AZStd::hash_combine(value, y); + image.push_back(static_cast(value)); + } + } + + EXPECT_EQ(image.size(), imageSize); + return image; + } + + AZ::Data::Asset BuildBasicMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed) + { + using namespace AZ; + + RPI::ImageMipChainAssetCreator assetCreator; + + assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()), mipLevels, arraySize); + + RHI::ImageSubresourceLayout layout = BuildSubImageLayout(width, height, pixelSize); + + assetCreator.BeginMip(layout); + + for (AZ::u32 arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex) + { + AZStd::vector data = BuildBasicImageData(width, height, pixelSize, seed); + assetCreator.AddSubImage(data.data(), data.size()); + } + + assetCreator.EndMip(); + + Data::Asset asset; + EXPECT_TRUE(assetCreator.End(asset)); + EXPECT_TRUE(asset.IsReady()); + EXPECT_NE(asset.Get(), nullptr); + + return asset; + } + + AZStd::vector BuildSpecificPixelImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY) + { + const size_t imageSize = width * height * pixelSize; + + AZStd::vector image; + image.reserve(imageSize); + + const AZ::u8 pixelValue = 255; + + // Image data should be stored inverted on the y axis relative to our engine, so loop backwards through y. + for (int y = static_cast(height) - 1; y >= 0; --y) + { + for (AZ::u32 x = 0; x < width; ++x) + { + if ((x == static_cast(pixelX)) && (y == static_cast(pixelY))) + { + image.push_back(pixelValue); + } + else + { + image.push_back(0); + } + } + } + + EXPECT_EQ(image.size(), imageSize); + return image; + } + + AZ::Data::Asset BuildSpecificPixelMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY) + { + using namespace AZ; + + RPI::ImageMipChainAssetCreator assetCreator; + + assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()), mipLevels, arraySize); + + RHI::ImageSubresourceLayout layout = BuildSubImageLayout(width, height, pixelSize); + + assetCreator.BeginMip(layout); + + for (AZ::u32 arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex) + { + AZStd::vector data = BuildSpecificPixelImageData(width, height, pixelSize, pixelX, pixelY); + assetCreator.AddSubImage(data.data(), data.size()); + } + + assetCreator.EndMip(); + + Data::Asset asset; + EXPECT_TRUE(assetCreator.End(asset)); + EXPECT_TRUE(asset.IsReady()); + EXPECT_NE(asset.Get(), nullptr); + + return asset; + } + + AZ::Data::Asset CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed) + { + auto randomAssetId = AZ::Data::AssetId(AZ::Uuid::CreateRandom()); + auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset( + randomAssetId, AZ::Data::AssetLoadBehavior::Default); + + const AZ::u32 arraySize = 1; + const AZ::u32 mipCountTotal = 1; + const auto format = AZ::RHI::Format::R8_UNORM; + const AZ::u32 pixelSize = AZ::RHI::GetFormatComponentCount(format); + + AZ::Data::Asset mipChain = BuildBasicMipChainAsset(mipCountTotal, arraySize, width, height, pixelSize, seed); + + AZ::RPI::StreamingImageAssetCreator assetCreator; + assetCreator.Begin(randomAssetId); + + AZ::RHI::ImageDescriptor imageDesc = AZ::RHI::ImageDescriptor::Create2DArray(AZ::RHI::ImageBindFlags::ShaderRead, width, height, arraySize, format); + imageDesc.m_mipLevels = static_cast(mipCountTotal); + + assetCreator.SetImageDescriptor(imageDesc); + assetCreator.AddMipChainAsset(*mipChain.Get()); + + EXPECT_TRUE(assetCreator.End(imageAsset)); + EXPECT_TRUE(imageAsset.IsReady()); + EXPECT_NE(imageAsset.Get(), nullptr); + + return imageAsset; + } + + AZ::Data::Asset CreateSpecificPixelImageAsset(AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY) + { + auto randomAssetId = AZ::Data::AssetId(AZ::Uuid::CreateRandom()); + auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset( + randomAssetId, AZ::Data::AssetLoadBehavior::Default); + + const AZ::u32 arraySize = 1; + const AZ::u32 mipCountTotal = 1; + const auto format = AZ::RHI::Format::R8_UNORM; + const AZ::u32 pixelSize = AZ::RHI::GetFormatComponentCount(format); + + AZ::Data::Asset mipChain = BuildSpecificPixelMipChainAsset(mipCountTotal, arraySize, width, height, pixelSize, pixelX, pixelY); + + AZ::RPI::StreamingImageAssetCreator assetCreator; + assetCreator.Begin(randomAssetId); + + AZ::RHI::ImageDescriptor imageDesc = AZ::RHI::ImageDescriptor::Create2DArray(AZ::RHI::ImageBindFlags::ShaderRead, width, height, arraySize, format); + imageDesc.m_mipLevels = static_cast(mipCountTotal); + + assetCreator.SetImageDescriptor(imageDesc); + assetCreator.AddMipChainAsset(*mipChain.Get()); + + EXPECT_TRUE(assetCreator.End(imageAsset)); + EXPECT_TRUE(imageAsset.IsReady()); + EXPECT_NE(imageAsset.Get(), nullptr); + return imageAsset; + } + + void GradientSignalTestHelpers::CompareGetValueAndGetValues(AZ::EntityId gradientEntityId, float queryMin, float queryMax) { // Create a gradient sampler and run through a series of points to see if they match expectations. - const AZ::Aabb queryRegion = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-shapeHalfBounds), AZ::Vector3(shapeHalfBounds)); + const AZ::Aabb queryRegion = AZ::Aabb::CreateFromMinMax(AZ::Vector3(queryMin), AZ::Vector3(queryMax)); const AZ::Vector2 stepSize(1.0f, 1.0f); GradientSignal::GradientSampler gradientSampler; @@ -118,6 +296,7 @@ namespace UnitTest AZStd::vector results(totalQueryPoints); GradientSignal::GradientRequestBus::Event( gradientId, &GradientSignal::GradientRequestBus::Events::GetValues, positions, results); + benchmark::DoNotOptimize(results); } } @@ -174,6 +353,7 @@ namespace UnitTest // Query and get the results. AZStd::vector results(totalQueryPoints); gradientSampler.GetValues(positions, results); + benchmark::DoNotOptimize(results); } } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.h index 8a175939ee..8f20bb4732 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestHelpers.h @@ -12,12 +12,76 @@ #include #include +#include +#include +#include + namespace UnitTest { + //! Helper method to build a AZ::RHI::ImageSubresourceLayout + //! @param width The width of the image + //! @param height The height of the image + //! @param pixelSize Number of bytes per pixel + //! @return The AZ::RHI::ImageSubresourceLayout that has been filled out appropriately + AZ::RHI::ImageSubresourceLayout BuildSubImageLayout(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize); + + //! Build a deterministic random set of image pixel data + //! @param width Width of the image + //! @param height Height of the image + //! @param pixelSize Number of bytes per pixel + //! @param seed The random seed for generating the data + //! @return A vector of bytes for the image data + AZStd::vector BuildBasicImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed); + + //! Build a mip chain asset that contains the basic image data from BuildBasicImageData + //! @param mipLevels Number of mip levels in the chain + //! @param arraySize Number of sub images within a mip level + //! @param width The width of the image + //! @param height The height of the image + //! @param pixelSize The number of bytes per pixel + //! @param seed The random seed for generating the data + //! @return A mip chain asset with the specified basic image data + AZ::Data::Asset BuildBasicMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed); + + //! Construct an array of image data where all the pixels are 0 except for one at the given coordinate + //! @param width Width of the image + //! @param height Height of the image + //! @param pixelSize Number of bytes per pixel + //! @param pixelX The X coordinate of the pixel to set to 1 + //! @param pixelY The Y coordinate of the pixel to set to 1 + //! @return A vector of bytes for the image data + AZStd::vector BuildSpecificPixelImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY); + + //! Build a mip chain asset that contains the specific image data from BuildSpecificPixelImageData + //! @param mipLevels Number of mip levels in the chain + //! @param arraySize Number of sub images within a mip level + //! @param width The width of the image + //! @param height The height of the image + //! @param pixelSize The number of bytes per pixel + //! @param pixelX The X coordinate of the pixel to set to 1 + //! @param pixelY The Y coordinate of the pixel to set to 1 + //! @return A mip chain asset with the specific pixel image data + AZ::Data::Asset BuildSpecificPixelMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY); + + //! Creates a deterministically random set of pixel data as an AZ::RPI::StreamingImageAsset. + //! \param width The width of the AZ::RPI::StreamingImageAsset + //! \param height The height of the AZ::RPI::StreamingImageAsset + //! \param seed The random seed to use for generating the random data + //! \return The AZ::RPI::StreamingImageAsset in a loaded ready state + AZ::Data::Asset CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed); + + //! Creates an AZ::RPI::StreamingImageAsset where all the pixels are 0 except for the one pixel at the given coordinates, which is set to 1. + //! \param width The width of the AZ::RPI::StreamingImageAsset + //! \param height The height of the AZ::RPI::StreamingImageAsset + //! \param pixelX The X coordinate of the pixel to set to 1 + //! \param pixelY The Y coordinate of the pixel to set to 1 + //! \return The AZ::RPI::StreamingImageAsset in a loaded ready state + AZ::Data::Asset CreateSpecificPixelImageAsset(AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY); + class GradientSignalTestHelpers { public: - static void CompareGetValueAndGetValues(AZ::EntityId gradientEntityId, float shapeHalfBounds); + static void CompareGetValueAndGetValues(AZ::EntityId gradientEntityId, float queryMin, float queryMax); #ifdef HAVE_BENCHMARK // We use an enum to list out the different types of GetValue() benchmarks to run so that way we can condense our test cases diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.cpp deleted file mode 100644 index 7ac6ef1ecc..0000000000 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include - -namespace UnitTest -{ - AZ::Data::Asset ImageAssetMockAssetHandler::CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed) - { - auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset( - AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetLoadBehavior::Default); - - imageAsset->m_imageWidth = width; - imageAsset->m_imageHeight = height; - imageAsset->m_bytesPerPixel = 1; - imageAsset->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8; - imageAsset->m_imageData.reserve(width * height); - - size_t value = 0; - AZStd::hash_combine(value, seed); - - for (AZ::u32 x = 0; x < width; ++x) - { - for (AZ::u32 y = 0; y < height; ++y) - { - AZStd::hash_combine(value, x); - AZStd::hash_combine(value, y); - imageAsset->m_imageData.push_back(static_cast(value)); - } - } - - return imageAsset; - } - - AZ::Data::Asset ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset( - AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY) - { - auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset( - AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetLoadBehavior::Default); - - imageAsset->m_imageWidth = width; - imageAsset->m_imageHeight = height; - imageAsset->m_bytesPerPixel = 1; - imageAsset->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8; - imageAsset->m_imageData.reserve(width * height); - - const AZ::u8 pixelValue = 255; - - // Image data should be stored inverted on the y axis relative to our engine, so loop backwards through y. - for (int y = static_cast(height) - 1; y >= 0; --y) - { - for (AZ::u32 x = 0; x < width; ++x) - { - if ((x == static_cast(pixelX)) && (y == static_cast(pixelY))) - { - imageAsset->m_imageData.push_back(pixelValue); - } - else - { - imageAsset->m_imageData.push_back(0); - } - } - } - - return imageAsset; - } -} - diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h index 30f262d9b4..c8e69e0d51 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h @@ -22,58 +22,12 @@ #include #include #include +#include #include #include namespace UnitTest { - // Mock asset handler for GradientSignal::ImageAsset that we can use in unit tests to pretend to load an image asset with. - // Also includes utility functions for creating image assets with specific testable patterns. - struct ImageAssetMockAssetHandler : public AZ::Data::AssetHandler - { - //! Creates a deterministically random set of pixel data as an ImageAsset. - //! \param width The width of the ImageAsset - //! \param height The height of the ImageAsset - //! \param seed The random seed to use for generating the random data - //! \return The ImageAsset in a loaded ready state - static AZ::Data::Asset CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed); - - //! Creates an ImageAsset where all the pixels are 0 except for the one pixel at the given coordinates, which is set to 1. - //! \param width The width of the ImageAsset - //! \param height The height of the ImageAsset - //! \param pixelX The X coordinate of the pixel to set to 1 - //! \param pixelY The Y coordinate of the pixel to set to 1 - //! \return The ImageAsset in a loaded ready state - static AZ::Data::Asset CreateSpecificPixelImageAsset( - AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY); - - AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override - { - // For our mock handler, always mark our assets as immediately ready. - return aznew GradientSignal::ImageAsset(id, AZ::Data::AssetData::AssetStatus::Ready); - } - - void DestroyAsset(AZ::Data::AssetPtr ptr) override - { - if (ptr) - { - delete ptr; - } - } - - void GetHandledAssetTypes([[maybe_unused]] AZStd::vector& assetTypes) override - { - } - - AZ::Data::AssetHandler::LoadResult LoadAssetData( - [[maybe_unused]] const AZ::Data::Asset& asset, - [[maybe_unused]] AZStd::shared_ptr stream, - [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) override - { - return AZ::Data::AssetHandler::LoadResult::LoadComplete; - } - }; - struct MockGradientRequestsBus : public GradientSignal::GradientRequestBus::Handler { @@ -162,4 +116,64 @@ namespace UnitTest bool m_constrainToShape; }; + // Mock out a SurfaceProvider component so that we can control exactly what surface weights get returned + // at which points for our unit tests. + struct MockSurfaceProviderComponent + : public AZ::Component + , public SurfaceData::SurfaceDataProviderRequestBus::Handler + { + public: + AZ_COMPONENT(MockSurfaceProviderComponent, "{18C71877-DB29-4CEC-B34C-B4B44E05203D}", AZ::Component); + + void Activate() override + { + SurfaceData::SurfaceDataRegistryEntry providerRegistryEntry; + providerRegistryEntry.m_entityId = GetEntityId(); + providerRegistryEntry.m_bounds = m_bounds; + providerRegistryEntry.m_tags = m_tags; + + SurfaceData::SurfaceDataSystemRequestBus::BroadcastResult( + m_providerHandle, &SurfaceData::SurfaceDataSystemRequestBus::Events::RegisterSurfaceDataProvider, providerRegistryEntry); + SurfaceData::SurfaceDataProviderRequestBus::Handler::BusConnect(m_providerHandle); + } + + void Deactivate() override + { + SurfaceData::SurfaceDataSystemRequestBus::Broadcast( + &SurfaceData::SurfaceDataSystemRequestBus::Events::UnregisterSurfaceDataProvider, m_providerHandle); + m_providerHandle = SurfaceData::InvalidSurfaceDataRegistryHandle; + SurfaceData::SurfaceDataProviderRequestBus::Handler::BusDisconnect(); + } + + static void Reflect([[maybe_unused]] AZ::ReflectContext* reflect) + { + } + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("SurfaceDataProviderService")); + } + + void GetSurfacePoints(const AZ::Vector3& inPosition, SurfaceData::SurfacePointList& surfacePointList) const override + { + auto surfacePoints = m_surfacePoints.find(AZStd::make_pair(inPosition.GetX(), inPosition.GetY())); + + if (surfacePoints != m_surfacePoints.end()) + { + surfacePointList = surfacePoints->second; + } + } + + // m_surfacePoints is a mapping of locations to surface tags / weights that should be returned. + AZStd::unordered_map, SurfaceData::SurfacePointList> m_surfacePoints; + + // m_bounds is the AABB to use for our mock surface provider. + AZ::Aabb m_bounds; + + // m_tags are the possible set of tags that this provider will return. + SurfaceData::SurfaceTagVector m_tags; + + SurfaceData::SurfaceDataRegistryHandle m_providerHandle = SurfaceData::InvalidSurfaceDataRegistryHandle; + }; + } diff --git a/Gems/GradientSignal/Code/gradientsignal_shared_tests_files.cmake b/Gems/GradientSignal/Code/gradientsignal_shared_tests_files.cmake index 98ab57b7b0..5e11406bae 100644 --- a/Gems/GradientSignal/Code/gradientsignal_shared_tests_files.cmake +++ b/Gems/GradientSignal/Code/gradientsignal_shared_tests_files.cmake @@ -11,6 +11,5 @@ set(FILES Tests/GradientSignalTestHelpers.h Tests/GradientSignalTestFixtures.cpp Tests/GradientSignalTestFixtures.h - Tests/GradientSignalTestMocks.cpp Tests/GradientSignalTestMocks.h ) diff --git a/Gems/GraphCanvas/Code/Source/Components/SceneComponent.cpp b/Gems/GraphCanvas/Code/Source/Components/SceneComponent.cpp index e821ea9be2..425334293a 100644 --- a/Gems/GraphCanvas/Code/Source/Components/SceneComponent.cpp +++ b/Gems/GraphCanvas/Code/Source/Components/SceneComponent.cpp @@ -1285,39 +1285,40 @@ namespace GraphCanvas void SceneComponent::ReadSaveData(const EntitySaveDataContainer& saveDataContainer) { GRAPH_CANVAS_PROFILE_FUNCTION(); - const SceneComponentSaveData* saveData = saveDataContainer.FindSaveDataAs(); - - for (const GraphCanvasConstructSaveData* currentConstruct : saveData->m_constructs) + if (const SceneComponentSaveData* saveData = saveDataContainer.FindSaveDataAs()) { - AZ::Entity* constructEntity = nullptr; - switch (currentConstruct->m_constructType) + for (const GraphCanvasConstructSaveData* currentConstruct : saveData->m_constructs) { - case ConstructType::CommentNode: - GraphCanvasRequestBus::BroadcastResult(constructEntity, &GraphCanvasRequests::CreateCommentNode); - break; - case ConstructType::NodeGroup: - GraphCanvasRequestBus::BroadcastResult(constructEntity, &GraphCanvasRequests::CreateNodeGroup); - break; - case ConstructType::BookmarkAnchor: - GraphCanvasRequestBus::BroadcastResult(constructEntity, &GraphCanvasRequests::CreateBookmarkAnchor); - break; - default: - break; + AZ::Entity* constructEntity = nullptr; + switch (currentConstruct->m_constructType) + { + case ConstructType::CommentNode: + GraphCanvasRequestBus::BroadcastResult(constructEntity, &GraphCanvasRequests::CreateCommentNode); + break; + case ConstructType::NodeGroup: + GraphCanvasRequestBus::BroadcastResult(constructEntity, &GraphCanvasRequests::CreateNodeGroup); + break; + case ConstructType::BookmarkAnchor: + GraphCanvasRequestBus::BroadcastResult(constructEntity, &GraphCanvasRequests::CreateBookmarkAnchor); + break; + default: + break; + } + + if (constructEntity) + { + constructEntity->Init(); + constructEntity->Activate(); + + EntitySaveDataRequestBus::Event(constructEntity->GetId(), &EntitySaveDataRequests::ReadSaveData, currentConstruct->m_saveDataContainer); + + Add(constructEntity->GetId()); + } } - if (constructEntity) - { - constructEntity->Init(); - constructEntity->Activate(); - - EntitySaveDataRequestBus::Event(constructEntity->GetId(), &EntitySaveDataRequests::ReadSaveData, currentConstruct->m_saveDataContainer); - - Add(constructEntity->GetId()); - } + m_viewParams = saveData->m_viewParams; + m_bookmarkCounter = saveData->m_bookmarkCounter; } - - m_viewParams = saveData->m_viewParams; - m_bookmarkCounter = saveData->m_bookmarkCounter; } AZStd::any* SceneComponent::GetUserData() diff --git a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp index 0ef02837da..89e2968639 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp @@ -26,7 +26,7 @@ void LuaBuilder::BuilderPluginComponent::Activate() AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Lua Worker Builder"; builderDescriptor.m_version = 7; - builderDescriptor.m_analysisFingerprint = AZStd::string::format("%d", static_cast(AZ::ScriptAsset::AssetVersion)); + builderDescriptor.m_analysisFingerprint = AZStd::string::format("%s-%d", LuaBuilderWorker::GetAnalysisFingerprint().c_str(), static_cast(AZ::ScriptAsset::AssetVersion)); builderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.lua", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); builderDescriptor.m_createJobFunction = AZStd::bind(&LuaBuilderWorker::CreateJobs, &m_luaBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); diff --git a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.cpp b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.cpp index b3ba419321..69ba5e0ea1 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.cpp @@ -14,13 +14,13 @@ #include #include #include -#include #include #include #include #include +#include // for lua_tostring namespace LuaBuilder { @@ -36,8 +36,15 @@ namespace LuaBuilder static const AZ::u32 s_BuildTypeKey = AZ_CRC("BuildType", 0xd01cbdd7); static const char* s_BuildTypeCompiled = "Compiled"; - static const char* s_BuildTypeText = "Text"; } + static const char* s_BuildTypeText = "Text"; + } + AZStd::string LuaBuilderWorker::GetAnalysisFingerprint() + { + // mutating the Analysis Fingerprint will cause the CreateJobs function to run even + // on files which have not changed. + return AZ::ScriptDataContext::GetInterpreterVersion(); + } ////////////////////////////////////////////////////////////////////////// // CreateJobs void LuaBuilderWorker::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) @@ -57,6 +64,11 @@ namespace LuaBuilder descriptor.m_jobKey = "Lua Compile"; descriptor.SetPlatformIdentifier(info.m_identifier.c_str()); descriptor.m_critical = true; + // mutating the AdditionalFingerprintInfo will cause the job to run even if + // nothing else has changed (ie, files are the same, version of this builder didnt change) + // by doing this, changing the version of the interpreter is enough to cause the files to rebuild + // automatically. + descriptor.m_additionalFingerprintInfo = GetAnalysisFingerprint(); descriptor.m_jobParameters[s_BuildTypeKey] = info.HasTag("android") ? s_BuildTypeText : s_BuildTypeCompiled; response.m_createJobOutputs.push_back(descriptor); } diff --git a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.h b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.h index 6f2aeecb8f..3371329846 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.h +++ b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderWorker.h @@ -34,6 +34,8 @@ namespace LuaBuilder void ShutDown() override; ////////////////////////////////////////////////////////////////////////// + static AZStd::string GetAnalysisFingerprint(); + void ParseDependencies(const AZStd::string& file, AssetBuilderSDK::ProductPathDependencySet& outDependencies); private: diff --git a/Gems/LyShine/Code/Editor/HierarchyMenu.cpp b/Gems/LyShine/Code/Editor/HierarchyMenu.cpp index 004fe53354..4fb09ea1f8 100644 --- a/Gems/LyShine/Code/Editor/HierarchyMenu.cpp +++ b/Gems/LyShine/Code/Editor/HierarchyMenu.cpp @@ -387,7 +387,9 @@ void HierarchyMenu::New_ElementFromSlice(HierarchyWidget* hierarchy, AZ::Vector2 viewportPosition(-1.0f,-1.0f); // indicates no viewport position specified if (optionalPos) { - viewportPosition = QtHelpers::QPointFToVector2(*optionalPos); + // Convert position to render viewport coords + QPointF scaledPosition = *optionalPos * hierarchy->GetEditorWindow()->GetViewport()->WidgetToViewportFactor(); + viewportPosition = QtHelpers::QPointFToVector2(scaledPosition); } SliceMenuHelpers::CreateInstantiateSliceMenu(hierarchy, @@ -405,7 +407,9 @@ void HierarchyMenu::New_ElementFromSlice(HierarchyWidget* hierarchy, AZ::Vector2 viewportPosition(-1.0f,-1.0f); // indicates no viewport position specified if (optionalPos) { - viewportPosition = QtHelpers::QPointFToVector2(*optionalPos); + // Convert position to render viewport coords + QPointF scaledPosition = *optionalPos * hierarchy->GetEditorWindow()->GetViewport()->WidgetToViewportFactor(); + viewportPosition = QtHelpers::QPointFToVector2(scaledPosition); } hierarchy->GetEditorWindow()->GetSliceManager()->InstantiateSliceUsingBrowser(hierarchy, viewportPosition); } diff --git a/Gems/LyShine/Code/Editor/HierarchyWidget.cpp b/Gems/LyShine/Code/Editor/HierarchyWidget.cpp index 30cb7e51dc..cd80e5a278 100644 --- a/Gems/LyShine/Code/Editor/HierarchyWidget.cpp +++ b/Gems/LyShine/Code/Editor/HierarchyWidget.cpp @@ -1239,11 +1239,13 @@ void HierarchyWidget::AddElement(const QTreeWidgetItemRawPtrQList& selectedItems this, selectedItems, childIndex, - [optionalPos](AZ::Entity* element) + [this, optionalPos](AZ::Entity* element) { if (optionalPos) { - EntityHelpers::MoveElementToGlobalPosition(element, *optionalPos); + // Convert position to render viewport coords + QPoint scaledPosition = *optionalPos * GetEditorWindow()->GetViewport()->WidgetToViewportFactor(); + EntityHelpers::MoveElementToGlobalPosition(element, scaledPosition); } }); } diff --git a/Gems/MotionMatching/Code/CMakeLists.txt b/Gems/MotionMatching/Code/CMakeLists.txt index ae613f5d7f..22d2f28f3b 100644 --- a/Gems/MotionMatching/Code/CMakeLists.txt +++ b/Gems/MotionMatching/Code/CMakeLists.txt @@ -121,27 +121,27 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googletest( NAME Gem::MotionMatching.Tests ) -endif() -# If we are a host platform we want to add tools test like editor tests here -if(PAL_TRAIT_BUILD_HOST_TOOLS) - ly_add_target( - NAME MotionMatching.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} - NAMESPACE Gem - FILES_CMAKE - motionmatching_editor_tests_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - Tests - Source - BUILD_DEPENDENCIES - PRIVATE - AZ::AzTest - Gem::MotionMatching.Editor - ) + # If we are a host platform we want to add tools test like editor tests here + if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_target( + NAME MotionMatching.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + motionmatching_editor_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Tests + Source + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + Gem::MotionMatching.Editor + ) - # Add MotionMatching.Editor.Tests to googletest - ly_add_googletest( - NAME Gem::MotionMatching.Editor.Tests - ) + # Add MotionMatching.Editor.Tests to googletest + ly_add_googletest( + NAME Gem::MotionMatching.Editor.Tests + ) + endif() endif() diff --git a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp index 751c04952c..aac758b96e 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp @@ -153,7 +153,7 @@ namespace AZ::SceneAPI::Behaviors // all mesh data nodes left in the meshIndexContainer do not have a matching TransformData node // since the nodes have an identity transform, so map the MeshData index with an Invalid mesh index to // indicate the transform should not be set to a default value - for( const auto meshIndex : meshIndexContainer) + for( const auto& meshIndex : meshIndexContainer) { MeshTransformPair pair{ meshIndex, Containers::SceneGraph::NodeIndex{} }; meshTransformMap.emplace(MeshTransformEntry{ graph.GetNodeParent(meshIndex), AZStd::move(pair) }); diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index 3127a99ef6..7024a01570 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -3543,11 +3543,9 @@ namespace ScriptCanvasEditor GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::SignalLoadStart); - auto saveDataIter = m_graphCanvasSaveData.find(GetEntityId()); - - if (saveDataIter != m_graphCanvasSaveData.end()) + for (auto& saveDataIter : m_graphCanvasSaveData) { - GraphCanvas::EntitySaveDataRequestBus::Event(graphCanvasGraphId, &GraphCanvas::EntitySaveDataRequests::ReadSaveData, (*saveDataIter->second)); + GraphCanvas::EntitySaveDataRequestBus::Event(graphCanvasGraphId, &GraphCanvas::EntitySaveDataRequests::ReadSaveData, (*saveDataIter.second)); } ScriptCanvas::NodeIdList nodeList = GetNodes(); diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp index 596c2d9dbf..069b7a5f48 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ - + #include #include #include @@ -17,7 +17,7 @@ namespace AZ JsonSerializationResult::Result EditorScriptCanvasComponentSerializer::Load ( void* outputValue - , const Uuid& outputValueTypeId + , [[maybe_unused]] const Uuid& outputValueTypeId , const rapidjson::Value& inputValue , JsonDeserializerContext& context) { @@ -32,9 +32,7 @@ namespace AZ JsonSerializationResult::ResultCode result = BaseJsonSerializer::Load(outputValue , azrtti_typeid(), inputValue, context); - // load child data one by one... - result.Combine(BaseJsonSerializer::Load(outputValue, outputValueTypeId, inputValue, context)); - + // load child data one by one if (result.GetProcessing() != JSR::Processing::Halted) { result.Combine(ContinueLoadingFromJsonObjectField diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h index f8b4ca7264..4cafd97237 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h @@ -1098,7 +1098,7 @@ protected: slotConfiguration.SetType(Data::FromAZType>()); slotConfiguration.SetConnectionType(ConnectionType::Output); - node.AddSlot(slotConfiguration); + AZ_VerifyError("ScriptCanvas", node.AddSlot(slotConfiguration).IsValid(), "Node failed to add a required Data Out slot"); } }; @@ -1115,12 +1115,11 @@ protected: static void CreateDataSlot(Node& node, ConnectionType connectionType) { DataSlotConfiguration slotConfiguration; - slotConfiguration.m_name = t_Traits::GetResultName(Index); slotConfiguration.SetType(Data::FromAZType>>()); - slotConfiguration.SetConnectionType(connectionType); - node.AddSlot(slotConfiguration); + + AZ_VerifyError("ScriptCanvas", node.AddSlot(slotConfiguration).IsValid(), "Node failed to add a required Data Out slot"); } template diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h index 549c56d07d..102b255cda 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h @@ -82,15 +82,30 @@ namespace ScriptCanvas static const size_t s_numNames = SCRIPT_CANVAS_FUNCTION_VAR_ARGS(__VA_ARGS__);\ /*static const size_t s_numResults = ScriptCanvas::Internal::extended_tuple_size::value;*/\ \ - static const char* GetArgName(size_t i)\ + static AZStd::string GetArgName(size_t i)\ {\ - return GetName(i).data();\ + AZStd::string_view argName = GetName(i);\ + if (!argName.empty())\ + {\ + return argName;\ + }\ + else\ + {\ + return AZStd::string::format("Input [%zu]", i);\ + }\ }\ \ - static const char* GetResultName(size_t i)\ + static AZStd::string GetResultName(size_t i)\ {\ - AZStd::string_view result = GetName(i + s_numArgs);\ - return !result.empty() ? result.data() : "Result";\ + AZStd::string_view resultName = GetName(i + s_numArgs);\ + if (!resultName.empty())\ + {\ + return resultName;\ + }\ + else\ + {\ + return AZStd::string::format("Result [%zu]", i);\ + }\ }\ \ static const char* GetDependency() { return CATEGORY; }\ @@ -260,7 +275,7 @@ namespace ScriptCanvas slotConfiguration.ConfigureDatum(AZStd::move(Datum(Data::FromAZType(Data::Traits::GetAZType()), Datum::eOriginality::Copy))); slotConfiguration.SetConnectionType(connectionType); - AddSlot(slotConfiguration); + AZ_VerifyError("ScriptCanvas", AddSlot(slotConfiguration).IsValid(), "NodeFunctionGenericMultiReturn failed to add a required data slot"); } template @@ -278,12 +293,12 @@ namespace ScriptCanvas { { ExecutionSlotConfiguration slotConfiguration("In", ConnectionType::Input); - AddSlot(slotConfiguration); + AZ_VerifyError("ScriptCanvas", AddSlot(slotConfiguration).IsValid(), "NodeFunctionGenericMultiReturn failed to add a required Execution In slot"); } { ExecutionSlotConfiguration slotConfiguration("Out", ConnectionType::Output); - AddSlot(slotConfiguration); + AZ_VerifyError("ScriptCanvas", AddSlot(slotConfiguration).IsValid(), "NodeFunctionGenericMultiReturn failed to add a required Execution Out slot"); } AddInputDatumSlotHelper(typename AZStd::function_traits::arg_sequence{}, AZStd::make_index_sequence::arity>{}); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h index 9a389404a2..760610b10e 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h @@ -257,7 +257,7 @@ namespace ScriptCanvas r.SetLength(static_cast(optionalScale)); return std::make_tuple(r, length); } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{49A2D7F6-6CD3-420E-8A79-D46B00DB6CED}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{49A2D7F6-6CD3-420E-8A79-D46B00DB6CED}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale", "Direction", "Length"); using Registrar = RegistrarGeneric < AbsoluteNode diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h index f5e09ef78f..30e6643d44 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h @@ -343,8 +343,17 @@ namespace ScriptCanvas r.SetLength(static_cast(optionalScale)); return std::make_tuple(r, length); } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{28FBD529-4C9A-4E34-B8A0-A13B5DB3C331}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS + ( DirectionTo + , DirectionToDefaults + , k_categoryName, "{28FBD529-4C9A-4E34-B8A0-A13B5DB3C331}" + , "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0" + , "From" + , "To" + , "Scale" + , "Direction" + , "Length"); using Registrar = RegistrarGeneric < AbsoluteNode diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h index 30e1b691bf..39e9718824 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h @@ -228,7 +228,7 @@ namespace ScriptCanvas r.SetLength(static_cast(optionalScale)); return std::make_tuple(r, length); } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{463762DE-E541-4AFE-80C2-FED1C5273319}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{463762DE-E541-4AFE-80C2-FED1C5273319}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale", "Direction", "Length"); using Registrar = RegistrarGeneric < AbsoluteNode, diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp index f0eae04383..08bd3883ca 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLuaUtility.cpp @@ -8,6 +8,8 @@ #include "GraphToLuaUtility.h" +#include + #include #include #include @@ -23,6 +25,23 @@ namespace GraphToLuaUtilityCpp { + class ScopedLocale + { + public: + ScopedLocale() + { + m_previousLocale = std::setlocale(LC_NUMERIC, "en_US.UTF-8"); + } + + ~ScopedLocale() + { + std::setlocale(LC_NUMERIC, m_previousLocale); + } + + private: + char* m_previousLocale = nullptr; + }; + AZStd::string EqualSigns(size_t numEqualSignsRequired) { AZStd::string equalSigns = ""; @@ -183,6 +202,8 @@ namespace ScriptCanvas AZStd::string ToValueString(const Datum& datum, const Configuration& config) { + GraphToLuaUtilityCpp::ScopedLocale scopedLocal; + switch (datum.GetType().GetType()) { case Data::eType::AABB: diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.h b/Gems/SurfaceData/Code/Include/SurfaceData/Components/SurfaceDataColliderComponent.h similarity index 100% rename from Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.h rename to Gems/SurfaceData/Code/Include/SurfaceData/Components/SurfaceDataColliderComponent.h diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h b/Gems/SurfaceData/Code/Include/SurfaceData/Components/SurfaceDataShapeComponent.h similarity index 100% rename from Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h rename to Gems/SurfaceData/Code/Include/SurfaceData/Components/SurfaceDataShapeComponent.h diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h b/Gems/SurfaceData/Code/Include/SurfaceData/Components/SurfaceDataSystemComponent.h similarity index 95% rename from Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h rename to Gems/SurfaceData/Code/Include/SurfaceData/Components/SurfaceDataSystemComponent.h index bb554cec78..3e1291e524 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/Components/SurfaceDataSystemComponent.h @@ -57,6 +57,10 @@ namespace SurfaceData void UpdateSurfaceDataModifier(const SurfaceDataRegistryHandle& handle, const SurfaceDataRegistryEntry& entry) override; void RefreshSurfaceData(const AZ::Aabb& dirtyArea) override; + + SurfaceDataRegistryHandle GetSurfaceDataProviderHandle(const AZ::EntityId& providerEntityId) override; + SurfaceDataRegistryHandle GetSurfaceDataModifierHandle(const AZ::EntityId& modifierEntityId) override; + private: SurfaceDataRegistryHandle RegisterSurfaceDataProviderInternal(const SurfaceDataRegistryEntry& entry); SurfaceDataRegistryEntry UnregisterSurfaceDataProviderInternal(const SurfaceDataRegistryHandle& handle); diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h index 616f069184..d4e84c5974 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h @@ -58,6 +58,10 @@ namespace SurfaceData // Notify any dependent systems that they need to refresh their surface data for the provided area. virtual void RefreshSurfaceData(const AZ::Aabb& dirtyArea) = 0; + + // Get the SurfaceDataRegistryHandle for a given entityId. + virtual SurfaceDataRegistryHandle GetSurfaceDataProviderHandle(const AZ::EntityId& providerEntityId) = 0; + virtual SurfaceDataRegistryHandle GetSurfaceDataModifierHandle(const AZ::EntityId& modifierEntityId) = 0; }; typedef AZ::EBus SurfaceDataSystemRequestBus; diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h b/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h index 82a321756d..bafe215402 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h @@ -250,6 +250,16 @@ namespace UnitTest { } + SurfaceData::SurfaceDataRegistryHandle GetSurfaceDataProviderHandle(const AZ::EntityId& providerEntityId) override + { + return GetSurfaceProviderHandle(providerEntityId); + } + + SurfaceData::SurfaceDataRegistryHandle GetSurfaceDataModifierHandle(const AZ::EntityId& modifierEntityId) override + { + return GetSurfaceModifierHandle(modifierEntityId); + } + SurfaceData::SurfaceDataRegistryHandle GetSurfaceProviderHandle(AZ::EntityId id) { return GetEntryHandle(id, m_providers); diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp b/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp index 86a165b7d8..35f377bfe0 100644 --- a/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp +++ b/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp @@ -6,7 +6,7 @@ * */ -#include "SurfaceDataColliderComponent.h" +#include #include #include diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp index 481372b7dc..973fca232a 100644 --- a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp +++ b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp @@ -6,7 +6,7 @@ * */ -#include "SurfaceDataShapeComponent.h" +#include #include #include diff --git a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataColliderComponent.h b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataColliderComponent.h index 211d819b4d..a25061c245 100644 --- a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataColliderComponent.h +++ b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataColliderComponent.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include namespace SurfaceData diff --git a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataShapeComponent.h b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataShapeComponent.h index 79218b9317..202511c4c7 100644 --- a/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataShapeComponent.h +++ b/Gems/SurfaceData/Code/Source/Editor/EditorSurfaceDataShapeComponent.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include namespace SurfaceData diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataEditorModule.cpp b/Gems/SurfaceData/Code/Source/SurfaceDataEditorModule.cpp index 936cac5954..5f1ead9873 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataEditorModule.cpp +++ b/Gems/SurfaceData/Code/Source/SurfaceDataEditorModule.cpp @@ -7,7 +7,7 @@ */ #include -#include +#include #include #include #include diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataModule.cpp b/Gems/SurfaceData/Code/Source/SurfaceDataModule.cpp index 35064bf4a4..36b8936e23 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataModule.cpp +++ b/Gems/SurfaceData/Code/Source/SurfaceDataModule.cpp @@ -7,9 +7,9 @@ */ #include -#include -#include -#include +#include +#include +#include namespace SurfaceData { diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp index 66b8c83a58..7dc6711b72 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp +++ b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp @@ -12,7 +12,7 @@ #include #include -#include "SurfaceDataSystemComponent.h" +#include #include #include #include @@ -175,6 +175,34 @@ namespace SurfaceData SurfaceDataSystemNotificationBus::Broadcast(&SurfaceDataSystemNotificationBus::Events::OnSurfaceChanged, AZ::EntityId(), dirtyBounds, dirtyBounds); } + SurfaceDataRegistryHandle SurfaceDataSystemComponent::GetSurfaceDataProviderHandle(const AZ::EntityId& providerEntityId) + { + AZStd::shared_lock registrationLock(m_registrationMutex); + + for (auto& [providerHandle, providerEntry] : m_registeredSurfaceDataProviders) + { + if (providerEntry.m_entityId == providerEntityId) + { + return providerHandle; + } + } + return {}; + } + + SurfaceDataRegistryHandle SurfaceDataSystemComponent::GetSurfaceDataModifierHandle(const AZ::EntityId& modifierEntityId) + { + AZStd::shared_lock registrationLock(m_registrationMutex); + + for (auto& [modifierHandle, modifierEntry] : m_registeredSurfaceDataModifiers) + { + if (modifierEntry.m_entityId == modifierEntityId) + { + return modifierHandle; + } + } + return {}; + } + void SurfaceDataSystemComponent::GetSurfacePoints(const AZ::Vector3& inPosition, const SurfaceTagVector& desiredTags, SurfacePointList& surfacePointList) const { const bool useTagFilters = HasValidTags(desiredTags); diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp b/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp index 04c1ada677..a25273896e 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp +++ b/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp @@ -226,9 +226,7 @@ namespace SurfaceData void SurfacePointList::ReserveSpace(size_t maxPointsPerInput) { - AZ_Assert( - m_surfacePositionList.size() < maxPointsPerInput, - "Trying to reserve space on a list that is already using more points than requested."); + AZ_Assert(m_surfacePositionList.empty(), "Trying to reserve space on a list that is already being used."); m_surfaceCreatorIdList.reserve(maxPointsPerInput); m_surfacePositionList.reserve(maxPointsPerInput); diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp index f8b4c675a5..df011113da 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp @@ -21,8 +21,8 @@ #include #include #include -#include -#include +#include +#include namespace UnitTest { diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp index 884c831393..aca5a53f4d 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp index f4ff0cb04c..8500e557bf 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataTestFixtures.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataTestFixtures.cpp index 2ec531d2e4..28f7ea6b03 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataTestFixtures.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataTestFixtures.cpp @@ -11,9 +11,9 @@ #include #include -#include -#include -#include +#include +#include +#include namespace UnitTest diff --git a/Gems/SurfaceData/Code/surfacedata_files.cmake b/Gems/SurfaceData/Code/surfacedata_files.cmake index 1c36ca43a0..8e7435abb3 100644 --- a/Gems/SurfaceData/Code/surfacedata_files.cmake +++ b/Gems/SurfaceData/Code/surfacedata_files.cmake @@ -7,6 +7,9 @@ # set(FILES + Include/SurfaceData/Components/SurfaceDataColliderComponent.h + Include/SurfaceData/Components/SurfaceDataShapeComponent.h + Include/SurfaceData/Components/SurfaceDataSystemComponent.h Include/SurfaceData/SurfaceDataConstants.h Include/SurfaceData/SurfaceDataTypes.h Include/SurfaceData/SurfaceDataSystemRequestBus.h @@ -18,12 +21,9 @@ set(FILES Include/SurfaceData/SurfaceTag.h Include/SurfaceData/Utility/SurfaceDataUtility.h Source/SurfaceDataSystemComponent.cpp - Source/SurfaceDataSystemComponent.h Source/SurfaceDataTypes.cpp Source/SurfaceTag.cpp Source/Components/SurfaceDataColliderComponent.cpp - Source/Components/SurfaceDataColliderComponent.h Source/Components/SurfaceDataShapeComponent.cpp - Source/Components/SurfaceDataShapeComponent.h Source/SurfaceDataUtility.cpp ) diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp index 5f2a50f903..fc4b821578 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp @@ -8,21 +8,19 @@ #include -#include -#include #include +#include #include -#include -#include -#include +#include #include +#include +#include #include -#include -#include - #include +#include +#include #include namespace Terrain @@ -38,15 +36,14 @@ namespace Terrain if (auto edit = serialize->GetEditContext()) { - edit->Class("Terrain Surface Gradient Mapping", "Mapping between a surface and a material.") + edit->Class("Terrain surface gradient mapping", "Mapping between a surface and a material.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) - - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &TerrainSurfaceMaterialMapping::m_surfaceTag, "Surface Tag", "Surface type to map to a material.") - ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialMapping::m_materialAsset, "Material Asset", "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &TerrainSurfaceMaterialMapping::m_surfaceTag, "Surface tag", "Surface type to map to a material.") + ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialMapping::m_materialAsset, "Material asset", "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true) ; } } @@ -60,7 +57,8 @@ namespace Terrain if (serialize) { serialize->Class() - ->Version(1) + ->Version(2) + ->Field("DefaultMaterial", &TerrainSurfaceMaterialsListConfig::m_defaultSurfaceMaterial) ->Field("Mappings", &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials); AZ::EditContext* edit = serialize->GetEditContext(); @@ -68,10 +66,13 @@ namespace Terrain { edit->Class( "Terrain Surface Material List Component", "Provide mapping between surfaces and render materials.") + ->SetDynamicEditDataProvider(&TerrainSurfaceMaterialsListConfig::GetDynamicData) ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialsListConfig::m_defaultSurfaceMaterial, + "Default Material", "The default material to fall back to where no other material surface mappings exist.") ->DataElement( AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials, "Material Mappings", "Maps surfaces to materials."); @@ -79,6 +80,26 @@ namespace Terrain } } + TerrainSurfaceMaterialsListConfig::TerrainSurfaceMaterialsListConfig() + { + m_hideSurfaceTagData.m_attributes.push_back( + { + AZ::Edit::Attributes::Visibility, + aznew AZ::Edit::AttributeData(AZ::Edit::PropertyVisibility::Hide) + } + ); + } + + const AZ::Edit::ElementData* TerrainSurfaceMaterialsListConfig::GetDynamicData(const void* handlerPtr, const void* elementPtr, const AZ::Uuid& ) + { + const TerrainSurfaceMaterialsListConfig* owner = reinterpret_cast(handlerPtr); + if (elementPtr == &owner->m_defaultSurfaceMaterial.m_surfaceTag) + { + return &owner->m_hideSurfaceTagData; + } + return nullptr; + } + void TerrainSurfaceMaterialsListComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services) { services.push_back(AZ_CRC_CE("TerrainMaterialProviderService")); @@ -116,15 +137,21 @@ namespace Terrain { m_cachedAabb = AZ::Aabb::CreateNull(); + auto checkLoadMaterial = [&](TerrainSurfaceMaterialMapping& material) + { + if (material.m_materialAsset.GetId().IsValid()) + { + material.m_active = false; + material.m_materialAsset.QueueLoad(); + AZ::Data::AssetBus::MultiHandler::BusConnect(material.m_materialAsset.GetId()); + } + }; + // Set all the materials as inactive and start loading. + checkLoadMaterial(m_configuration.m_defaultSurfaceMaterial); for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { - if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid()) - { - surfaceMaterialMapping.m_active = false; - surfaceMaterialMapping.m_materialAsset.QueueLoad(); - AZ::Data::AssetBus::MultiHandler::BusConnect(surfaceMaterialMapping.m_materialAsset.GetId()); - } + checkLoadMaterial(surfaceMaterialMapping); } // Announce initial shape using OnShapeChanged @@ -135,24 +162,35 @@ namespace Terrain { TerrainAreaMaterialRequestBus::Handler::BusDisconnect(); + auto checkResetMaterial = [&](TerrainSurfaceMaterialMapping& material) + { + if (material.m_materialAsset.GetId().IsValid()) + { + AZ::Data::AssetBus::MultiHandler::BusDisconnect(material.m_materialAsset.GetId()); + material.m_materialAsset.Release(); + material.m_materialInstance.reset(); + material.m_activeMaterialAssetId = AZ::Data::AssetId(); + } + }; + + checkResetMaterial(m_configuration.m_defaultSurfaceMaterial); for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { - if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid()) - { - AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_materialAsset.GetId()); - surfaceMaterialMapping.m_materialAsset.Release(); - surfaceMaterialMapping.m_materialInstance.reset(); - surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId(); - } + checkResetMaterial(surfaceMaterialMapping); } HandleMaterialStateChanges(); } - int TerrainSurfaceMaterialsListComponent::CountMaterialIDInstances(AZ::Data::AssetId id) const + int TerrainSurfaceMaterialsListComponent::CountMaterialIdInstances(AZ::Data::AssetId id) const { int count = 0; + if (m_configuration.m_defaultSurfaceMaterial.m_activeMaterialAssetId == id) + { + count++; + } + for (const auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { if (surfaceMaterialMapping.m_activeMaterialAssetId == id) @@ -169,28 +207,63 @@ namespace Terrain bool anyMaterialIsActive = false; bool anyMaterialWasAlreadyActive = false; - for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { - const bool wasPreviouslyActive = surfaceMaterialMapping.m_active; - const bool isNowActive = (surfaceMaterialMapping.m_materialInstance != nullptr); + // Handle default material first + auto& defaultMaterial = m_configuration.m_defaultSurfaceMaterial; - if (wasPreviouslyActive) - { - anyMaterialWasAlreadyActive = true; - } + const bool wasPreviouslyActive = defaultMaterial.m_active; + defaultMaterial.m_active = (defaultMaterial.m_materialInstance != nullptr); - if (isNowActive) - { - anyMaterialIsActive = true; - } - - surfaceMaterialMapping.m_active = isNowActive; - - if (!wasPreviouslyActive && !isNowActive) + anyMaterialWasAlreadyActive = wasPreviouslyActive; + anyMaterialIsActive = defaultMaterial.m_active; + + if (!wasPreviouslyActive && !defaultMaterial.m_active) { // A material has been assigned but has not yet completed loading. } - else if (!wasPreviouslyActive && isNowActive) + else if (!wasPreviouslyActive && defaultMaterial.m_active) + { + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialCreated, GetEntityId(), + defaultMaterial.m_materialInstance); + defaultMaterial.m_previousChangeId = defaultMaterial.m_materialInstance->GetCurrentChangeId(); + } + else if (wasPreviouslyActive && !defaultMaterial.m_active) + { + // Don't disconnect from the AssetBus if this material is mapped more than once. + if (CountMaterialIdInstances(defaultMaterial.m_activeMaterialAssetId) == 1) + { + AZ::Data::AssetBus::MultiHandler::BusDisconnect(defaultMaterial.m_activeMaterialAssetId); + } + defaultMaterial = {}; + + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialDestroyed, GetEntityId()); + } + else if (defaultMaterial.m_materialInstance->GetAssetId() != defaultMaterial.m_activeMaterialAssetId || + defaultMaterial.m_materialInstance->GetCurrentChangeId() != defaultMaterial.m_previousChangeId) + { + defaultMaterial.m_previousChangeId = defaultMaterial.m_materialInstance->GetCurrentChangeId(); + defaultMaterial.m_activeMaterialAssetId = defaultMaterial.m_materialInstance->GetAssetId(); + + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialChanged, GetEntityId(), defaultMaterial.m_materialInstance); + } + } + + for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) + { + const bool wasPreviouslyActive = surfaceMaterialMapping.m_active; + surfaceMaterialMapping.m_active = surfaceMaterialMapping.m_materialInstance != nullptr; + + anyMaterialWasAlreadyActive = anyMaterialWasAlreadyActive || wasPreviouslyActive; + anyMaterialIsActive = anyMaterialIsActive || surfaceMaterialMapping.m_active; + + if (!wasPreviouslyActive && !surfaceMaterialMapping.m_active) + { + // A material has been assigned but has not yet completed loading. + } + else if (!wasPreviouslyActive && surfaceMaterialMapping.m_active) { // Remember the asset id so we can disconnect from the AssetBus if the material asset is removed. surfaceMaterialMapping.m_activeMaterialAssetId = surfaceMaterialMapping.m_materialAsset.GetId(); @@ -199,27 +272,47 @@ namespace Terrain &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingCreated, GetEntityId(), surfaceMaterialMapping.m_surfaceTag, surfaceMaterialMapping.m_materialInstance); + + surfaceMaterialMapping.m_previousChangeId = surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId(); + surfaceMaterialMapping.m_previousTag = surfaceMaterialMapping.m_surfaceTag; } - else if (wasPreviouslyActive && !isNowActive) + else if (wasPreviouslyActive && !surfaceMaterialMapping.m_active) { // Don't disconnect from the AssetBus if this material is mapped more than once. - if (CountMaterialIDInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1) + if (CountMaterialIdInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1) { AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_activeMaterialAssetId); } - surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId(); + surfaceMaterialMapping.m_activeMaterialAssetId = {}; + surfaceMaterialMapping.m_previousChangeId = AZ::RPI::Material::DEFAULT_CHANGE_ID; + surfaceMaterialMapping.m_previousTag = {}; TerrainAreaMaterialNotificationBus::Broadcast( &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingDestroyed, GetEntityId(), surfaceMaterialMapping.m_surfaceTag); } - else + else { - TerrainAreaMaterialNotificationBus::Broadcast( - &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingChanged, GetEntityId(), - surfaceMaterialMapping.m_surfaceTag, - surfaceMaterialMapping.m_materialInstance); + if (surfaceMaterialMapping.m_previousTag != surfaceMaterialMapping.m_surfaceTag) + { + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingTagChanged, GetEntityId(), + surfaceMaterialMapping.m_previousTag, + surfaceMaterialMapping.m_surfaceTag); + surfaceMaterialMapping.m_previousTag = surfaceMaterialMapping.m_surfaceTag; + } + if (surfaceMaterialMapping.m_materialInstance->GetAssetId() != surfaceMaterialMapping.m_activeMaterialAssetId || + surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId() != surfaceMaterialMapping.m_previousChangeId) + { + surfaceMaterialMapping.m_previousChangeId = surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId(); + surfaceMaterialMapping.m_activeMaterialAssetId = surfaceMaterialMapping.m_materialInstance->GetAssetId(); + + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingMaterialChanged, GetEntityId(), + surfaceMaterialMapping.m_surfaceTag, + surfaceMaterialMapping.m_materialInstance); + } } } @@ -290,14 +383,28 @@ namespace Terrain void TerrainSurfaceMaterialsListComponent::OnAssetReady(AZ::Data::Asset asset) { // Find the missing material instance with the correct id. - for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) + auto checkUpdateMaterialAsset = [](TerrainSurfaceMaterialMapping& mapping, const AZ::Data::Asset& asset) -> bool { - if (surfaceMaterialMapping.m_materialAsset.GetId() == asset.GetId() && - (!surfaceMaterialMapping.m_materialInstance || - surfaceMaterialMapping.m_materialInstance->GetAssetId() != surfaceMaterialMapping.m_materialAsset.GetId())) + if (mapping.m_materialAsset.GetId() == asset.GetId() && + (!mapping.m_materialInstance || mapping.m_materialInstance->GetAssetId() != mapping.m_materialAsset.GetId())) { - surfaceMaterialMapping.m_materialInstance = AZ::RPI::Material::FindOrCreate(surfaceMaterialMapping.m_materialAsset); - surfaceMaterialMapping.m_materialAsset.Release(); + mapping.m_materialInstance = AZ::RPI::Material::FindOrCreate(mapping.m_materialAsset); + mapping.m_materialAsset.Release(); + return true; + } + return false; + }; + + // First check the default material + if (!checkUpdateMaterialAsset(m_configuration.m_defaultSurfaceMaterial, asset)) + { + // If the default materail wasn't updated, then check all the surface material mappings. + for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) + { + if (checkUpdateMaterialAsset(surfaceMaterialMapping, asset)) + { + break; + } } } HandleMaterialStateChanges(); diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h index 0e32cb12c0..96a7da60de 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h @@ -8,15 +8,18 @@ #pragma once -#include -#include #include #include +#include + +#include +#include + #include + #include #include - namespace LmbrCentral { template @@ -27,16 +30,20 @@ namespace Terrain { struct TerrainSurfaceMaterialMapping final { - public: AZ_CLASS_ALLOCATOR(TerrainSurfaceMaterialMapping, AZ::SystemAllocator, 0); AZ_RTTI(TerrainSurfaceMaterialMapping, "{37D2A586-CDDD-4FB7-A7D6-0B4CC575AB8C}"); static void Reflect(AZ::ReflectContext* context); - SurfaceData::SurfaceTag m_surfaceTag; - AZ::Data::AssetId m_activeMaterialAssetId; AZ::Data::Asset m_materialAsset; AZ::Data::Instance m_materialInstance; + AZ::Data::AssetId m_activeMaterialAssetId; + AZ::RPI::Material::ChangeId m_previousChangeId = AZ::RPI::Material::DEFAULT_CHANGE_ID; + + // Surface tags not used by default material + SurfaceData::SurfaceTag m_surfaceTag; + SurfaceData::SurfaceTag m_previousTag; + bool m_active = false; }; @@ -47,7 +54,13 @@ namespace Terrain AZ_RTTI(TerrainSurfaceMaterialsListConfig, "{68A1CB1B-C835-4C3A-8D1C-08692E07711A}", AZ::ComponentConfig); static void Reflect(AZ::ReflectContext* context); + TerrainSurfaceMaterialsListConfig(); + + TerrainSurfaceMaterialMapping m_defaultSurfaceMaterial; AZStd::vector m_surfaceMaterials; + private: + static const AZ::Edit::ElementData* GetDynamicData(const void* handlerPtr, const void* elementPtr, const AZ::Uuid& elementType); + AZ::Edit::ElementData m_hideSurfaceTagData; }; class TerrainSurfaceMaterialsListComponent @@ -78,7 +91,7 @@ namespace Terrain private: void HandleMaterialStateChanges(); - int CountMaterialIDInstances(AZ::Data::AssetId id) const; + int CountMaterialIdInstances(AZ::Data::AssetId id) const; //////////////////////////////////////////////////////////////////////// // ShapeComponentNotificationsBus diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h index ae36a2639e..a2225702ef 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h @@ -45,6 +45,27 @@ namespace Terrain static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; ////////////////////////////////////////////////////////////////////////// + //! The default surface material has been assigned and loaded + virtual void OnTerrainDefaultSurfaceMaterialCreated( + [[maybe_unused]] AZ::EntityId entityId, + [[maybe_unused]] AZ::Data::Instance material) + { + } + + //! The default surface material has been unassigned + virtual void OnTerrainDefaultSurfaceMaterialDestroyed( + [[maybe_unused]] AZ::EntityId entityId) + { + } + + //! The default surface material has been changed to a different material + virtual void OnTerrainDefaultSurfaceMaterialChanged( + [[maybe_unused]] AZ::EntityId entityId, + [[maybe_unused]] AZ::Data::Instance newMaterial) + { + } + + //! A loaded material mapped to a valid surface tag has been created virtual void OnTerrainSurfaceMaterialMappingCreated( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] SurfaceData::SurfaceTag surface, @@ -52,19 +73,30 @@ namespace Terrain { } + //! Either the material or surface tag was unassigned, making this mapping invalid virtual void OnTerrainSurfaceMaterialMappingDestroyed( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] SurfaceData::SurfaceTag surface) { } - virtual void OnTerrainSurfaceMaterialMappingChanged( + //! The surface tag has changed to tag for an existing material + virtual void OnTerrainSurfaceMaterialMappingTagChanged( + [[maybe_unused]] AZ::EntityId entityId, + [[maybe_unused]] SurfaceData::SurfaceTag oldSurface, + [[maybe_unused]] SurfaceData::SurfaceTag newSurface) + { + } + + //! The material has changed for an existing surface tag + virtual void OnTerrainSurfaceMaterialMappingMaterialChanged( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] SurfaceData::SurfaceTag surface, [[maybe_unused]] AZ::Data::Instance material) { } + //! The bounds of this set of surface material mappings has changed virtual void OnTerrainSurfaceMaterialMappingRegionChanged( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] const AZ::Aabb& oldRegion, diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp index a00d2efe59..f817c138a7 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp @@ -106,6 +106,8 @@ namespace Terrain return; } + InitializePassthroughDetailMaterial(); + ClipmapBoundsDescriptor desc; desc.m_clipmapUpdateMultiple = 1; desc.m_clipToWorldScale = DetailTextureScale; @@ -260,20 +262,73 @@ namespace Terrain m_dirtyDetailRegion.AddAabb(dirtyRegion); } } + + bool TerrainDetailMaterialManager::ForSurfaceTag(DetailMaterialListRegion& materialRegion, + SurfaceData::SurfaceTag surfaceTag, DefaultMaterialSurfaceCallback callback) + { + for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + { + if (surface.m_surfaceTag == surfaceTag) + { + callback(surface); + return true; + } + } + return false; + } + void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialCreated(AZ::EntityId entityId, MaterialInstance material) + { + DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); + AZ_Error("TerrainDetailMaterialManager", materialRegion.m_defaultDetailMaterialId == InvalidDetailMaterailId, + "Default detail material created but was already set for this region."); + + materialRegion.m_defaultDetailMaterialId = CreateOrUpdateDetailMaterial(material); + m_detailMaterials.GetData(materialRegion.m_defaultDetailMaterialId).refCount++; + m_dirtyDetailRegion.AddAabb(materialRegion.m_region); + } + + void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialDestroyed(AZ::EntityId entityId) + { + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) + { + AZ_Assert(false, "OnTerrainDefaultSurfaceMaterialDestroyed() called for region that doesn't exist."); + return; + } + + CheckDetailMaterialForDeletion(materialRegion->m_defaultDetailMaterialId); + materialRegion->m_defaultDetailMaterialId = InvalidDetailMaterailId; + } + + void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialChanged(AZ::EntityId entityId, MaterialInstance newMaterial) + { + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) + { + AZ_Assert(false, "OnTerrainDefaultSurfaceMaterialChanged() called for region that doesn't exist."); + return; + } + + // Update existing entry or create a new material entry + uint16_t materialId = CreateOrUpdateDetailMaterial(newMaterial); + if (materialRegion->m_defaultDetailMaterialId != materialId) + { + ++m_detailMaterials.GetData(materialId).refCount; + CheckDetailMaterialForDeletion(materialRegion->m_defaultDetailMaterialId); + materialRegion->m_defaultDetailMaterialId = materialId; + } + } + void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingCreated(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) { DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); // Validate that the surface tag is new - for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + ForSurfaceTag(materialRegion, surfaceTag, [](DetailMaterialSurface&) { - if (surface.m_surfaceTag == surfaceTag) - { - AZ_Error(TerrainDetailMaterialManagerName, false, "Already have a surface material mapping for this surface tag."); - return; - } - } + AZ_Error(TerrainDetailMaterialManagerName, false, "Already have a surface material mapping for this surface tag."); + }); uint16_t detailMaterialId = CreateOrUpdateDetailMaterial(material); materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, detailMaterialId }); @@ -284,52 +339,71 @@ namespace Terrain void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingDestroyed(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag) { DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); - - for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + + [[maybe_unused]] bool found = ForSurfaceTag(materialRegion, surfaceTag, + [&](DetailMaterialSurface& surface) { - if (surface.m_surfaceTag == surfaceTag) - { - CheckDetailMaterialForDeletion(surface.m_detailMaterialId); + CheckDetailMaterialForDeletion(surface.m_detailMaterialId); - if (surface.m_surfaceTag != materialRegion.m_materialsForSurfaces.back().m_surfaceTag) - { - AZStd::swap(surface, materialRegion.m_materialsForSurfaces.back()); - } - materialRegion.m_materialsForSurfaces.pop_back(); - m_dirtyDetailRegion.AddAabb(materialRegion.m_region); - return; + if (surface.m_surfaceTag != materialRegion.m_materialsForSurfaces.back().m_surfaceTag) + { + AZStd::swap(surface, materialRegion.m_materialsForSurfaces.back()); } + materialRegion.m_materialsForSurfaces.pop_back(); + m_dirtyDetailRegion.AddAabb(materialRegion.m_region); + return; + }); + + AZ_Error(TerrainDetailMaterialManagerName, found, "Could not find surface tag to destroy for OnTerrainSurfaceMaterialMappingDestroyed()."); + } + + void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingMaterialChanged( + AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) + { + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) + { + AZ_Assert(false, "OnTerrainSurfaceMaterialMappingMaterialChanged() called for region that doesn't exist."); + return; } - AZ_Error(TerrainDetailMaterialManagerName, false, "Could not find surface tag to destroy for OnTerrainSurfaceMaterialMappingDestroyed()."); + + // Update existing entry or create a new material entry + uint16_t materialId = CreateOrUpdateDetailMaterial(material); + + [[maybe_unused]] bool found = ForSurfaceTag(*materialRegion, surfaceTag, + [&](DetailMaterialSurface& surface) + { + if (surface.m_detailMaterialId != materialId) + { + // Updated material was a different asset than the old material, decrement ref count and + // delete if no other surface tags are using it. + ++m_detailMaterials.GetData(materialId).refCount; + CheckDetailMaterialForDeletion(surface.m_detailMaterialId); + surface.m_detailMaterialId = materialId; + } + m_dirtyDetailRegion.AddAabb(materialRegion->m_region); + }); + + AZ_Assert(found, "OnTerrainSurfaceMaterialMappingMaterialChanged() called for tag that doesn't exist."); } - void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) + void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingTagChanged( + AZ::EntityId entityId, SurfaceData::SurfaceTag oldTag, SurfaceData::SurfaceTag newTag) { - DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); - - bool found = false; - uint16_t materialId = CreateOrUpdateDetailMaterial(material); - for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) { - if (surface.m_surfaceTag == surfaceTag) - { - found = true; - if (surface.m_detailMaterialId != materialId) - { - ++m_detailMaterials.GetData(materialId).refCount; - CheckDetailMaterialForDeletion(surface.m_detailMaterialId); - surface.m_detailMaterialId = materialId; - } - break; - } + AZ_Assert(false, "OnTerrainSurfaceMaterialMappingTagChanged() called for region that doesn't exist."); + return; } - - if (!found) + + [[maybe_unused]] bool found = ForSurfaceTag(*materialRegion, oldTag, + [&](DetailMaterialSurface& surface) { - ++m_detailMaterials.GetData(materialId).refCount; - materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, materialId }); - } - m_dirtyDetailRegion.AddAabb(materialRegion.m_region); + surface.m_surfaceTag = newTag; + m_dirtyDetailRegion.AddAabb(materialRegion->m_region); + }); + AZ_Assert(found, "OnTerrainSurfaceMaterialMappingTagChanged() called for tag that doesn't exist."); } void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) @@ -667,23 +741,38 @@ namespace Terrain bool isFirstMaterial = true; float firstWeight = 0.0f; AZ::Vector2 position(surfacePoint.m_position.GetX(), surfacePoint.m_position.GetY()); + const DetailMaterialListRegion* region = FindRegionForPosition(position); + + if (region == nullptr) + { + pixels.at(index).m_material1 = m_passthroughMaterialId; + ++index; + return; + } + for (const auto& surfaceTagWeight : surfacePoint.m_surfaceTags) { if (surfaceTagWeight.m_weight > 0.0f) { AZ::Crc32 surfaceType = surfaceTagWeight.m_surfaceType; - uint16_t materialId = GetDetailMaterialForSurfaceTypeAndPosition(surfaceType, position); - if (materialId != m_detailMaterials.NoFreeSlot && materialId < 255) + uint16_t materialId = GetDetailMaterialForSurfaceType(*region, surfaceType); + if (materialId < 255) { if (isFirstMaterial) { + // First material is valid. Save its weight to calculate blend later pixels.at(index).m_material1 = aznumeric_cast(materialId); firstWeight = surfaceTagWeight.m_weight; - // m_blend only needs to be calculated is material 2 is found, otherwise the initial value of 0 is correct. isFirstMaterial = false; + static constexpr float MaxValueBeforeRounding = 254.5f / 255.0f; + if (firstWeight >= MaxValueBeforeRounding) + { + break; + } } else { + // Second material is valid, weight is relative based on first material's weight. pixels.at(index).m_material2 = aznumeric_cast(materialId); float totalWeight = firstWeight + surfaceTagWeight.m_weight; float blendWeight = 1.0f - (firstWeight / totalWeight); @@ -691,11 +780,37 @@ namespace Terrain break; } } + continue; // search for second material } else { - break; // since the list is ordered, no other materials are in the list with positive weights. + // No more valid materials in list since surfaceTagWeight is ordered. + + uint8_t defaultMaterial = region->m_defaultDetailMaterialId == InvalidDetailMaterailId ? m_passthroughMaterialId : + aznumeric_cast(m_detailMaterials.GetData(region->m_defaultDetailMaterialId).m_detailMaterialBufferIndex); + + if (isFirstMaterial) + { + // Only one material and it's the default material. + pixels.at(index).m_material1 = defaultMaterial; + } + else + { + // Second material is default, weight is exactly what the first material requested + pixels.at(index).m_material2 = defaultMaterial; + float blendWeight = 1.0f - AZStd::clamp(firstWeight, 0.0f, 1.0f); + pixels.at(index).m_blend = aznumeric_cast(AZStd::round(blendWeight * 255.0f)); + } } + + if (pixels.at(index).m_material1 == pixels.at(index).m_material2) + { + // If the materials are the same, then make the blend 100% on the first id so the shader + // doesn't blend identical materials + pixels.at(index).m_blend = 0; + } + + break; } ++index; }; @@ -723,23 +838,37 @@ namespace Terrain m_detailTextureImage->UpdateImageContents(imageUpdateRequest); } - - uint16_t TerrainDetailMaterialManager::GetDetailMaterialForSurfaceTypeAndPosition(AZ::Crc32 surfaceType, const AZ::Vector2& position) + + uint16_t TerrainDetailMaterialManager::GetDetailMaterialForSurfaceType(const DetailMaterialListRegion& materialRegion, AZ::Crc32 surfaceType) const + { + for (const auto& materialSurface : materialRegion.m_materialsForSurfaces) + { + if (materialSurface.m_surfaceTag == surfaceType) + { + return m_detailMaterials.GetData(materialSurface.m_detailMaterialId).m_detailMaterialBufferIndex; + } + } + return InvalidDetailMaterailId; + } + + auto TerrainDetailMaterialManager::FindRegionForPosition(const AZ::Vector2& position) const -> const DetailMaterialListRegion* { for (const auto& materialRegion : m_detailMaterialRegions.GetDataVector()) { if (materialRegion.m_region.Contains(AZ::Vector3(position.GetX(), position.GetY(), 0.0f))) { - for (const auto& materialSurface : materialRegion.m_materialsForSurfaces) - { - if (materialSurface.m_surfaceTag == surfaceType) - { - return m_detailMaterials.GetData(materialSurface.m_detailMaterialId).m_detailMaterialBufferIndex; - } - } + return &materialRegion; } } - return m_detailMaterials.NoFreeSlot; + return nullptr; + } + + void TerrainDetailMaterialManager::InitializePassthroughDetailMaterial() + { + m_passthroughMaterialId = aznumeric_cast(m_detailMaterialShaderData.Reserve()); + DetailMaterialShaderData& materialShaderData = m_detailMaterialShaderData.GetElement(m_passthroughMaterialId); + // Material defaults to white (1.0, 1.0, 1.0), set the blend mode to multiply so it passes through to the macro material. + materialShaderData.m_flags = DetailTextureFlags::BlendModeMultiply; } auto TerrainDetailMaterialManager::FindByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container) @@ -784,5 +913,5 @@ namespace Terrain } AZ_Assert(false, "Entity Id not found in container.") } - + } diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h index 3f63812e47..16423251ec 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -151,7 +152,11 @@ namespace Terrain AZ::EntityId m_entityId; AZ::Aabb m_region{AZ::Aabb::CreateNull()}; AZStd::vector m_materialsForSurfaces; + uint16_t m_defaultDetailMaterialId; }; + + using DetailMaterialContainer = AZ::Render::IndexedDataVector; + static constexpr auto InvalidDetailMaterailId = DetailMaterialContainer::NoFreeSlot; // System-level parameters static constexpr int32_t DetailTextureSize{ 1024 }; @@ -162,9 +167,14 @@ namespace Terrain void OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) override; // TerrainAreaMaterialNotificationBus overrides... + void OnTerrainDefaultSurfaceMaterialCreated(AZ::EntityId entityId, AZ::Data::Instance material) override; + void OnTerrainDefaultSurfaceMaterialDestroyed(AZ::EntityId entityId) override; + void OnTerrainDefaultSurfaceMaterialChanged(AZ::EntityId entityId, AZ::Data::Instance newMaterial) override; void OnTerrainSurfaceMaterialMappingCreated(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override; void OnTerrainSurfaceMaterialMappingDestroyed(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag) override; - void OnTerrainSurfaceMaterialMappingChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override; + void OnTerrainSurfaceMaterialMappingMaterialChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override; + void OnTerrainSurfaceMaterialMappingTagChanged( + AZ::EntityId entityId, SurfaceData::SurfaceTag oldSurfaceTag, SurfaceData::SurfaceTag newSurfaceTag) override; void OnTerrainSurfaceMaterialMappingRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) override; //! Removes all images from all detail materials from the bindless image array @@ -186,22 +196,32 @@ namespace Terrain //! Updates the detail texture in a given area void UpdateDetailTexture(const AZ::Aabb& worldUpdateAabb, const Aabb2i& textureUpdateAabb); - //! Finds the detail material Id for a surface type and position - uint16_t GetDetailMaterialForSurfaceTypeAndPosition(AZ::Crc32 surfaceType, const AZ::Vector2& position); + //! Finds the detail material Id for a region and surface type + uint16_t GetDetailMaterialForSurfaceType(const DetailMaterialListRegion& materialRegion, AZ::Crc32 surfaceType) const; + //! Finds a region for a position. Returns nullptr if none found. + const DetailMaterialListRegion* FindRegionForPosition(const AZ::Vector2& position) const; + + //! Initializes shader data for the default passthrough material which is used when no other detail material is found. + void InitializePassthroughDetailMaterial(); + + using DefaultMaterialSurfaceCallback = AZStd::function; + bool ForSurfaceTag(DetailMaterialListRegion& materialRegion, + SurfaceData::SurfaceTag surfaceTag, DefaultMaterialSurfaceCallback callback); DetailMaterialListRegion* FindByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container); DetailMaterialListRegion& FindOrCreateByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container); void RemoveByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container); - + AZStd::shared_ptr m_bindlessImageHandler; AZ::Data::Instance m_detailTextureImage; - AZ::Render::IndexedDataVector m_detailMaterials; + DetailMaterialContainer m_detailMaterials; AZ::Render::IndexedDataVector m_detailMaterialRegions; AZ::Render::SparseVector m_detailMaterialShaderData; AZ::Render::GpuBufferHandler m_detailMaterialDataBuffer; - + uint8_t m_passthroughMaterialId = 0; + AZ::Aabb m_dirtyDetailRegion{ AZ::Aabb::CreateNull() }; ClipmapBounds m_detailMaterialIdBounds; @@ -212,6 +232,6 @@ namespace Terrain bool m_isInitialized{ false }; bool m_detailMaterialBufferNeedsUpdate{ false }; bool m_detailImageNeedsUpdate{ false }; - + }; } diff --git a/Gems/Vegetation/Code/Tests/VegetationMocks.h b/Gems/Vegetation/Code/Tests/VegetationMocks.h index d77862d578..33a320b03e 100644 --- a/Gems/Vegetation/Code/Tests/VegetationMocks.h +++ b/Gems/Vegetation/Code/Tests/VegetationMocks.h @@ -384,6 +384,16 @@ namespace UnitTest { ++m_count; } + + SurfaceData::SurfaceDataRegistryHandle GetSurfaceDataProviderHandle([[maybe_unused]] const AZ::EntityId& providerEntityId) override + { + return {}; + } + + SurfaceData::SurfaceDataRegistryHandle GetSurfaceDataModifierHandle([[maybe_unused]] const AZ::EntityId& modifierEntityId) override + { + return {}; + } }; struct MockMeshAsset diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py index 4514e5d812..6e0923b916 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py @@ -175,13 +175,20 @@ class AbstractResourceLocator(object): return os.path.join(self.build_directory(), 'AssetProcessor') def asset_processor_batch(self): - """" + """ Return path for the AssetProcessorBatch compatible with this build platform and configuration ex. engine_root/dev/mac/bin/profile/AssetProcessorBatch :return: path to AssetProcessorBatch """ return os.path.join(self.build_directory(), 'AssetProcessorBatch') + def ap_job_logs(self): + """ + Return path to the Asset Processor JobLogs directory. + :return: path to /user/log/JobLogs + """ + return os.path.join(self.project_log(), 'JobLogs') + def editor(self): """ Return path to the editor executable compatible with the current build. diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py index f363689066..3c4e2b49a4 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py @@ -851,11 +851,11 @@ class EditorTestSuite(): workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(run_id, workspace), log_name), f'({run_id}){log_name}') if return_code == 0: - # No need to scrap the output, as all the tests have passed + # No need to scrape the output, as all the tests have passed for test_spec in test_spec_list: results[test_spec.__name__] = Result.Pass.create(test_spec, output, editor_log_content) else: - # Scrap the output to attempt to find out which tests failed. + # Scrape the output to attempt to find out which tests failed. # This function should always populate the result list, if it didn't find it, it will have "Unknown" type of result results = self._get_results_using_output(test_spec_list, output, editor_log_content) assert len(results) == len(test_spec_list), "bug in _get_results_using_output(), the number of results don't match the tests ran" @@ -940,6 +940,9 @@ class EditorTestSuite(): editor_test_data.results.update(results) test_name, test_result = next(iter(results.items())) self._report_result(test_name, test_result) + # If test did not pass, save assets with errors and warnings + if not isinstance(test_result, Result.Pass): + editor_utils.save_failed_asset_joblogs(workspace) def _run_batched_tests(self, request: Request, workspace: AbstractWorkspace, editor: Editor, editor_test_data: TestData, test_spec_list: list[EditorSharedTest], extra_cmdline_args: list[str] = []) -> None: @@ -961,6 +964,11 @@ class EditorTestSuite(): extra_cmdline_args) assert results is not None editor_test_data.results.update(results) + # If at least one test did not pass, save assets with errors and warnings + for result in results: + if not isinstance(result, Result.Pass): + editor_utils.save_failed_asset_joblogs(workspace) + return def _run_parallel_tests(self, request: Request, workspace: AbstractWorkspace, editor: Editor, editor_test_data: TestData, test_spec_list: list[EditorSharedTest], extra_cmdline_args: list[str] = []) -> None: @@ -1007,8 +1015,14 @@ class EditorTestSuite(): for t in threads: t.join() + save_asset_logs = False for result in results_per_thread: editor_test_data.results.update(result) + if not isinstance(result, Result.Pass): + save_asset_logs = True + # If at least one test did not pass, save assets with errors and warnings + if save_asset_logs: + editor_utils.save_failed_asset_joblogs(workspace) def _run_parallel_batched_tests(self, request: Request, workspace: AbstractWorkspace, editor: Editor, editor_test_data: TestData, test_spec_list: list[EditorSharedTest], extra_cmdline_args: list[str] = []) -> None: @@ -1056,8 +1070,14 @@ class EditorTestSuite(): for t in threads: t.join() + save_asset_logs = False for result in results_per_thread: editor_test_data.results.update(result) + if not isinstance(result, Result.Pass): + save_asset_logs = True + # If at least one test did not pass, save assets with errors and warnings + if save_asset_logs: + editor_utils.save_failed_asset_joblogs(workspace) def _get_number_parallel_editors(self, request: Request) -> int: """ diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py index 7b36a82c07..4e678151bd 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py @@ -10,6 +10,7 @@ from __future__ import annotations import os import time import logging +import re import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.environment.waiter as waiter @@ -151,3 +152,41 @@ def retrieve_last_run_test_index_from_output(test_spec_list: list[EditorTestBase else: index += 1 return index + +def save_failed_asset_joblogs(workspace: AbstractWorkspace) -> None: + """ + Checks all asset logs in the JobLogs directory to see if the asset has any warnings or errors. If so, the asset is + saved via ArtifactManager. + + :param workspace: The AbstractWorkspace to access the JobLogs path + :return: None + """ + for walk_tuple in os.walk(workspace.paths.ap_job_logs()): + for log_file in walk_tuple[2]: + full_log_path = os.path.join(walk_tuple[0], log_file) + # Only save asset logs that contain errors or warnings + if _check_log_errors_warnings(full_log_path): + try: + workspace.artifact_manager.save_artifact(full_log_path) + except Exception as e: # Purposefully broad + logger.warning(f"Error when saving log at path:{full_log_path}\n{e}") + +def _check_log_errors_warnings(log_path: str) -> bool: + """ + Checks to see if the asset log contains any errors or warnings. Also returns True is no regex is found because + something probably went wrong. + Example log lines: ~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 0 errors, 1 warnings + + :param log_path: The full path to the asset log file to read + :return: True if the regex finds an error or warning, else False + """ + log_regex = "(\\d+) errors, (\\d+) warnings" + with open(log_path, 'r') as opened_asset_log: + for log_line in opened_asset_log: + regex_match = re.search(log_regex, log_line) + if regex_match is not None: + break + # If we match any non zero numbers in: n error, n warnings + if regex_match is None or (int)(regex_match.group(1)) != 0 or (int)(regex_match.group(2)) != 0: + return True + return False diff --git a/Tools/LyTestTools/tests/integ/sanity_tests.py b/Tools/LyTestTools/tests/integ/sanity_tests.py index 2e46d822c7..481349dfda 100755 --- a/Tools/LyTestTools/tests/integ/sanity_tests.py +++ b/Tools/LyTestTools/tests/integ/sanity_tests.py @@ -63,6 +63,27 @@ class TestAutomatedTestingProject(object): # Clean up processes after the test is finished process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True) + def test_StartServerLauncher_Sanity(self, project): + # Kill processes that may interfere with the test + process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True) + + try: + # Create the Workspace object, this locates the engine and project + workspace = helpers.create_builtin_workspace(project=project) + + # Create the Launcher object and add args, such as `-rhi=Null` which disables GPU rendering and allows the + # test to run on nodes without a GPU + launcher = launcher_helper.create_dedicated_launcher(workspace) + launcher.args.extend(['-rhi=Null']) + + # Call the game client executable + with launcher.start(): + # Wait for the process to exist + waiter.wait_for(lambda: process_utils.process_exists(f"{project}.ServerLauncher.exe", ignore_extensions=True)) + finally: + # Clean up processes after the test is finished + process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True) + def test_StartEditor_Sanity(self, project): """ The `test_StartEditor_Sanity` test function is similar to the previous example with minor adjustments. A diff --git a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py index f81d2fd8e6..cca9a161c8 100644 --- a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py +++ b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py @@ -170,3 +170,59 @@ class TestEditorTestUtils(unittest.TestCase): mock_test_list.append(mock_test) assert 0 == editor_test_utils.retrieve_last_run_test_index_from_output(mock_test_list, mock_editor_output) + + @mock.patch('ly_test_tools.o3de.editor_test_utils._check_log_errors_warnings') + @mock.patch('os.walk') + def test_SaveFailedAssetJoblogs_ManyValidLogs_SavesCorrectly(self, mock_walk, mock_check_log): + mock_workspace = mock.MagicMock() + mock_walk.return_value = [['MockDirectory', None, ['mock_log.log']], + ['MockDirectory2', None, ['mock_log2.log']]] + mock_check_log.return_value = True + + editor_test_utils.save_failed_asset_joblogs(mock_workspace) + + assert mock_workspace.artifact_manager.save_artifact.call_count == 2 + + @mock.patch('ly_test_tools.o3de.editor_test_utils._check_log_errors_warnings') + @mock.patch('os.walk') + def test_SaveFailedAssetJoblogs_ManyInvalidLogs_NoSaves(self, mock_walk, mock_check_log): + mock_workspace = mock.MagicMock() + mock_walk.return_value = [['MockDirectory', None, ['mock_log.log']], + ['MockDirectory2', None, ['mock_log2.log']]] + mock_check_log.return_value = False + + editor_test_utils.save_failed_asset_joblogs(mock_workspace) + + assert mock_workspace.artifact_manager.save_artifact.call_count == 0 + + def test_CheckLogErrorWarnings_ValidLine_ReturnsTrue(self): + mock_log = '~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 0 errors, 1 warnings' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert expected + + def test_CheckLogErrorWarnings_MultipleValidLine_ReturnsTrue(self): + mock_log = 'foo\nfoo\n~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 1 errors, 1 warnings' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert expected + + def test_CheckLogErrorWarnings_InvalidLine_ReturnsFalse(self): + mock_log = 'foo\n~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 0 errors, 0 warnings' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert not expected + + def test_CheckLogErrorWarnings_InvalidRegex_ReturnsTrue(self): + mock_log = 'Invalid last line' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert expected diff --git a/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py b/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py index 973366aa94..f63ec315eb 100644 --- a/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py +++ b/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py @@ -871,6 +871,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._report_result') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._exec_editor_test') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunSingleTest_ValidTest_ReportsResults(self, mock_setup_test, mock_exec_editor_test, mock_report_result): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() mock_test_data = mock.MagicMock() @@ -903,6 +904,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelTests_TwoTestsAndEditors_TwoThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() mock_get_num_editors.return_value = 2 @@ -919,6 +921,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelTests_TenTestsAndTwoEditors_TenThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() mock_get_num_editors.return_value = 2 @@ -937,6 +940,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelTests_TenTestsAndThreeEditors_TenThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() @@ -956,6 +960,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelBatchedTests_TwoTestsAndEditors_TwoThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() @@ -973,6 +978,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelBatchedTests_TenTestsAndTwoEditors_2Threads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() @@ -992,6 +998,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelBatchedTests_TenTestsAndThreeEditors_ThreeThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index d231954c49..2ffbe75084 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -19,7 +19,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS gla ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev4-android TARGETS TIFF PACKAGE_HASH 2c62cdf34a8ee6c7eb091d05d98f60b4da7634c74054d4dbb8736886182f4589) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-android TARGETS freetype PACKAGE_HASH df9e4d559ea0f03b0666b48c79813b1cd4d9624429148a249865de9f5c2c11cd) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-android TARGETS AWSNativeSDK PACKAGE_HASH 33771499f9080cbaab613459927e52911e68f94fa356397885e85005efbd1490) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300) +ly_associate_package(PACKAGE_NAME Lua-5.4.4-rev1-android TARGETS Lua PACKAGE_HASH 2adda1831577336454090f249baf09519f41bb73160cd1d5b5b33564729af4a2) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-android TARGETS PhysX PACKAGE_HASH b346e8f9bc55f367a97d781d94c8a5c3bff8059478b8a7007e5fd17708dc1d07) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-android TARGETS mikkelsen PACKAGE_HASH 075e8e4940884971063b5a9963014e2e517246fa269c07c7dc55b8cf2cd99705) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-android TARGETS googletest PACKAGE_HASH 95671be75287a61c9533452835c3647e9c1b30f81b34b43bcb0ec1997cc23894) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 5d30abfb4d..de36760ea4 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -24,7 +24,7 @@ ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-linux TARGETS TIFF PACKAGE_HASH 2377f48b2ebc2d1628d9f65186c881544c92891312abe478a20d10b85877409a) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux TARGETS freetype PACKAGE_HASH 3f10c703d9001ecd2bb51a3bd003d3237c02d8f947ad0161c0252fdc54cbcf97) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-linux TARGETS AWSNativeSDK PACKAGE_HASH f30b6969c6732a7c1a23a59d205a150633a7f219dcb60d837b543888d2c63ea1) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev7-linux TARGETS Lua PACKAGE_HASH 81a6ce4965c63e264f923d3ca04ddc40c27074b3e607073c6ad90eca32b9c260) +ly_associate_package(PACKAGE_NAME Lua-5.4.4-rev1-linux TARGETS Lua PACKAGE_HASH d582362c3ef90e1ef175a874abda2265839ffc2e40778fa293f10b443b4697ac) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-linux TARGETS PhysX PACKAGE_HASH fa72365df409376aef02d1763194dc91d255bdfcb4e8febcfbb64d23a3e50b96) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-linux TARGETS mcpp PACKAGE_HASH df7a998d0bc3fedf44b5bdebaf69ddad6033355b71a590e8642445ec77bc6c41) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux TARGETS mikkelsen PACKAGE_HASH 5973b1e71a64633588eecdb5b5c06ca0081f7be97230f6ef64365cbda315b9c8) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 082cefee5d..ae51076857 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -25,7 +25,7 @@ ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-mac TARGETS TIFF PACKAGE_HASH c2615ccdadcc0e1d6c5ed61e5965c4d3a82193d206591b79b805c3b3ff35a4bf) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-mac TARGETS freetype PACKAGE_HASH f159b346ac3251fb29cb8dd5f805c99b0015ed7fdb3887f656945ca701a61d0d) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-mac TARGETS AWSNativeSDK PACKAGE_HASH 6c27a49376870c606144e4639e15867f9db7e4a1ee5f1a726f152d3bd8459966) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) +ly_associate_package(PACKAGE_NAME Lua-5.4.4-rev1-mac TARGETS Lua PACKAGE_HASH b44daae6bfdf092c7935e4aebafded6772853250c6f0a209866a1ac599857d58) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-mac TARGETS PhysX PACKAGE_HASH 83940b3876115db82cd8ffcb9e902278e75846d6ad94a41e135b155cee1ee186) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-mac TARGETS mcpp PACKAGE_HASH be9558905c9c49179ef3d7d84f0a5472415acdf7fe2d76eb060d9431723ddf2e) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac TARGETS mikkelsen PACKAGE_HASH 83af99ca8bee123684ad254263add556f0cf49486c0b3e32e6d303535714e505) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index dd4d158d1c..3ce5730f2a 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -26,7 +26,7 @@ ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-windows TARGETS TIFF PACKAGE_HASH c6000a906e6d2a0816b652e93dfbeab41c9ed73cdd5a613acd53e553d0510b60) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-windows TARGETS freetype PACKAGE_HASH 9809255f1c59b07875097aa8d8c6c21c97c47a31fb35e30f2bb93188e99a85ff) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev2-windows TARGETS AWSNativeSDK PACKAGE_HASH 047de23fa57d33196666c22f45afc9c628bae354a6c39d774cbeee8054b2eb53) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) +ly_associate_package(PACKAGE_NAME Lua-5.4.4-rev1-windows TARGETS Lua PACKAGE_HASH 8ac853288712267ec9763be152a9274ce87b54728b8add97e2ba73c0fd5a0345) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-windows TARGETS PhysX PACKAGE_HASH 4e31a3e1f5bf3952d8af8e28d1a29f04167995a6362fc3a7c20c25f74bf01e23) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-windows TARGETS mcpp PACKAGE_HASH 794789aba639bfe2f4e8fcb4424d679933dd6290e523084aa0a4e287ac44acb2) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-windows TARGETS mikkelsen PACKAGE_HASH 872c4d245a1c86139aa929f2b465b63ea4ea55b04ced50309135dd4597457a4e) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index 3f1bb204f7..5854738338 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -19,7 +19,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS gla ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-ios TARGETS TIFF PACKAGE_HASH e9067e88649fb6e93a926d9ed38621a9fae360a2e6f6eb24ebca63c1bc7761ea) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-ios TARGETS freetype PACKAGE_HASH 3ac3c35e056ae4baec2e40caa023d76a7a3320895ef172b6655e9261b0dc2e29) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-ios TARGETS AWSNativeSDK PACKAGE_HASH c3c9478c259ecb569fb2ce6fcfa733647adc3b6bd2854e8eff9de64bcd18c745) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) +ly_associate_package(PACKAGE_NAME Lua-5.4.4-rev1-ios TARGETS Lua PACKAGE_HASH 82f27bf6c745c98395dcea7ec72f82cb5254fd19fca9f5ac7a6246527a30bacb) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-ios TARGETS PhysX PACKAGE_HASH 4a5e38b385837248590018eb133444b4e440190414e6756191200a10c8fa5615) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-ios TARGETS mikkelsen PACKAGE_HASH 976aaa3ccd8582346132a10af253822ccc5d5bcc9ea5ba44d27848f65ee88a8a) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-ios TARGETS googletest PACKAGE_HASH 2f121ad9784c0ab73dfaa58e1fee05440a82a07cc556bec162eeb407688111a7)