Ver código fonte

Merge branch 'main' into Atom/santorac/CavityMaps-ATOM-14040

Chris Santora 4 anos atrás
pai
commit
829d8ab2d8
100 arquivos alterados com 4543 adições e 823 exclusões
  1. 34 8
      CMakeLists.txt
  2. 6 14
      Gem/Code/CMakeLists.txt
  3. 2 4
      Gem/Code/Source/AreaLightExampleComponent.cpp
  4. 2 0
      Gem/Code/Source/AtomSampleViewerModule.cpp
  5. 0 1
      Gem/Code/Source/Automation/AssetStatusTracker.cpp
  6. 10 1
      Gem/Code/Source/Automation/ScriptManager.cpp
  7. 3 1
      Gem/Code/Source/Automation/ScriptManager.h
  8. 1 2
      Gem/Code/Source/Automation/ScriptReporter.cpp
  9. 0 2
      Gem/Code/Source/AuxGeomSharedDrawFunctions.cpp
  10. 227 0
      Gem/Code/Source/BakedShaderVariantExampleComponent.cpp
  11. 75 0
      Gem/Code/Source/BakedShaderVariantExampleComponent.h
  12. 65 65
      Gem/Code/Source/CullingAndLodExampleComponent.cpp
  13. 17 17
      Gem/Code/Source/CullingAndLodExampleComponent.h
  14. 2 2
      Gem/Code/Source/DecalExampleComponent.cpp
  15. 0 1
      Gem/Code/Source/DynamicMaterialTestComponent.cpp
  16. 34 82
      Gem/Code/Source/LightCullingExampleComponent.cpp
  17. 4 14
      Gem/Code/Source/LightCullingExampleComponent.h
  18. 14 3
      Gem/Code/Source/MaterialHotReloadTestComponent.cpp
  19. 2 0
      Gem/Code/Source/MaterialHotReloadTestComponent.h
  20. 19 18
      Gem/Code/Source/MultiRenderPipelineExampleComponent.cpp
  21. 8 8
      Gem/Code/Source/MultiRenderPipelineExampleComponent.h
  22. 18 14
      Gem/Code/Source/MultiSceneExampleComponent.cpp
  23. 4 4
      Gem/Code/Source/MultiSceneExampleComponent.h
  24. 17 16
      Gem/Code/Source/ParallaxMappingExampleComponent.cpp
  25. 5 5
      Gem/Code/Source/ParallaxMappingExampleComponent.h
  26. 7 1
      Gem/Code/Source/Passes/RayTracingAmbientOcclusionPass.cpp
  27. 1 1
      Gem/Code/Source/RHI/AlphaToCoverageExampleComponent.cpp
  28. 4 4
      Gem/Code/Source/RHI/AsyncComputeExampleComponent.cpp
  29. 7 7
      Gem/Code/Source/RHI/BindlessPrototypeExampleComponent.cpp
  30. 1 1
      Gem/Code/Source/RHI/BindlessPrototypeExampleComponent.h
  31. 2 2
      Gem/Code/Source/RHI/ComputeExampleComponent.cpp
  32. 1 1
      Gem/Code/Source/RHI/CopyQueueComponent.cpp
  33. 1 1
      Gem/Code/Source/RHI/DualSourceBlendingComponent.cpp
  34. 1 3
      Gem/Code/Source/RHI/IndirectRenderingExampleComponent.cpp
  35. 1 1
      Gem/Code/Source/RHI/InputAssemblyExampleComponent.cpp
  36. 7 7
      Gem/Code/Source/RHI/MRTExampleComponent.cpp
  37. 3 3
      Gem/Code/Source/RHI/MSAAExampleComponent.cpp
  38. 1 1
      Gem/Code/Source/RHI/MultiThreadComponent.cpp
  39. 2 2
      Gem/Code/Source/RHI/MultipleViewsComponent.cpp
  40. 3 3
      Gem/Code/Source/RHI/QueryExampleComponent.cpp
  41. 12 8
      Gem/Code/Source/RHI/RayTracingExampleComponent.cpp
  42. 2 2
      Gem/Code/Source/RHI/SphericalHarmonicsExampleComponent.cpp
  43. 1 1
      Gem/Code/Source/RHI/StencilExampleComponent.cpp
  44. 1 1
      Gem/Code/Source/RHI/SubpassExampleComponent.cpp
  45. 1 1
      Gem/Code/Source/RHI/Texture3dExampleComponent.cpp
  46. 3 3
      Gem/Code/Source/RHI/TextureArrayExampleComponent.cpp
  47. 1 1
      Gem/Code/Source/RHI/TextureExampleComponent.cpp
  48. 2 2
      Gem/Code/Source/RHI/TextureMapExampleComponent.cpp
  49. 2 2
      Gem/Code/Source/RHI/TriangleExampleComponent.cpp
  50. 6 6
      Gem/Code/Source/RHI/TrianglesConstantBufferExampleComponent.cpp
  51. 1 1
      Gem/Code/Source/SSRExampleComponent.cpp
  52. 6 5
      Gem/Code/Source/SampleComponentManager.cpp
  53. 1 1
      Gem/Code/Source/SampleComponentManager.h
  54. 2 1
      Gem/Code/Source/SampleComponentManagerBus.h
  55. 87 89
      Gem/Code/Source/ShadowExampleComponent.cpp
  56. 21 21
      Gem/Code/Source/ShadowExampleComponent.h
  57. 122 116
      Gem/Code/Source/ShadowedBistroExampleComponent.cpp
  58. 27 26
      Gem/Code/Source/ShadowedBistroExampleComponent.h
  59. 0 1
      Gem/Code/Source/StreamingImageExampleComponent.cpp
  60. 0 2
      Gem/Code/Source/TonemappingExampleComponent.cpp
  61. 2 0
      Gem/Code/atomsampleviewergem_private_files.cmake
  62. 4 3
      Materials/DynamicMaterialTest/EmissiveMaterial.azsl
  63. 1 1
      Objects/Bistro/CHANGELOG.txt
  64. 3 3
      Objects/Bistro/README.txt
  65. 15 15
      Passes/CheckerboardPipeline.pass
  66. 10 10
      Passes/ComplexPipeline.pass
  67. 1 1
      Passes/MSAA_2x_RPI_Pipeline.pass
  68. 1 1
      Passes/MSAA_4x_RPI_Pipeline.pass
  69. 1 1
      Passes/MSAA_8x_RPI_Pipeline.pass
  70. 4 4
      Passes/MSAA_RPI_Pipeline_Core.pass
  71. 8 8
      Passes/MainPipeline.pass
  72. 14 14
      Passes/MainPipeline_Mobile.pass
  73. 4 4
      Passes/No_MSAA_RPI_Pipeline.pass
  74. 2 2
      Passes/PassTemplates.azasset
  75. 10 10
      Passes/SsaoPipeline.pass
  76. 0 10
      Scripts/AreaLightTest.bv.lua
  77. 0 3
      Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_metal.ppm
  78. 0 3
      Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_rough_metal.ppm
  79. 0 3
      Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_rough_nonmetal.ppm
  80. 1 1
      Scripts/ExpectedScreenshots/CullingAndLod/screenshot_1.ppm
  81. 1 1
      Scripts/ExpectedScreenshots/LightCulling/screenshot_capsulelights.ppm
  82. 1 1
      Scripts/ExpectedScreenshots/LightCulling/screenshot_decals.ppm
  83. 1 1
      Scripts/ExpectedScreenshots/LightCulling/screenshot_disklights.ppm
  84. 1 1
      Scripts/ExpectedScreenshots/LightCulling/screenshot_quadlights.ppm
  85. 0 3
      Scripts/ExpectedScreenshots/LightCulling/screenshot_spotlights.ppm
  86. 1 1
      Scripts/ExpectedScreenshots/MultiScene/Start_MultiScene1.ppm
  87. 1 1
      Scripts/ExpectedScreenshots/MultiScene/Start_MultiScene2.ppm
  88. 1 1
      Scripts/ExpectedScreenshots/ShadowedBistro/initial.ppm
  89. 1 1
      Scripts/ExpectedScreenshots/ShadowedBistro/spot_nofilter_table.ppm
  90. 0 14
      Scripts/LightCulling.bv.lua
  91. 2 1
      Scripts/MaterialHotReloadTest.bv.lua
  92. 27 27
      Scripts/ShadowTest.bv.lua
  93. 20 0
      Scripts/_AutomatedPeriodicTestSuite_.bv.lua
  94. 39 0
      Scripts/_AutomatedReviewTestSuite_.bv.lua
  95. 104 63
      Scripts/_FullTestSuite_.bv.lua
  96. 24 0
      ShaderLib/raytracingscenesrg.srgi
  97. 245 0
      ShaderVariants/Materials/Types/EnhancedPBR_ForwardPass.shadervariantlist
  98. 245 0
      ShaderVariants/Materials/Types/EnhancedPBR_ForwardPass_EDS.shadervariantlist
  99. 1428 0
      ShaderVariants/Materials/Types/StandardPBR_ForwardPass.shadervariantlist
  100. 1411 0
      ShaderVariants/Materials/Types/StandardPBR_ForwardPass_EDS.shadervariantlist

+ 34 - 8
CMakeLists.txt

@@ -9,13 +9,39 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #
 
-file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json)
+#! Adds the --project-path argument to the VS IDE debugger command arguments
+function(add_vs_debugger_arguments)
+    # Inject the project root into the --project-path argument into the Visual Studio Debugger arguments by defaults
+    list(APPEND app_targets AtomSampleViewer.GameLauncher AtomSampleViewer.ServerLauncher)
+    list(APPEND app_targets AssetBuilder AssetProcessor AssetProcessorBatch Editor)
+    foreach(app_target IN LISTS app_targets)
+        if (TARGET ${app_target})
+            set_property(TARGET ${app_target} APPEND PROPERTY VS_DEBUGGER_COMMAND_ARGUMENTS "--project-path=\"${CMAKE_CURRENT_LIST_DIR}\"")
+        endif()
+    endforeach()
+endfunction()
 
-string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name")
-if(${json_error})
-    message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'")
-endif()
+if(NOT PROJECT_NAME)
+    cmake_minimum_required(VERSION 3.19)
+    project(AtomSampleViewer
+        LANGUAGES C CXX
+        VERSION 1.0.0.0
+    )
+    include(EngineFinder.cmake OPTIONAL)
+    find_package(o3de REQUIRED)
+    o3de_initialize()
+    add_vs_debugger_arguments()
+else()
+    # Add the project_name to global LY_PROJECTS_TARGET_NAME property
+    file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json)
+
+    string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name")
+    if(json_error)
+        message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'")
+    endif()
 
-set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name})
-add_subdirectory(Gem)
-add_subdirectory(Standalone)
+    set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name})
+
+    add_subdirectory(Gem)
+    add_subdirectory(Standalone)
+endif()

+ 6 - 14
Gem/Code/CMakeLists.txt

@@ -18,8 +18,7 @@ ly_add_target(
         atomsampleviewergem_lib_files.cmake
     INCLUDE_DIRECTORIES
         PUBLIC
-            Include
-                Lib
+            Lib
     BUILD_DEPENDENCIES
         PUBLIC
             AZ::AzGameFramework
@@ -36,10 +35,9 @@ ly_add_target(
         ${pal_dir}/atomsampleviewer_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
     INCLUDE_DIRECTORIES
         PUBLIC
-            Include
-                Lib
-                Source
-                ${pal_dir}
+            Lib
+            Source
+            ${pal_dir}
     BUILD_DEPENDENCIES
         PUBLIC
             AZ::AzGameFramework
@@ -55,9 +53,6 @@ ly_add_target(
     FILES_CMAKE
         atomsampleviewergem_private_shared_files.cmake
         ../../atomsampleviewer_asset_files.cmake
-    INCLUDE_DIRECTORIES
-        PUBLIC
-            Include
     PLATFORM_INCLUDE_FILES
         ${pal_dir}/additional_${PAL_PLATFORM_NAME_LOWERCASE}_runtime_library.cmake
     BUILD_DEPENDENCIES
@@ -77,9 +72,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
             atomsampleviewergem_tools_files.cmake
         INCLUDE_DIRECTORIES
             PUBLIC
-                Include
-                    .
-                    Tools
+                .
+                Tools
         BUILD_DEPENDENCIES
             PRIVATE
                 AZ::AzGameFramework
@@ -102,8 +96,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
                 .
                 Source
                 Source/Platform/${PAL_PLATFORM_NAME}
-            PUBLIC
-                Include
         BUILD_DEPENDENCIES
             PUBLIC
                 AZ::AzCore

+ 2 - 4
Gem/Code/Source/AreaLightExampleComponent.cpp

@@ -314,8 +314,6 @@ namespace AtomSampleViewer
 
             float radius = GetLerpValue(m_config.m_radius, index, m_config.GetVaryRadius());
             m_diskLightFeatureProcessor->SetDiskRadius(handle, radius);
-
-            m_diskLightFeatureProcessor->SetLightEmitsBothDirections(handle, m_config.m_emitsBothDirections);
         }
     }
 
@@ -685,7 +683,7 @@ namespace AtomSampleViewer
             }
         }
 
-        if (m_config.m_lightType == Disk || m_config.m_lightType == Quad || m_config.m_lightType == Polygon)
+        if (m_config.m_lightType == Quad || m_config.m_lightType == Polygon)
         {
             if (ScriptableImGui::Checkbox("Emit Both Directions", &m_config.m_emitsBothDirections))
             {
@@ -825,7 +823,7 @@ namespace AtomSampleViewer
                 transform.SetRotation(AZ::ConvertEulerRadiansToQuaternion(AZ::Vector3(m_config.m_rotations[0], -m_config.m_rotations[1], m_config.m_rotations[2])));
                 transform.SetTranslation(lightPos);
                 transform *= AZ::Transform::CreateFromQuaternion(AZ::ConvertEulerRadiansToQuaternion(AZ::Vector3(AZ::Constants::Pi * 0.5f, 0.0f, 0.0f)));
-                m_auxGeom->DrawQuad(m_config.m_quadSize[0], m_config.m_quadSize[1], transform, nitsColor, drawStyle);
+                m_auxGeom->DrawQuad(m_config.m_quadSize[0], m_config.m_quadSize[1], AZ::Matrix3x4::CreateFromTransform(transform), nitsColor, drawStyle);
                 break;
             }
             case Polygon:

+ 2 - 0
Gem/Code/Source/AtomSampleViewerModule.cpp

@@ -17,6 +17,7 @@
 #include <AssetLoadTestComponent.h>
 #include <AuxGeomExampleComponent.h>
 #include <AtomSampleViewerSystemComponent.h>
+#include <BakedShaderVariantExampleComponent.h>
 #include <BistroBenchmarkComponent.h>
 #include <BloomExampleComponent.h>
 #include <CheckerboardExampleComponent.h>
@@ -126,6 +127,7 @@ namespace AtomSampleViewer
             m_descriptors.insert(m_descriptors.end(), {
                 AreaLightExampleComponent::CreateDescriptor(),
                 AssetLoadTestComponent::CreateDescriptor(),
+                BakedShaderVariantExampleComponent::CreateDescriptor(),
                 BistroBenchmarkComponent::CreateDescriptor(),
                 BloomExampleComponent::CreateDescriptor(),
                 CheckerboardExampleComponent::CreateDescriptor(),

+ 0 - 1
Gem/Code/Source/Automation/AssetStatusTracker.cpp

@@ -61,7 +61,6 @@ namespace AtomSampleViewer
 
         for (auto& assetData : m_allAssetStatusData)
         {
-            const AZStd::string& assetPath = assetData.first;
             const AssetStatusEvents& status = assetData.second;
 
             if (status.m_expecteCount > (status.m_succeeded + status.m_failed))

+ 10 - 1
Gem/Code/Source/Automation/ScriptManager.cpp

@@ -448,11 +448,12 @@ namespace AtomSampleViewer
         m_showScriptRunnerDialog = true;
     }
 
-    void ScriptManager::RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd)
+    void ScriptManager::RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd, int randomSeed)
     {
         m_testSuiteRunConfig.m_automatedRunEnabled = true;
         m_testSuiteRunConfig.m_testSuitePath = suiteFilePath;
         m_testSuiteRunConfig.m_closeOnTestScriptFinish = exitOnTestEnd;
+        m_testSuiteRunConfig.m_randomSeed = randomSeed;
     }
 
     void ScriptManager::AbortScripts(const AZStd::string& reason)
@@ -508,6 +509,8 @@ namespace AtomSampleViewer
             ImGui::Text("Settings");
             ImGui::Indent();
 
+            ImGui::InputInt("Random Seed for Test Order Execution", &m_testSuiteRunConfig.m_randomSeed);
+
             m_imageComparisonOptions.DrawImGuiSettings();
             if (ImGui::Button("Reset"))
             {
@@ -733,6 +736,7 @@ namespace AtomSampleViewer
         behaviorContext->Method("NormalizePath", &Script_NormalizePath);
         behaviorContext->Method("DegToRad", &Script_DegToRad);
         behaviorContext->Method("GetRenderApiName", &Script_GetRenderApiName);
+        behaviorContext->Method("GetRandomTestSeed", &Script_GetRandomTestSeed);
 
         // Samples...
         behaviorContext->Method("OpenSample", &Script_OpenSample);
@@ -1375,6 +1379,11 @@ namespace AtomSampleViewer
         
     }
 
+    int ScriptManager::Script_GetRandomTestSeed()
+    {
+        return s_instance->m_testSuiteRunConfig.m_randomSeed;
+    }
+
     void ScriptManager::CheckArcBallControllerHandler()
     {
         if (0 == AZ::Debug::ArcBallControllerRequestBus::GetNumOfEventHandlers(s_instance->m_cameraEntity->GetId()))

+ 3 - 1
Gem/Code/Source/Automation/ScriptManager.h

@@ -67,7 +67,7 @@ namespace AtomSampleViewer
 
         void OpenScriptRunnerDialog();
 
-        void RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd);
+        void RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd, int randomSeed);
         
     private:
 
@@ -99,6 +99,7 @@ namespace AtomSampleViewer
         static AZStd::string Script_NormalizePath(const AZStd::string& path);
         static float Script_DegToRad(float degrees);
         static AZStd::string Script_GetRenderApiName();
+        static int Script_GetRandomTestSeed();
 
         // Samples...
         static void Script_OpenSample(const AZStd::string& sampleName);
@@ -223,6 +224,7 @@ namespace AtomSampleViewer
             bool m_isStarted = false;
             bool m_closeOnTestScriptFinish = false;
             AZStd::string m_testSuitePath;
+            int m_randomSeed = 0; // Used to shuffle test order in a random manner
         };
 
         TestSuiteExecutionConfig m_testSuiteRunConfig;

+ 1 - 2
Gem/Code/Source/Automation/ScriptReporter.cpp

@@ -913,8 +913,7 @@ namespace AtomSampleViewer
         // Get source folder
         if (m_officialBaselineSourceFolder.empty())
         {
-            AZStd::string projectPath = AZ::Utils::GetProjectPath();
-            AzFramework::StringFunc::Path::Join(projectPath.c_str(), "Scripts/ExpectedScreenshots", m_officialBaselineSourceFolder);
+            m_officialBaselineSourceFolder = (AZ::IO::FixedMaxPath(AZ::Utils::GetProjectPath()) / "Scripts" / "ExpectedScreenshots").String();
 
             if (!io->Exists(m_officialBaselineSourceFolder.c_str()))
             {

+ 0 - 2
Gem/Code/Source/AuxGeomSharedDrawFunctions.cpp

@@ -936,9 +936,7 @@ namespace AtomSampleViewer
         float right = left + width;
         float bottom = -1.0f;
         float top = bottom + width;
-        float spacing = 1.0f;
         float yStart = -1.0f;
-        float y = yStart;
 
         //Draw opaque cube using DrawTriangles
         right = left + width;

+ 227 - 0
Gem/Code/Source/BakedShaderVariantExampleComponent.cpp

@@ -0,0 +1,227 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+
+#include <Automation/ScriptRunnerBus.h>
+#include <Automation/ScriptableImGui.h>
+#include <BakedShaderVariantExampleComponent.h>
+#include <SampleComponentConfig.h>
+#include <SampleComponentManager.h>
+
+#include <Atom/Feature/Material/MaterialAssignment.h>
+#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
+#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
+#include <Atom/RPI.Reflect/Model/ModelAsset.h>
+
+#include <Atom/RPI.Public/Pass/PassFilter.h>
+#include <Atom/RPI.Public/RPISystemInterface.h>
+#include <AzCore/Console/Console.h>
+#include <AzCore/IO/Path/Path.h>
+#include <AzCore/Utils/Utils.h>
+#include <AzFramework/Asset/AssetProcessorMessages.h>
+#include <AzFramework/Asset/AssetSystemBus.h>
+#include <AzFramework/IO/LocalFileIO.h>
+
+#include <RHI/BasicRHIComponent.h>
+
+namespace AtomSampleViewer
+{
+    using namespace AZ;
+    using namespace RPI;
+
+    namespace
+    {
+        namespace Products
+        {
+            static constexpr const char ModelFilePath[] = "objects/plane.azmodel";
+        } // namespace Products
+    } // namespace
+
+    void BakedShaderVariantExampleComponent::Reflect(ReflectContext* context)
+    {
+        if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
+        {
+            serializeContext->Class<BakedShaderVariantExampleComponent, CommonSampleComponentBase>()->Version(0);
+        }
+    }
+
+    BakedShaderVariantExampleComponent::BakedShaderVariantExampleComponent()
+        : m_imguiSidebar{"@user@/BakedShaderVariantExampleComponent/sidebar.xml"}
+        , m_materialBrowser{"@user@/BakedShaderVariantExampleComponent/material_browser.xml"}
+        , m_imGuiFrameTimer(FrameTimeLogSize, FrameTimeLogSize)
+        , m_imGuiForwardPassTimer(PassTimeLogSize, PassTimeLogSize)
+    {
+    }
+
+    void BakedShaderVariantExampleComponent::Activate()
+    {
+        TickBus::Handler::BusConnect();
+        m_imguiSidebar.Activate();
+
+        m_materialBrowser.SetFilter([this](const AZ::Data::AssetInfo& assetInfo) {
+            if (!AzFramework::StringFunc::Path::IsExtension(assetInfo.m_relativePath.c_str(), "azmaterial"))
+            {
+                return false;
+            }
+            return assetInfo.m_assetId.m_subId == 0;
+        });
+        m_materialBrowser.Activate();
+
+        Data::AssetId modelAssetId;
+        Data::AssetCatalogRequestBus::BroadcastResult(
+            modelAssetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, Products::ModelFilePath, nullptr, false);
+        AZ_Assert(modelAssetId.IsValid(), "Failed to get model asset id: %s", Products::ModelFilePath);
+        m_modelAsset.Create(modelAssetId);
+
+        const Transform cameraTransform = Transform::CreateFromQuaternionAndTranslation(
+            Quaternion::CreateFromAxisAngle(Vector3::CreateAxisZ(), AZ::Constants::Pi), Vector3{0.0f, 0.4f, 0.0f});
+        AZ::TransformBus::Event(GetCameraEntityId(), &AZ::TransformBus::Events::SetWorldTM, cameraTransform);
+
+        m_meshFeatureProcessor = Scene::GetFeatureProcessorForEntityContextId<Render::MeshFeatureProcessorInterface>(GetEntityContextId());
+
+        InitLightingPresets(true);
+
+        Transform meshTransform =
+            Transform::CreateFromQuaternion(Quaternion::CreateFromAxisAngle(Vector3::CreateAxisX(), -AZ::Constants::HalfPi));
+        m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_modelAsset, m_material);
+        m_meshFeatureProcessor->SetTransform(m_meshHandle, meshTransform);
+
+        AZStd::vector<AZStd::string> passHierarchy;
+        passHierarchy.push_back("ForwardMSAAPass");
+        AZ::RPI::PassHierarchyFilter passFilter(passHierarchy);
+        AZStd::vector<AZ::RPI::Pass*> foundPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passFilter);
+        m_forwardPass = foundPasses[0];
+        m_forwardPass->SetTimestampQueryEnabled(true);
+
+        SetRootVariantUsage(true);
+    }
+
+    void BakedShaderVariantExampleComponent::Deactivate()
+    {
+        SetRootVariantUsage(false);
+        
+        m_forwardPass->SetTimestampQueryEnabled(false);
+
+        m_meshFeatureProcessor->ReleaseMesh(m_meshHandle);
+
+        Data::AssetBus::Handler::BusDisconnect();
+        TickBus::Handler::BusDisconnect();
+        m_imguiSidebar.Deactivate();
+
+        m_material = nullptr;
+
+        ShutdownLightingPresets();
+    }
+
+    void BakedShaderVariantExampleComponent::OnTick(float deltaTime, ScriptTimePoint /*scriptTime*/)
+    {
+        m_imGuiFrameTimer.PushValue(deltaTime);
+
+        AZ::RPI::TimestampResult forwardTimestampResult = m_forwardPass->GetLatestTimestampResult();
+        double gpuForwardFrameTimeMs = aznumeric_cast<double>(forwardTimestampResult.GetDurationInNanoseconds()) / 1000000;
+        m_imGuiForwardPassTimer.PushValue(gpuForwardFrameTimeMs);
+
+
+        bool materialNeedsUpdate = false;
+        if (m_imguiSidebar.Begin())
+        {
+            ImGuiLightingPreset();
+
+            ImGuiAssetBrowser::WidgetSettings assetBrowserSettings;
+
+            assetBrowserSettings.m_labels.m_root = "Materials";
+            materialNeedsUpdate |= m_materialBrowser.Tick(assetBrowserSettings);
+
+            ImGui::Spacing();
+            ImGui::Separator();
+            ImGui::Spacing();
+
+
+            ImGui::Text("Shader Variant Usage:");
+            if (ScriptableImGui::Button("Force Root Variant"))
+            {
+                SetRootVariantUsage(true);
+            }
+            ImGui::SameLine();
+            if (ScriptableImGui::Button("Optimize Variant"))
+            {
+                SetRootVariantUsage(false);
+            }
+
+            ImGui::Spacing();
+            ImGui::Separator();
+            ImGui::Spacing();
+
+            ImGui::Text("FPS");
+            ImGuiHistogramQueue::WidgetSettings settings;
+            settings.m_reportInverse = true;
+            settings.m_units = "fps";
+            m_imGuiFrameTimer.Tick(deltaTime, settings);
+
+            ImGui::Spacing();
+            ImGui::Separator();
+            ImGui::Spacing();
+
+            ImGui::Text("GPU Forward Pass");
+            ImGuiHistogramQueue::WidgetSettings gpuMetricsSettings;
+            gpuMetricsSettings.m_units = "ms";
+            m_imGuiForwardPassTimer.Tick(gpuForwardFrameTimeMs, gpuMetricsSettings);
+
+            ImGui::Spacing();
+            ImGui::Separator();
+            ImGui::Spacing();
+
+            if (m_material && ImGui::Button("Material Details..."))
+            {
+                m_imguiMaterialDetails.SetMaterial(m_material);
+                m_imguiMaterialDetails.OpenDialog();
+            }
+
+            m_imguiSidebar.End();
+        }
+
+        m_imguiMaterialDetails.Tick();
+
+        if (materialNeedsUpdate)
+        {
+            MaterialChange();
+        }
+    }
+
+    void BakedShaderVariantExampleComponent::SetRootVariantUsage(bool enabled)
+    {
+        AZ::IConsole* console = AZ::Interface<AZ::IConsole>::Get();
+        console->PerformCommand(AZStd::string::format("r_forceRootShaderVariantUsage %s", enabled ? "true" : "false").c_str());
+    }
+
+    void BakedShaderVariantExampleComponent::MaterialChange()
+    {
+        AZ::Data::AssetId selectedMaterialAssetId = m_materialBrowser.GetSelectedAssetId();
+        if (!selectedMaterialAssetId.IsValid())
+        {
+            selectedMaterialAssetId =
+                AZ::RPI::AssetUtils::GetAssetIdForProductPath(DefaultPbrMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error);
+
+            if (!selectedMaterialAssetId.IsValid())
+            {
+                AZ_Error("BakedShaderVariantExampleComponent", false, "Failed to select material to render with.");
+                return;
+            }
+        }
+        else
+        {
+            AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset;
+            materialAsset.Create(selectedMaterialAssetId);
+            m_material = AZ::RPI::Material::FindOrCreate(materialAsset);
+            m_meshFeatureProcessor->SetMaterialAssignmentMap(m_meshHandle, m_material);
+        }
+    }
+} // namespace AtomSampleViewer

+ 75 - 0
Gem/Code/Source/BakedShaderVariantExampleComponent.h

@@ -0,0 +1,75 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+
+#pragma once
+
+#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
+#include <Atom/RPI.Reflect/Model/ModelAsset.h>
+#include <AzCore/Component/TickBus.h>
+#include <AzFramework/Asset/AssetSystemTypes.h>
+#include <CommonSampleComponentBase.h>
+#include <Utils/ImGuiSidebar.h>
+#include <Utils/ImGuiAssetBrowser.h>
+#include <Utils/ImGuiMaterialDetails.h>
+#include <Utils/ImGuiHistogramQueue.h>
+
+namespace AtomSampleViewer
+{
+    //! This test is for collecting metrics on the shader variant system by allowing users to switch from using
+    //! root shader variant to the optimized variant. To generate shader variants, use the Shader Management Console.
+    //! The shader options used by the material can be verified using the Material Details button in the sidebar.
+    //! FPS and root pass metrics are shown on the sidebar as well. To view metrics for specific passes, use the GPU
+    //! profiler.
+    class BakedShaderVariantExampleComponent final
+        : public CommonSampleComponentBase
+        , public AZ::TickBus::Handler
+        , public AZ::Data::AssetBus::Handler
+    {
+    public:
+        AZ_COMPONENT(BakedShaderVariantExampleComponent, "{4986DD5D-347E-4E11-BBD5-E364061666A1}", CommonSampleComponentBase);
+        BakedShaderVariantExampleComponent();
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        // AZ::Component overrides...
+        void Activate() override;
+        void Deactivate() override;
+
+    private:
+        AZ_DISABLE_COPY_MOVE(BakedShaderVariantExampleComponent);
+
+        // AZ::TickBus::Handler overrides...
+        void OnTick(float deltaTime, AZ::ScriptTimePoint scriptTime) override;
+
+        void MaterialChange();
+        void SetRootVariantUsage(bool enabled);
+
+        static constexpr uint32_t FrameTimeLogSize = 50;
+        static constexpr uint32_t PassTimeLogSize = 50;
+        ImGuiSidebar m_imguiSidebar;
+        ImGuiMaterialDetails m_imguiMaterialDetails;
+        ImGuiAssetBrowser m_materialBrowser;
+        ImGuiHistogramQueue m_imGuiFrameTimer;
+        ImGuiHistogramQueue m_imGuiForwardPassTimer;
+
+        AZ::Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr;
+
+        AZ::Data::Asset<AZ::RPI::MaterialAsset> m_materialAsset;
+        AZ::Data::Instance<AZ::RPI::Material> m_material;
+        AZ::Data::Asset<AZ::RPI::ModelAsset> m_modelAsset;
+        AZ::Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle;
+
+        AZ::RHI::Ptr<AZ::RPI::Pass> m_forwardPass;
+
+        size_t m_selectedShaderIndex = 0;
+    };
+} // namespace AtomSampleViewer

+ 65 - 65
Gem/Code/Source/CullingAndLodExampleComponent.cpp

@@ -102,7 +102,7 @@ namespace AtomSampleViewer
         ClearMeshes();
 
         m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
-        UpdateSpotLightCount(0);
+        UpdateDiskLightCount(0);
     }
 
     void CullingAndLodExampleComponent::OnTick(float deltaTime, AZ::ScriptTimePoint timePoint)
@@ -209,14 +209,14 @@ namespace AtomSampleViewer
         using namespace AZ;
 
         m_directionalLightShadowmapSizeIndex = s_shadowmapSizeIndexDefault;
-        m_spotLightShadowmapSize = Render::ShadowmapSize::None; // random
+        m_diskLightShadowmapSize = Render::ShadowmapSize::None; // random
         m_cascadeCount = s_cascadesCountDefault;
         m_ratioLogarithmUniform = s_ratioLogarithmUniformDefault;
-        m_spotLightCount = 0;
+        m_diskLightCount = 0;
 
         RPI::Scene* scene = RPI::Scene::GetSceneForEntityContextId(GetEntityContextId());
         m_directionalLightFeatureProcessor = scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
-        m_spotLightFeatureProcessor = scene->GetFeatureProcessor<Render::SpotLightFeatureProcessorInterface>();
+        m_diskLightFeatureProcessor = scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
 
         // directional light
         {
@@ -245,57 +245,61 @@ namespace AtomSampleViewer
             m_directionalLightHandle = handle;
         }
 
-        // spot lights
+        // disk lights
         {
-            m_spotLights.clear();
-            m_spotLights.reserve(SpotLightCountMax);
-            const float spotlightSpacing = 10.0f;
-            const int spotLightsPerRow = 10;
+            m_diskLights.clear();
+            m_diskLights.reserve(DiskLightCountMax);
+            const float disklightSpacing = 10.0f;
+            const int diskLightsPerRow = 10;
             const Color colors[5] = {Colors::Red, Colors::Green, Colors::Blue, Colors::Orange, Colors::Pink};
-            for (int index = 0; index < SpotLightCountMax; ++index)
+            for (int index = 0; index < DiskLightCountMax; ++index)
             {
-                float xPos = (index % spotLightsPerRow) * spotlightSpacing;
-                float yPos = (index / spotLightsPerRow) * spotlightSpacing;
-                m_spotLights.emplace_back(
+                float xPos = (index % diskLightsPerRow) * disklightSpacing;
+                float yPos = (index / diskLightsPerRow) * disklightSpacing;
+                m_diskLights.emplace_back(
                     colors[index % 5],
                     Vector3(xPos, yPos, 10.0f),
                     Vector3(1.0f, 1.0f, -1.0f).GetNormalized(),
                     Render::ShadowmapSize::Size256);
             }
-            UpdateSpotLightCount(20);
+            UpdateDiskLightCount(20);
         }
     }
 
-    void CullingAndLodExampleComponent::UpdateSpotLightCount(uint16_t count)
+    void CullingAndLodExampleComponent::UpdateDiskLightCount(uint16_t count)
     {
         using namespace AZ;
 
-        for (int index = count; index < m_spotLightCount; ++index)
+        for (int index = count; index < m_diskLightCount; ++index)
         {
-            SpotLightHandle& handle = m_spotLights[index].m_handle;
-            m_spotLightFeatureProcessor->ReleaseLight(handle);
+            DiskLightHandle& handle = m_diskLights[index].m_handle;
+            m_diskLightFeatureProcessor->ReleaseLight(handle);
         }
 
-        const int previousSpotLightCount = m_spotLightCount;
+        const int previousDiskLightCount = m_diskLightCount;
 
-        for (int index = previousSpotLightCount; index < count; ++index)
+        for (int index = previousDiskLightCount; index < count; ++index)
         {
-            Render::SpotLightFeatureProcessorInterface* const spotLightFP = m_spotLightFeatureProcessor;
-            const SpotLightHandle handle = spotLightFP->AcquireLight();
-            const SpotLight &spotLight = m_spotLights[index];
-
-            spotLightFP->SetPosition(handle, spotLight.m_position);
-            spotLightFP->SetDirection(handle, spotLight.m_direction);
-            spotLightFP->SetRgbIntensity(handle, Render::PhotometricColor<Render::PhotometricUnit::Candela>(spotLight.m_color * m_spotLightIntensity));
-            const float radius = sqrtf(m_spotLightIntensity / CutoffIntensity);
-            spotLightFP->SetAttenuationRadius(handle, radius);
-            spotLightFP->SetShadowmapSize(handle, m_spotLightShadowEnabled ? m_spotLights[index].m_shadowmapSize : Render::ShadowmapSize::None);
-            spotLightFP->SetConeAngles(handle, 45.f, 55.f);
-
-            m_spotLights[index].m_handle = handle;
+            Render::DiskLightFeatureProcessorInterface* const diskLightFP = m_diskLightFeatureProcessor;
+            const DiskLightHandle handle = diskLightFP->AcquireLight();
+            const DiskLight &diskLight = m_diskLights[index];
+
+            diskLightFP->SetPosition(handle, diskLight.m_position);
+            diskLightFP->SetDirection(handle, diskLight.m_direction);
+            diskLightFP->SetRgbIntensity(handle, Render::PhotometricColor<Render::PhotometricUnit::Candela>(diskLight.m_color * m_diskLightIntensity));
+            const float radius = sqrtf(m_diskLightIntensity / CutoffIntensity);
+            diskLightFP->SetAttenuationRadius(handle, radius);
+            diskLightFP->SetShadowsEnabled(handle, m_diskLightShadowEnabled);
+            if (m_diskLightShadowEnabled)
+            {
+                diskLightFP->SetShadowmapMaxResolution(handle, m_diskLights[index].m_shadowmapSize);
+            }
+            diskLightFP->SetConeAngles(handle, DegToRad(45.f), DegToRad(55.f));
+
+            m_diskLights[index].m_handle = handle;
         }
 
-        m_spotLightCount = count;
+        m_diskLightCount = count;
     }
 
     void CullingAndLodExampleComponent::DrawSidebar()
@@ -419,42 +423,42 @@ namespace AtomSampleViewer
 
         ImGui::Separator();
 
-        ImGui::Text("Spot Lights");
+        ImGui::Text("Disk Lights");
         ImGui::Indent();
         {
-            int spotLightCount = m_spotLightCount;
-            if (ImGui::SliderInt("Number", &spotLightCount, 0, SpotLightCountMax))
+            int diskLightCount = m_diskLightCount;
+            if (ImGui::SliderInt("Number", &diskLightCount, 0, DiskLightCountMax))
             {
-                UpdateSpotLightCount(spotLightCount);
+                UpdateDiskLightCount(diskLightCount);
             }
 
-            if (ImGui::SliderFloat("Intensity##spot", &m_spotLightIntensity, 0.f, 100000.f, "%.1f", 4.f))
+            if (ImGui::SliderFloat("Intensity##disk", &m_diskLightIntensity, 0.f, 100000.f, "%.1f", 4.f))
             {
-                for (const SpotLight& light : m_spotLights)
+                for (const DiskLight& light : m_diskLights)
                 {
                     if (light.m_handle.IsValid())
                     {
-                        m_spotLightFeatureProcessor->SetRgbIntensity(light.m_handle, Render::PhotometricColor<Render::PhotometricUnit::Candela>(light.m_color * m_spotLightIntensity));
-                        const float radius = sqrtf(m_spotLightIntensity / CutoffIntensity);
-                        m_spotLightFeatureProcessor->SetAttenuationRadius(light.m_handle, radius);
+                        m_diskLightFeatureProcessor->SetRgbIntensity(light.m_handle, Render::PhotometricColor<Render::PhotometricUnit::Candela>(light.m_color * m_diskLightIntensity));
+                        const float radius = sqrtf(m_diskLightIntensity / CutoffIntensity);
+                        m_diskLightFeatureProcessor->SetAttenuationRadius(light.m_handle, radius);
                     }
                 }
             }
 
-            bool spotLightShadowmapChanged = ImGui::Checkbox("Enable Shadow", &m_spotLightShadowEnabled);
+            bool diskLightShadowmapChanged = ImGui::Checkbox("Enable Shadow", &m_diskLightShadowEnabled);
             
             ImGui::Text("Shadowmap Size");
-            int newSize = static_cast<int>(m_spotLightShadowmapSize);
+            int newSize = static_cast<int>(m_diskLightShadowmapSize);
             // To avoid GPU memory consumption, we avoid bigger shadowmap sizes here.
-            spotLightShadowmapChanged = spotLightShadowmapChanged ||
+            diskLightShadowmapChanged = diskLightShadowmapChanged ||
                 ImGui::RadioButton("256", &newSize, static_cast<int>(Render::ShadowmapSize::Size256)) ||
                 ImGui::RadioButton("512", &newSize, static_cast<int>(Render::ShadowmapSize::Size512)) ||
                 ImGui::RadioButton("Random", &newSize, static_cast<int>(Render::ShadowmapSize::None));
 
-            if (spotLightShadowmapChanged)
+            if (diskLightShadowmapChanged)
             {
-                m_spotLightShadowmapSize = static_cast<Render::ShadowmapSize>(newSize);
-                UpdateSpotLightShadowmapSize();
+                m_diskLightShadowmapSize = static_cast<Render::ShadowmapSize>(newSize);
+                UpdateDiskLightShadowmapSize();
             }
         }
         ImGui::Unindent();
@@ -474,47 +478,43 @@ namespace AtomSampleViewer
         m_imguiSidebar.End();
     }
 
-    void CullingAndLodExampleComponent::UpdateSpotLightShadowmapSize()
+    void CullingAndLodExampleComponent::UpdateDiskLightShadowmapSize()
     {
         using namespace AZ::Render;
-        SpotLightFeatureProcessorInterface* const featureProcessor = m_spotLightFeatureProcessor;
+        DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
 
-        if (!m_spotLightShadowEnabled)
+        if (!m_diskLightShadowEnabled)
         {
             // disabled shadows
-            for (const SpotLight& light : m_spotLights)
+            for (const DiskLight& light : m_diskLights)
             {
                 if (light.m_handle.IsValid())
                 {
-                    featureProcessor->SetShadowmapSize(
-                        light.m_handle,
-                        ShadowmapSize::None);
+                    featureProcessor->SetShadowsEnabled(light.m_handle, false);
                 }
             }
         }
-        else if (m_spotLightShadowmapSize != ShadowmapSize::None)
+        else if (m_diskLightShadowmapSize != ShadowmapSize::None)
         {
             // uniform size
-            for (const SpotLight& light : m_spotLights)
+            for (const DiskLight& light : m_diskLights)
             {
                 if (light.m_handle.IsValid())
                 {
-                    featureProcessor->SetShadowmapSize(
-                        light.m_handle,
-                        m_spotLightShadowmapSize);
+                    featureProcessor->SetShadowsEnabled(light.m_handle, true);
+                    featureProcessor->SetShadowmapMaxResolution(light.m_handle, m_diskLightShadowmapSize);
                 }
             }
         }
         else
         {
             // random sizes
-            for (const SpotLight& light : m_spotLights)
+            for (const DiskLight& light : m_diskLights)
             {
                 if (light.m_handle.IsValid())
                 {
-                    featureProcessor->SetShadowmapSize(
-                        light.m_handle,
-                        light.m_shadowmapSize);
+                    featureProcessor->SetShadowsEnabled(light.m_handle, true);
+                    featureProcessor->SetShadowmapMaxResolution(light.m_handle, light.m_shadowmapSize);
                 }
             }
         }

+ 17 - 17
Gem/Code/Source/CullingAndLodExampleComponent.h

@@ -14,8 +14,8 @@
 
 #include <CommonSampleComponentBase.h>
 #include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
+#include <Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/ShadowConstants.h>
-#include <Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h>
 #include <Atom/Feature/Mesh/MeshFeatureProcessor.h>
 #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
 #include <Atom/RPI.Reflect/Model/ModelAsset.h>
@@ -49,30 +49,30 @@ namespace AtomSampleViewer
 
     private:
         using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle;
-        using SpotLightHandle = AZ::Render::SpotLightFeatureProcessorInterface::LightHandle;
+        using DiskLightHandle = AZ::Render::DiskLightFeatureProcessorInterface::LightHandle;
 
-        class SpotLight
+        class DiskLight
         {
         public:
-            SpotLight() = delete;
-            explicit SpotLight(const AZ::Color& color, const AZ::Vector3& position,
+            DiskLight() = delete;
+            explicit DiskLight(const AZ::Color& color, const AZ::Vector3& position,
                 const AZ::Vector3& direction, AZ::Render::ShadowmapSize shadowmapSize)
                 : m_color(color)
                 , m_position(position)
                 , m_direction(direction)
                 , m_shadowmapSize(shadowmapSize)
             {}
-            ~SpotLight() = default;
+            ~DiskLight() = default;
 
             const AZ::Color m_color;
             const AZ::Vector3 m_position;
             const AZ::Vector3 m_direction;
             const AZ::Render::ShadowmapSize m_shadowmapSize;
-            SpotLightHandle m_handle;
+            DiskLightHandle m_handle;
         };
 
-        static constexpr int SpotLightCountMax = 100;
-        static constexpr int SpotLightCountDefault = 10;
+        static constexpr int DiskLightCountMax = 100;
+        static constexpr int DiskLightCountDefault = 10;
         static constexpr float CutoffIntensity = 0.5f;
 
         static const AZ::Color DirectionalLightColor;
@@ -89,18 +89,18 @@ namespace AtomSampleViewer
         void ClearMeshes();
         void SpawnModelsIn2DGrid(uint32_t numAlongXAxis, uint32_t numAlongYAxis);
         void SetupLights();
-        void UpdateSpotLightCount(uint16_t count);
+        void UpdateDiskLightCount(uint16_t count);
 
         void DrawSidebar();
-        void UpdateSpotLightShadowmapSize();
+        void UpdateDiskLightShadowmapSize();
 
         float m_originalFarClipDistance = 0.f;
 
         // lights
         AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
-        AZ::Render::SpotLightFeatureProcessorInterface* m_spotLightFeatureProcessor = nullptr;
+        AZ::Render::DiskLightFeatureProcessorInterface* m_diskLightFeatureProcessor = nullptr;
         DirectionalLightHandle m_directionalLightHandle;
-        AZStd::vector<SpotLight> m_spotLights;
+        AZStd::vector<DiskLight> m_diskLights;
 
         // models
         AZStd::vector<AZ::Render::MeshFeatureProcessorInterface::MeshHandle> m_meshHandles;
@@ -111,8 +111,8 @@ namespace AtomSampleViewer
         float m_directionalLightPitch = -1.22;
         float m_directionalLightYaw = 0.7f;
         float m_directionalLightIntensity = 4.f;
-        float m_spotLightIntensity = 2000.f;
-        int m_spotLightCount = 0;
+        float m_diskLightIntensity = 2000.f;
+        int m_diskLightCount = 0;
 
         // Shadowmap
         static const AZ::Render::ShadowmapSize s_shadowmapSizes[];
@@ -123,8 +123,8 @@ namespace AtomSampleViewer
         int m_directionalLightShadowmapSizeIndex = 0;
         int m_cascadeCount = 0;
         float m_ratioLogarithmUniform = 0.f;
-        AZ::Render::ShadowmapSize m_spotLightShadowmapSize = AZ::Render::ShadowmapSize::None;
-        bool m_spotLightShadowEnabled = true;
+        AZ::Render::ShadowmapSize m_diskLightShadowmapSize = AZ::Render::ShadowmapSize::None;
+        bool m_diskLightShadowEnabled = true;
 
         // Edge-softening of directional light shadows
         static const AZ::Render::ShadowFilterMethod s_shadowFilterMethods[];

+ 2 - 2
Gem/Code/Source/DecalExampleComponent.cpp

@@ -33,8 +33,8 @@ namespace AtomSampleViewer
 {
     namespace
     {
-        static constexpr char* TargetMeshName = "objects/plane.azmodel";
-        static constexpr char* TargetMaterialName = "materials/defaultpbr.azmaterial";
+        static constexpr const char* TargetMeshName = "objects/plane.azmodel";
+        static constexpr const char* TargetMaterialName = "materials/defaultpbr.azmaterial";
     }
 
     void DecalExampleComponent::Reflect(AZ::ReflectContext* context)

+ 0 - 1
Gem/Code/Source/DynamicMaterialTestComponent.cpp

@@ -173,7 +173,6 @@ namespace AtomSampleViewer
 
         for (int i = 0; i < m_meshHandles.size(); ++i)
         {
-            auto& meshHandle = m_meshHandles[i];
             auto& material = m_materials[i];
 
             static const float CylesPerSecond = 0.5f;

+ 34 - 82
Gem/Code/Source/LightCullingExampleComponent.cpp

@@ -29,6 +29,7 @@
 #include <AzCore/Component/TransformBus.h>
 #include <AzCore/Math/Transform.h>
 #include <AzCore/Math/Obb.h>
+#include <AzCore/Math/Matrix3x4.h>
 #include <AzFramework/Components/CameraBus.h>
 #include <Atom/RPI.Public/RPISystemInterface.h>
 #include <Atom/RPI.Public/Scene.h>
@@ -282,14 +283,6 @@ namespace AtomSampleViewer
         }
     }
 
-    void LightCullingExampleComponent::CreateSpotLights()
-    {
-        for (int i = 0; i < m_settings[(int)LightType::Spot].m_numActive; ++i)
-        {
-            CreateSpotLight(i);
-        }
-    }
-
     void LightCullingExampleComponent::CreateDiskLights()
     {
         for (int i = 0; i < m_settings[(int)LightType::Disk].m_numActive; ++i)
@@ -360,7 +353,6 @@ namespace AtomSampleViewer
         ImGui::Separator();
 
         DrawSidebarPointLightsSection(&m_settings[(int)LightType::Point]);
-        DrawSidebarSpotLightsSection(&m_settings[(int)LightType::Spot]);
         DrawSidebarDiskLightsSection(&m_settings[(int)LightType::Disk]);
         DrawSidebarCapsuleLightSection(&m_settings[(int)LightType::Capsule]);
         DrawSidebarQuadLightsSections(&m_settings[(int)LightType::Quad]);
@@ -384,21 +376,6 @@ namespace AtomSampleViewer
         }
     }
 
-    void LightCullingExampleComponent::DrawSidebarSpotLightsSection(LightSettings* lightSettings)
-    {
-        ScriptableImGui::ScopedNameContext context{"Spot Lights"};
-        if (ImGui::CollapsingHeader("Spot Lights", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
-        {
-            m_refreshLights |= ScriptableImGui::SliderInt("Spot light count", &lightSettings->m_numActive, 0, MaxNumLights);
-            m_refreshLights |= ScriptableImGui::SliderFloat("Spot Intensity", &lightSettings->m_intensity, 0.0f, 200.0f);
-            m_refreshLights |= ScriptableImGui::Checkbox("Enable automatic light falloff (Spot)", &lightSettings->m_enableAutomaticFalloff);
-            m_refreshLights |= ScriptableImGui::SliderFloat("Spot Attenuation Radius", &lightSettings->m_attenuationRadius, 0.0f, 20.0f);
-            m_refreshLights |= ScriptableImGui::SliderFloat("Inner Cone (degrees)", &m_spotInnerConeDegrees, 0.0f, 180.0f);
-            m_refreshLights |= ScriptableImGui::SliderFloat("Outer Cone (degrees)", &m_spotOuterConeDegrees, 0.0f, 180.0f);
-            ScriptableImGui::Checkbox("Draw Debug Cones", &lightSettings->m_enableDebugDraws);
-        }
-    }
-
     void LightCullingExampleComponent::DrawSidebarDiskLightsSection(LightSettings* lightSettings)
     {
         ScriptableImGui::ScopedNameContext context{"Disk Lights"};
@@ -408,8 +385,18 @@ namespace AtomSampleViewer
             m_refreshLights |= ScriptableImGui::SliderFloat("Disk Radius", &m_diskRadius, 0.0f, 20.0f);
             m_refreshLights |= ScriptableImGui::SliderFloat("Disk Attenuation Radius", &lightSettings->m_attenuationRadius, 0.0f, 20.0f);
             m_refreshLights |= ScriptableImGui::SliderFloat("Disk Intensity", &lightSettings->m_intensity, 0.0f, 200.0f);
-            m_refreshLights |= ScriptableImGui::Checkbox("Double sided disk", &m_isDiskDoubleSided);
-            ScriptableImGui::Checkbox("Draw disk lights", &lightSettings->m_enableDebugDraws);
+            m_refreshLights |= ScriptableImGui::Checkbox("Enable Disk Cone", &m_diskConesEnabled);
+
+            if (m_diskConesEnabled)
+            {
+                m_refreshLights |= ScriptableImGui::SliderFloat("Inner Cone (degrees)", &m_diskInnerConeDegrees, 0.0f, 180.0f);
+                m_refreshLights |= ScriptableImGui::SliderFloat("Outer Cone (degrees)", &m_diskOuterConeDegrees, 0.0f, 180.0f);
+                ScriptableImGui::Checkbox("Draw Debug Cones", &lightSettings->m_enableDebugDraws);
+            }
+            else
+            {
+                ScriptableImGui::Checkbox("Draw disk lights", &lightSettings->m_enableDebugDraws);
+            }
         }
     }
 
@@ -496,9 +483,13 @@ namespace AtomSampleViewer
         m_diskLightFeatureProcessor->SetPosition(light.m_lightHandle, light.m_position);
         m_diskLightFeatureProcessor->SetRgbIntensity(light.m_lightHandle, PhotometricColor<PhotometricUnit::Candela>(settings.m_intensity * light.m_color));
         m_diskLightFeatureProcessor->SetDirection(light.m_lightHandle, light.m_direction);
-        m_diskLightFeatureProcessor->SetLightEmitsBothDirections(light.m_lightHandle, m_isDiskDoubleSided);
+        
+        m_diskLightFeatureProcessor->SetConstrainToConeLight(light.m_lightHandle, m_diskConesEnabled);
+        if (m_diskConesEnabled)
+        {
+            m_diskLightFeatureProcessor->SetConeAngles(light.m_lightHandle, DegToRad(m_diskInnerConeDegrees), DegToRad(m_diskOuterConeDegrees));
+        }
 
-        float attenuationRadius = settings.m_enableAutomaticFalloff ? AutoCalculateAttenuationRadius(light.m_color, settings.m_intensity) : settings.m_attenuationRadius;
         m_diskLightFeatureProcessor->SetAttenuationRadius(light.m_lightHandle, m_settings[(int)LightType::Disk].m_attenuationRadius);
     }
 
@@ -538,21 +529,6 @@ namespace AtomSampleViewer
         m_quadLightFeatureProcessor->SetPosition(light.m_lightHandle, light.m_position);
     }
 
-    void LightCullingExampleComponent::CreateSpotLight(int index)
-    {
-        auto& light = m_spotLights[index];
-        light.m_lightHandle = m_spotLightFeatureProcessor->AcquireLight();
-        const LightSettings& settings = m_settings[(int)LightType::Spot];
-
-        m_spotLightFeatureProcessor->SetPosition(light.m_lightHandle, light.m_position);
-        m_spotLightFeatureProcessor->SetDirection(light.m_lightHandle, light.m_direction);
-        m_spotLightFeatureProcessor->SetRgbIntensity(light.m_lightHandle, PhotometricColor<PhotometricUnit::Candela>(settings.m_intensity * light.m_color));
-
-        float attenuationRadius = settings.m_enableAutomaticFalloff ? AutoCalculateAttenuationRadius(light.m_color, settings.m_intensity) : settings.m_attenuationRadius;
-        m_spotLightFeatureProcessor->SetAttenuationRadius(light.m_lightHandle, attenuationRadius);
-        m_spotLightFeatureProcessor->SetConeAngles(light.m_lightHandle, m_spotInnerConeDegrees, m_spotOuterConeDegrees);
-    }
-
     void LightCullingExampleComponent::CreateDecal(int index)
     {
         Decal& decal = m_decals[index];
@@ -594,25 +570,6 @@ namespace AtomSampleViewer
         }
     }
 
-    void LightCullingExampleComponent::DrawSpotLightDebugCones(AZ::RPI::AuxGeomDrawPtr auxGeom)
-    {
-        const LightSettings& settings = m_settings[(int)LightType::Spot];
-        int numToDraw = AZStd::min(settings.m_numActive, aznumeric_cast<int>(m_spotLights.size()));
-        for (int i = 0; i < numToDraw; ++i)
-        {
-            const auto& light = m_spotLights[i];
-            if (light.m_lightHandle.IsNull())
-            {
-                continue;
-            }
-
-            float height = settings.m_enableAutomaticFalloff ? AutoCalculateAttenuationRadius(light.m_color, settings.m_intensity) : settings.m_attenuationRadius;
-            float angleRadians = AZ::DegToRad(m_spotOuterConeDegrees * 0.5f);
-            float radius = tanf(angleRadians) * height;
-            auxGeom->DrawCone(light.m_position + light.m_direction * height, -light.m_direction, radius, height, light.m_color, AZ::RPI::AuxGeomDraw::DrawStyle::Shaded);
-        }
-    }
-
     void LightCullingExampleComponent::DrawDecalDebugBoxes(AZ::RPI::AuxGeomDrawPtr auxGeom)
     {
         int numToDraw = AZStd::min(m_settings[(int)LightType::Decal].m_numActive, aznumeric_cast<int>(m_decals.size()));
@@ -666,7 +623,7 @@ namespace AtomSampleViewer
 
                 // Rotate 90 degrees so that the debug draw is aligned properly with the quad light
                 transform *= AZ::Transform::CreateFromQuaternion(AZ::ConvertEulerRadiansToQuaternion(AZ::Vector3(AZ::Constants::HalfPi, 0.0f, 0.0f)));
-                auxGeom->DrawQuad(m_quadLightSize[0], m_quadLightSize[1], transform, light.m_color);
+                auxGeom->DrawQuad(m_quadLightSize[0], m_quadLightSize[1], AZ::Matrix3x4::CreateFromTransform(transform), light.m_color);
             }
         }
     }
@@ -680,10 +637,6 @@ namespace AtomSampleViewer
             {
                 DrawPointLightDebugSpheres(auxGeom);
             }
-            if (m_settings[(int)LightType::Spot].m_enableDebugDraws)
-            {
-                DrawSpotLightDebugCones(auxGeom);
-            }
             if (m_settings[(int)LightType::Disk].m_enableDebugDraws)
             {
                 DrawDiskLightDebugObjects(auxGeom);
@@ -725,35 +678,37 @@ namespace AtomSampleViewer
 
     void LightCullingExampleComponent::InitLightArrays()
     {
-        // Set seed to the same value each time so values are consistent between multiple app runs.
-        // Intended for use with the screenshot comparison tool
-        m_random.SetSeed(0);
-
         const auto InitLight = [this](auto& light)
             {
                 light.m_color = GetRandomColor();
                 light.m_position = GetRandomPositionInsideWorldModel();
                 light.m_direction = GetRandomDirection();
             };
-
+        
+        // Set seed to a specific value for each light type so values are consistent between multiple app runs
+        // And changes to one type don't polute the random numbers for another type.
+        // Intended for use with the screenshot comparison tool
+        m_random.SetSeed(0);
         m_pointLights.resize(MaxNumLights);
         AZStd::for_each(m_pointLights.begin(), m_pointLights.end(), InitLight);
-
-        m_spotLights.resize(MaxNumLights);
-        AZStd::for_each(m_spotLights.begin(), m_spotLights.end(), InitLight);
-
+        
+        m_random.SetSeed(1);
         m_diskLights.resize(MaxNumLights);
         AZStd::for_each(m_diskLights.begin(), m_diskLights.end(), InitLight);
-
+        
+        m_random.SetSeed(2);
         m_capsuleLights.resize(MaxNumLights);
         AZStd::for_each(m_capsuleLights.begin(), m_capsuleLights.end(), InitLight);
+
+        m_random.SetSeed(3);
         m_decals.resize(MaxNumLights);
         AZStd::for_each(m_decals.begin(), m_decals.end(), [&](Decal& decal)
             {
                 decal.m_position = GetRandomPositionInsideWorldModel();
                 decal.m_quaternion = AZ::Quaternion::CreateFromAxisAngle(GetRandomDirection(), GetRandomNumber(0.0f, AZ::Constants::TwoPi));
             });
-
+        
+        m_random.SetSeed(4);
         m_quadLights.resize(MaxNumLights);
         AZStd::for_each(m_quadLights.begin(), m_quadLights.end(), InitLight);
     }
@@ -762,7 +717,6 @@ namespace AtomSampleViewer
     {
         AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get();
         m_pointLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::PointLightFeatureProcessorInterface>();
-        m_spotLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::SpotLightFeatureProcessorInterface>();
         m_diskLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::DiskLightFeatureProcessorInterface>();
         m_capsuleLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::CapsuleLightFeatureProcessorInterface>();
         m_quadLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::QuadLightFeatureProcessorInterface>();
@@ -798,7 +752,7 @@ namespace AtomSampleViewer
                         trianglePass->SetEnabled(m_heatmapOpacity > 0.0f);
                         Data::Instance<ShaderResourceGroup> srg = trianglePass->GetShaderResourceGroup();
                         RHI::ShaderInputConstantIndex opacityIndex = srg->FindShaderInputConstantIndex(AZ::Name("m_heatmapOpacity"));
-                        bool setOk = srg->SetConstant<float>(opacityIndex, m_heatmapOpacity);
+                        [[maybe_unused]] bool setOk = srg->SetConstant<float>(opacityIndex, m_heatmapOpacity);
                         AZ_Warning("LightCullingExampleComponent", setOk, "Unable to set heatmap opacity");
                     }
                 }
@@ -867,7 +821,6 @@ namespace AtomSampleViewer
     void LightCullingExampleComponent::DestroyLightsAndDecals()
     {
         DestroyLights(m_pointLightFeatureProcessor, m_pointLights);
-        DestroyLights(m_spotLightFeatureProcessor, m_spotLights);
         DestroyLights(m_diskLightFeatureProcessor, m_diskLights);
         DestroyLights(m_capsuleLightFeatureProcessor, m_capsuleLights);
         DestroyLights(m_quadLightFeatureProcessor, m_quadLights);
@@ -877,7 +830,6 @@ namespace AtomSampleViewer
     void LightCullingExampleComponent::CreateLightsAndDecals()
     {
         CreatePointLights();
-        CreateSpotLights();
         CreateDiskLights();
         CreateCapsuleLights();
         CreateQuadLights();

+ 4 - 14
Gem/Code/Source/LightCullingExampleComponent.h

@@ -24,7 +24,6 @@
 
 #include <Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h>
-#include <Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/CapsuleLightFeatureProcessorInterface.h>
 #include <Atom/Feature/Decals/DecalFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/QuadLightFeatureProcessorInterface.h>
@@ -65,7 +64,6 @@ namespace AtomSampleViewer
         enum class LightType
         {
             Point,
-            Spot,
             Disk,
             Capsule,
             Quad,
@@ -83,7 +81,6 @@ namespace AtomSampleViewer
         };
 
         using PointLightHandle = AZ::Render::PointLightFeatureProcessorInterface::LightHandle;
-        using SpotLightHandle = AZ::Render::SpotLightFeatureProcessorInterface::LightHandle;
         using DiskLightHandle = AZ::Render::DiskLightFeatureProcessorInterface::LightHandle;
         using CapsuleLightHandle = AZ::Render::CapsuleLightFeatureProcessorInterface::LightHandle;
         using QuadLightHandle = AZ::Render::QuadLightFeatureProcessorInterface::LightHandle;
@@ -105,7 +102,6 @@ namespace AtomSampleViewer
 
         void DrawDebuggingHelpers();
         void DrawPointLightDebugSpheres(AZ::RPI::AuxGeomDrawPtr auxGeom);
-        void DrawSpotLightDebugCones(AZ::RPI::AuxGeomDrawPtr auxGeom);
         void DrawDiskLightDebugObjects(AZ::RPI::AuxGeomDrawPtr auxGeom);
         void DrawCapsuleLightDebugObjects(AZ::RPI::AuxGeomDrawPtr auxGeom);
         void DrawDecalDebugBoxes(AZ::RPI::AuxGeomDrawPtr auxGeom);
@@ -125,9 +121,6 @@ namespace AtomSampleViewer
         void CreatePointLights();
         void CreatePointLight(int index);
 
-        void CreateSpotLights();
-        void CreateSpotLight(int index);
-
         void CreateDiskLights();
         void CreateDiskLight(int index);
 
@@ -157,7 +150,6 @@ namespace AtomSampleViewer
         void DestroyLightsAndDecals();
 
         void DrawSidebarPointLightsSection(LightSettings* lightSettings);
-        void DrawSidebarSpotLightsSection(LightSettings* lightSettings);
         void DrawSidebarDiskLightsSection(LightSettings* lightSettings);
         void DrawSidebarCapsuleLightSection(LightSettings* lightSettings);
         void DrawSidebarDecalSection(LightSettings* lightSettings);
@@ -193,7 +185,6 @@ namespace AtomSampleViewer
         AZStd::array<LightSettings, (size_t)LightType::Count> m_settings;
 
         AZStd::vector<Light<PointLightHandle>> m_pointLights;
-        AZStd::vector<Light<SpotLightHandle>> m_spotLights;
         AZStd::vector<Light<DiskLightHandle>> m_diskLights;
         AZStd::vector<Light<CapsuleLightHandle>> m_capsuleLights;
         AZStd::vector<Light<QuadLightHandle>> m_quadLights;
@@ -217,14 +208,14 @@ namespace AtomSampleViewer
         float m_smoothedFPS = 0.0f;
         float m_bulbRadius = 3.0f;
 
-        float m_spotInnerConeDegrees = 22.0f;
-        float m_spotOuterConeDegrees = 90.0f;
-
+        bool m_diskConesEnabled = false;
+        float m_diskInnerConeDegrees = 22.0f;
+        float m_diskOuterConeDegrees = 90.0f;
+        
         float m_capsuleRadius = 0.1f;
         float m_capsuleLength = 3.0f;
 
         float m_diskRadius = 3.0f;
-        bool m_isDiskDoubleSided = false;
         bool m_isQuadLightDoubleSided = false;
         bool m_quadLightsUseFastApproximation = false;
 
@@ -240,7 +231,6 @@ namespace AtomSampleViewer
         AZ::Data::Asset<AZ::Data::AssetData> m_decalMaterial;
 
         AZ::Render::PointLightFeatureProcessorInterface* m_pointLightFeatureProcessor = nullptr;
-        AZ::Render::SpotLightFeatureProcessorInterface* m_spotLightFeatureProcessor = nullptr;
         AZ::Render::DiskLightFeatureProcessorInterface* m_diskLightFeatureProcessor = nullptr;
         AZ::Render::CapsuleLightFeatureProcessorInterface* m_capsuleLightFeatureProcessor = nullptr;
         AZ::Render::QuadLightFeatureProcessorInterface* m_quadLightFeatureProcessor = nullptr;

+ 14 - 3
Gem/Code/Source/MaterialHotReloadTestComponent.cpp

@@ -162,6 +162,7 @@ namespace AtomSampleViewer
         DeleteTestFile(Sources::ShaderVariantListFileName);
 
         m_initStatus = InitStatus::ClearingTestAssets;
+        m_clearAssetsTimeout = 5.0f;
 
         // Wait until the test material is fully initialized. Use a long timeout because it can take a while for the shaders to compile.
         ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScriptWithTimeout, LongTimeout);
@@ -368,13 +369,23 @@ namespace AtomSampleViewer
     {
         if (m_initStatus == InitStatus::ClearingTestAssets)
         {
+            m_clearAssetsTimeout -= deltaTime;
+
             Data::AssetId materialAssetId = GetAssetId(Products::MaterialFilePath);
             Data::AssetId materialTypeAssetId = GetAssetId(Products::MaterialTypeFilePath);
             Data::AssetId shaderAssetId = GetAssetId(Products::ShaderFilePath);
 
-            if (!materialAssetId.IsValid() &&
-                !materialTypeAssetId.IsValid() &&
-                !shaderAssetId.IsValid())
+            bool proceed = !materialAssetId.IsValid() && !materialTypeAssetId.IsValid() && !shaderAssetId.IsValid();
+
+            if (!proceed && m_clearAssetsTimeout < 0)
+            {
+                // There was a specific bug in the Asset Processor where deleting a source file does not always remove the corresponding product
+                // from the cache and from the asset database.
+                AZ_Error("MaterialHotReloadTestComponent", false, "Timed out while waiting for test assets to be removed.");
+                proceed = true;
+            }
+
+            if (proceed)
             {
                 // [GFX TODO] [ATOM-5899] Once this ticket is addressed, This block can call all required CopyTestFile() at once,
                 //            and the states InitStatus::CopyingDefault***TestFile won't be needed.

+ 2 - 0
Gem/Code/Source/MaterialHotReloadTestComponent.h

@@ -113,5 +113,7 @@ namespace AtomSampleViewer
         AZ::Data::Instance<AZ::RPI::Material>  m_shaderVariantIndicatorMaterial_current;
 
         FileIOErrorHandler m_fileIoErrorHandler;
+
+        float m_clearAssetsTimeout = 0.0f;
     };
 } // namespace AtomSampleViewer

+ 19 - 18
Gem/Code/Source/MultiRenderPipelineExampleComponent.cpp

@@ -77,7 +77,7 @@ namespace AtomSampleViewer
         m_scene = RPI::RPISystemInterface::Get()->GetDefaultScene();
 
         // Save references of different feature processors
-        m_spotLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::SpotLightFeatureProcessorInterface>();
+        m_diskLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
         m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
         m_skyboxFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::SkyBoxFeatureProcessorInterface>();
         m_postProcessFeatureProcessor = m_scene->GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessorInterface>();
@@ -156,9 +156,9 @@ namespace AtomSampleViewer
         {
             AddDirectionalLight();
         }
-        if (m_hasSpotLight)
+        if (m_hasDiskLight)
         {
-            AddSpotLight();
+            AddDiskLight();
         }
         if (m_enabledSkybox)
         {
@@ -247,31 +247,32 @@ namespace AtomSampleViewer
         }
     }
 
-    void MultiRenderPipelineExampleComponent::AddSpotLight()
+    void MultiRenderPipelineExampleComponent::AddDiskLight()
     {
-        Render::SpotLightFeatureProcessorInterface* const featureProcessor = m_spotLightFeatureProcessor;
+        Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
 
-        const SpotLightHandle handle = featureProcessor->AcquireLight();
+        const DiskLightHandle handle = featureProcessor->AcquireLight();
 
         AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(Colors::Green * 500.0f);
         featureProcessor->SetRgbIntensity(handle, lightColor);
         featureProcessor->SetAttenuationRadius(handle, 30.0f);
-        featureProcessor->SetConeAngles(handle, 35*0.9f, 35);
-        featureProcessor->SetShadowmapSize(handle, Render::ShadowmapSize::Size1024);
+        featureProcessor->SetConeAngles(handle, DegToRad(17.5f * 0.9f), DegToRad(17.5f));
+        featureProcessor->SetShadowsEnabled(handle, true);
+        featureProcessor->SetShadowmapMaxResolution(handle, Render::ShadowmapSize::Size1024);
         Vector3 position(0, 5, 7);
         Vector3 direction = -position;
         direction.Normalize();
         featureProcessor->SetPosition(handle, position);
         featureProcessor->SetDirection(handle, direction);
 
-        m_spotLightHandle = handle;
+        m_diskLightHandle = handle;
     }
 
-    void MultiRenderPipelineExampleComponent::RemoveSpotLight()
+    void MultiRenderPipelineExampleComponent::RemoveDiskLight()
     {
-        if (m_spotLightHandle.IsValid())
+        if (m_diskLightHandle.IsValid())
         {
-            m_spotLightFeatureProcessor->ReleaseLight(m_spotLightHandle);
+            m_diskLightFeatureProcessor->ReleaseLight(m_diskLightHandle);
         }
     }
 
@@ -386,7 +387,7 @@ namespace AtomSampleViewer
     {
         RemoveIBL();
         DisableSkybox();
-        RemoveSpotLight();
+        RemoveDiskLight();
         RemoveDirectionalLight();
         DisableDepthOfField();
 
@@ -407,7 +408,7 @@ namespace AtomSampleViewer
         CleanUpScene();
 
         m_directionalLightFeatureProcessor = nullptr;
-        m_spotLightFeatureProcessor = nullptr;
+        m_diskLightFeatureProcessor = nullptr;
         m_skyboxFeatureProcessor = nullptr;
         m_scene = nullptr;
     }
@@ -538,15 +539,15 @@ namespace AtomSampleViewer
                 ImGui::Unindent();
             }
 
-            if (ScriptableImGui::Checkbox("Add/Remove Spot Light", &m_hasSpotLight))
+            if (ScriptableImGui::Checkbox("Add/Remove Spot Light", &m_hasDiskLight))
             {
-                if (m_hasSpotLight)
+                if (m_hasDiskLight)
                 {
-                    AddSpotLight();
+                    AddDiskLight();
                 }
                 else
                 {
-                    RemoveSpotLight();
+                    RemoveDiskLight();
                 }
             }
 

+ 8 - 8
Gem/Code/Source/MultiRenderPipelineExampleComponent.h

@@ -24,7 +24,7 @@
 #include <AzFramework/Windowing/NativeWindow.h>
 
 #include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
-#include <Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h>
+#include <Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/ShadowConstants.h>
 #include <Atom/Feature/SkyBox/SkyBoxFeatureProcessorInterface.h>
 #include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
@@ -78,8 +78,8 @@ namespace AtomSampleViewer
         void AddDirectionalLight();
         void RemoveDirectionalLight();
 
-        void AddSpotLight();
-        void RemoveSpotLight();
+        void AddDiskLight();
+        void RemoveDiskLight();
 
         void EnableSkybox();
         void DisableSkybox();
@@ -95,15 +95,15 @@ namespace AtomSampleViewer
         
         // For scene content
         using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle;
-        using SpotLightHandle = AZ::Render::SpotLightFeatureProcessorInterface::LightHandle;
+        using DiskLightHandle = AZ::Render::DiskLightFeatureProcessorInterface::LightHandle;
         using MeshHandle = AZ::Render::MeshFeatureProcessorInterface::MeshHandle;
 
         // Directional light
         AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
         DirectionalLightHandle m_directionalLightHandle;
-        // Spot light
-        AZ::Render::SpotLightFeatureProcessorInterface* m_spotLightFeatureProcessor = nullptr;
-        SpotLightHandle m_spotLightHandle;
+        // Disk light
+        AZ::Render::DiskLightFeatureProcessorInterface* m_diskLightFeatureProcessor = nullptr;
+        DiskLightHandle m_diskLightHandle;
         // Meshes
         MeshHandle m_floorMeshHandle;
 
@@ -120,7 +120,7 @@ namespace AtomSampleViewer
         // flags of features enabled
         bool m_enabledDepthOfField = true;
         bool m_hasDirectionalLight = true;
-        bool m_hasSpotLight = true;
+        bool m_hasDiskLight = true;
         bool m_enabledSkybox = true;
         bool m_hasIBL = true;
         bool m_enableSecondRenderPipeline = true;

+ 18 - 14
Gem/Code/Source/MultiSceneExampleComponent.cpp

@@ -71,6 +71,8 @@ namespace AtomSampleViewer
 
         // Create the RPI::Scene, add some feature processors
         RPI::SceneDescriptor sceneDesc;
+        sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimplePointLightFeatureProcessor");
+        sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimpleSpotLightFeatureProcessor");
         sceneDesc.m_featureProcessorNames.push_back("AZ::Render::CapsuleLightFeatureProcessor");
         sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DecalTextureArrayFeatureProcessor");
         sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DirectionalLightFeatureProcessor");
@@ -82,8 +84,9 @@ namespace AtomSampleViewer
         sceneDesc.m_featureProcessorNames.push_back("AZ::Render::QuadLightFeatureProcessor");
         sceneDesc.m_featureProcessorNames.push_back("ReflectionProbeFeatureProcessor");
         sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SkyBoxFeatureProcessor");
-        sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SpotLightFeatureProcessor");
+        sceneDesc.m_featureProcessorNames.push_back("AZ::Render::DiskLightFeatureProcessor");
         sceneDesc.m_featureProcessorNames.push_back("AZ::Render::TransformServiceFeatureProcessor");
+        sceneDesc.m_featureProcessorNames.push_back("AZ::Render::ProjectedShadowFeatureProcessor");
         m_scene = RPI::Scene::CreateScene(sceneDesc);
 
         // Setup scene srg modification callback (to push per-frame values to the shaders)
@@ -143,7 +146,7 @@ namespace AtomSampleViewer
         m_meshFeatureProcessor = m_scene->GetFeatureProcessor<Render::MeshFeatureProcessorInterface>();
         m_skyBoxFeatureProcessor = m_scene->GetFeatureProcessor<Render::SkyBoxFeatureProcessorInterface>();
         m_pointLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::PointLightFeatureProcessorInterface>();
-        m_spotLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::SpotLightFeatureProcessorInterface>();
+        m_diskLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
         m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
         m_reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor<Render::ReflectionProbeFeatureProcessorInterface>();
         m_postProcessFeatureProcessor = m_scene->GetFeatureProcessor<Render::PostProcessFeatureProcessorInterface>();
@@ -214,26 +217,27 @@ namespace AtomSampleViewer
             m_pointLightFeatureProcessor->SetBulbRadius(m_pointLightHandle, 4.0f);
         }
 
-        // Create SpotLight
+        // Create DiskLight
         {
-            m_spotLightHandle = m_spotLightFeatureProcessor->AcquireLight();
+            m_diskLightHandle = m_diskLightFeatureProcessor->AcquireLight();
 
-            const Vector3 spotLightPosition(3.0f, 0.0f, 4.0f);
-            m_spotLightFeatureProcessor->SetPosition(m_spotLightHandle, spotLightPosition);
+            const Vector3 diskLightPosition(3.0f, 0.0f, 4.0f);
+            m_diskLightFeatureProcessor->SetPosition(m_diskLightHandle, diskLightPosition);
 
             Render::PhotometricValue rgbIntensity;
-            m_spotLightFeatureProcessor->SetRgbIntensity(m_spotLightHandle, Render::PhotometricColor<Render::PhotometricUnit::Candela>(Color::CreateOne() * 2000.0f));
+            m_diskLightFeatureProcessor->SetRgbIntensity(m_diskLightHandle, Render::PhotometricColor<Render::PhotometricUnit::Candela>(Color::CreateOne() * 2000.0f));
 
             const auto lightDir = Transform::CreateLookAt(
-                spotLightPosition,
+                diskLightPosition,
                 Vector3::CreateZero());
-            m_spotLightFeatureProcessor->SetDirection(m_spotLightHandle, lightDir.GetBasis(1));
+            m_diskLightFeatureProcessor->SetDirection(m_diskLightHandle, lightDir.GetBasis(1));
 
             const float radius = sqrtf(2000.0f / 0.5f);
-            m_spotLightFeatureProcessor->SetAttenuationRadius(m_spotLightHandle, radius);
-            m_spotLightFeatureProcessor->SetShadowmapSize(m_spotLightHandle, Render::ShadowmapSize::Size512);
-            m_spotLightFeatureProcessor->SetConeAngles(m_spotLightHandle, 45.f, 55.f);
-            m_spotLightFeatureProcessor->SetShadowBoundaryWidthAngle(m_spotLightHandle, 0.25f);
+            m_diskLightFeatureProcessor->SetAttenuationRadius(m_diskLightHandle, radius);
+            m_diskLightFeatureProcessor->SetShadowsEnabled(m_diskLightHandle, true);
+            m_diskLightFeatureProcessor->SetShadowmapMaxResolution(m_diskLightHandle, Render::ShadowmapSize::Size512);
+            m_diskLightFeatureProcessor->SetConeAngles(m_diskLightHandle, DegToRad(22.5f), DegToRad(27.5f));
+            m_diskLightFeatureProcessor->SetSofteningBoundaryWidthAngle(m_diskLightHandle, DegToRad(0.25f));
         }
 
         // Create DirectionalLight
@@ -324,7 +328,7 @@ namespace AtomSampleViewer
 
         // Release all the light types
         m_pointLightFeatureProcessor->ReleaseLight(m_pointLightHandle);
-        m_spotLightFeatureProcessor->ReleaseLight(m_spotLightHandle);
+        m_diskLightFeatureProcessor->ReleaseLight(m_diskLightHandle);
         m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
 
         // Release the probe

+ 4 - 4
Gem/Code/Source/MultiSceneExampleComponent.h

@@ -24,7 +24,7 @@
 #include <AzFramework/Windowing/NativeWindow.h>
 
 #include <Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h>
-#include <Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h>
+#include <Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
 #include <Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h>
 #include <Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h>
@@ -41,7 +41,7 @@ namespace AtomSampleViewer
     {
         using ModelChangedHandler = AZ::Render::MeshFeatureProcessorInterface::ModelChangedEvent::Handler;
         using PointLightHandle = AZ::Render::PointLightFeatureProcessorInterface::LightHandle;
-        using SpotLightHandle = AZ::Render::SpotLightFeatureProcessorInterface::LightHandle;
+        using DiskLightHandle = AZ::Render::DiskLightFeatureProcessorInterface::LightHandle;
         using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle;
         using ReflectinoProbeHandle = AZ::Render::ReflectionProbeHandle;
 
@@ -81,7 +81,7 @@ namespace AtomSampleViewer
         AZ::Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr;
         AZ::Render::SkyBoxFeatureProcessorInterface* m_skyBoxFeatureProcessor = nullptr;
         AZ::Render::PointLightFeatureProcessorInterface* m_pointLightFeatureProcessor = nullptr;
-        AZ::Render::SpotLightFeatureProcessorInterface* m_spotLightFeatureProcessor = nullptr;
+        AZ::Render::DiskLightFeatureProcessorInterface* m_diskLightFeatureProcessor = nullptr;
         AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
         AZ::Render::PostProcessFeatureProcessorInterface* m_postProcessFeatureProcessor = nullptr;
         AZ::Render::ReflectionProbeFeatureProcessorInterface* m_reflectionProbeFeatureProcessor = nullptr;
@@ -95,7 +95,7 @@ namespace AtomSampleViewer
 
         // Various FeatureProcessor handles
         PointLightHandle m_pointLightHandle;
-        SpotLightHandle m_spotLightHandle;
+        DiskLightHandle m_diskLightHandle;
         DirectionalLightHandle m_directionalLightHandle;
         ReflectinoProbeHandle m_reflectionProbeHandle;
 

+ 17 - 16
Gem/Code/Source/ParallaxMappingExampleComponent.cpp

@@ -121,8 +121,8 @@ namespace AtomSampleViewer
         AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get();
         m_directionalLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::DirectionalLightFeatureProcessorInterface>();
         CreateDirectionalLight();
-        m_spotLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::SpotLightFeatureProcessorInterface>();
-        CreateSpotLight();
+        m_diskLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::DiskLightFeatureProcessorInterface>();
+        CreateDiskLight();
 
         m_imguiSidebar.Activate();
         AZ::TickBus::Handler::BusConnect();
@@ -139,7 +139,7 @@ namespace AtomSampleViewer
             &AZ::Debug::CameraControllerRequestBus::Events::Disable);
 
         m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
-        m_spotLightFeatureProcessor->ReleaseLight(m_spotLightHandle);
+        m_diskLightFeatureProcessor->ReleaseLight(m_diskLightHandle);
 
         m_imguiSidebar.Deactivate();
         AZ::TickBus::Handler::BusDisconnect();
@@ -180,16 +180,17 @@ namespace AtomSampleViewer
         m_directionalLightHandle = handle;
     }
 
-    void ParallaxMappingExampleComponent::CreateSpotLight()
+    void ParallaxMappingExampleComponent::CreateDiskLight()
     {
-        AZ::Render::SpotLightFeatureProcessorInterface* const featureProcessor = m_spotLightFeatureProcessor;
-        const AZ::Render::SpotLightFeatureProcessorInterface::LightHandle handle = featureProcessor->AcquireLight();
+        AZ::Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
+        const AZ::Render::DiskLightFeatureProcessorInterface::LightHandle handle = featureProcessor->AcquireLight();
 
-        featureProcessor->SetAttenuationRadius( handle, sqrtf(500.f / CutoffIntensity));
-        featureProcessor->SetConeAngles( handle, 45.f * ConeAngleInnerRatio, 45.f);
-        featureProcessor->SetShadowmapSize( handle, AZ::Render::ShadowmapSize::Size2048);
+        featureProcessor->SetAttenuationRadius(handle, sqrtf(500.f / CutoffIntensity));
+        featureProcessor->SetConeAngles(handle, AZ::DegToRad(22.5f) * ConeAngleInnerRatio, AZ::DegToRad(22.5f));
+        featureProcessor->SetShadowsEnabled(handle, true);
+        featureProcessor->SetShadowmapMaxResolution(handle, AZ::Render::ShadowmapSize::Size2048);
 
-        m_spotLightHandle = handle;
+        m_diskLightHandle = handle;
         
     }
 
@@ -211,20 +212,20 @@ namespace AtomSampleViewer
         if (m_lightType)
         {
             AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux> directionalLightColor(AZ::Color::CreateZero());
-            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> spotLightColor(AZ::Color::CreateOne() * 500.f);
+            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> diskLightColor(AZ::Color::CreateOne() * 500.f);
             m_directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, directionalLightColor);
-            m_spotLightFeatureProcessor->SetRgbIntensity(m_spotLightHandle, spotLightColor);
+            m_diskLightFeatureProcessor->SetRgbIntensity(m_diskLightHandle, diskLightColor);
         }
         else
         {
             AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux> directionalLightColor(AZ::Color::CreateOne() * 5.f);
-            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> spotLightColor(AZ::Color::CreateZero());
+            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> diskLightColor(AZ::Color::CreateZero());
             m_directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, directionalLightColor);
-            m_spotLightFeatureProcessor->SetRgbIntensity(m_spotLightHandle, spotLightColor);
+            m_diskLightFeatureProcessor->SetRgbIntensity(m_diskLightHandle, diskLightColor);
         }
 
-        m_spotLightFeatureProcessor->SetPosition(m_spotLightHandle, location);
-        m_spotLightFeatureProcessor->SetDirection(m_spotLightHandle, transform.GetBasis(1));
+        m_diskLightFeatureProcessor->SetPosition(m_diskLightHandle, location);
+        m_diskLightFeatureProcessor->SetDirection(m_diskLightHandle, transform.GetBasis(1));
         m_directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, transform.GetBasis(1));
 
         // Camera Configuration

+ 5 - 5
Gem/Code/Source/ParallaxMappingExampleComponent.h

@@ -13,7 +13,7 @@
 #pragma once
 #include <CommonSampleComponentBase.h>
 #include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
-#include <Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h>
+#include <Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h>
 #include <AzCore/Component/TickBus.h>
 
 #include <Utils/ImGuiSidebar.h>
@@ -50,7 +50,7 @@ namespace AtomSampleViewer
             AZ::Data::Instance<AZ::RPI::Material> material,
             AZ::Transform transform);
         void CreateDirectionalLight();
-        void CreateSpotLight();
+        void CreateDiskLight();
         void DrawSidebar();
 
         void SaveCameraConfiguration();
@@ -64,13 +64,13 @@ namespace AtomSampleViewer
 
         // Light
         AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
-        AZ::Render::SpotLightFeatureProcessorInterface* m_spotLightFeatureProcessor = nullptr;
+        AZ::Render::DiskLightFeatureProcessorInterface* m_diskLightFeatureProcessor = nullptr;
         AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle m_directionalLightHandle;
-        AZ::Render::SpotLightFeatureProcessorInterface::LightHandle m_spotLightHandle;
+        AZ::Render::DiskLightFeatureProcessorInterface::LightHandle m_diskLightHandle;
 
         float m_lightRotationAngle = 0.f; // in radian
         bool m_lightAutoRotate = true;
-        int m_lightType = 0; // 0: diectionalLight, 1: spotLight
+        int m_lightType = 0; // 0: diectionalLight, 1: diskLight
 
         //Assets
         AZ::Data::Asset<AZ::RPI::ModelAsset> m_planeAsset;

+ 7 - 1
Gem/Code/Source/Passes/RayTracingAmbientOcclusionPass.cpp

@@ -227,13 +227,19 @@ namespace AZ
             RPI::PassAttachment* outputAttachment = GetOutputBinding(0).m_attachment.get();
             RHI::Size targetImageSize = outputAttachment->m_descriptor.m_image.m_size;
 
+            const RHI::ShaderResourceGroup* shaderResourceGroups[] =
+            {
+                m_shaderResourceGroup->GetRHIShaderResourceGroup()
+            };
+
             RHI::DispatchRaysItem dispatchRaysItem;
             dispatchRaysItem.m_width = targetImageSize.m_width;
             dispatchRaysItem.m_height = targetImageSize.m_height;
             dispatchRaysItem.m_depth = 1;
             dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState.get();
             dispatchRaysItem.m_rayTracingShaderTable = m_rayTracingShaderTable.get();
-            dispatchRaysItem.m_globalSrg = m_shaderResourceGroup->GetRHIShaderResourceGroup();
+            dispatchRaysItem.m_shaderResourceGroupCount = 1;
+            dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups;
             dispatchRaysItem.m_globalPipelineState = m_globalPipelineState.get();
 
             // submit the DispatchRays item

+ 1 - 1
Gem/Code/Source/RHI/AlphaToCoverageExampleComponent.cpp

@@ -268,7 +268,7 @@ namespace AtomSampleViewer
             subpass->DepthStencilAttachment(s_depthFormat);
         }
 
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
 

+ 4 - 4
Gem/Code/Source/RHI/AsyncComputeExampleComponent.cpp

@@ -312,7 +312,7 @@ namespace AtomSampleViewer
 
             attachmentsBuilder.AddSubpass()
                 ->DepthStencilAttachment(RHI::Format::D32_FLOAT);
-            RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             {
@@ -371,7 +371,7 @@ namespace AtomSampleViewer
                 ->RenderTargetAttachment(RHI::Format::R16G16B16A16_FLOAT)
                 ->DepthStencilAttachment(depthStencilFormat);
 
-            RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             {
@@ -427,7 +427,7 @@ namespace AtomSampleViewer
             attachmentsBuilder.Reset();
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             RHI::TargetBlendState& blendstate = pipelineDesc.m_renderStates.m_blendState.m_targets[0];
@@ -468,7 +468,7 @@ namespace AtomSampleViewer
             attachmentsBuilder.Reset();
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(RHI::Format::R32_FLOAT);
-            RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             RHI::InputStreamLayoutBuilder layoutBuilder;

+ 7 - 7
Gem/Code/Source/RHI/BindlessPrototypeExampleComponent.cpp

@@ -219,7 +219,7 @@ namespace AtomSampleViewer
         bufferPoolDesc.m_budgetInBytes = m_poolSizeInBytes;
 
         const RHI::Ptr<RHI::Device> device = Utils::GetRHIDevice();
-        RHI::ResultCode resultCode = m_bufferPool->Init(*device, bufferPoolDesc);
+        [[maybe_unused]] RHI::ResultCode resultCode = m_bufferPool->Init(*device, bufferPoolDesc);
         AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to create Material Buffer Pool");
     };
 
@@ -232,7 +232,7 @@ namespace AtomSampleViewer
         bufferRequest.m_descriptor.m_byteCount = byteCount;
         bufferRequest.m_buffer = m_buffer.get();
 
-        RHI::ResultCode resultCode = m_bufferPool->InitBuffer(bufferRequest);
+        [[maybe_unused]] RHI::ResultCode resultCode = m_bufferPool->InitBuffer(bufferRequest);
         AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to create Material Buffer");
     };
 
@@ -415,7 +415,7 @@ namespace AtomSampleViewer
             {
                 bufferView->SetName(Name(m_floatBufferSrgName));
                 RHI::BufferViewDescriptor bufferViewDesc = RHI::BufferViewDescriptor::CreateStructured(0u, m_bufferFloatCount, sizeof(float));
-                RHI::ResultCode resultCode = bufferView->Init(*m_floatBuffer->m_buffer, bufferViewDesc);
+                [[maybe_unused]] RHI::ResultCode resultCode = bufferView->Init(*m_floatBuffer->m_buffer, bufferViewDesc);
                 AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to initialize buffer view");
             }
             m_bindlessSrg->SetBufferView(m_floatBufferSrgName, floatBufferId, bufferView.get());
@@ -444,7 +444,7 @@ namespace AtomSampleViewer
                 attachmentsBuilder.AddSubpass()
                     ->RenderTargetAttachment(m_outputFormat)
                     ->DepthStencilAttachment(AZ::RHI::Format::D32_FLOAT);
-                AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+                attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
                 pipelineStateDescriptor.m_renderStates.m_depthStencilState.m_depth.m_func = RHI::ComparisonFunc::GreaterEqual;
                 pipelineStateDescriptor.m_renderStates.m_depthStencilState.m_depth.m_enable = true;
 
@@ -471,7 +471,7 @@ namespace AtomSampleViewer
             for (uint32_t textuerIdx = 0u; textuerIdx < InternalBP::ImageCount; textuerIdx++)
             {
                 AZ::Data::Instance<AZ::RPI::StreamingImage> image = LoadStreamingImage(InternalBP::Images[textuerIdx], InternalBP::SampleName);
-                bool result = imageSrg->SetImage(imageIndex, image, textuerIdx);
+                [[maybe_unused]] bool result = imageSrg->SetImage(imageIndex, image, textuerIdx);
                 AZ_Assert(result, "Failed to set image into shader resource group.");
             }
 
@@ -738,7 +738,7 @@ namespace AtomSampleViewer
     {
         AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> srg = GetSrg(srgName);
         const AZ::RHI::ShaderInputBufferIndex inputIndex = srg->FindShaderInputBufferIndex(AZ::Name(srgId));
-        bool set = srg->SetBufferView(inputIndex, bufferView);
+        [[maybe_unused]] bool set = srg->SetBufferView(inputIndex, bufferView);
         AZ_Assert(set, "Failed to set the buffer view");
 
         return false;
@@ -804,7 +804,7 @@ namespace AtomSampleViewer
     bool BindlessPrototypeExampleComponent::FloatBuffer::MapData(const RHI::BufferMapRequest& mapRequest, const void* data)
     {
         RHI::BufferMapResponse response;
-        RHI::ResultCode result = m_bufferPool->MapBuffer(mapRequest, response);
+        [[maybe_unused]] RHI::ResultCode result = m_bufferPool->MapBuffer(mapRequest, response);
         // ResultCode::Unimplemented is used by Null Renderer and hence is a valid use case
         AZ_Assert(result == RHI::ResultCode::Success || result == RHI::ResultCode::Unimplemented, "Failed to map object buffer]");
         if (response.m_data)

+ 1 - 1
Gem/Code/Source/RHI/BindlessPrototypeExampleComponent.h

@@ -179,7 +179,7 @@ namespace AtomSampleViewer
         void AllocateMaterial(FloatBufferHandle& handle)
         {
             T material;
-            bool result = m_floatBuffer->AllocateOrUpdateBuffer(handle, static_cast<void*>(&material), sizeof(T));
+            [[maybe_unused]] bool result = m_floatBuffer->AllocateOrUpdateBuffer(handle, static_cast<void*>(&material), sizeof(T));
             AZ_Assert(result, "Failed to allocate FloatBuffer");
         }
 

+ 2 - 2
Gem/Code/Source/RHI/ComputeExampleComponent.cpp

@@ -214,7 +214,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_drawPipelineState = shader->AcquirePipelineState(pipelineDesc);
@@ -283,7 +283,7 @@ namespace AtomSampleViewer
         {
             // attach compute buffer
             {
-                RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(m_bufferAttachmentId, m_computeBuffer);
+                [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(m_bufferAttachmentId, m_computeBuffer);
                 AZ_Error(s_computeExampleName, result == RHI::ResultCode::Success, "Failed to import compute buffer with error %d", result);
 
                 RHI::BufferScopeAttachmentDescriptor desc;

+ 1 - 1
Gem/Code/Source/RHI/CopyQueueComponent.cpp

@@ -177,7 +177,7 @@ namespace AtomSampleViewer
             RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             m_pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);

+ 1 - 1
Gem/Code/Source/RHI/DualSourceBlendingComponent.cpp

@@ -153,7 +153,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         pipelineDesc.m_renderStates.m_blendState.m_targets[0].m_enable = 1;

+ 1 - 3
Gem/Code/Source/RHI/IndirectRenderingExampleComponent.cpp

@@ -266,7 +266,7 @@ namespace AtomSampleViewer
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat)
                 ->DepthStencilAttachment(RHI::Format::D32_FLOAT);
-            RHI::ResultCode result = attachmentsBuilder.End(drawPipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(drawPipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             drawPipelineStateDescriptor.m_renderStates.m_depthStencilState = AZ::RHI::DepthStencilState::CreateDepth();
@@ -705,8 +705,6 @@ namespace AtomSampleViewer
                 m_drawIndirect.m_countBufferByteOffset = 0;
             }
 
-            float screenAspect = GetViewportWidth() / GetViewportHeight();
-
             // Update the cull area
             float cullScale = 0.75f;
             AZ::Vector2 cullPlane = AZ::Vector2(-m_cullOffset, m_cullOffset) * AZ::Vector2(cullScale) + AZ::Vector2(cullScale - 1.0f);

+ 1 - 1
Gem/Code/Source/RHI/InputAssemblyExampleComponent.cpp

@@ -218,7 +218,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_drawPipelineState = shader->AcquirePipelineState(pipelineDesc);

+ 7 - 7
Gem/Code/Source/RHI/MRTExampleComponent.cpp

@@ -74,7 +74,7 @@ namespace AtomSampleViewer
     }
 
     void MRTExampleComponent::Activate()
-    {   
+    {
         // Init buffers & views
         CreateInputAssemblyBuffersAndViews();
         // Init render targets
@@ -85,7 +85,7 @@ namespace AtomSampleViewer
 
         CreateRenderTargetScope();
         CreateScreenScope();
-        
+
         AZ::RHI::RHISystemNotificationBus::Handler::BusConnect();
     }
 
@@ -110,7 +110,7 @@ namespace AtomSampleViewer
         auto shader = LoadShader(MRTTargetShaderFilePath, sampleName);
         if (shader == nullptr)
             return;
-        
+
         RHI::PipelineStateDescriptorForDraw pipelineDesc;
         shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId).ConfigurePipelineState(pipelineDesc);
         pipelineDesc.m_inputStreamLayout = m_inputStreamLayout;
@@ -120,7 +120,7 @@ namespace AtomSampleViewer
             ->RenderTargetAttachment(RHI::Format::R8G8B8A8_UNORM_SRGB)
             ->RenderTargetAttachment(RHI::Format::R16G16_FLOAT)
             ->RenderTargetAttachment(RHI::Format::R32_FLOAT);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_pipelineStates[0] = shader->AcquirePipelineState(pipelineDesc);
@@ -154,7 +154,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_pipelineStates[1] = shader->AcquirePipelineState(pipelineDesc);
@@ -327,7 +327,7 @@ namespace AtomSampleViewer
         using namespace AZ;
 
         const auto prepareFunctionScreen = [this](RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData)
-        {            
+        {
             // Binds the swap chain as a color attachment. Clears it to white.
             {
                 RHI::ImageScopeAttachmentDescriptor descriptor;
@@ -361,7 +361,7 @@ namespace AtomSampleViewer
         };
 
         const auto executeFunctionScreen = [this](const RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData)
-        {            
+        {
             RHI::CommandList* commandList = context.GetCommandList();
 
             // Set persistent viewport and scissor state.

+ 3 - 3
Gem/Code/Source/RHI/MSAAExampleComponent.cpp

@@ -182,7 +182,7 @@ namespace AtomSampleViewer
         const Name objectMatrixConstantId{ "m_objectMatrix" };
         FindShaderInputIndex(&m_objectMatrixConstantIndex, m_triangleShaderResourceGroup, objectMatrixConstantId, SampleName);
 
-        bool success = m_triangleShaderResourceGroup->SetConstant(m_objectMatrixConstantIndex, AZ::Matrix4x4::CreateIdentity());
+        [[maybe_unused]] bool success = m_triangleShaderResourceGroup->SetConstant(m_objectMatrixConstantIndex, AZ::Matrix4x4::CreateIdentity());
         AZ_Warning("MSAAExampleComponent", success, "Failed to set SRG Constant m_objectMatrix");
         m_triangleShaderResourceGroup->Compile();
     }
@@ -264,7 +264,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat, properties.m_resolve);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         pipelineStateDescriptor.m_renderStates.m_multisampleState.m_samples = properties.m_samplesCount;
@@ -402,7 +402,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_customResolveMSAAPipelineState = m_customMSAAResolveShader->AcquirePipelineState(pipelineStateDescriptor);

+ 1 - 1
Gem/Code/Source/RHI/MultiThreadComponent.cpp

@@ -233,7 +233,7 @@ namespace AtomSampleViewer
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat)
             ->DepthStencilAttachment(device->GetNearestSupportedFormat(AZ::RHI::Format::D24_UNORM_S8_UINT, AZ::RHI::FormatCapabilities::DepthStencil));
-        AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_pipelineState = shader->AcquirePipelineState(pipelineDesc);

+ 2 - 2
Gem/Code/Source/RHI/MultipleViewsComponent.cpp

@@ -332,7 +332,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->DepthStencilAttachment(AZ::RHI::Format::D32_FLOAT);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_pipelineStates[0] = shader->AcquirePipelineState(pipelineDesc);
@@ -369,7 +369,7 @@ namespace AtomSampleViewer
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat)
             ->DepthStencilAttachment(depthStencilFormat);
-        AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_pipelineStates[1] = shader->AcquirePipelineState(pipelineDesc);

+ 3 - 3
Gem/Code/Source/RHI/QueryExampleComponent.cpp

@@ -133,7 +133,7 @@ namespace AtomSampleViewer
         }
         {
             auto scaleMatrix = AZ::Matrix4x4::CreateScale(AZ::Vector3(0.2, 0.2, 0.2));
-            bool success = m_shaderResourceGroups[2]->SetConstant(m_objectMatrixConstantIndex, scaleMatrix * AZ::Matrix4x4::CreateTranslation(AZ::Vector3(0, 0, 0.49)));
+            [[maybe_unused]] bool success = m_shaderResourceGroups[2]->SetConstant(m_objectMatrixConstantIndex, scaleMatrix * AZ::Matrix4x4::CreateTranslation(AZ::Vector3(0, 0, 0.49)));
             AZ_Warning(QueryExample::SampleName, success, "Failed to set SRG Constant data");
         }
 
@@ -216,7 +216,7 @@ namespace AtomSampleViewer
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(format)
             ->DepthStencilAttachment(AZ::RHI::Format::D32_FLOAT);
-        AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         pipelineStateDescriptor.m_renderStates.m_blendState.m_targets[0] = blendState;
@@ -286,7 +286,7 @@ namespace AtomSampleViewer
                 return;
             }
             
-            RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(RHI::AttachmentId{QueryExample::PredicationBufferId}, m_predicationBuffer);
+            [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(RHI::AttachmentId{QueryExample::PredicationBufferId}, m_predicationBuffer);
             AZ_Error(QueryExample::SampleName, result == RHI::ResultCode::Success, "Failed to import predication buffer with error %d", result);
 
             frameGraph.UseQueryPool(

+ 12 - 8
Gem/Code/Source/RHI/RayTracingExampleComponent.cpp

@@ -53,7 +53,7 @@ namespace AtomSampleViewer
             RHI::BufferPoolDescriptor bufferPoolDesc;
             bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly;
             bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
-            RHI::ResultCode resultCode = m_inputAssemblyBufferPool->Init(*device, bufferPoolDesc);
+            [[maybe_unused]] RHI::ResultCode resultCode = m_inputAssemblyBufferPool->Init(*device, bufferPoolDesc);
             AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to initialize input assembly buffer pool");
         }
 
@@ -63,7 +63,7 @@ namespace AtomSampleViewer
             imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite;
 
             m_imagePool = RHI::Factory::Get().CreateImagePool();
-            RHI::ResultCode result = m_imagePool->Init(*device, imagePoolDesc);
+            [[maybe_unused]] RHI::ResultCode result = m_imagePool->Init(*device, imagePoolDesc);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize output image pool");
         }
 
@@ -186,12 +186,11 @@ namespace AtomSampleViewer
 
         // create output image
         m_outputImage = RHI::Factory::Get().CreateImage();
-        uint32_t imageSize = m_imageWidth * m_imageHeight * RHI::GetFormatSize(RHI::Format::R8G8B8A8_UNORM);
 
         RHI::ImageInitRequest request;
         request.m_image = m_outputImage.get();
         request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, m_imageWidth, m_imageHeight, RHI::Format::R8G8B8A8_UNORM);
-        RHI::ResultCode result = m_imagePool->InitImage(request);
+        [[maybe_unused]] RHI::ResultCode result = m_imagePool->InitImage(request);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize output image");
 
         m_outputImageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::R8G8B8A8_UNORM, 0, 0);
@@ -220,7 +219,7 @@ namespace AtomSampleViewer
 
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()->RenderTargetAttachment(m_outputFormat);
-        RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create draw render attachment layout");
 
         m_drawPipelineState = drawShader->AcquirePipelineState(pipelineDesc);
@@ -500,7 +499,7 @@ namespace AtomSampleViewer
         {
             // attach output image
             {
-                RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(m_outputImageAttachmentId, m_outputImage);
+                [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(m_outputImageAttachmentId, m_outputImage);
                 AZ_Error(RayTracingExampleName, result == RHI::ResultCode::Success, "Failed to import output image with error %d", result);
 
                 RHI::ImageScopeAttachmentDescriptor desc;
@@ -514,7 +513,7 @@ namespace AtomSampleViewer
             // attach TLAS buffer
             if (m_rayTracingTlas->GetTlasBuffer())
             {
-                RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(m_tlasBufferAttachmentId, m_rayTracingTlas->GetTlasBuffer());
+                [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(m_tlasBufferAttachmentId, m_rayTracingTlas->GetTlasBuffer());
                 AZ_Error(RayTracingExampleName, result == RHI::ResultCode::Success, "Failed to import TLAS buffer with error %d", result);
 
                 RHI::BufferScopeAttachmentDescriptor desc;
@@ -599,13 +598,18 @@ namespace AtomSampleViewer
 
             RHI::CommandList* commandList = context.GetCommandList();
 
+            const RHI::ShaderResourceGroup* shaderResourceGroups[] = {
+                m_globalSrg->GetRHIShaderResourceGroup()
+            };
+
             RHI::DispatchRaysItem dispatchRaysItem;
             dispatchRaysItem.m_width = m_imageWidth;
             dispatchRaysItem.m_height = m_imageHeight;
             dispatchRaysItem.m_depth = 1;
             dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState.get();
             dispatchRaysItem.m_rayTracingShaderTable = m_rayTracingShaderTable.get();
-            dispatchRaysItem.m_globalSrg = m_globalSrg->GetRHIShaderResourceGroup();
+            dispatchRaysItem.m_shaderResourceGroupCount = RHI::ArraySize(shaderResourceGroups);
+            dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups;
             dispatchRaysItem.m_globalPipelineState = m_globalPipelineState.get();
 
             // submit the DispatchRays item

+ 2 - 2
Gem/Code/Source/RHI/SphericalHarmonicsExampleComponent.cpp

@@ -179,7 +179,7 @@ namespace AtomSampleViewer
 
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             m_demoPipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);
@@ -223,7 +223,7 @@ namespace AtomSampleViewer
             attachmentsBuilder.Reset();
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             m_renderPipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);

+ 1 - 1
Gem/Code/Source/RHI/StencilExampleComponent.cpp

@@ -146,7 +146,7 @@ namespace AtomSampleViewer
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat)
                 ->DepthStencilAttachment(depthStencilFormat);
-            AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             pipelineStateDescriptor.m_renderStates.m_depthStencilState.m_stencil.m_enable = 1;

+ 1 - 1
Gem/Code/Source/RHI/SubpassExampleComponent.cpp

@@ -244,7 +244,7 @@ namespace AtomSampleViewer
             ->DepthStencilAttachment(m_depthStencilAttachmentId);
 
         RHI::RenderAttachmentLayout renderAttachmentLayout;
-        RHI::ResultCode result = attachmentsBuilder.End(renderAttachmentLayout);
+        [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(renderAttachmentLayout);
         AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
         {
             // GBuffer Scope Pipelines

+ 1 - 1
Gem/Code/Source/RHI/Texture3dExampleComponent.cpp

@@ -160,7 +160,7 @@ namespace AtomSampleViewer
             RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             pipelineStateDescriptor.m_inputStreamLayout.SetTopology(AZ::RHI::PrimitiveTopology::TriangleStrip);

+ 3 - 3
Gem/Code/Source/RHI/TextureArrayExampleComponent.cpp

@@ -98,7 +98,7 @@ namespace AtomSampleViewer
                 for (uint32_t textuerIdx = 0u; textuerIdx < InternalTA::TextureCount; textuerIdx++)
                 {
                     AZ::Data::Instance<AZ::RPI::StreamingImage> image = LoadStreamingImage(filePath[textuerIdx], InternalTA::SampleName);
-                    bool result = m_textureArraySrg->SetImage(m_textureArray, image, textuerIdx);
+                    [[maybe_unused]] bool result = m_textureArraySrg->SetImage(m_textureArray, image, textuerIdx);
                     AZ_Error(InternalTA::SampleName, result, "Failed to set image into shader resource group.");
                 }
                 m_textureArraySrg->Compile();
@@ -121,7 +121,7 @@ namespace AtomSampleViewer
             RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor);
@@ -190,7 +190,7 @@ namespace AtomSampleViewer
 
             const auto compileFunction = [this]([[maybe_unused]] const AZ::RHI::FrameGraphCompileContext& context, [[maybe_unused]] const ScopeData& scopeData)
             {
-                bool success = m_textureIndexSrg->SetConstant(m_textureIndex, InternalTA::g_textureIndex);
+                [[maybe_unused]] bool success = m_textureIndexSrg->SetConstant(m_textureIndex, InternalTA::g_textureIndex);
                 AZ_Warning("TriangleExampleComponent", success, "Failed to set SRG Constant m_objectMatrix");
                 m_textureIndexSrg->Compile();
             };

+ 1 - 1
Gem/Code/Source/RHI/TextureExampleComponent.cpp

@@ -147,7 +147,7 @@ namespace AtomSampleViewer
             RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             m_pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);

+ 2 - 2
Gem/Code/Source/RHI/TextureMapExampleComponent.cpp

@@ -440,7 +440,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(s_textureFormat);
-        AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         for (int i = 0; i < s_numOfTargets; ++i)
@@ -468,7 +468,7 @@ namespace AtomSampleViewer
         RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
         attachmentsBuilder.AddSubpass()
             ->RenderTargetAttachment(m_outputFormat);
-        AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+        [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
         AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
         m_screenPipelineStates[target] = shader->AcquirePipelineState(pipelineDesc);

+ 2 - 2
Gem/Code/Source/RHI/TriangleExampleComponent.cpp

@@ -48,7 +48,7 @@ namespace AtomSampleViewer
                 cosf(time) * 0.25f,
                 0.0f);
 
-            bool success = m_shaderResourceGroup->SetConstant(m_objectMatrixConstantIndex, AZ::Matrix4x4::CreateTranslation(translation));
+            [[maybe_unused]] bool success = m_shaderResourceGroup->SetConstant(m_objectMatrixConstantIndex, AZ::Matrix4x4::CreateTranslation(translation));
             AZ_Warning("TriangleExampleComponent", success, "Failed to set SRG Constant m_objectMatrix");
             m_shaderResourceGroup->Compile();
         }
@@ -145,7 +145,7 @@ namespace AtomSampleViewer
             RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             m_pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);

+ 6 - 6
Gem/Code/Source/RHI/TrianglesConstantBufferExampleComponent.cpp

@@ -122,7 +122,7 @@ namespace AtomSampleViewer
             mapRequest.m_byteOffset = triangleIdx * elementSize;
 
             AZ::RHI::BufferMapResponse mapResponse;
-            AZ::RHI::ResultCode resultCode = m_constantBufferPool->MapBuffer(mapRequest, mapResponse);
+            m_constantBufferPool->MapBuffer(mapRequest, mapResponse);
             if (mapResponse.m_data)
             {
                 memcpy(mapResponse.m_data, data + triangleIdx, sizeof(InstanceInfo));
@@ -142,7 +142,7 @@ namespace AtomSampleViewer
             mapRequest.m_byteOffset = 0u;
 
             AZ::RHI::BufferMapResponse mapResponse;
-            AZ::RHI::ResultCode resultCode = m_constantBufferPool->MapBuffer(mapRequest, mapResponse);
+            m_constantBufferPool->MapBuffer(mapRequest, mapResponse);
 
             if(mapResponse.m_data)
             {
@@ -231,7 +231,7 @@ namespace AtomSampleViewer
             constantBufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::Constant;
             constantBufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
             constantBufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write;
-            RHI::ResultCode result = m_constantBufferPool->Init(*device, constantBufferPoolDesc);
+            [[maybe_unused]] RHI::ResultCode result = m_constantBufferPool->Init(*device, constantBufferPoolDesc);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialized constant buffer pool");
         }
 
@@ -248,7 +248,7 @@ namespace AtomSampleViewer
             RHI::BufferInitRequest request;
             request.m_buffer = m_constantBuffer.get();
             request.m_descriptor = RHI::BufferDescriptor{ RHI::BufferBindFlags::Constant, constantBufferSize };
-            RHI::ResultCode result = m_constantBufferPool->InitBuffer(request);
+            [[maybe_unused]] RHI::ResultCode result = m_constantBufferPool->InitBuffer(request);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize constant buffer");
 
             for (uint32_t triangleIdx = 0u; triangleIdx < s_numberOfTrianglesSingleCB; ++triangleIdx)
@@ -305,7 +305,7 @@ namespace AtomSampleViewer
             RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
             attachmentsBuilder.AddSubpass()
                 ->RenderTargetAttachment(m_outputFormat);
-            RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
+            [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineStateDescriptor.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
             AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout");
 
             m_pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);
@@ -324,7 +324,7 @@ namespace AtomSampleViewer
             uint32_t viewIdx = 0u;
             for (const AZ::RHI::Ptr<AZ::RHI::BufferView>& bufferView : m_constantBufferViewArray)
             {
-                bool set = m_shaderResourceGroup->SetBufferView(trianglesBufferIndex, bufferView.get(), viewIdx);
+                [[maybe_unused]] bool set = m_shaderResourceGroup->SetBufferView(trianglesBufferIndex, bufferView.get(), viewIdx);
                 AZ_Assert(set, "Failed to set the buffer view");
                 viewIdx++;
             }

+ 1 - 1
Gem/Code/Source/SSRExampleComponent.cpp

@@ -88,7 +88,7 @@ namespace AtomSampleViewer
 
     void SSRExampleComponent::CreateModels()
     {
-        AZ::Render::MeshFeatureProcessorInterface* meshFeatureProcessor = GetMeshFeatureProcessor();
+        GetMeshFeatureProcessor();
 
         // statue
         {

+ 6 - 5
Gem/Code/Source/SampleComponentManager.cpp

@@ -69,6 +69,7 @@
 #include <AreaLightExampleComponent.h>
 #include <AssetLoadTestComponent.h>
 #include <AuxGeomExampleComponent.h>
+#include <BakedShaderVariantExampleComponent.h>
 #include <BistroBenchmarkComponent.h>
 #include <BloomExampleComponent.h>
 #include <CheckerboardExampleComponent.h>
@@ -257,6 +258,7 @@ namespace AtomSampleViewer
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/TrianglesConstantBuffer", azrtti_typeid<TrianglesConstantBufferExampleComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/AssetLoadTest", azrtti_typeid<AssetLoadTestComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/AuxGeom", azrtti_typeid<AuxGeomExampleComponent>() ));
+        SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/BakedShaderVariant", azrtti_typeid<BakedShaderVariantExampleComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/BistroBenchmark", azrtti_typeid<BistroBenchmarkComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/CullingAndLod", azrtti_typeid<CullingAndLodExampleComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/Decals", azrtti_typeid<DecalExampleComponent>() ));
@@ -282,7 +284,6 @@ namespace AtomSampleViewer
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Parallax", azrtti_typeid<ParallaxMappingExampleComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Shadow", azrtti_typeid<ShadowExampleComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/ShadowedBistro", azrtti_typeid<ShadowedBistroExampleComponent>() ));
-        SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/SkinnedMesh", azrtti_typeid<SkinnedMeshExampleComponent>() ));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/SSAO", azrtti_typeid<SsaoExampleComponent>()));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/SSR", azrtti_typeid<SSRExampleComponent>()));
         SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Tonemapping", azrtti_typeid<TonemappingExampleComponent>() ));
@@ -1087,7 +1088,7 @@ namespace AtomSampleViewer
         {
             AZ::Render::ImGuiSystemRequestBus::Broadcast(&AZ::Render::ImGuiSystemRequestBus::Events::HideAllImGuiPasses);
 
-            // We also hide lumberyard's debug text
+            // We also hide Open 3D Engine's debug text
             AzFramework::ConsoleRequestBus::Broadcast(&AzFramework::ConsoleRequests::ExecuteConsoleCommand, "r_DisplayInfo 0");
             // The ExecuteConsoleCommand request is handled in a deferred manner, so we have to delay the screenshot a bit.
             m_countdownForFrameCapture = 1;
@@ -1106,7 +1107,7 @@ namespace AtomSampleViewer
         {
             AZ::Render::ImGuiSystemRequestBus::Broadcast(&AZ::Render::ImGuiSystemRequestBus::Events::ShowAllImGuiPasses);
 
-            // We also show lumberyard's debug text
+            // We also show Open 3D Engine's debug text
             AzFramework::ConsoleRequestBus::Broadcast(&AzFramework::ConsoleRequests::ExecuteConsoleCommand, "r_DisplayInfo 1");
         }
 
@@ -1119,11 +1120,11 @@ namespace AtomSampleViewer
         return m_isFrameCapturePending;
     }
 
-    void SampleComponentManager::RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd)
+    void SampleComponentManager::RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd, int randomSeed)
     {
         if (m_scriptManager)
         {
-            m_scriptManager->RunMainTestSuite(suiteFilePath, exitOnTestEnd);
+            m_scriptManager->RunMainTestSuite(suiteFilePath, exitOnTestEnd, randomSeed);
         }
     }
 

+ 1 - 1
Gem/Code/Source/SampleComponentManager.h

@@ -147,7 +147,7 @@ namespace AtomSampleViewer
         bool ShowTool(const AZStd::string& toolName, bool enable) override;
         void RequestFrameCapture(const AZStd::string& filePath, bool hideImGui) override;
         bool IsFrameCapturePending() override;
-        void RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd) override;
+        void RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd, int randomSeed) override;
 
         // FrameCaptureNotificationBus overrides...
         void OnCaptureFinished(AZ::Render::FrameCaptureResult result, const AZStd::string& info) override;

+ 2 - 1
Gem/Code/Source/SampleComponentManagerBus.h

@@ -40,7 +40,8 @@ namespace AtomSampleViewer
         //! Runs the main test suite, in an automated mode and closes AtomSampleViewer when the suite finished running
         //! @param suiteFilePath path to the compiled luac test script
         //! @param exitOnTestEnd if true, exits AtomSampleViewerStandalone when the script finishes, used in jenkins
-        virtual void RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd) = 0;
+        //! @param randomSeed the seed for the random generator, frequently used inside lua tests to shuffle the order of the test execution
+        virtual void RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd, int randomSeed) = 0;
     };
     using SampleComponentManagerRequestBus = AZ::EBus<SampleComponentManagerRequests>;
 

+ 87 - 89
Gem/Code/Source/ShadowExampleComponent.cpp

@@ -39,7 +39,7 @@ namespace AtomSampleViewer
     };
 
     const AZ::Color ShadowExampleComponent::DirectionalLightColor = AZ::Color::CreateOne();
-    AZ::Color ShadowExampleComponent::s_spotLightColors[] = {
+    AZ::Color ShadowExampleComponent::s_diskLightColors[] = {
         // they will be initialized in the constructor.
         AZ::Color::CreateZero(),
         AZ::Color::CreateZero(),
@@ -77,9 +77,9 @@ namespace AtomSampleViewer
     ShadowExampleComponent::ShadowExampleComponent()
         : m_imguiSidebar("@user@/ShadowExampleComponent/sidebar.xml")
     {
-        s_spotLightColors[0] = AZ::Colors::Red;
-        s_spotLightColors[1] = AZ::Colors::Green;
-        s_spotLightColors[2] = AZ::Colors::Blue;
+        s_diskLightColors[0] = AZ::Colors::Red;
+        s_diskLightColors[1] = AZ::Colors::Green;
+        s_diskLightColors[2] = AZ::Colors::Blue;
     }
 
     void ShadowExampleComponent::Reflect(AZ::ReflectContext* context)
@@ -123,9 +123,9 @@ namespace AtomSampleViewer
         m_floorMeshIsReady = false;
 
         m_directionalLightImageSizeIndex = 2; // image size is 1024.
-        for (uint32_t index = 0; index < SpotLightCount; ++index)
+        for (uint32_t index = 0; index < DiskLightCount; ++index)
         {
-            m_spotLightImageSizeIndices[index] = 2; // image size is 1024.
+            m_diskLightImageSizeIndices[index] = 2; // image size is 1024.
         }
         m_cascadeCount = 2;
         m_ratioLogarithmUniform = 0.5f;
@@ -134,11 +134,11 @@ namespace AtomSampleViewer
 
         RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get();
         m_directionalLightFeatureProcessor = scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
-        m_spotLightFeatureProcessor = scene->GetFeatureProcessor<Render::SpotLightFeatureProcessorInterface>();
+        m_diskLightFeatureProcessor = scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
 
         CreateMeshes();
         CreateDirectionalLight();
-        CreateSpotLights();
+        CreateDiskLights();
 
         m_elapsedTime = 0.f;
         m_imguiSidebar.Activate();
@@ -156,9 +156,9 @@ namespace AtomSampleViewer
         GetMeshFeatureProcessor()->ReleaseMesh(m_bunnyMeshHandle);
 
         m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
-        for (SpotLightHandle& handle : m_spotLightHandles)
+        for (DiskLightHandle& handle : m_diskLightHandles)
         {
-            m_spotLightFeatureProcessor->ReleaseLight(handle);
+            m_diskLightFeatureProcessor->ReleaseLight(handle);
         }
 
         m_imguiSidebar.Deactivate();
@@ -168,9 +168,9 @@ namespace AtomSampleViewer
     {
         using namespace AZ;
         constexpr float directionalLightPeriodTime = 5.f; // 5 seconds for a rotation of directional light position.
-        constexpr float spotLightPeriodTime = 7.f; // 7 seconds for a rotation of spot light positions.
+        constexpr float diskLightPeriodTime = 7.f; // 7 seconds for a rotation of disk light positions.
         constexpr float directionalLightDist = 10.f;
-        constexpr float spotLightDist = 5.f;
+        constexpr float diskLightDist = 5.f;
 
         if (m_elapsedTime == 0.f)
         {
@@ -185,9 +185,9 @@ namespace AtomSampleViewer
         {
             m_directionalLightRotationAngle = fmodf(m_directionalLightRotationAngle + deltaTime * Constants::TwoPi / directionalLightPeriodTime, Constants::TwoPi);
         }
-        if (m_isSpotLightAutoRotate)
+        if (m_isDiskLightAutoRotate)
         {
-            m_spotLightRotationAngle = fmodf(m_spotLightRotationAngle - deltaTime * Constants::TwoPi / spotLightPeriodTime + Constants::TwoPi, Constants::TwoPi);
+            m_diskLightRotationAngle = fmodf(m_diskLightRotationAngle - deltaTime * Constants::TwoPi / diskLightPeriodTime + Constants::TwoPi, Constants::TwoPi);
         }
 
         // Directional Light Transform
@@ -202,19 +202,19 @@ namespace AtomSampleViewer
             m_directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, lightTransform.GetBasis(1));
         }
 
-        // Spot Lights Transform
-        for (uint32_t index = 0; index < SpotLightCount; ++index)
+        // Disk Lights Transform
+        for (uint32_t index = 0; index < DiskLightCount; ++index)
         { 
-            const float angle = m_spotLightRotationAngle + index * Constants::TwoPi / 3;
+            const float angle = m_diskLightRotationAngle + index * Constants::TwoPi / 3;
             const auto location = Vector3(
-                spotLightDist * sinf(angle),
-                spotLightDist * cosf(angle),
-                m_spotLightHeights[index]);
+                diskLightDist * sinf(angle),
+                diskLightDist * cosf(angle),
+                m_diskLightHeights[index]);
             const auto transform = Transform::CreateLookAt(
                 location,
                 Vector3::CreateZero());
-            m_spotLightFeatureProcessor->SetPosition(m_spotLightHandles[index], location);
-            m_spotLightFeatureProcessor->SetDirection(m_spotLightHandles[index], transform.GetBasis(1));
+            m_diskLightFeatureProcessor->SetPosition(m_diskLightHandles[index], location);
+            m_diskLightFeatureProcessor->SetDirection(m_diskLightHandles[index], transform.GetBasis(1));
         }
 
         Camera::CameraRequestBus::Event(
@@ -399,35 +399,35 @@ namespace AtomSampleViewer
         SetupDebugFlags();
     }
 
-    void ShadowExampleComponent::CreateSpotLights()
+    void ShadowExampleComponent::CreateDiskLights()
     {
         using namespace AZ;
-        Render::SpotLightFeatureProcessorInterface* const featureProcessor = m_spotLightFeatureProcessor;
+        Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
 
-        for (uint32_t index = 0; index < SpotLightCount; ++index)
+        for (uint32_t index = 0; index < DiskLightCount; ++index)
         {
-            const SpotLightHandle handle = featureProcessor->AcquireLight();
+            const DiskLightHandle handle = featureProcessor->AcquireLight();
 
-            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(s_spotLightColors[index] * m_spotLightIntensities[index]);
+            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(s_diskLightColors[index] * m_diskLightIntensities[index]);
             featureProcessor->SetRgbIntensity(handle, lightColor);
             featureProcessor->SetAttenuationRadius(
                 handle,
-                sqrtf(m_spotLightIntensities[index] / CutoffIntensity));
+                sqrtf(m_diskLightIntensities[index] / CutoffIntensity));
             featureProcessor->SetConeAngles(
                 handle,
-                m_outerConeAngles[index] * ConeAngleInnerRatio,
-                m_outerConeAngles[index]);
-            featureProcessor->SetShadowmapSize(
-                handle,
-                m_spotLightShadowEnabled[index] ?
-                s_shadowmapImageSizes[m_spotLightImageSizeIndices[index]] :
-                Render::ShadowmapSize::None);
-            featureProcessor->SetShadowFilterMethod(handle, s_shadowFilterMethods[m_shadowFilterMethodIndicesSpot[index]]);
-            featureProcessor->SetShadowBoundaryWidthAngle(handle, m_boundaryWidthsSpot[index]);
-            featureProcessor->SetPredictionSampleCount(handle, m_predictionSampleCountsSpot[index]);
-            featureProcessor->SetFilteringSampleCount(handle, m_filteringSampleCountsSpot[index]);
-            featureProcessor->SetPcfMethod(handle, m_pcfMethod[index]);
-            m_spotLightHandles[index] = handle;
+                DegToRad(m_outerConeAngles[index]) * ConeAngleInnerRatio,
+                DegToRad(m_outerConeAngles[index]));
+            featureProcessor->SetShadowsEnabled(handle, m_diskLightShadowEnabled[index]);
+            if (m_diskLightShadowEnabled[index])
+            {
+                featureProcessor->SetShadowmapMaxResolution(handle, s_shadowmapImageSizes[m_diskLightImageSizeIndices[index]]);
+                featureProcessor->SetShadowFilterMethod(handle, s_shadowFilterMethods[m_shadowFilterMethodIndicesDisk[index]]);
+                featureProcessor->SetSofteningBoundaryWidthAngle(handle, AZ::DegToRad(m_boundaryWidthsDisk[index]));
+                featureProcessor->SetPredictionSampleCount(handle, m_predictionSampleCountsDisk[index]);
+                featureProcessor->SetFilteringSampleCount(handle, m_filteringSampleCountsDisk[index]);
+                featureProcessor->SetPcfMethod(handle, m_pcfMethod[index]);
+            }
+            m_diskLightHandles[index] = handle;
         }
     }
 
@@ -589,69 +589,69 @@ namespace AtomSampleViewer
 
             ImGui::Separator();
 
-            ImGui::Text("Spot Lights");
+            ImGui::Text("Disk Lights");
             ImGui::Indent();
             {
-                ScriptableImGui::Checkbox("Auto Rotation##Spot", &m_isSpotLightAutoRotate);
-                ScriptableImGui::SliderAngle("Base Direction##Spot", &m_spotLightRotationAngle, 0, 360);
+                ScriptableImGui::Checkbox("Auto Rotation##Disk", &m_isDiskLightAutoRotate);
+                ScriptableImGui::SliderAngle("Base Direction##Disk", &m_diskLightRotationAngle, 0, 360);
 
                 ImGui::Spacing();
 
                 ImGui::Text("Control Target");
-                ScriptableImGui::RadioButton("Red", &m_controlTargetSpotLightIndex, 0);
+                ScriptableImGui::RadioButton("Red", &m_controlTargetDiskLightIndex, 0);
                 ImGui::SameLine();
-                ScriptableImGui::RadioButton("Green", &m_controlTargetSpotLightIndex, 1);
+                ScriptableImGui::RadioButton("Green", &m_controlTargetDiskLightIndex, 1);
                 ImGui::SameLine();
-                ScriptableImGui::RadioButton("Blue", &m_controlTargetSpotLightIndex, 2);
+                ScriptableImGui::RadioButton("Blue", &m_controlTargetDiskLightIndex, 2);
 
-                const int index = m_controlTargetSpotLightIndex;
-                const SpotLightHandle lightId = m_spotLightHandles[index];
+                const int index = m_controlTargetDiskLightIndex;
+                const DiskLightHandle lightId = m_diskLightHandles[index];
 
-                ScriptableImGui::SliderFloat("Height##Spot",
-                    &m_spotLightHeights[index], 1.f, 30.f, "%.1f", 2.f);
+                ScriptableImGui::SliderFloat("Height##Disk",
+                    &m_diskLightHeights[index], 1.f, 30.f, "%.1f", 2.f);
 
                 if (ScriptableImGui::SliderFloat("Cone Angle", &m_outerConeAngles[index], 0.f, 120.f))
                 {
-                    m_spotLightFeatureProcessor->SetConeAngles(
+                    m_diskLightFeatureProcessor->SetConeAngles(
                         lightId,
-                        m_outerConeAngles[index] * ConeAngleInnerRatio,
-                        m_outerConeAngles[index]);
+                        AZ::DegToRad(m_outerConeAngles[index]) * ConeAngleInnerRatio,
+                        AZ::DegToRad(m_outerConeAngles[index]));
                 }
 
-                if (ScriptableImGui::SliderFloat("Intensity##Spot", &m_spotLightIntensities[index], 0.f, 20000.f, "%.1f", 2.f))
+                if (ScriptableImGui::SliderFloat("Intensity##Disk", &m_diskLightIntensities[index], 0.f, 20000.f, "%.1f", 2.f))
                 {
-                    AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(s_spotLightColors[index] * m_spotLightIntensities[index]);
-                    m_spotLightFeatureProcessor->SetRgbIntensity(lightId, lightColor);
-                    m_spotLightFeatureProcessor->SetAttenuationRadius(
+                    AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(s_diskLightColors[index] * m_diskLightIntensities[index]);
+                    m_diskLightFeatureProcessor->SetRgbIntensity(lightId, lightColor);
+                    m_diskLightFeatureProcessor->SetAttenuationRadius(
                         lightId,
-                        sqrtf(m_spotLightIntensities[index] / CutoffIntensity));
+                        sqrtf(m_diskLightIntensities[index] / CutoffIntensity));
                 }
 
                 bool shadowmapSizeChanged =
-                    ScriptableImGui::Checkbox("Enable Shadow", &m_spotLightShadowEnabled[index]);
+                    ScriptableImGui::Checkbox("Enable Shadow", &m_diskLightShadowEnabled[index]);
 
                 ImGui::Text("Shadowmap Size");
                 shadowmapSizeChanged = shadowmapSizeChanged ||
                     ScriptableImGui::Combo(
-                        "Size##Spot",
-                        &m_spotLightImageSizeIndices[index],
+                        "Size##Disk",
+                        &m_diskLightImageSizeIndices[index],
                         s_shadowmapImageSizeLabels,
                         AZ_ARRAY_SIZE(s_shadowmapImageSizeLabels));
                 if (shadowmapSizeChanged)
                 {
-                    m_spotLightFeatureProcessor->SetShadowmapSize(
-                        lightId,
-                        m_spotLightShadowEnabled[index] ?
-                        s_shadowmapImageSizes[m_spotLightImageSizeIndices[index]] :
-                        ShadowmapSize::None);
+                    m_diskLightFeatureProcessor->SetShadowsEnabled(lightId, m_diskLightShadowEnabled[index]);
+                    if (m_diskLightShadowEnabled[index])
+                    {
+                        m_diskLightFeatureProcessor->SetShadowmapMaxResolution(lightId, s_shadowmapImageSizes[m_diskLightImageSizeIndices[index]]);
+                    }
 
                     // Reset shadow parameters when shadow is disabled.
-                    if (!m_spotLightShadowEnabled[index])
+                    if (!m_diskLightShadowEnabled[index])
                     {
-                        m_shadowFilterMethodIndicesSpot[index] = 0;
-                        m_boundaryWidthsSpot[index] = 0.f;
-                        m_predictionSampleCountsSpot[index] = 0;
-                        m_filteringSampleCountsSpot[index] = 0;
+                        m_shadowFilterMethodIndicesDisk[index] = 0;
+                        m_boundaryWidthsDisk[index] = 0.f;
+                        m_predictionSampleCountsDisk[index] = 0;
+                        m_filteringSampleCountsDisk[index] = 0;
                     }
                 }
 
@@ -659,40 +659,38 @@ namespace AtomSampleViewer
 
                 ImGui::Text("Filtering");
                 if (ScriptableImGui::Combo(
-                    "Filter Method##Spot",
-                    &m_shadowFilterMethodIndicesSpot[index],
+                    "Filter Method##Disk",
+                    &m_shadowFilterMethodIndicesDisk[index],
                     s_shadowFilterMethodLabels,
                     AZ_ARRAY_SIZE(s_shadowFilterMethodLabels)))
                 {
-                    m_spotLightFeatureProcessor->SetShadowFilterMethod(
+                    m_diskLightFeatureProcessor->SetShadowFilterMethod(
                         lightId,
-                        s_shadowFilterMethods[m_shadowFilterMethodIndicesSpot[index]]);
+                        s_shadowFilterMethods[m_shadowFilterMethodIndicesDisk[index]]);
                 }
 
-                if (m_shadowFilterMethodIndicesSpot[index] != aznumeric_cast<int>(ShadowFilterMethod::None))
+                if (m_shadowFilterMethodIndicesDisk[index] != aznumeric_cast<int>(ShadowFilterMethod::None))
                 {
                     ImGui::Text("Boundary Width in degrees");
-                    if (ScriptableImGui::SliderFloat("Width##Spot", &m_boundaryWidthsSpot[index], 0.f, 1.0f, "%.3f"))
+                    if (ScriptableImGui::SliderFloat("Width##Disk", &m_boundaryWidthsDisk[index], 0.f, 1.0f, "%.3f"))
                     {
-                        m_spotLightFeatureProcessor->SetShadowBoundaryWidthAngle(
-                            lightId,
-                            m_boundaryWidthsSpot[index]);
+                        m_diskLightFeatureProcessor->SetSofteningBoundaryWidthAngle(lightId, AZ::DegToRad(m_boundaryWidthsDisk[index]));
                     }
                 }
 
-                if (m_shadowFilterMethodIndicesSpot[index] == aznumeric_cast<int>(ShadowFilterMethod::Pcf) ||
-                    m_shadowFilterMethodIndicesSpot[index] == aznumeric_cast<int>(ShadowFilterMethod::EsmPcf))
+                if (m_shadowFilterMethodIndicesDisk[index] == aznumeric_cast<int>(ShadowFilterMethod::Pcf) ||
+                    m_shadowFilterMethodIndicesDisk[index] == aznumeric_cast<int>(ShadowFilterMethod::EsmPcf))
                 {
                     ImGui::Spacing();
                     ImGui::Text("Filtering (PCF specific)");
                     
-                    if (m_pcfMethod[index] == PcfMethod::BoundarySearch && ScriptableImGui::SliderInt("Prediction # ##Spot", &m_predictionSampleCountsSpot[index], 4, 16))
+                    if (m_pcfMethod[index] == PcfMethod::BoundarySearch && ScriptableImGui::SliderInt("Prediction # ##Disk", &m_predictionSampleCountsDisk[index], 4, 16))
                     {
-                        m_spotLightFeatureProcessor->SetPredictionSampleCount(lightId, m_predictionSampleCountsSpot[index]);
+                        m_diskLightFeatureProcessor->SetPredictionSampleCount(lightId, m_predictionSampleCountsDisk[index]);
                     }
-                    if (ScriptableImGui::SliderInt("Filtering # ##Spot", &m_filteringSampleCountsSpot[index], 4, 64))
+                    if (ScriptableImGui::SliderInt("Filtering # ##Disk", &m_filteringSampleCountsDisk[index], 4, 64))
                     {
-                        m_spotLightFeatureProcessor->SetFilteringSampleCount(lightId, m_filteringSampleCountsSpot[index]);
+                        m_diskLightFeatureProcessor->SetFilteringSampleCount(lightId, m_filteringSampleCountsDisk[index]);
                     }
 
                     int pcfMethodAsInteger = aznumeric_cast<int>(m_pcfMethod[index]);
@@ -700,13 +698,13 @@ namespace AtomSampleViewer
                             "Boundary Search filtering", &pcfMethodAsInteger, static_cast<int>(PcfMethod::BoundarySearch)))
                     {
                         m_pcfMethod[index] = PcfMethod::BoundarySearch;
-                        m_spotLightFeatureProcessor->SetPcfMethod(lightId, m_pcfMethod[index]);
+                        m_diskLightFeatureProcessor->SetPcfMethod(lightId, m_pcfMethod[index]);
                     }
                     if (ScriptableImGui::RadioButton(
                             "Bicubic filtering", &pcfMethodAsInteger, static_cast<int>(PcfMethod::Bicubic)))
                     {
                         m_pcfMethod[index] = PcfMethod::Bicubic;
-                        m_spotLightFeatureProcessor->SetPcfMethod(lightId, m_pcfMethod[index]);
+                        m_diskLightFeatureProcessor->SetPcfMethod(lightId, m_pcfMethod[index]);
                     }
 
                 }

+ 21 - 21
Gem/Code/Source/ShadowExampleComponent.h

@@ -16,7 +16,7 @@
 
 #include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/ShadowConstants.h>
-#include <Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h>
+#include <Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h>
 
 #include <AzCore/Component/TickBus.h>
 
@@ -31,7 +31,7 @@ namespace AtomSampleViewer
     * At the 3rd step, we made the number of cascades configurable.
     * At the 4th step, we implement softening shadow edge by PCF (Percentage Closer Filtering).
     * At the 5th step, we implement softening shadow edge by ESM (Exponential Shadow Maps).
-    * At the 6th step, we implement spot light shadows.
+    * At the 6th step, we implement disk light shadows.
     */
     class ShadowExampleComponent final
         : public CommonSampleComponentBase
@@ -50,7 +50,7 @@ namespace AtomSampleViewer
 
     private:
         using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle;
-        using SpotLightHandle = AZ::Render::SpotLightFeatureProcessorInterface::LightHandle;
+        using DiskLightHandle = AZ::Render::DiskLightFeatureProcessorInterface::LightHandle;
         
         // AZ::TickBus::Handler overrides...
         void OnTick(float deltaTime, AZ::ScriptTimePoint time);
@@ -67,19 +67,19 @@ namespace AtomSampleViewer
 
         void CreateMeshes();
         void CreateDirectionalLight();
-        void CreateSpotLights();
+        void CreateDiskLights();
         void SetInitialShadowParams();
         void SetupDebugFlags();
 
         void DrawSidebar();
 
-        static constexpr uint32_t SpotLightCount = 3;
+        static constexpr uint32_t DiskLightCount = 3;
         static constexpr float ConeAngleInnerRatio = 0.9f;
         static constexpr float CutoffIntensity = 0.1f;
         static constexpr float FarClipDistance = 20.f;
 
         static const AZ::Color DirectionalLightColor;
-        static AZ::Color s_spotLightColors[SpotLightCount];
+        static AZ::Color s_diskLightColors[DiskLightCount];
         
         // Mesh Handles
         using MeshHandle = AZ::Render::MeshFeatureProcessorInterface::MeshHandle;
@@ -88,9 +88,9 @@ namespace AtomSampleViewer
 
         // lights
         AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
-        AZ::Render::SpotLightFeatureProcessorInterface* m_spotLightFeatureProcessor = nullptr;
+        AZ::Render::DiskLightFeatureProcessorInterface* m_diskLightFeatureProcessor = nullptr;
         DirectionalLightHandle m_directionalLightHandle;
-        SpotLightHandle m_spotLightHandles[SpotLightCount];
+        DiskLightHandle m_diskLightHandles[DiskLightCount];
 
         // asset
         AZ::Data::Asset<AZ::RPI::ModelAsset> m_bunnyModelAsset;
@@ -108,23 +108,23 @@ namespace AtomSampleViewer
         // GUI
         float m_elapsedTime = 0.f;
 
-        int m_controlTargetSpotLightIndex = 0;
+        int m_controlTargetDiskLightIndex = 0;
         float m_directionalLightRotationAngle = 0.f; // in radian
-        float m_spotLightRotationAngle = 0.f; // in radian
+        float m_diskLightRotationAngle = 0.f; // in radian
         bool m_isDirectionalLightAutoRotate = true;
-        bool m_isSpotLightAutoRotate = true;
+        bool m_isDiskLightAutoRotate = true;
         float m_directionalLightHeight = 10.f;
-        float m_spotLightHeights[SpotLightCount] = {5.f, 6.f, 7.f};
+        float m_diskLightHeights[DiskLightCount] = {5.f, 6.f, 7.f};
         float m_directionalLightIntensity = 5.f;
-        float m_spotLightIntensities[SpotLightCount] = {500.f, 900.f, 500.f};
-        float m_outerConeAngles[SpotLightCount] = {35.f, 40.f, 45.f};
+        float m_diskLightIntensities[DiskLightCount] = {500.f, 900.f, 500.f};
+        float m_outerConeAngles[DiskLightCount] = {17.5f, 20.f, 22.5f};
         float m_cameraFovY = AZ::Constants::QuarterPi;
 
         // Shadowmap
         static const AZ::Render::ShadowmapSize s_shadowmapImageSizes[];
         static const char* s_shadowmapImageSizeLabels[];
         int m_directionalLightImageSizeIndex = 2; // image size is 1024.
-        int m_spotLightImageSizeIndices[SpotLightCount] = {2, 2, 2}; // image size is 1024.
+        int m_diskLightImageSizeIndices[DiskLightCount] = {2, 2, 2}; // image size is 1024.
         int m_cascadeCount = 2;
         bool m_shadowmapFrustumSplitIsAutomatic = true;
         float m_ratioLogarithmUniform = 0.5f;
@@ -138,20 +138,20 @@ namespace AtomSampleViewer
         bool m_isCascadeCorrectionEnabled = false;
         bool m_isDebugColoringEnabled = false;
         bool m_isDebugBoundingBoxEnabled = false;
-        bool m_spotLightShadowEnabled[SpotLightCount] = {true, true, true};
+        bool m_diskLightShadowEnabled[DiskLightCount] = {true, true, true};
 
         // Edge-softening of shadows
         static const AZ::Render::ShadowFilterMethod s_shadowFilterMethods[];
         static const char* s_shadowFilterMethodLabels[];
         int m_shadowFilterMethodIndexDirectional = 0; // filter method is None.
-        int m_shadowFilterMethodIndicesSpot[SpotLightCount] = { 0, 0, 0 }; // filter method is None.
+        int m_shadowFilterMethodIndicesDisk[DiskLightCount] = { 0, 0, 0 }; // filter method is None.
         float m_boundaryWidthDirectional = 0.03f; // 3cm
-        float m_boundaryWidthsSpot[SpotLightCount] = { 0.25f, 0.25f, 0.25f }; // 0.25 degrees
+        float m_boundaryWidthsDisk[DiskLightCount] = { 0.25f, 0.25f, 0.25f }; // 0.25 degrees
         int m_predictionSampleCountDirectional = 8;
-        int m_predictionSampleCountsSpot[SpotLightCount] = { 8, 8, 8 };
+        int m_predictionSampleCountsDisk[DiskLightCount] = { 8, 8, 8 };
         int m_filteringSampleCountDirectional = 32;
-        int m_filteringSampleCountsSpot[SpotLightCount] = { 32, 32, 32 };
-        AZ::Render::PcfMethod m_pcfMethod[SpotLightCount] = {
+        int m_filteringSampleCountsDisk[DiskLightCount] = { 32, 32, 32 };
+        AZ::Render::PcfMethod m_pcfMethod[DiskLightCount] = {
             AZ::Render::PcfMethod::BoundarySearch, AZ::Render::PcfMethod::BoundarySearch, AZ::Render::PcfMethod::BoundarySearch};
 
         ImGuiSidebar m_imguiSidebar;

+ 122 - 116
Gem/Code/Source/ShadowedBistroExampleComponent.cpp

@@ -73,20 +73,20 @@ namespace AtomSampleViewer
     {
         using namespace AZ;
         m_directionalLightShadowmapSizeIndex = s_shadowmapSizeIndexDefault;
-        m_spotLightShadowmapSize = Render::ShadowmapSize::None; // random
+        m_diskLightShadowmapSize = Render::ShadowmapSize::None; // random
         m_cascadeCount = s_cascadesCountDefault;
         m_ratioLogarithmUniform = s_ratioLogarithmUniformDefault;
-        m_spotLightCount = 0;
+        m_diskLightCount = 0;
 
-        // heuristic spot light default position configuration
-        m_spotLightsBasePosition[0] = 0.04f;
-        m_spotLightsBasePosition[1] = 0.04f;;
-        m_spotLightsBasePosition[2] = -0.03f;
-        m_spotLightsPositionScatteringRatio = 0.27f;
+        // heuristic disk light default position configuration
+        m_diskLightsBasePosition[0] = 0.04f;
+        m_diskLightsBasePosition[1] = 0.04f;;
+        m_diskLightsBasePosition[2] = -0.03f;
+        m_diskLightsPositionScatteringRatio = 0.27f;
 
         RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get();
         m_directionalLightFeatureProcessor = scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
-        m_spotLightFeatureProcessor = scene->GetFeatureProcessor<Render::SpotLightFeatureProcessorInterface>();
+        m_diskLightFeatureProcessor = scene->GetFeatureProcessor<Render::DiskLightFeatureProcessorInterface>();
 
         SetupScene();
 
@@ -129,7 +129,7 @@ namespace AtomSampleViewer
         GetMeshFeatureProcessor()->ReleaseMesh(m_meshHandle);
 
         m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
-        UpdateSpotLightCount(0);
+        UpdateDiskLightCount(0);
     }
 
     void ShadowedBistroExampleComponent::OnTick(float deltaTime, AZ::ScriptTimePoint timePoint)
@@ -176,7 +176,7 @@ namespace AtomSampleViewer
     {
         m_bistroExteriorAssetLoaded = true;
         m_worldAabb = model->GetAabb();
-        UpdateSpotLightCount(SpotLightCountDefault);
+        UpdateDiskLightCount(DiskLightCountDefault);
 
         // Now that the models are initialized, we can allow the script to continue.
         ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
@@ -269,27 +269,27 @@ namespace AtomSampleViewer
             SetupDebugFlags();
         }
 
-        // spot lights are initialized after loading models.
-        BuildSpotLightParameters();
+        // disk lights are initialized after loading models.
+        BuildDiskLightParameters();
     }
 
-    void ShadowedBistroExampleComponent::BuildSpotLightParameters()
+    void ShadowedBistroExampleComponent::BuildDiskLightParameters()
     {
         m_random.SetSeed(0);
-        m_spotLights.clear();
-        m_spotLights.reserve(SpotLightCountMax);
-        for (int index = 0; index < SpotLightCountMax; ++index)
+        m_diskLights.clear();
+        m_diskLights.reserve(DiskLightCountMax);
+        for (int index = 0; index < DiskLightCountMax; ++index)
         {
-            m_spotLights.emplace_back(
+            m_diskLights.emplace_back(
                 GetRandomColor(),
                 GetRandomPosition(),
                 GetRandomShadowmapSize());
         }
     }
 
-    void ShadowedBistroExampleComponent::UpdateSpotLightCount(uint16_t count)
+    void ShadowedBistroExampleComponent::UpdateDiskLightCount(uint16_t count)
     {
-        // We suppose m_spotLights has been initialized except m_entity.
+        // We suppose m_diskLights has been initialized except m_entity.
         using namespace AZ;
 
         // Don't assert here if count == 0, since the count is set to 0 during Deactivate
@@ -299,40 +299,43 @@ namespace AtomSampleViewer
             return;
         }
 
-        for (int index = count; index < m_spotLightCount; ++index)
+        for (int index = count; index < m_diskLightCount; ++index)
         {
-            SpotLightHandle& handle = m_spotLights[index].m_handle;
-            m_spotLightFeatureProcessor->ReleaseLight(handle);
+            DiskLightHandle& handle = m_diskLights[index].m_handle;
+            m_diskLightFeatureProcessor->ReleaseLight(handle);
         }
 
-        const int previousSpotLightCount = m_spotLightCount;
+        const int previousDiskLightCount = m_diskLightCount;
 
-        for (int index = previousSpotLightCount; index < count; ++index)
+        for (int index = previousDiskLightCount; index < count; ++index)
         {
-            Render::SpotLightFeatureProcessorInterface* const featureProcessor = m_spotLightFeatureProcessor;
-            const SpotLightHandle handle = featureProcessor->AcquireLight();
+            Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
+            const DiskLightHandle handle = featureProcessor->AcquireLight();
 
-            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(m_spotLights[index].m_color * m_spotLightIntensity);
+            AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(m_diskLights[index].m_color * m_diskLightIntensity);
             featureProcessor->SetRgbIntensity(handle, lightColor);
             featureProcessor->SetAttenuationRadius(
                 handle,
-                sqrtf(m_spotLightIntensity / CutoffIntensity));
-            featureProcessor->SetShadowmapSize(
-                handle,
-                m_spotLightShadowEnabled ?
-                m_spotLights[index].m_shadowmapSize :
-                Render::ShadowmapSize::None);
-            featureProcessor->SetConeAngles(handle, 45.f, 55.f);
-            featureProcessor->SetShadowFilterMethod(handle, aznumeric_cast<Render::ShadowFilterMethod>(m_shadowFilterMethodIndexSpot));
-            featureProcessor->SetPredictionSampleCount(handle, aznumeric_cast<uint16_t>(m_predictionSampleCountSpot));
-            featureProcessor->SetFilteringSampleCount(handle, aznumeric_cast<uint16_t>(m_filteringSampleCountSpot));
-
-            m_spotLights[index].m_handle = handle;
+                sqrtf(m_diskLightIntensity / CutoffIntensity));
+            featureProcessor->SetConeAngles(handle, DegToRad(22.5f), DegToRad(27.5));
+            featureProcessor->SetShadowsEnabled(handle, m_diskLightShadowEnabled);
+            if (m_diskLightShadowEnabled)
+            {
+                featureProcessor->SetShadowmapMaxResolution(
+                    handle,
+                    m_diskLightShadowEnabled ?
+                    m_diskLights[index].m_shadowmapSize :
+                    Render::ShadowmapSize::None);
+                featureProcessor->SetShadowFilterMethod(handle, aznumeric_cast<Render::ShadowFilterMethod>(m_shadowFilterMethodIndexDisk));
+                featureProcessor->SetPredictionSampleCount(handle, aznumeric_cast<uint16_t>(m_predictionSampleCountDisk));
+                featureProcessor->SetFilteringSampleCount(handle, aznumeric_cast<uint16_t>(m_filteringSampleCountDisk));
+            }
+            m_diskLights[index].m_handle = handle;
 
-            UpdateSpotLightPosition(index);
+            UpdateDiskLightPosition(index);
         }
 
-        m_spotLightCount = count;
+        m_diskLightCount = count;
     }
 
     const AZ::Color& ShadowedBistroExampleComponent::GetRandomColor()
@@ -505,7 +508,23 @@ namespace AtomSampleViewer
             {
                 ImGui::Spacing();
                 ImGui::Text("Filtering (PCF specific)");
-                if (ScriptableImGui::SliderInt("Prediction # ##Directional", &m_predictionSampleCountDirectional, 4, 16))
+
+                int pcfMethodAsInteger = aznumeric_cast<int>(m_pcfMethodDirectional);
+                if (ScriptableImGui::RadioButton(
+                        "Boundary Search filtering", &pcfMethodAsInteger, static_cast<int>(PcfMethod::BoundarySearch)))
+                {
+                    m_pcfMethodDirectional = PcfMethod::BoundarySearch;
+                    m_directionalLightFeatureProcessor->SetPcfMethod(m_directionalLightHandle, m_pcfMethodDirectional);
+                }
+                if (ScriptableImGui::RadioButton("Bicubic filtering", &pcfMethodAsInteger, static_cast<int>(PcfMethod::Bicubic)))
+                {
+                    m_pcfMethodDirectional = PcfMethod::Bicubic;
+                    m_directionalLightFeatureProcessor->SetPcfMethod(m_directionalLightHandle, m_pcfMethodDirectional);
+                }
+
+                if (m_pcfMethodDirectional ==
+                    AZ::Render::PcfMethod::BoundarySearch && ScriptableImGui::SliderInt(
+                        "Prediction # ##Directional", &m_predictionSampleCountDirectional, 4, 16))
                 {
                     m_directionalLightFeatureProcessor->SetPredictionSampleCount(
                         m_directionalLightHandle,
@@ -526,96 +545,96 @@ namespace AtomSampleViewer
         ImGui::Text("Spot Lights");
         ImGui::Indent();
         {
-            int spotLightCount = m_spotLightCount;
-            if (ScriptableImGui::SliderInt("Number", &spotLightCount, 0, SpotLightCountMax))
+            int diskLightCount = m_diskLightCount;
+            if (ScriptableImGui::SliderInt("Number", &diskLightCount, 0, DiskLightCountMax))
             {
-                UpdateSpotLightCount(spotLightCount);
+                UpdateDiskLightCount(diskLightCount);
             }
 
-            if (ScriptableImGui::SliderFloat("Intensity##spot", &m_spotLightIntensity, 0.f, 100000.f, "%.1f", 4.f))
+            if (ScriptableImGui::SliderFloat("Intensity##spot", &m_diskLightIntensity, 0.f, 100000.f, "%.1f", 4.f))
             {
-                for (const SpotLight& light : m_spotLights)
+                for (const DiskLight& light : m_diskLights)
                 {
                     if (light.m_handle.IsValid())
                     {
-                        AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(light.m_color * m_spotLightIntensity);
-                        m_spotLightFeatureProcessor->SetRgbIntensity(light.m_handle, lightColor);
-                        m_spotLightFeatureProcessor->SetAttenuationRadius(
+                        AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> lightColor(light.m_color * m_diskLightIntensity);
+                        m_diskLightFeatureProcessor->SetRgbIntensity(light.m_handle, lightColor);
+                        m_diskLightFeatureProcessor->SetAttenuationRadius(
                             light.m_handle,
-                            sqrtf(m_spotLightIntensity / CutoffIntensity));
+                            sqrtf(m_diskLightIntensity / CutoffIntensity));
                     }
                 }
             }
 
             // avoiding SliderFloat3 since its sliders are too narrow.
-            if (ScriptableImGui::SliderFloat("Center X", &m_spotLightsBasePosition[0], -0.5f, 0.5f) ||
-                ScriptableImGui::SliderFloat("Center Y", &m_spotLightsBasePosition[1], -0.5f, 0.5f) ||
-                ScriptableImGui::SliderFloat("Center Z", &m_spotLightsBasePosition[2], -0.5f, 0.5f) ||
-                ScriptableImGui::SliderFloat("Pos. Scatt. Ratio", &m_spotLightsPositionScatteringRatio, 0.f, 1.f))
+            if (ScriptableImGui::SliderFloat("Center X", &m_diskLightsBasePosition[0], -0.5f, 0.5f) ||
+                ScriptableImGui::SliderFloat("Center Y", &m_diskLightsBasePosition[1], -0.5f, 0.5f) ||
+                ScriptableImGui::SliderFloat("Center Z", &m_diskLightsBasePosition[2], -0.5f, 0.5f) ||
+                ScriptableImGui::SliderFloat("Pos. Scatt. Ratio", &m_diskLightsPositionScatteringRatio, 0.f, 1.f))
             {
-                UpdateSpotLightPositions();
+                UpdateDiskLightPositions();
             }
 
-            bool spotLightShadowmapChanged = ScriptableImGui::Checkbox("Enable Shadow", &m_spotLightShadowEnabled);
+            bool diskLightShadowmapChanged = ScriptableImGui::Checkbox("Enable Shadow", &m_diskLightShadowEnabled);
 
             ImGui::Text("Shadowmap Size");
-            int newSize = static_cast<int>(m_spotLightShadowmapSize);
+            int newSize = static_cast<int>(m_diskLightShadowmapSize);
             // To avoid GPU memory consumption, we avoid bigger shadowmap sizes here.
-            spotLightShadowmapChanged = spotLightShadowmapChanged ||
+            diskLightShadowmapChanged = diskLightShadowmapChanged ||
                 ScriptableImGui::RadioButton("256", &newSize, static_cast<int>(Render::ShadowmapSize::Size256)) ||
                 ScriptableImGui::RadioButton("512", &newSize, static_cast<int>(Render::ShadowmapSize::Size512)) ||
                 ScriptableImGui::RadioButton("1024", &newSize, static_cast<int>(Render::ShadowmapSize::Size1024)) ||
                 ScriptableImGui::RadioButton("Random", &newSize, static_cast<int>(Render::ShadowmapSize::None));
 
-            if (spotLightShadowmapChanged)
+            if (diskLightShadowmapChanged)
             {
-                m_spotLightShadowmapSize = static_cast<Render::ShadowmapSize>(newSize);
-                UpdateSpotLightShadowmapSize();
+                m_diskLightShadowmapSize = static_cast<Render::ShadowmapSize>(newSize);
+                UpdateDiskLightShadowmapSize();
             }
 
             ImGui::Spacing();
             ImGui::Text("Filtering");
             if (ScriptableImGui::Combo(
                 "Filter Method##Spot",
-                &m_shadowFilterMethodIndexSpot,
+                &m_shadowFilterMethodIndexDisk,
                 s_shadowFilterMethodLabels,
                 AZ_ARRAY_SIZE(s_shadowFilterMethodLabels)))
             {
-                for (int index = 0; index < m_spotLightCount; ++index)
+                for (int index = 0; index < m_diskLightCount; ++index)
                 {
-                    m_spotLightFeatureProcessor->SetShadowFilterMethod(m_spotLights[index].m_handle, aznumeric_cast<ShadowFilterMethod>(m_shadowFilterMethodIndexSpot));
+                    m_diskLightFeatureProcessor->SetShadowFilterMethod(m_diskLights[index].m_handle, aznumeric_cast<ShadowFilterMethod>(m_shadowFilterMethodIndexDisk));
                 }
             }
 
-            if (m_shadowFilterMethodIndexSpot != aznumeric_cast<int>(ShadowFilterMethod::None))
+            if (m_shadowFilterMethodIndexDisk != aznumeric_cast<int>(ShadowFilterMethod::None))
             {
                 ImGui::Text("Boundary Width in degrees");
-                if (ScriptableImGui::SliderFloat("Width##Spot", &m_boundaryWidthSpot, 0.f, 1.f, "%.3f"))
+                if (ScriptableImGui::SliderFloat("Width##Spot", &m_boundaryWidthDisk, 0.f, 1.f, "%.3f"))
                 {
-                    for (int index = 0; index < m_spotLightCount; ++index)
+                    for (int index = 0; index < m_diskLightCount; ++index)
                     {
-                        m_spotLightFeatureProcessor->SetShadowBoundaryWidthAngle(m_spotLights[index].m_handle, m_boundaryWidthSpot);
+                        m_diskLightFeatureProcessor->SetSofteningBoundaryWidthAngle(m_diskLights[index].m_handle, DegToRad(m_boundaryWidthDisk));
                     }
                 }
             }
 
-            if (m_shadowFilterMethodIndexSpot == aznumeric_cast<int>(ShadowFilterMethod::Pcf) ||
-                m_shadowFilterMethodIndexSpot == aznumeric_cast<int>(ShadowFilterMethod::EsmPcf))
+            if (m_shadowFilterMethodIndexDisk == aznumeric_cast<int>(ShadowFilterMethod::Pcf) ||
+                m_shadowFilterMethodIndexDisk == aznumeric_cast<int>(ShadowFilterMethod::EsmPcf))
             {
                 ImGui::Spacing();
                 ImGui::Text("Filtering (PCF specific)");
-                if (ScriptableImGui::SliderInt("Predictiona # ##Spot", &m_predictionSampleCountSpot, 4, 16))
+                if (ScriptableImGui::SliderInt("Predictiona # ##Spot", &m_predictionSampleCountDisk, 4, 16))
                 {
-                    for (int index = 0; index < m_spotLightCount; ++index)
+                    for (int index = 0; index < m_diskLightCount; ++index)
                     {
-                        m_spotLightFeatureProcessor->SetPredictionSampleCount(m_spotLights[index].m_handle, m_predictionSampleCountSpot);
+                        m_diskLightFeatureProcessor->SetPredictionSampleCount(m_diskLights[index].m_handle, m_predictionSampleCountDisk);
                     }
                 }
-                if (ScriptableImGui::SliderInt("Filtering # ##Spot", &m_filteringSampleCountSpot, 4, 64))
+                if (ScriptableImGui::SliderInt("Filtering # ##Spot", &m_filteringSampleCountDisk, 4, 64))
                 {
-                    for (int index = 0; index < m_spotLightCount; ++index)
+                    for (int index = 0; index < m_diskLightCount; ++index)
                     {
-                        m_spotLightFeatureProcessor->SetFilteringSampleCount(m_spotLights[index].m_handle, m_filteringSampleCountSpot);
+                        m_diskLightFeatureProcessor->SetFilteringSampleCount(m_diskLights[index].m_handle, m_filteringSampleCountDisk);
                     }
                 }
             }
@@ -625,45 +644,32 @@ namespace AtomSampleViewer
         m_imguiSidebar.End();
     }
 
-    void ShadowedBistroExampleComponent::UpdateSpotLightShadowmapSize()
+    void ShadowedBistroExampleComponent::UpdateDiskLightShadowmapSize()
     {
         using namespace AZ::Render;
-        SpotLightFeatureProcessorInterface* const featureProcessor = m_spotLightFeatureProcessor;
+        DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
 
-        if (!m_spotLightShadowEnabled)
+        for (const DiskLight& light : m_diskLights)
         {
-            // disabled shadows
-            for (const SpotLight& light : m_spotLights)
+            if (!light.m_handle.IsValid())
             {
-                if (light.m_handle.IsValid())
-                {
-                    featureProcessor->SetShadowmapSize(
-                        light.m_handle,
-                        ShadowmapSize::None);
-                }
+                continue;
             }
-        }
-        else if (m_spotLightShadowmapSize != ShadowmapSize::None)
-        {
-            // uniform size
-            for (const SpotLight& light : m_spotLights)
+
+            featureProcessor->SetShadowsEnabled(light.m_handle, m_diskLightShadowEnabled);
+            if (m_diskLightShadowEnabled)
             {
-                if (light.m_handle.IsValid())
+                if (m_diskLightShadowmapSize != ShadowmapSize::None)
                 {
-                    featureProcessor->SetShadowmapSize(
+                    // Uniform size
+                    featureProcessor->SetShadowmapMaxResolution(
                         light.m_handle,
-                        m_spotLightShadowmapSize);
+                        m_diskLightShadowmapSize);
                 }
-            }
-        }
-        else
-        {
-            // random sizes
-            for (const SpotLight& light : m_spotLights)
-            {
-                if (light.m_handle.IsValid())
+                else
                 {
-                    featureProcessor->SetShadowmapSize(
+                    // Random sizes
+                    featureProcessor->SetShadowmapMaxResolution(
                         light.m_handle,
                         light.m_shadowmapSize);
                 }
@@ -671,18 +677,18 @@ namespace AtomSampleViewer
         }
     }
 
-    void ShadowedBistroExampleComponent::UpdateSpotLightPositions()
+    void ShadowedBistroExampleComponent::UpdateDiskLightPositions()
     {
-        for (int index = 0; index < m_spotLightCount; ++index)
+        for (int index = 0; index < m_diskLightCount; ++index)
         {
-            UpdateSpotLightPosition(index);
+            UpdateDiskLightPosition(index);
         }
     }
 
-    void ShadowedBistroExampleComponent::UpdateSpotLightPosition(int index)
+    void ShadowedBistroExampleComponent::UpdateDiskLightPosition(int index)
     {
         using namespace AZ;
-        Render::SpotLightFeatureProcessorInterface* const featureProcessor = m_spotLightFeatureProcessor;
+        Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
 
 
         if (!m_worldAabb.IsValid() || !m_worldAabb.IsFinite())
@@ -692,19 +698,19 @@ namespace AtomSampleViewer
         }
 
         const Vector3 basePosition(
-            m_spotLightsBasePosition[0],
-            m_spotLightsBasePosition[1],
-            m_spotLightsBasePosition[2]);
-        const Vector3 relativePosition = basePosition + m_spotLights[index].m_relativePosition * m_spotLightsPositionScatteringRatio;
+            m_diskLightsBasePosition[0],
+            m_diskLightsBasePosition[1],
+            m_diskLightsBasePosition[2]);
+        const Vector3 relativePosition = basePosition + m_diskLights[index].m_relativePosition * m_diskLightsPositionScatteringRatio;
         const Vector3 position = m_worldAabb.GetCenter() +
             m_worldAabb.GetExtents() * relativePosition;
         const auto transform =
             Transform::CreateTranslation(position) * Transform::CreateRotationX(-Constants::HalfPi);
         featureProcessor->SetPosition(
-            m_spotLights[index].m_handle,
+            m_diskLights[index].m_handle,
             position);
         featureProcessor->SetDirection(
-            m_spotLights[index].m_handle,
+            m_diskLights[index].m_handle,
             transform.GetBasis(1));
     }
 

+ 27 - 26
Gem/Code/Source/ShadowedBistroExampleComponent.h

@@ -15,7 +15,7 @@
 #include <CommonSampleComponentBase.h>
 #include <Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h>
 #include <Atom/Feature/CoreLights/ShadowConstants.h>
-#include <Atom/Feature/CoreLights/SpotLightFeatureProcessorInterface.h>
+#include <Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h>
 #include <AzCore/Component/TickBus.h>
 #include <AzCore/std/containers/vector.h>
 #include <AzCore/Math/Aabb.h>
@@ -44,13 +44,13 @@ namespace AtomSampleViewer
 
     private:
         using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle;
-        using SpotLightHandle = AZ::Render::SpotLightFeatureProcessorInterface::LightHandle;
+        using DiskLightHandle = AZ::Render::DiskLightFeatureProcessorInterface::LightHandle;
 
-        class SpotLight
+        class DiskLight
         {
         public:
-            SpotLight() = delete;
-            explicit SpotLight(
+            DiskLight() = delete;
+            explicit DiskLight(
                 const AZ::Color& color,
                 const AZ::Vector3& relativePosition,
                 AZ::Render::ShadowmapSize shadowmapSize)
@@ -58,16 +58,16 @@ namespace AtomSampleViewer
                 , m_relativePosition{ relativePosition }
                 , m_shadowmapSize{ shadowmapSize }
             {}
-            ~SpotLight() = default;
+            ~DiskLight() = default;
 
             const AZ::Color m_color;
             const AZ::Vector3 m_relativePosition;
             const AZ::Render::ShadowmapSize m_shadowmapSize;
-            SpotLightHandle m_handle;
+            DiskLightHandle m_handle;
         };
 
-        static constexpr int SpotLightCountMax = 50;
-        static constexpr int SpotLightCountDefault = 10;
+        static constexpr int DiskLightCountMax = 50;
+        static constexpr int DiskLightCountDefault = 10;
         static constexpr float CutoffIntensity = 0.1f;
 
         static const AZ::Color DirectionalLightColor;
@@ -82,25 +82,25 @@ namespace AtomSampleViewer
         void SetInitialCameraTransform();
 
         void SetupScene();
-        void BuildSpotLightParameters();
-        void UpdateSpotLightCount(uint16_t count);
+        void BuildDiskLightParameters();
+        void UpdateDiskLightCount(uint16_t count);
         const AZ::Color& GetRandomColor();
         AZ::Vector3 GetRandomPosition();
         AZ::Render::ShadowmapSize GetRandomShadowmapSize();
 
         void DrawSidebar();
-        void UpdateSpotLightShadowmapSize();
-        void UpdateSpotLightPositions();
-        void UpdateSpotLightPosition(int index);
+        void UpdateDiskLightShadowmapSize();
+        void UpdateDiskLightPositions();
+        void UpdateDiskLightPosition(int index);
         void SetupDebugFlags();
 
         float m_originalFarClipDistance = 0.f;
 
         // lights
         AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr;
-        AZ::Render::SpotLightFeatureProcessorInterface* m_spotLightFeatureProcessor = nullptr;
+        AZ::Render::DiskLightFeatureProcessorInterface* m_diskLightFeatureProcessor = nullptr;
         DirectionalLightHandle m_directionalLightHandle;
-        AZStd::vector<SpotLight> m_spotLights;
+        AZStd::vector<DiskLight> m_diskLights;
 
         // scene setup
         AZ::SimpleLcgRandom m_random;
@@ -119,10 +119,10 @@ namespace AtomSampleViewer
         float m_directionalLightPitch = -AZ::Constants::QuarterPi;
         float m_directionalLightYaw = 0.f;
         float m_directionalLightIntensity = 5.f;
-        float m_spotLightIntensity = 500.f;
-        int m_spotLightCount = 0;
-        float m_spotLightsBasePosition[3] = {0.f, 0.f, 0.f};
-        float m_spotLightsPositionScatteringRatio = 0.0f;
+        float m_diskLightIntensity = 500.f;
+        int m_diskLightCount = 0;
+        float m_diskLightsBasePosition[3] = {0.f, 0.f, 0.f};
+        float m_diskLightsPositionScatteringRatio = 0.0f;
         bool m_cameraTransformInitialized = false;
 
         // Shadowmap
@@ -134,20 +134,21 @@ namespace AtomSampleViewer
         int m_directionalLightShadowmapSizeIndex = 0;
         int m_cascadeCount = 0;
         float m_ratioLogarithmUniform = 0.f;
-        AZ::Render::ShadowmapSize m_spotLightShadowmapSize = AZ::Render::ShadowmapSize::None;
-        bool m_spotLightShadowEnabled = true;
+        AZ::Render::ShadowmapSize m_diskLightShadowmapSize = AZ::Render::ShadowmapSize::None;
+        bool m_diskLightShadowEnabled = true;
 
         // Edge-softening of directional light shadows
         static const AZ::Render::ShadowFilterMethod s_shadowFilterMethods[];
         static const char* s_shadowFilterMethodLabels[];
         int m_shadowFilterMethodIndexDirectional = 0; // filter method is None.
-        int m_shadowFilterMethodIndexSpot = 0; // filter method is None
+        int m_shadowFilterMethodIndexDisk = 0; // filter method is None
         float m_boundaryWidthDirectional = 0.03f; // 3cm
-        float m_boundaryWidthSpot = 0.25f; // 0.25 degrees
+        float m_boundaryWidthDisk = 0.25f; // 0.25 degrees
         int m_predictionSampleCountDirectional = 4;
-        int m_predictionSampleCountSpot = 4;
+        int m_predictionSampleCountDisk = 4;
         int m_filteringSampleCountDirectional = 16;
-        int m_filteringSampleCountSpot = 16;
+        AZ::Render::PcfMethod m_pcfMethodDirectional = AZ::Render::PcfMethod::BoundarySearch;
+        int m_filteringSampleCountDisk = 16;
 
         bool m_isCascadeCorrectionEnabled = false;
         bool m_isDebugColoringEnabled = false;

+ 0 - 1
Gem/Code/Source/StreamingImageExampleComponent.cpp

@@ -127,7 +127,6 @@ namespace AtomSampleViewer
         }
 
         m_loadImageStart = AZStd::GetTimeUTCMilliSecond();
-        AZ::u64 m_initialImageTime = 0;
 
         // Queue load all the textures under Textures\Streaming folder
         for (uint32_t index = 0; index < TestDDSCount; index++)

+ 0 - 2
Gem/Code/Source/TonemappingExampleComponent.cpp

@@ -65,8 +65,6 @@ namespace AtomSampleViewer
 
         m_dynamicDraw = RPI::DynamicDrawInterface::Get();
 
-        RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get();
-
         m_imguiSidebar.Activate();
 
         AZ::TickBus::Handler::BusConnect();

+ 2 - 0
Gem/Code/atomsampleviewergem_private_files.cmake

@@ -91,6 +91,8 @@ set(FILES
     Source/AuxGeomExampleComponent.h
     Source/AuxGeomSharedDrawFunctions.cpp
     Source/AuxGeomSharedDrawFunctions.h
+    Source/BakedShaderVariantExampleComponent.h
+    Source/BakedShaderVariantExampleComponent.cpp
     Source/BistroBenchmarkComponent.cpp
     Source/BistroBenchmarkComponent.h
     Source/BloomExampleComponent.cpp

+ 4 - 3
Materials/DynamicMaterialTest/EmissiveMaterial.azsl

@@ -55,14 +55,14 @@ struct VSOutput
 };
 
 #include <Atom/Features/PBR/LightingModel.azsli>
-
+#include <Atom/Features/Vertex/VertexHelper.azsli>
 option bool o_emissive_useTexture; 
 
 VSOutput MainVS(VSInput IN)
 {
     VSOutput OUT;
     float3 worldPosition = mul(ObjectSrg::GetWorldMatrix(), float4(IN.m_position, 1.0)).xyz;
-    PbrVsHelper(IN, OUT, worldPosition);
+    VertexHelper(IN, OUT, worldPosition);
     OUT.m_uv = IN.m_uv;
     return OUT;
 }
@@ -92,7 +92,8 @@ ForwardPassOutput MainPS(VSOutput IN)
         emissive *= TransformColor(sampledValue.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
     }
 
-    PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, 
+    PbrLightingOutput lightingOutput = PbrLighting(IN, 
+        baseColor, metallic, roughness, specularF0Factor, 
         normal, IN.m_tangent, IN.m_bitangent, anisotropy,
         emissive, occlusion, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque);
 

+ 1 - 1
Objects/Bistro/CHANGELOG.txt

@@ -1,4 +1,4 @@
-Amazon Lumberyard Bistro
+Amazon Open 3D Engine Bistro
 
 v1: Initial release
 

+ 3 - 3
Objects/Bistro/README.txt

@@ -1,4 +1,4 @@
-Amazon Lumberyard Bistro
+Amazon Open 3D Engine Bistro
 
 Vertex counts:
 - Interior: 814,435
@@ -24,8 +24,8 @@ Also included:
 How to cite use of this asset:
 
   @misc{ORCAAmazonBistro,
-   title = {Amazon Lumberyard Bistro, Open Research Content Archive (ORCA)},
-   author = {Amazon Lumberyard},
+   title = {Amazon Open 3D Engine Bistro, Open Research Content Archive (ORCA)},
+   author = {Amazon Open 3D Engine},
    year = {2017},
    month = {July},
    note = {\small \texttt{http://developer.nvidia.com/orca/amazon-lumberyard-bistro}},

+ 15 - 15
Passes/CheckerboardPipeline.pass

@@ -9,7 +9,7 @@
             "Slots": [
                 {
                     "Name": "SwapChainOutput",
-                    "SlotType": "Output",
+                    "SlotType": "InputOutput",
                     "ScopeAttachmentUsage": "RenderTarget"
                 }
             ],
@@ -50,12 +50,12 @@
                     ]
                 },
                 {
-                    "Name": "SpotLightShadowmapsPass",
-                    "TemplateName": "SpotLightShadowmapsTemplate",
+                    "Name": "ProjectedShadowmapsPass",
+                    "TemplateName": "ProjectedShadowmapsTemplate",
                     "PassData": {
                         "$type": "RasterPassData",
                         "DrawListTag": "shadow",
-                        "PipelineViewTag": "SpotLightView"
+                        "PipelineViewTag": "ProjectedShadowView"
                     },
                     "Connections": [
                         {
@@ -85,17 +85,17 @@
                     ]
                 },
                 {
-                    "Name": "EsmShadowmapsPassSpot",
+                    "Name": "EsmShadowmapsPassProjected",
                     "TemplateName": "EsmShadowmapsTemplate",
                     "PassData": {
                         "$type": "EsmShadowmapsPassData",
-                        "LightType": "spot"
+                        "LightType": "projected"
                     },
                     "Connections": [
                         {
                             "LocalSlot": "DepthShadowmaps",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         }
@@ -241,16 +241,16 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedShadowmap",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "ExponentialShadowmapSpot",
+                            "LocalSlot": "ExponentialShadowmapProjected",
                             "AttachmentRef": {
-                                "Pass": "EsmShadowmapsPassSpot",
+                                "Pass": "EsmShadowmapsPassProjected",
                                 "Attachment": "EsmShadowmaps"
                             }
                         },
@@ -602,16 +602,16 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedShadowmap",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "ExponentialShadowmapSpot",
+                            "LocalSlot": "ExponentialShadowmapProjected",
                             "AttachmentRef": {
-                                "Pass": "EsmShadowmapsPassSpot",
+                                "Pass": "EsmShadowmapsPassProjected",
                                 "Attachment": "EsmShadowmaps"
                             }
                         },

+ 10 - 10
Passes/ComplexPipeline.pass

@@ -49,12 +49,12 @@
                     ]
                 },
                 {
-                    "Name": "SpotLightShadowmapsPass",
-                    "TemplateName": "SpotLightShadowmapsTemplate",
+                    "Name": "ProjectedShadowmapsPass",
+                    "TemplateName": "ProjectedLightShadowmapsTemplate",
                     "PassData": {
                         "$type": "RasterPassData",
                         "DrawListTag": "shadow",
-                        "PipelineViewTag": "SpotLightView"
+                        "PipelineViewTag": "ProjectedShadowView"
                     },
                     "Connections": [
                         {
@@ -84,17 +84,17 @@
                     ]
                 },
                 {
-                    "Name": "EsmShadowmapsPassSpot",
+                    "Name": "EsmShadowmapsPassProjected",
                     "TemplateName": "EsmShadowmapsTemplate",
                     "PassData": {
                         "$type": "EsmShadowmapsPassData",
-                        "LightType": "spot"
+                        "LightType": "projected"
                     },
                     "Connections": [
                         {
                             "LocalSlot": "DepthShadowmaps",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         }
@@ -190,16 +190,16 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedLightShadowmap",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "ExponentialShadowmapSpot",
+                            "LocalSlot": "ExponentialShadowmapProjected",
                             "AttachmentRef": {
-                                "Pass": "EsmShadowmapsPassSpot",
+                                "Pass": "EsmShadowmapsPassProjected",
                                 "Attachment": "EsmShadowmaps"
                             }
                         },

+ 1 - 1
Passes/MSAA_2x_RPI_Pipeline.pass

@@ -10,7 +10,7 @@
             "Slots": [
                 {
                     "Name": "SwapChainOutput",
-                    "SlotType": "Output"
+                    "SlotType": "InputOutput"
                 }
             ],
             "PassRequests": [

+ 1 - 1
Passes/MSAA_4x_RPI_Pipeline.pass

@@ -10,7 +10,7 @@
             "Slots": [
                 {
                     "Name": "SwapChainOutput",
-                    "SlotType": "Output"
+                    "SlotType": "InputOutput"
                 }
             ],
             "PassRequests": [

+ 1 - 1
Passes/MSAA_8x_RPI_Pipeline.pass

@@ -10,7 +10,7 @@
             "Slots": [
                 {
                     "Name": "SwapChainOutput",
-                    "SlotType": "Output"
+                    "SlotType": "InputOutput"
                 }
             ],
             "PassRequests": [

+ 4 - 4
Passes/MSAA_RPI_Pipeline_Core.pass

@@ -13,7 +13,7 @@
                 },
                 {
                     "Name": "SwapChainOutput",
-                    "SlotType": "Output"
+                    "SlotType": "InputOutput"
                 }
             ],
             "PassRequests": [
@@ -71,12 +71,12 @@
                     ]
                 },
                 {
-                    "Name": "SpotLightShadowmapsPass",
-                    "TemplateName": "SpotLightShadowmapsTemplate",
+                    "Name": "ProjectedShadowmapsPass",
+                    "TemplateName": "ProjectedShadowmapsTemplate",
                     "PassData": {
                         "$type": "RasterPassData",
                         "DrawListTag": "shadow",
-                        "PipelineViewTag": "SpotLightView"
+                        "PipelineViewTag": "ProjectedShadowView"
                     }
                 },
                 {

+ 8 - 8
Passes/MainPipeline.pass

@@ -155,17 +155,17 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedShadowmap",
                             "AttachmentRef": {
                                 "Pass": "ShadowPass",
-                                "Attachment": "SpotLightShadowmap"
+                                "Attachment": "ProjectedShadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightESM",
+                            "LocalSlot": "ProjectedESM",
                             "AttachmentRef": {
                                 "Pass": "ShadowPass",
-                                "Attachment": "SpotLightESM"
+                                "Attachment": "ProjectedESM"
                             }
                         },
                         {
@@ -224,17 +224,17 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedShadowmap",
                             "AttachmentRef": {
                                 "Pass": "ShadowPass",
-                                "Attachment": "SpotLightShadowmap"
+                                "Attachment": "ProjectedShadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightESM",
+                            "LocalSlot": "ProjectedESM",
                             "AttachmentRef": {
                                 "Pass": "ShadowPass",
-                                "Attachment": "SpotLightESM"
+                                "Attachment": "ProjectedESM"
                             }
                         },
                         {

+ 14 - 14
Passes/MainPipeline_Mobile.pass

@@ -50,12 +50,12 @@
                     ]
                 },
                 {
-                    "Name": "SpotLightShadowmapsPass",
-                    "TemplateName": "SpotLightShadowmapsTemplate",
+                    "Name": "ProjectedShadowmapsPass",
+                    "TemplateName": "ProjectedShadowmapsTemplate",
                     "PassData": {
                         "$type": "RasterPassData",
                         "DrawListTag": "shadow",
-                        "PipelineViewTag": "SpotLightView"
+                        "PipelineViewTag": "ProjectedShadowView"
                     },
                     "Connections": [
                         {
@@ -85,17 +85,17 @@
                     ]
                 },
                 {
-                    "Name": "EsmShadowmapsPassSpot",
+                    "Name": "EsmShadowmapsPassProjected",
                     "TemplateName": "EsmShadowmapsTemplate",
                     "PassData": {
                         "$type": "EsmShadowmapsPassData",
-                        "LightType": "spot"
+                        "LightType": "projected"
                     },
                     "Connections": [
                         {
                             "LocalSlot": "DepthShadowmaps",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         }
@@ -191,16 +191,16 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedShadowmap",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "ExponentialShadowmapSpot",
+                            "LocalSlot": "ExponentialShadowmapProjected",
                             "AttachmentRef": {
-                                "Pass": "EsmShadowmapsPassSpot",
+                                "Pass": "EsmShadowmapsPassProjected",
                                 "Attachment": "EsmShadowmaps"
                             }
                         },
@@ -546,16 +546,16 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedShadowmap",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "ExponentialShadowmapSpot",
+                            "LocalSlot": "ExponentialShadowmapProjected",
                             "AttachmentRef": {
-                                "Pass": "EsmShadowmapsPassSpot",
+                                "Pass": "EsmShadowmapsPassProjected",
                                 "Attachment": "EsmShadowmaps"
                             }
                         },

+ 4 - 4
Passes/No_MSAA_RPI_Pipeline.pass

@@ -9,7 +9,7 @@
             "Slots": [
                 {
                     "Name": "SwapChainOutput",
-                    "SlotType": "Output"
+                    "SlotType": "InputOutput"
                 }
             ],
             "PassRequests": [
@@ -102,12 +102,12 @@
                     ]
                 },
                 {
-                    "Name": "SpotLightShadowmapsPass",
-                    "TemplateName": "SpotLightShadowmapsTemplate",
+                    "Name": "ProjectedShadowmapsPass",
+                    "TemplateName": "ProjectedShadowmapsTemplate",
                     "PassData": {
                         "$type": "RasterPassData",
                         "DrawListTag": "shadow",
-                        "PipelineViewTag": "SpotLightView"
+                        "PipelineViewTag": "ProjectedShadowView"
                     },
                     "Connections": [
                         {

+ 2 - 2
Passes/PassTemplates.azasset

@@ -293,8 +293,8 @@
                 "Path": "Passes/LightCullingRemap.pass"
             },
             {
-                "Name": "SpotLightShadowmapsTemplate",
-                "Path": "Passes/SpotLightShadowmaps.pass"
+                "Name": "ProjectedShadowmapsTemplate",
+                "Path": "Passes/ProjectedShadowmaps.pass"
             },
             {
                 "Name": "EnvironmentCubeMapPipeline",

+ 10 - 10
Passes/SsaoPipeline.pass

@@ -54,12 +54,12 @@
                     ]
                 },
                 {
-                    "Name": "SpotLightShadowmapsPass",
-                    "TemplateName": "SpotLightShadowmapsTemplate",
+                    "Name": "ProjectedShadowmapsPass",
+                    "TemplateName": "ProjectedShadowmapsTemplate",
                     "PassData": {
                         "$type": "RasterPassData",
                         "DrawListTag": "shadow",
-                        "PipelineViewTag": "SpotLightView"
+                        "PipelineViewTag": "ProjectedShadowView"
                     },
                     "Connections": [
                         {
@@ -89,17 +89,17 @@
                     ]
                 },
                 {
-                    "Name": "EsmShadowmapsPassSpot",
+                    "Name": "EsmShadowmapsPassProjected",
                     "TemplateName": "EsmShadowmapsTemplate",
                     "PassData": {
                         "$type": "EsmShadowmapsPassData",
-                        "LightType": "spot"
+                        "LightType": "projected"
                     },
                     "Connections": [
                         {
                             "LocalSlot": "DepthShadowmaps",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         }
@@ -230,16 +230,16 @@
                             }
                         },
                         {
-                            "LocalSlot": "SpotLightShadowmap",
+                            "LocalSlot": "ProjectedShadowmap",
                             "AttachmentRef": {
-                                "Pass": "SpotLightShadowmapsPass",
+                                "Pass": "ProjectedShadowmapsPass",
                                 "Attachment": "Shadowmap"
                             }
                         },
                         {
-                            "LocalSlot": "ExponentialShadowmapSpot",
+                            "LocalSlot": "ExponentialShadowmapProjected",
                             "AttachmentRef": {
-                                "Pass": "EsmShadowmapsPassSpot",
+                                "Pass": "EsmShadowmapsPassProjected",
                                 "Attachment": "EsmShadowmaps"
                             }
                         },

+ 0 - 10
Scripts/AreaLightTest.bv.lua

@@ -27,15 +27,6 @@ function SetupDiskLights()
     SetImguiValue('AreaLightSample/Emit Both Directions', false)
 end
 
-function SetupDiskLightsDoubleSided()
-    SetImguiValue('AreaLightSample/LightType/Disk', true)
-    SetImguiValue('AreaLightSample/Position Offset', Vector3(0.0, -0.5, -1.25))
-    SetImguiValue('AreaLightSample/Radius', 0.75)
-    SetImguiValue('AreaLightSample/X rotation', -1.45)
-    SetImguiValue('AreaLightSample/Y rotation', -0.5)
-    SetImguiValue('AreaLightSample/Emit Both Directions', true)
-end
-
 function SetupCapsuleLights()
     SetImguiValue('AreaLightSample/LightType/Capsule', true)
     SetImguiValue('AreaLightSample/Position Offset', Vector3(0.0, 0.0, 0.0))
@@ -139,7 +130,6 @@ lightSetups =
 {
     point = SetupPointLights,
     disk = SetupDiskLights,
-    disk_double_sided = SetupDiskLightsDoubleSided,
     capsule = SetupCapsuleLights,
     quad = SetupQuadLights,
     quad_double_sided = SetupQuadLightsDoubleSided,

+ 0 - 3
Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_metal.ppm

@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e98dc8763abe88b813d01de5d6c9004e82c40526a149c9b63fd84c9f28df35c0
-size 1920016

+ 0 - 3
Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_rough_metal.ppm

@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:20447abab4e19cb2bbb42b87d10870bc5fd303f1f6dcad422ba5b1e030e1a3eb
-size 1920016

+ 0 - 3
Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_rough_nonmetal.ppm

@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e619203ae401b87654a20ef2699fc2a048ed4b377c286dfd5a600532e1ab606f
-size 1920016

+ 1 - 1
Scripts/ExpectedScreenshots/CullingAndLod/screenshot_1.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:869c2ff7bd66ed93d0561a7b901f936c8b38c77f7b064d90020d71d3b9e02e0e
+oid sha256:8ea3411921b0a10fa812a152382709995bd5ae4265f899f4c90a8bc10444ac76
 size 750015

+ 1 - 1
Scripts/ExpectedScreenshots/LightCulling/screenshot_capsulelights.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:03f768e3f5e03b1faa333cf463960d5cbbc66ca89302593b66e7d99fd22f0318
+oid sha256:e5eefe346d6e04846923e983fec6fd812ed68f4bbe5d84dae900ab60617ae6e9
 size 4320016

+ 1 - 1
Scripts/ExpectedScreenshots/LightCulling/screenshot_decals.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8188131d5cb77040bdf3f1ec9b1b70d4e2bff0d4d58c3dd138ef1690e7194459
+oid sha256:0a98fae2e19ac0fa161d1e93ff69beed58f013dff0023da056d28af045c5621f
 size 4320016

+ 1 - 1
Scripts/ExpectedScreenshots/LightCulling/screenshot_disklights.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0ac5b1b223677517baac2c3e6796acdbd1ba6f58050fd6095fb81d88768654e5
+oid sha256:a4ee644113c4900187d3808fc8c5723b4b58946356921ae6cf3f7f5a625f6cfb
 size 4320016

+ 1 - 1
Scripts/ExpectedScreenshots/LightCulling/screenshot_quadlights.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:28d24236f116e18b3070f7705e1e4836376a6ca948dc837ab67df4e895141fdc
+oid sha256:b7cca1b103c6039dbd70a84847a1358f89d82d874fdb1683064b0035131c125c
 size 4320016

+ 0 - 3
Scripts/ExpectedScreenshots/LightCulling/screenshot_spotlights.ppm

@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5f882f45a7f6c15370b9a5b9239047e824e3039b3c1afaa06efe178d3420c13d
-size 4320016

+ 1 - 1
Scripts/ExpectedScreenshots/MultiScene/Start_MultiScene1.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:df97cd869806868e380f68716f77037bbef46b687ef1680b2f3d6aca68a3d904
+oid sha256:7fd5fb514c95bf9be7632ac5b1f2a306326ef0cbe351c06a27ae3ea411296137
 size 1440015

+ 1 - 1
Scripts/ExpectedScreenshots/MultiScene/Start_MultiScene2.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8eeb50968a988a6bbde17eac2ad017c7945429c97051d8fec1c018853d3ac63f
+oid sha256:f60b43675fe75c897c58aacf766e56a6bc9a70947bba23eca9a6f2b94dc154af
 size 2764816

+ 1 - 1
Scripts/ExpectedScreenshots/ShadowedBistro/initial.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:087cfb5dd627b1525834827a2d5d5a47effedcb467c277ab0061da8e72660ecb
+oid sha256:472c22b404c140e0d4a4dd68ec31f809cd7beba6d8e9fcc1141e8e1a40b4b67c
 size 1440015

+ 1 - 1
Scripts/ExpectedScreenshots/ShadowedBistro/spot_nofilter_table.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:89b1d114b29fdf51eeb131103abf7064bb364f81d2ccbe17a446d5ece72187d2
+oid sha256:d95cea86930a4e7b35c129d07f192dba3b261fed19b0a6195ad3186611505bf7
 size 1440015

+ 0 - 14
Scripts/LightCulling.bv.lua

@@ -14,7 +14,6 @@
 
 function ResetEntityCounts()
     SetImguiValue('Point Lights/Point light count', 0)
-    SetImguiValue('Spot Lights/Spot light count', 0)
     SetImguiValue('Decals/Decal count', 0)
     SetImguiValue('Disk Lights/Disk light count', 0)
     SetImguiValue('Capsule Lights/Capsule light count', 0)
@@ -38,18 +37,6 @@ function TakeScreenshotPointLights()
     CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_pointlights.ppm')
 end
 
-function TakeScreenshotSpotLights()
-
-    ResetEntityCounts()
-
-    NoClipCameraController_SetFov(DegToRad(90))
-    SetImguiValue('Spot Lights/Spot light count', 150)
-    SetImguiValue('Spot Lights/Spot Intensity', 70)
-    
-    IdleFrames(1) 
-    CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_spotlights.ppm')
-end
-
 function TakeScreenshotDiskLights()
 
     ResetEntityCounts()
@@ -129,7 +116,6 @@ ResizeViewport(1600, 900)
 EnableOnlyTestHeatmap()
 
 TakeScreenshotPointLights()
-TakeScreenshotSpotLights()
 TakeScreenshotDiskLights()
 TakeScreenshotCapsuleLights()
 TakeScreenshotQuadLights()

+ 2 - 1
Scripts/MaterialHotReloadTest.bv.lua

@@ -112,7 +112,8 @@ AssetTracking_ExpectAsset(g_assetFolder .. "HotReloadTest.materialtype")
 AssetTracking_ExpectAsset(g_assetFolder .. "HotReloadTest.shader")
 AssetTracking_IdleUntilExpectedAssetsFinish(60)
 IdleSeconds(1) -- Idle for a bit to give time for the assets to reload
-CaptureScreenshot(g_screenshotOutputFolder .. '/12_Variants_None_AfterUpdatingShader.ppm')
+--[GFX TODO][ATOM-15079] This test is consistently failing due to an Asset Processor bug. Re-enable this test once SPEC-5888 is fixed.
+--CaptureScreenshot(g_screenshotOutputFolder .. '/12_Variants_None_AfterUpdatingShader.ppm')
 
 -- Here we prepare to test a specific edge case. First, the material should be using a full baked shader variant, so we set up that precondition and verify with a screenshot.
 AssetTracking_Start()

+ 27 - 27
Scripts/ShadowTest.bv.lua

@@ -19,24 +19,24 @@ OpenSample('Features/Shadow')
 ResizeViewport(800, 600)
 SelectImageComparisonToleranceLevel("Level H")
 SetImguiValue('Auto Rotation##Directional', false)
-SetImguiValue('Auto Rotation##Spot', false)
+SetImguiValue('Auto Rotation##Disk', false)
 
 -- Initial
 SetImguiValue('Direction##Directional', 0.0)
-SetImguiValue('Base Direction##Spot', 0.0)
+SetImguiValue('Base Direction##Disk', 0.0)
 IdleFrames(1)
 CaptureScreenshot(g_screenshotOutputFolder .. '/initial.ppm')
 
 -- Directional Light Initial
--- Diabling spot lights
+-- Diabling Disk lights
 SetImguiValue('Red', true)
-SetImguiValue('Intensity##Spot', 0.0)
+SetImguiValue('Intensity##Disk', 0.0)
 IdleFrames(1)
 SetImguiValue('Green', true)
-SetImguiValue('Intensity##Spot', 0.0)
+SetImguiValue('Intensity##Disk', 0.0)
 IdleFrames(1)
 SetImguiValue('Blue', true)
-SetImguiValue('Intensity##Spot', 0.0)
+SetImguiValue('Intensity##Disk', 0.0)
 -- Set Camera
 ArcBallCameraController_SetHeading(DegToRad(90.0))
 ArcBallCameraController_SetPitch(DegToRad(-45.0))
@@ -98,60 +98,60 @@ SetImguiValue('Filter Method##Directional', 'ESM+PCF')
 IdleFrames(1)
 CaptureScreenshot(g_screenshotOutputFolder .. '/directional_esm_pcf.ppm')
 
--- Spot Light Initial
+-- Disk Light Initial
 -- Disabling directional light
 SetImguiValue('Intensity##Directional', 0.0)
 SetImguiValue('Red', true)
-SetImguiValue('Intensity##Spot', 500.0)
+SetImguiValue('Intensity##Disk', 500.0)
 IdleFrames(1)
 SetImguiValue('Green', true)
-SetImguiValue('Height##Spot', 4.0)
-SetImguiValue('Intensity##Spot', 400.0)
+SetImguiValue('Height##Disk', 4.0)
+SetImguiValue('Intensity##Disk', 400.0)
 IdleFrames(1)
 SetImguiValue('Blue', true)
-SetImguiValue('Intensity##Spot', 500.0)
+SetImguiValue('Intensity##Disk', 500.0)
 IdleFrames(1)
 CaptureScreenshot(g_screenshotOutputFolder .. '/spot_initial.ppm')
 
--- Spot Light Disabling Shadow for Red
+-- Disk Light Disabling Shadow for Red
 SetImguiValue('Red', true)
 SetImguiValue('Enable Shadow', false)
 IdleFrames(1)
 CaptureScreenshot(g_screenshotOutputFolder .. '/spot_no_red_shadow.ppm')
 
--- Spot Light Various Shadowmap Sizes
+-- Disk Light Various Shadowmap Sizes
 SetImguiValue('Red', true)
 SetImguiValue('Enable Shadow', true)
 IdleFrames(1)
-SetImguiValue('Size##Spot', '2048')
+SetImguiValue('Size##Disk', '2048')
 IdleFrames(1)
 SetImguiValue('Green', true)
-SetImguiValue('Size##Spot', '1024')
+SetImguiValue('Size##Disk', '1024')
 IdleFrames(1)
 SetImguiValue('Blue', true)
-SetImguiValue('Size##Spot', '512')
+SetImguiValue('Size##Disk', '512')
 IdleFrames(1)
 CaptureScreenshot(g_screenshotOutputFolder .. '/spot_shadowmap_size.ppm')
 
--- Spot Light Various Filter Method
+-- Disk Light Various Filter Method
 SetImguiValue('Red', true)
-SetImguiValue('Filter Method##Spot', 'PCF')
+SetImguiValue('Filter Method##Disk', 'PCF')
 IdleFrames(1)
-SetImguiValue('Width##Spot', 0.5)
-SetImguiValue('Prediction # ##Spot', 16)
-SetImguiValue('Filtering # ##Spot', 64)
+SetImguiValue('Width##Disk', 0.5)
+SetImguiValue('Prediction # ##Disk', 16)
+SetImguiValue('Filtering # ##Disk', 64)
 IdleFrames(1)
 SetImguiValue('Green', true)
-SetImguiValue('Filter Method##Spot', 'ESM')
+SetImguiValue('Filter Method##Disk', 'ESM')
 IdleFrames(1)
-SetImguiValue('Width##Spot', 0.5)
+SetImguiValue('Width##Disk', 0.5)
 IdleFrames(1)
 SetImguiValue('Blue', true)
-SetImguiValue('Filter Method##Spot', 'ESM+PCF')
+SetImguiValue('Filter Method##Disk', 'ESM+PCF')
 IdleFrames(1)
-SetImguiValue('Width##Spot', 0.5)
-SetImguiValue('Prediction # ##Spot', 16)
-SetImguiValue('Filtering # ##Spot', 64)
+SetImguiValue('Width##Disk', 0.5)
+SetImguiValue('Prediction # ##Disk', 16)
+SetImguiValue('Filtering # ##Disk', 64)
 IdleFrames(1)
 CaptureScreenshot(g_screenshotOutputFolder .. '/spot_filter_method.ppm')
 

+ 20 - 0
Scripts/_AutomatedPeriodicTestSuite_.bv.lua

@@ -0,0 +1,20 @@
+----------------------------------------------------------------------------------------------------
+--
+-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+-- its licensors.
+--
+-- For complete copyright and license terms please see the LICENSE at the root of this
+-- distribution (the "License"). All use of this software is governed by the License,
+-- or, if provided, by the license below or the license accompanying this file. Do not
+-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+--
+--
+----------------------------------------------------------------------------------------------------
+
+-- "Periodic" suite tests for the automated review process.
+-- These tests run as part of the periodic suite of tests and do not block any code submissions.
+-- The purpose of this periodic test is to ensure the "_FullTestSuite_.bv.lua" script continues to function.
+-- This is because if no developer ran the "_FullTestSuite_.bv.lua" script locally we would not know of any failures, so this script ensures we catch them.
+
+RunScript('scripts/_FullTestSuite_.bv.lua')

+ 39 - 0
Scripts/_AutomatedReviewTestSuite_.bv.lua

@@ -0,0 +1,39 @@
+----------------------------------------------------------------------------------------------------
+--
+-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+-- its licensors.
+--
+-- For complete copyright and license terms please see the LICENSE at the root of this
+-- distribution (the "License"). All use of this software is governed by the License,
+-- or, if provided, by the license below or the license accompanying this file. Do not
+-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+--
+--
+----------------------------------------------------------------------------------------------------
+
+-- "Main" suite tests for the automated review process.
+-- These tests run on the nightly builds currently due to insufficient GPU node count (see SPEC-6031).
+-- In the future when we have more GPU nodes, these tests will run as part of the gating process for automated review.
+-- Failures in that gating process will block submission of your code in the automated review process and require a bug to be filed.
+
+RunScript('scripts/decals.bv.luac')
+RunScript('scripts/dynamicdraw.bv.luac')
+RunScript('scripts/dynamicmaterialtest.bv.luac')
+RunScript('scripts/materialscreenshottests.bv.luac')
+RunScript('scripts/materialhotreloadtest.bv.luac')
+RunScript('scripts/msaa_rpi_test.bv.luac')
+RunScript('scripts/cullingandlod.bv.luac')
+RunScript('scripts/multirenderpipeline.bv.luac')
+RunScript('scripts/lightculling.bv.luac')
+RunScript('scripts/transparenttest.bv.luac')
+RunScript('scripts/streamingimagetest.bv.luac')
+RunScript('scripts/parallaxtest.bv.luac')
+RunScript('scripts/checkerboardtest.bv.luac')
+RunScript('scripts/scenereloadsoaktest.bv.luac')
+RunScript('scripts/diffusegitest.bv.luac')
+RunScript('scripts/arealighttest.bv.luac')
+RunScript('scripts/multiscene.bv.luac')
+RunScript('scripts/shadowtest.bv.luac')
+RunScript('scripts/shadowedbistrotest.bv.luac')
+RunScript('scripts/PassTree.bv.luac')

+ 104 - 63
Scripts/_FullTestSuite_.bv.lua

@@ -12,78 +12,119 @@
 --
 ----------------------------------------------------------------------------------------------------
 
+-- "Full" suite of tests that need to be run locally by developers before opening a pull request.
+-- This suite of tests is NOT part of the automated review process.
+
+-- This test suite is capable of randomly shuffling the order of the tests below if a random seed is provided that is not ZERO.
+-- NOTE: If the random seed is zero, then the order is not shuffled at all.
+-- The seed can be provided either in imGui or via commandline switch --randomtestseed
+
+
 -- Fast check for a sample which doesn't have a dedicated test script
 function FastCheckSample(sampleName)
-    Print("========= Begin Fast-check " .. sampleName .. " =========")
-    OpenSample(sampleName)
-    IdleSeconds(2) 
-    OpenSample(nil)
-    Print("========= End Fast-check " .. sampleName .. " =========")
+    return function()
+        Print("========= Begin Fast-check " .. sampleName .. " =========")
+        OpenSample(sampleName)
+        IdleSeconds(2) 
+        OpenSample(nil)
+        Print("========= End Fast-check " .. sampleName .. " =========")
+    end
+end
+
+-- Test helper functions
+function random_shuffle(list)
+    for i = #list, 2, -1 do
+        local j = math.random(i)
+        list[i], list[j] = list[j], list[i]
+    end
+end
+
+-- A helper wrapper to create a lambda-like behavior in Lua, this allows us to create a table of functions that call various tests
+function RunScriptWrapper(name)
+    return function() RunScript(name) end
 end
 
-RunScript('scripts/decals.bv.luac')
-RunScript('scripts/dynamicdraw.bv.luac')
-RunScript('scripts/dynamicmaterialtest.bv.luac')
-RunScript('scripts/materialscreenshottests.bv.luac')
-RunScript('scripts/materialhotreloadtest.bv.luac')
-RunScript('scripts/msaa_rpi_test.bv.luac')
-RunScript('scripts/cullingandlod.bv.luac')
-RunScript('scripts/multirenderpipeline.bv.luac')
-RunScript('scripts/lightculling.bv.luac')
-RunScript('scripts/transparenttest.bv.luac')
-RunScript('scripts/streamingimagetest.bv.luac')
-RunScript('scripts/parallaxtest.bv.luac')
-RunScript('scripts/checkerboardtest.bv.luac')
-RunScript('scripts/scenereloadsoaktest.bv.luac')
-RunScript('scripts/diffusegitest.bv.luac')
-RunScript('scripts/arealighttest.bv.luac')
-RunScript('scripts/multiscene.bv.luac')
-RunScript('scripts/shadowtest.bv.luac')
-RunScript('scripts/shadowedbistrotest.bv.luac')
-RunScript('scripts/PassTree.bv.luac')
+-- A table of lambda-like functions that invoke various tests. This table is shuffled if a random seed is provided below.
+tests= {
+    RunScriptWrapper('scripts/decals.bv.luac'),
+    RunScriptWrapper('scripts/dynamicdraw.bv.luac'),
+    RunScriptWrapper('scripts/dynamicmaterialtest.bv.luac'),
+    RunScriptWrapper('scripts/materialscreenshottests.bv.luac'),
+    RunScriptWrapper('scripts/materialhotreloadtest.bv.luac'),
+    RunScriptWrapper('scripts/msaa_rpi_test.bv.luac'),
+    RunScriptWrapper('scripts/cullingandlod.bv.luac'),
+    RunScriptWrapper('scripts/multirenderpipeline.bv.luac'),
+    RunScriptWrapper('scripts/lightculling.bv.luac'),
+    RunScriptWrapper('scripts/transparenttest.bv.luac'),
+    RunScriptWrapper('scripts/streamingimagetest.bv.luac'),
+    RunScriptWrapper('scripts/parallaxtest.bv.luac'),
+    RunScriptWrapper('scripts/checkerboardtest.bv.luac'),
+    RunScriptWrapper('scripts/scenereloadsoaktest.bv.luac'),
+    RunScriptWrapper('scripts/diffusegitest.bv.luac'),
+    RunScriptWrapper('scripts/arealighttest.bv.luac'),
+    RunScriptWrapper('scripts/multiscene.bv.luac'),
+    RunScriptWrapper('scripts/shadowtest.bv.luac'),
+    RunScriptWrapper('scripts/shadowedbistrotest.bv.luac'),
+    RunScriptWrapper('scripts/PassTree.bv.luac'),
 
---Fast checking for the samples which don't have a test. Samples should be removed from this list once they have their own tests
+    --Fast checking for the samples which don't have a test. Samples should be removed from this list once they have their own tests
+
+    FastCheckSample('RHI/AlphaToCoverage'),
+    FastCheckSample('RHI/AsyncCompute'),
+    FastCheckSample('RHI/BindlessPrototype'),
+    FastCheckSample('RHI/Compute'),
+    FastCheckSample('RHI/CopyQueue'),
+    FastCheckSample('RHI/DualSourceBlending'),
+    FastCheckSample('RHI/IndirectRendering'),
+    FastCheckSample('RHI/InputAssembly'),
+    FastCheckSample('RHI/MSAA'),
+    FastCheckSample('RHI/MultipleViews'),
+    FastCheckSample('RHI/MultiRenderTarget'),
+    FastCheckSample('RHI/MultiThread'),
+    FastCheckSample('RHI/Queries'),
+    FastCheckSample('RHI/SphericalHarmonics'),
+    FastCheckSample('RHI/Stencil'),
+    FastCheckSample('RHI/Swapchain'),
+    FastCheckSample('RHI/Texture'),
+    FastCheckSample('RHI/Texture3d'),
+    FastCheckSample('RHI/TextureArray'),
+    FastCheckSample('RHI/TextureMap'),
+    FastCheckSample('RHI/Triangle'),
+    FastCheckSample('RHI/TrianglesConstantBuffer'),
+
+    FastCheckSample('RPI/AssetLoadTest'),
+    FastCheckSample('RPI/AuxGeom'),
+    FastCheckSample('RPI/BistroBenchmark'),
+    FastCheckSample('RPI/MultiViewSingleSceneAuxGeom'),
+    FastCheckSample('RPI/RootConstants'),
+    FastCheckSample('RPI/Shading'),
+
+    FastCheckSample('Features/Bloom'),
+    FastCheckSample('Features/DepthOfField'),
+    FastCheckSample('Features/Exposure'),
+    FastCheckSample('Features/SkinnedMesh'),
+    FastCheckSample('Features/SSAO'),
+    FastCheckSample('Features/SSR'),
+    FastCheckSample('Features/Tonemapping'),
+}
 
-FastCheckSample('RHI/AlphaToCoverage')
-FastCheckSample('RHI/AsyncCompute')
-FastCheckSample('RHI/BindlessPrototype')
-FastCheckSample('RHI/Compute')
-FastCheckSample('RHI/CopyQueue')
-FastCheckSample('RHI/DualSourceBlending')
-FastCheckSample('RHI/IndirectRendering')
-FastCheckSample('RHI/InputAssembly')
-FastCheckSample('RHI/MSAA')
-FastCheckSample('RHI/MultipleViews')
-FastCheckSample('RHI/MultiRenderTarget')
-FastCheckSample('RHI/MultiThread')
-FastCheckSample('RHI/Queries')
 if (GetRenderApiName() == "dx12") then 
-    FastCheckSample('RHI/RayTracing')
+    table.insert(tests, FastCheckSample('RHI/RayTracing'))
 end
-FastCheckSample('RHI/SphericalHarmonics')
-FastCheckSample('RHI/Stencil')
+
 if (GetRenderApiName() ~= "dx12") then 
-    FastCheckSample('RHI/Subpass') 
+    table.insert(tests, FastCheckSample('RHI/Subpass'))
 end
-FastCheckSample('RHI/Swapchain')
-FastCheckSample('RHI/Texture')
-FastCheckSample('RHI/Texture3d')
-FastCheckSample('RHI/TextureArray')
-FastCheckSample('RHI/TextureMap')
-FastCheckSample('RHI/Triangle')
-FastCheckSample('RHI/TrianglesConstantBuffer')
 
-FastCheckSample('RPI/AssetLoadTest')
-FastCheckSample('RPI/AuxGeom')
-FastCheckSample('RPI/BistroBenchmark')
-FastCheckSample('RPI/MultiViewSingleSceneAuxGeom')
-FastCheckSample('RPI/RootConstants')
-FastCheckSample('RPI/Shading')
+seed = GetRandomTestSeed()
+if (seed == 0) then
+    Print("========= A random seed was not provided, running the tests in the original order =========")
+else
+    Print("========= Using " .. seed .. " as a random seed to sort the tests =========")
+    math.randomseed(seed)
+    random_shuffle(tests)
+end
 
-FastCheckSample('Features/Bloom')
-FastCheckSample('Features/DepthOfField')
-FastCheckSample('Features/Exposure')
-FastCheckSample('Features/SkinnedMesh')
-FastCheckSample('Features/SSAO')
-FastCheckSample('Features/SSR')
-FastCheckSample('Features/Tonemapping')
+for k,test in pairs(tests) do
+    test()
+end

+ 24 - 0
ShaderLib/raytracingscenesrg.srgi

@@ -0,0 +1,24 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+
+#pragma once
+
+#include <Atom/Features/SrgSemantics.azsli>
+
+partial ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
+{
+/* Intentionally Empty. Helps define the SrgSemantic for RayTracingSceneSrg once.*/
+};
+
+#define AZ_COLLECTING_PARTIAL_SRGS
+#include <Atom/Feature/Common/Assets/ShaderResourceGroups/RayTracingSceneSrgAll.azsli>
+#undef AZ_COLLECTING_PARTIAL_SRGS

+ 245 - 0
ShaderVariants/Materials/Types/EnhancedPBR_ForwardPass.shadervariantlist

@@ -0,0 +1,245 @@
+{
+    "Shader": "Materials/Types/EnhancedPBR_ForwardPass.shader",
+    "Variants": [
+        {
+            "StableId": 1,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "true",
+                "o_detail_blendMask_useTexture": "true",
+                "o_detail_normal_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 2,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "false",
+                "o_detail_blendMask_useTexture": "false",
+                "o_detail_normal_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 3,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "false",
+                "o_detail_blendMask_useTexture": "false",
+                "o_detail_normal_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 4,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "true",
+                "o_detail_blendMask_useTexture": "false",
+                "o_detail_normal_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 5,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "false",
+                "o_detail_blendMask_useTexture": "true",
+                "o_detail_normal_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 6,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "true",
+                "o_detail_blendMask_useTexture": "true",
+                "o_detail_normal_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        }
+    ]
+}

+ 245 - 0
ShaderVariants/Materials/Types/EnhancedPBR_ForwardPass_EDS.shadervariantlist

@@ -0,0 +1,245 @@
+{
+    "Shader": "Materials/Types/EnhancedPBR_ForwardPass_EDS.shader",
+    "Variants": [
+        {
+            "StableId": 1,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "true",
+                "o_detail_blendMask_useTexture": "true",
+                "o_detail_normal_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 2,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "false",
+                "o_detail_blendMask_useTexture": "false",
+                "o_detail_normal_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 3,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "false",
+                "o_detail_blendMask_useTexture": "false",
+                "o_detail_normal_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 4,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "true",
+                "o_detail_blendMask_useTexture": "false",
+                "o_detail_normal_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 5,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "false",
+                "o_detail_blendMask_useTexture": "true",
+                "o_detail_normal_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        },
+        {
+            "StableId": 6,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_detail_baseColor_useTexture": "true",
+                "o_detail_blendMask_useTexture": "true",
+                "o_detail_normal_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAnisotropy": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false"
+            }
+        }
+    ]
+}

+ 1428 - 0
ShaderVariants/Materials/Types/StandardPBR_ForwardPass.shadervariantlist

@@ -0,0 +1,1428 @@
+{
+    "Shader": "Materials/Types/StandardPBR_ForwardPass.shader",
+    "Variants": [
+        {
+            "StableId": 1,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 2,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 3,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "true",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 4,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "true",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 5,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 6,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "true",
+                "o_clearCoat_factor_useTexture": "true",
+                "o_clearCoat_feature_enabled": "true",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 7,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Cutout",
+                "o_opacity_source": "OpacitySource::Split",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 8,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 9,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "true",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 10,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Cutout",
+                "o_opacity_source": "OpacitySource::Split",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 11,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 12,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "true",
+                "o_clearCoat_normal_useTexture": "true",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 13,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 14,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "true",
+                "o_emissive_useTexture": "true",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 15,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "true",
+                "o_emissive_useTexture": "true",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 16,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 17,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "true",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "true",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 18,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Lerp",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 19,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 20,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Blended",
+                "o_opacity_source": "OpacitySource::Split",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 21,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 22,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::POM",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "true",
+                "o_parallax_quality": "ParallaxQuality::High",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "true"
+            }
+        },
+        {
+            "StableId": 23,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "true",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 24,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "true",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 25,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 26,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 27,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Cutout",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 28,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "true",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 29,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::LinearLight",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 30,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Blended",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 31,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 32,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Lerp",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 33,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Lerp",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 34,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::POM",
+                "o_parallax_enablePixelDepthOffset": "true",
+                "o_parallax_feature_enabled": "true",
+                "o_parallax_quality": "ParallaxQuality::High",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "true"
+            }
+        },
+        {
+            "StableId": 35,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "true",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::ThickObject",
+                "o_transmission_useTexture": "true",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 36,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::POM",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "true",
+                "o_parallax_quality": "ParallaxQuality::High",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "true"
+            }
+        },
+        {
+            "StableId": 37,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 38,
+            "Options": {
+                "o_applySpecularAA": "true",
+                "o_emissiveEnabled": "false",
+                "o_enableAreaLights": "false",
+                "o_enableDirectionalLights": "false",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "false",
+                "o_enableShadows": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_specularF0_enableMultiScatterCompensation": "false"
+            }
+        }
+    ]
+}

+ 1411 - 0
ShaderVariants/Materials/Types/StandardPBR_ForwardPass_EDS.shadervariantlist

@@ -0,0 +1,1411 @@
+{
+    "Shader": "Materials/Types/StandardPBR_ForwardPass_EDS.shader",
+    "Variants": [
+        {
+            "StableId": 1,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 2,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 3,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "true",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 4,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "true",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 5,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 6,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "true",
+                "o_clearCoat_factor_useTexture": "true",
+                "o_clearCoat_feature_enabled": "true",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 7,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Cutout",
+                "o_opacity_source": "OpacitySource::Split",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 8,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 9,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "true",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 10,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Cutout",
+                "o_opacity_source": "OpacitySource::Split",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 11,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 12,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "true",
+                "o_clearCoat_normal_useTexture": "true",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 13,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 14,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "true",
+                "o_emissive_useTexture": "true",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 15,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "true",
+                "o_emissive_useTexture": "true",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 16,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 17,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "true",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "true",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 18,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Lerp",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 19,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 20,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Blended",
+                "o_opacity_source": "OpacitySource::Split",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 21,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 22,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::POM",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "true",
+                "o_parallax_quality": "ParallaxQuality::High",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "true"
+            }
+        },
+        {
+            "StableId": 23,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "true",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 24,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "true",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "true",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "true",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 25,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 26,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 27,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Cutout",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 28,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "true",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 29,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::LinearLight",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 30,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Blended",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 31,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 32,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Lerp",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 33,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Lerp",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "true",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 34,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "true",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::POM",
+                "o_parallax_enablePixelDepthOffset": "true",
+                "o_parallax_feature_enabled": "true",
+                "o_parallax_quality": "ParallaxQuality::High",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "true"
+            }
+        },
+        {
+            "StableId": 35,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "true",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::ThickObject",
+                "o_transmission_useTexture": "true",
+                "o_useDepthMap": "false"
+            }
+        },
+        {
+            "StableId": 36,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "false",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "true",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "true",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::POM",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "true",
+                "o_parallax_quality": "ParallaxQuality::High",
+                "o_roughness_useTexture": "true",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "true"
+            }
+        },
+        {
+            "StableId": 37,
+            "Options": {
+                "o_ambientOcclusion_useTexture": "true",
+                "o_applySpecularAA": "false",
+                "o_baseColorTextureBlendMode": "TextureBlendMode::Multiply",
+                "o_baseColor_useTexture": "false",
+                "o_clearCoat_enabled": "false",
+                "o_clearCoat_factor_useTexture": "false",
+                "o_clearCoat_feature_enabled": "false",
+                "o_clearCoat_normal_useTexture": "false",
+                "o_clearCoat_roughness_useTexture": "false",
+                "o_emissiveEnabled": "false",
+                "o_emissive_useTexture": "false",
+                "o_enableAreaLights": "true",
+                "o_enableDirectionalLights": "true",
+                "o_enableIBL": "true",
+                "o_enablePunctualLights": "true",
+                "o_enableShadows": "true",
+                "o_enableSubsurfaceScattering": "false",
+                "o_materialUseForwardPassIBLSpecular": "false",
+                "o_metallic_useTexture": "false",
+                "o_normal_useTexture": "false",
+                "o_opacity_mode": "OpacityMode::Opaque",
+                "o_opacity_source": "OpacitySource::Packed",
+                "o_parallax_algorithm": "ParallaxAlgorithm::Basic",
+                "o_parallax_enablePixelDepthOffset": "false",
+                "o_parallax_feature_enabled": "false",
+                "o_parallax_quality": "ParallaxQuality::Low",
+                "o_roughness_useTexture": "false",
+                "o_specularF0_enableMultiScatterCompensation": "false",
+                "o_specularF0_useTexture": "false",
+                "o_subsurfaceScattering_useTexture": "false",
+                "o_transmission_mode": "TransmissionMode::None",
+                "o_transmission_useTexture": "false",
+                "o_useDepthMap": "false"
+            }
+        }
+    ]
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff