Переглянути джерело

Merge branch 'main' into Atom/moudgils/DisableMacShaders

moudgils 4 роки тому
батько
коміт
10b36a37f0
100 змінених файлів з 1233 додано та 751 видалено
  1. 4 1
      .gitignore
  2. 34 8
      CMakeLists.txt
  3. 6 14
      Gem/Code/CMakeLists.txt
  4. 2 4
      Gem/Code/Source/AreaLightExampleComponent.cpp
  5. 2 0
      Gem/Code/Source/AtomSampleViewerModule.cpp
  6. 0 1
      Gem/Code/Source/Automation/AssetStatusTracker.cpp
  7. 10 1
      Gem/Code/Source/Automation/ScriptManager.cpp
  8. 3 1
      Gem/Code/Source/Automation/ScriptManager.h
  9. 8 2
      Gem/Code/Source/Automation/ScriptReporter.cpp
  10. 1 0
      Gem/Code/Source/Automation/ScriptReporter.h
  11. 0 2
      Gem/Code/Source/AuxGeomSharedDrawFunctions.cpp
  12. 227 0
      Gem/Code/Source/BakedShaderVariantExampleComponent.cpp
  13. 75 0
      Gem/Code/Source/BakedShaderVariantExampleComponent.h
  14. 65 65
      Gem/Code/Source/CullingAndLodExampleComponent.cpp
  15. 17 17
      Gem/Code/Source/CullingAndLodExampleComponent.h
  16. 0 1
      Gem/Code/Source/DynamicMaterialTestComponent.cpp
  17. 34 82
      Gem/Code/Source/LightCullingExampleComponent.cpp
  18. 4 14
      Gem/Code/Source/LightCullingExampleComponent.h
  19. 14 3
      Gem/Code/Source/MaterialHotReloadTestComponent.cpp
  20. 2 0
      Gem/Code/Source/MaterialHotReloadTestComponent.h
  21. 19 18
      Gem/Code/Source/MultiRenderPipelineExampleComponent.cpp
  22. 8 8
      Gem/Code/Source/MultiRenderPipelineExampleComponent.h
  23. 18 14
      Gem/Code/Source/MultiSceneExampleComponent.cpp
  24. 4 4
      Gem/Code/Source/MultiSceneExampleComponent.h
  25. 18 17
      Gem/Code/Source/ParallaxMappingExampleComponent.cpp
  26. 6 6
      Gem/Code/Source/ParallaxMappingExampleComponent.h
  27. 7 1
      Gem/Code/Source/Passes/RayTracingAmbientOcclusionPass.cpp
  28. 16 0
      Gem/Code/Source/Platform/Android/SSRExampleComponent_Traits_Platform.h
  29. 16 0
      Gem/Code/Source/Platform/Android/TriangleConstantBufferExampleComponent_Traits_Platform.h
  30. 0 8
      Gem/Code/Source/Platform/Android/additional_android_runtime_library.cmake
  31. 2 0
      Gem/Code/Source/Platform/Android/atomsampleviewer_android_files.cmake
  32. 13 0
      Gem/Code/Source/Platform/Linux/SSRExampleComponent_Traits_Platform.h
  33. 14 0
      Gem/Code/Source/Platform/Linux/TriangleConstantBufferExampleComponent_Traits_Platform.h
  34. 2 0
      Gem/Code/Source/Platform/Linux/atomsampleviewer_linux_files.cmake
  35. 13 0
      Gem/Code/Source/Platform/Mac/SSRExampleComponent_Traits_Platform.h
  36. 14 0
      Gem/Code/Source/Platform/Mac/TriangleConstantBufferExampleComponent_Traits_Platform.h
  37. 2 0
      Gem/Code/Source/Platform/Mac/atomsampleviewer_mac_files.cmake
  38. 13 0
      Gem/Code/Source/Platform/Windows/SSRExampleComponent_Traits_Platform.h
  39. 14 0
      Gem/Code/Source/Platform/Windows/TriangleConstantBufferExampleComponent_Traits_Platform.h
  40. 2 0
      Gem/Code/Source/Platform/Windows/atomsampleviewer_windows_files.cmake
  41. 13 0
      Gem/Code/Source/Platform/iOS/SSRExampleComponent_Traits_Platform.h
  42. 14 0
      Gem/Code/Source/Platform/iOS/TriangleConstantBufferExampleComponent_Traits_Platform.h
  43. 2 0
      Gem/Code/Source/Platform/iOS/atomsampleviewer_ios_files.cmake
  44. 1 1
      Gem/Code/Source/RHI/AlphaToCoverageExampleComponent.cpp
  45. 4 4
      Gem/Code/Source/RHI/AsyncComputeExampleComponent.cpp
  46. 7 7
      Gem/Code/Source/RHI/BindlessPrototypeExampleComponent.cpp
  47. 1 1
      Gem/Code/Source/RHI/BindlessPrototypeExampleComponent.h
  48. 2 2
      Gem/Code/Source/RHI/ComputeExampleComponent.cpp
  49. 1 1
      Gem/Code/Source/RHI/CopyQueueComponent.cpp
  50. 1 1
      Gem/Code/Source/RHI/DualSourceBlendingComponent.cpp
  51. 1 3
      Gem/Code/Source/RHI/IndirectRenderingExampleComponent.cpp
  52. 1 1
      Gem/Code/Source/RHI/InputAssemblyExampleComponent.cpp
  53. 7 7
      Gem/Code/Source/RHI/MRTExampleComponent.cpp
  54. 3 3
      Gem/Code/Source/RHI/MSAAExampleComponent.cpp
  55. 1 1
      Gem/Code/Source/RHI/MultiThreadComponent.cpp
  56. 2 2
      Gem/Code/Source/RHI/MultipleViewsComponent.cpp
  57. 3 3
      Gem/Code/Source/RHI/QueryExampleComponent.cpp
  58. 12 8
      Gem/Code/Source/RHI/RayTracingExampleComponent.cpp
  59. 2 2
      Gem/Code/Source/RHI/SphericalHarmonicsExampleComponent.cpp
  60. 1 1
      Gem/Code/Source/RHI/StencilExampleComponent.cpp
  61. 1 1
      Gem/Code/Source/RHI/SubpassExampleComponent.cpp
  62. 1 1
      Gem/Code/Source/RHI/Texture3dExampleComponent.cpp
  63. 3 3
      Gem/Code/Source/RHI/TextureArrayExampleComponent.cpp
  64. 1 1
      Gem/Code/Source/RHI/TextureExampleComponent.cpp
  65. 2 2
      Gem/Code/Source/RHI/TextureMapExampleComponent.cpp
  66. 2 2
      Gem/Code/Source/RHI/TriangleExampleComponent.cpp
  67. 10 8
      Gem/Code/Source/RHI/TrianglesConstantBufferExampleComponent.cpp
  68. 4 2
      Gem/Code/Source/SSRExampleComponent.cpp
  69. 6 5
      Gem/Code/Source/SampleComponentManager.cpp
  70. 1 1
      Gem/Code/Source/SampleComponentManager.h
  71. 2 1
      Gem/Code/Source/SampleComponentManagerBus.h
  72. 87 89
      Gem/Code/Source/ShadowExampleComponent.cpp
  73. 21 21
      Gem/Code/Source/ShadowExampleComponent.h
  74. 122 116
      Gem/Code/Source/ShadowedBistroExampleComponent.cpp
  75. 27 26
      Gem/Code/Source/ShadowedBistroExampleComponent.h
  76. 0 1
      Gem/Code/Source/StreamingImageExampleComponent.cpp
  77. 0 2
      Gem/Code/Source/TonemappingExampleComponent.cpp
  78. 2 0
      Gem/Code/atomsampleviewergem_private_files.cmake
  79. 59 24
      Materials/DynamicMaterialTest/EmissiveMaterial.azsl
  80. 1 1
      Objects/Bistro/CHANGELOG.txt
  81. 3 3
      Objects/Bistro/README.txt
  82. 17 17
      Passes/CheckerboardPipeline.pass
  83. 10 10
      Passes/ComplexPipeline.pass
  84. 1 1
      Passes/MSAA_2x_RPI_Pipeline.pass
  85. 1 1
      Passes/MSAA_4x_RPI_Pipeline.pass
  86. 1 1
      Passes/MSAA_8x_RPI_Pipeline.pass
  87. 6 6
      Passes/MSAA_RPI_Pipeline_Core.pass
  88. 8 8
      Passes/MainPipeline.pass
  89. 16 16
      Passes/MainPipeline_Mobile.pass
  90. 6 6
      Passes/No_MSAA_RPI_Pipeline.pass
  91. 10 2
      Passes/PassTemplates.azasset
  92. 10 10
      Passes/SsaoPipeline.pass
  93. 0 10
      Scripts/AreaLightTest.bv.lua
  94. 0 3
      Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_metal.ppm
  95. 0 3
      Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_rough_metal.ppm
  96. 0 3
      Scripts/ExpectedScreenshots/AreaLights/disk_double_sided_vary_rough_nonmetal.ppm
  97. 1 1
      Scripts/ExpectedScreenshots/AutoBrick/brick.ppm
  98. 1 1
      Scripts/ExpectedScreenshots/AutoBrick/tile.ppm
  99. 1 1
      Scripts/ExpectedScreenshots/CullingAndLod/screenshot_1.ppm
  100. 1 1
      Scripts/ExpectedScreenshots/LightCulling/screenshot_capsulelights.ppm

+ 4 - 1
.gitignore

@@ -1,3 +1,6 @@
 _savebackup/
 .mayaSwatches/
-*.swatches
+*.swatches
+[Bb]uild/
+[Cc]ache/
+[Uu]ser/

+ 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;

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

@@ -446,6 +446,8 @@ namespace AtomSampleViewer
             ImGui::Combo("Display", &displayOption, DiplayOptions, AZ_ARRAY_SIZE(DiplayOptions));
             m_displayOption = (DisplayOption)displayOption;
 
+            ImGui::Checkbox("Force Show 'Update' Buttons", &m_forceShowUpdateButtons);
+
             bool showWarnings = (m_displayOption == DisplayOption::AllResults) || (m_displayOption == DisplayOption::WarningsAndErrors);
             bool showAll = (m_displayOption == DisplayOption::AllResults);
 
@@ -610,7 +612,7 @@ namespace AtomSampleViewer
                                 ShowDiffButton("View Diff", screenshotResult.m_officialBaselineScreenshotFilePath, screenshotResult.m_screenshotFilePath);
                                 ImGui::PopID();
 
-                                if (!screenshotPassed && ImGui::Button("Update"))
+                                if ((!screenshotPassed || m_forceShowUpdateButtons) && ImGui::Button("Update##Official"))
                                 {
                                     if (screenshotResult.m_localComparisonResult.m_resultCode == ImageComparisonResult::ResultCode::FileNotFound)
                                     {
@@ -649,7 +651,7 @@ namespace AtomSampleViewer
                                 ShowDiffButton("View Diff", screenshotResult.m_localBaselineScreenshotFilePath, screenshotResult.m_screenshotFilePath);
                                 ImGui::PopID();
 
-                                if (localBaselineWarning && ImGui::Button("Update"))
+                                if ((localBaselineWarning || m_forceShowUpdateButtons) && ImGui::Button("Update##Local"))
                                 {
                                     if (screenshotResult.m_localComparisonResult.m_resultCode == ImageComparisonResult::ResultCode::FileNotFound)
                                     {
@@ -911,9 +913,13 @@ namespace AtomSampleViewer
         // Get source folder
         if (m_officialBaselineSourceFolder.empty())
         {
+
             auto 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()))
             {
                 AZ_Error("Automation", false, "Could not find source folder '%s'. Copying to source baseline can only be used on dev platforms.", m_officialBaselineSourceFolder.c_str());

+ 1 - 0
Gem/Code/Source/Automation/ScriptReporter.h

@@ -248,6 +248,7 @@ namespace AtomSampleViewer
         AZStd::vector<size_t> m_currentScriptIndexStack; //< Tracks which of the scripts in m_scriptReports is currently active
         bool m_showReportDialog = false;
         DisplayOption m_displayOption = DisplayOption::AllResults;
+        bool m_forceShowUpdateButtons = false; //< By default, the "Update" buttons are visible only for failed screenshots. This forces them to be visible.
         AZStd::string m_officialBaselineSourceFolder; //< Used for updating official baseline screenshots
     };
 

+ 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[];

+ 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;
 

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

@@ -32,7 +32,7 @@ namespace AtomSampleViewer
     static const char* ParallaxQualityName = "parallax.quality";
     static const char* ParallaxUvIndexName = "parallax.textureMapUv";
 
-    static const char* AmbientOcclusionUvIndexName = "ambientOcclusion.textureMapUv";
+    static const char* AmbientOcclusionUvIndexName = "occlusion.diffuseTextureMapUv";
     static const char* BaseColorUvIndexName = "baseColor.textureMapUv";
     static const char* NormalUvIndexName = "normal.textureMapUv";
     static const char* RoughnessUvIndexName = "roughness.textureMapUv";
@@ -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

+ 6 - 6
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;
@@ -104,7 +104,7 @@ namespace AtomSampleViewer
         // parallax setting
         bool m_parallaxEnable = true;
         bool m_pdoEnable = true;
-        float m_parallaxFactor = 0.03f;
+        float m_parallaxFactor = 0.05f;
         // see StandardPbr.materialtype for the full enum list.
         int m_parallaxAlgorithm = 2; // POM
         int m_parallaxQuality = 2;   // High

+ 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

+ 16 - 0
Gem/Code/Source/Platform/Android/SSRExampleComponent_Traits_Platform.h

@@ -0,0 +1,16 @@
+/*
+* 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.
+*
+*/
+
+// Mali devices have a memory limitation of vertex buffer (180MB), so low resolution mesh model is needed.
+// https://community.arm.com/developer/tools-software/graphics/b/blog/posts/memory-limits-with-vulkan-on-mali-gpus
+// [ATOM-14947]
+#define ATOMSAMPLEVIEWER_TRAIT_SSR_SAMPLE_LUCY_MODEL_NAME                       "objects/lucy/lucy_low.azmodel"

+ 16 - 0
Gem/Code/Source/Platform/Android/TriangleConstantBufferExampleComponent_Traits_Platform.h

@@ -0,0 +1,16 @@
+/*
+* 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.
+*
+*/
+
+// https://jira.agscollab.com/browse/ATOM-14949
+// The number need to be within the uniform limitations of android devices with lower specs where 15 total would be the lower bound on the devices.
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_SINGLE_CONSTANT_BUFFER_SIZE       6u  
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_MULTIPLE_CONSTANT_BUFFER_SIZE     6u

+ 0 - 8
Gem/Code/Source/Platform/Android/additional_android_runtime_library.cmake

@@ -11,12 +11,4 @@
 
 set(LY_RUNTIME_DEPENDENCIES
     3rdParty::VkValidation
-)
-
-set(VKVALIDATION_VERSION
-    r21d
-)
-
-set(VKVALIDATION_3RDPARTY_PLATFORM_DIRECTORY
-    android-ndk
 )

+ 2 - 0
Gem/Code/Source/Platform/Android/atomsampleviewer_android_files.cmake

@@ -12,6 +12,8 @@
 set(FILES
     AtomSampleViewerOptions_Android.cpp
     MultiThreadComponent_Traits_Platform.h
+    SSRExampleComponent_Traits_Platform.h
+    TriangleConstantBufferExampleComponent_Traits_Platform.h
     SampleComponentManager_Android.cpp
     StreamingImageExampleComponent_Android.cpp
     Utils_Android.cpp

+ 13 - 0
Gem/Code/Source/Platform/Linux/SSRExampleComponent_Traits_Platform.h

@@ -0,0 +1,13 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_SSR_SAMPLE_LUCY_MODEL_NAME                       "objects/lucy/lucy_high.azmodel"

+ 14 - 0
Gem/Code/Source/Platform/Linux/TriangleConstantBufferExampleComponent_Traits_Platform.h

@@ -0,0 +1,14 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_SINGLE_CONSTANT_BUFFER_SIZE       15u  
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_MULTIPLE_CONSTANT_BUFFER_SIZE     15u    

+ 2 - 0
Gem/Code/Source/Platform/Linux/atomsampleviewer_linux_files.cmake

@@ -12,6 +12,8 @@
 set(FILES
     AtomSampleViewerOptions_Linux.cpp
     MultiThreadComponent_Traits_Platform.h
+    SSRExampleComponent_Traits_Platform.h
+    TriangleConstantBufferExampleComponent_Traits_Platform.h
     SampleComponentManager_Linux.cpp
     StreamingImageExampleComponent_Linux.cpp
     Utils_Linux.cpp

+ 13 - 0
Gem/Code/Source/Platform/Mac/SSRExampleComponent_Traits_Platform.h

@@ -0,0 +1,13 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_SSR_SAMPLE_LUCY_MODEL_NAME                       "objects/lucy/lucy_high.azmodel"

+ 14 - 0
Gem/Code/Source/Platform/Mac/TriangleConstantBufferExampleComponent_Traits_Platform.h

@@ -0,0 +1,14 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_SINGLE_CONSTANT_BUFFER_SIZE       15u  
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_MULTIPLE_CONSTANT_BUFFER_SIZE     15u

+ 2 - 0
Gem/Code/Source/Platform/Mac/atomsampleviewer_mac_files.cmake

@@ -13,6 +13,8 @@ set(FILES
     ../../../../Resources/MacLauncher/Info.plist
     AtomSampleViewerOptions_Mac.cpp
     MultiThreadComponent_Traits_Platform.h
+    SSRExampleComponent_Traits_Platform.h
+    TriangleConstantBufferExampleComponent_Traits_Platform.h
     SampleComponentManager_Mac.cpp
     StreamingImageExampleComponent_Mac.cpp
     Utils_Mac.cpp

+ 13 - 0
Gem/Code/Source/Platform/Windows/SSRExampleComponent_Traits_Platform.h

@@ -0,0 +1,13 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_SSR_SAMPLE_LUCY_MODEL_NAME                       "objects/lucy/lucy_high.azmodel"

+ 14 - 0
Gem/Code/Source/Platform/Windows/TriangleConstantBufferExampleComponent_Traits_Platform.h

@@ -0,0 +1,14 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_SINGLE_CONSTANT_BUFFER_SIZE       15u  
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_MULTIPLE_CONSTANT_BUFFER_SIZE     15u

+ 2 - 0
Gem/Code/Source/Platform/Windows/atomsampleviewer_windows_files.cmake

@@ -12,6 +12,8 @@
 set(FILES
     AtomSampleViewerOptions_Windows.cpp
     MultiThreadComponent_Traits_Platform.h
+    SSRExampleComponent_Traits_Platform.h
+    TriangleConstantBufferExampleComponent_Traits_Platform.h
     SampleComponentManager_Windows.cpp
     StreamingImageExampleComponent_Windows.cpp
     Utils_Windows.cpp

+ 13 - 0
Gem/Code/Source/Platform/iOS/SSRExampleComponent_Traits_Platform.h

@@ -0,0 +1,13 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_SSR_SAMPLE_LUCY_MODEL_NAME                       "objects/lucy/lucy_high.azmodel"

+ 14 - 0
Gem/Code/Source/Platform/iOS/TriangleConstantBufferExampleComponent_Traits_Platform.h

@@ -0,0 +1,14 @@
+/*
+* 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.
+*
+*/
+
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_SINGLE_CONSTANT_BUFFER_SIZE       15u  
+#define ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_MULTIPLE_CONSTANT_BUFFER_SIZE     15u

+ 2 - 0
Gem/Code/Source/Platform/iOS/atomsampleviewer_ios_files.cmake

@@ -13,6 +13,8 @@ set(FILES
     ../../../../Resources/IOSLauncher/Info.plist
     AtomSampleViewerOptions_iOS.cpp
     MultiThreadComponent_Traits_Platform.h
+    SSRExampleComponent_Traits_Platform.h
+    TriangleConstantBufferExampleComponent_Traits_Platform.h
     SampleComponentManager_iOS.cpp
     StreamingImageExampleComponent_iOS.cpp
     Utils_iOS.cpp

+ 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);

+ 10 - 8
Gem/Code/Source/RHI/TrianglesConstantBufferExampleComponent.cpp

@@ -26,15 +26,17 @@
 
 #include <AzCore/Serialization/SerializeContext.h>
 
+#include <TriangleConstantBufferExampleComponent_Traits_Platform.h>
+
 namespace AtomSampleViewer
 {
     const char* TrianglesConstantBufferExampleComponent::s_trianglesConstantBufferExampleName = "TrianglesConstantBufferExample";
     // The number of triangles that are represented with a single constant buffer, that contains multiple buffer views;
     // each view containing a partial view of the constant buffer
-    const uint32_t TrianglesConstantBufferExampleComponent::s_numberOfTrianglesSingleCB = 15u;
+    const uint32_t TrianglesConstantBufferExampleComponent::s_numberOfTrianglesSingleCB = ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_SINGLE_CONSTANT_BUFFER_SIZE;
     // The number of triangles that are represented with multiple constant buffers;
     // each having their own constant buffer and view containing the whole buffer
-    const uint32_t TrianglesConstantBufferExampleComponent::s_numberOfTrianglesMultipleCB = 15u;
+    const uint32_t TrianglesConstantBufferExampleComponent::s_numberOfTrianglesMultipleCB = ATOMSAMPLEVIEWER_TRAIT_TRIANGLE_CONSTANT_BUFFER_SAMPLE_MULTIPLE_CONSTANT_BUFFER_SIZE;
     // The total number of views and triangles that will be rendered for this sample
     const uint32_t TrianglesConstantBufferExampleComponent::s_numberOfTrianglesTotal = s_numberOfTrianglesSingleCB + s_numberOfTrianglesMultipleCB;
 
@@ -122,7 +124,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 +144,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 +233,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 +250,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 +307,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 +326,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++;
             }

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

@@ -22,6 +22,8 @@
 #include <Automation/ScriptRunnerBus.h>
 #include <Utils/Utils.h>
 
+#include <SSRExampleComponent_Traits_Platform.h>
+
 namespace AtomSampleViewer
 {
     void SSRExampleComponent::Reflect(AZ::ReflectContext* context)
@@ -88,12 +90,12 @@ namespace AtomSampleViewer
 
     void SSRExampleComponent::CreateModels()
     {
-        AZ::Render::MeshFeatureProcessorInterface* meshFeatureProcessor = GetMeshFeatureProcessor();
+        GetMeshFeatureProcessor();
 
         // statue
         {
             AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("objects/lucy/lucy_stone.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
-            AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/lucy/lucy_high.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
+            AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>(ATOMSAMPLEVIEWER_TRAIT_SSR_SAMPLE_LUCY_MODEL_NAME, AZ::RPI::AssetUtils::TraceLevel::Assert);
             AZ::Transform transform = AZ::Transform::CreateIdentity();
             transform *= AZ::Transform::CreateRotationZ(AZ::Constants::Pi);
             transform.SetTranslation(0.0f, 0.0f, -0.05f);

+ 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

+ 59 - 24
Materials/DynamicMaterialTest/EmissiveMaterial.azsl

@@ -13,10 +13,12 @@
 #include <viewsrg.srgi>
 #include <Atom/Features/PBR/AlphaUtils.azsli>
 #include <Atom/Features/PBR/DefaultObjectSrg.azsli>
+#include <Atom/Features/PBR/ForwardPassSrg.azsli>
 #include <Atom/Features/PBR/ForwardPassOutput.azsli>
 #include <Atom/Features/ColorManagement/TransformColor.azsli>
 #include <Atom/Features/SrgSemantics.azsli>
-#include <Atom/Features/ColorManagement/TransformColor.azsli>
+#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
+#include <Atom/Features/PBR/Decals.azsli>
 
 ShaderResourceGroup MaterialSrg : SRG_PerMaterial
 {
@@ -54,47 +56,83 @@ struct VSOutput
     float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV3;
 };
 
-#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;
 }
 
 ForwardPassOutput MainPS(VSOutput IN)
 {
-    ForwardPassOutput OUT;
+    // ------- Surface -------
+
+    Surface surface;
     
-    const float3 baseColor = {0.05,0.05,0.05};
-    const float metallic = 0.0;
-    const float roughness = 1.0;
-    const float specularF0Factor = 0.5;
-    const float3 normal = normalize(IN.m_normal);
-    const float occlusion = 1;
-    const float clearCoatFactor = 0.0;
-    const float clearCoatRoughness = 0.0;
-    const float3 clearCoatNormal = {0,0,0};
-    const float4 transmissionTintThickness = {0,0,0,0};
-    const float4 transmissionParams = {0,0,0,0};
-    const float2 anisotropy = 0.0;	// Does not affect calculations unless 'o_enableAnisotropy' is enabled
-    const float alpha = 1.0;
+    // Position, Normal, Roughness
+    surface.position = IN.m_worldPosition.xyz;
+    surface.normal = normalize(IN.m_normal);
+    surface.roughnessLinear = 1.0f;
+    surface.CalculateRoughnessA();
+
+    // Albedo, SpecularF0
+    const float3 baseColor = float3(0.05f, 0.05f, 0.05f);
+    const float metallic = 0.0f;
+    const float specularF0Factor = 0.5f;
+    surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
+
+    // Clear Coat, Transmission
+    surface.clearCoat.InitializeToZero();
+    surface.transmission.InitializeToZero();
+
+    // ------- LightingData -------
+
+    LightingData lightingData;
+
+    // Light iterator
+    lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
+    lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
+
+    // Shadow, Occlusion
+    lightingData.shadowCoords = IN.m_shadowCoords;
 
+    // Emissive
     float3 emissive = MaterialSrg::m_emissiveColor.rgb * MaterialSrg::m_emissiveIntensity;
     if (o_emissive_useTexture)
     {
         float4 sampledValue = MaterialSrg::m_emissiveMap.Sample(MaterialSrg::m_sampler, IN.m_uv);
         emissive *= TransformColor(sampledValue.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
     }
+    lightingData.emissiveLighting = emissive;
 
-    PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, 
-        normal, IN.m_tangent, IN.m_bitangent, anisotropy,
-        emissive, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque);
+    // Diffuse and Specular response
+    lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
+    lightingData.diffuseResponse = 1.0f - lightingData.specularResponse;
+
+    const float alpha = 1.0f;
+
+    // ------- Lighting Calculation -------
+
+    // Apply Decals
+    ApplyDecals(lightingData.tileIterator, surface);
+
+    // Apply Direct Lighting
+    ApplyDirectLighting(surface, lightingData);
+
+    // Apply Image Based Lighting (IBL)
+    ApplyIBL(surface, lightingData);
+
+    // Finalize Lighting
+    lightingData.FinalizeLighting(surface.transmission.tint);
+
+    PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
+
+    ForwardPassOutput OUT;
 
     OUT.m_diffuseColor = lightingOutput.m_diffuseColor;
     OUT.m_diffuseColor.w = -1; // Subsurface scattering is disabled
@@ -102,9 +140,6 @@ ForwardPassOutput MainPS(VSOutput IN)
     OUT.m_specularF0 = lightingOutput.m_specularF0;
     OUT.m_albedo = lightingOutput.m_albedo;
     OUT.m_normal = lightingOutput.m_normal;
-    OUT.m_clearCoatNormal = lightingOutput.m_clearCoatNormal;
-    OUT.m_scatterDistance = float3(0,0,0);
-
     return OUT;
 }
 

+ 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}},

+ 17 - 17
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"
                             }
                         },
@@ -339,10 +339,10 @@
                             }
                         },
                         {
-                            "LocalSlot": "ClearCoatNormalInput",
+                            "LocalSlot": "AlbedoInput",
                             "AttachmentRef": {
                                 "Pass": "ForwardMSAAPass",
-                                "Attachment": "ClearCoatNormalOutput"
+                                "Attachment": "AlbedoOutput"
                             }
                         },
                         {
@@ -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": [

+ 6 - 6
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"
                     }
                 },
                 {
@@ -168,10 +168,10 @@
                             }
                         },
                         {
-                            "LocalSlot": "ClearCoatNormalInput",
+                            "LocalSlot": "AlbedoInput",
                             "AttachmentRef": {
                                 "Pass": "ForwardMSAAPass",
-                                "Attachment": "ClearCoatNormalOutput"
+                                "Attachment": "AlbedoOutput"
                             }
                         },
                         {

+ 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"
                             }
                         },
                         {

+ 16 - 16
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"
                             }
                         },
@@ -289,10 +289,10 @@
                             }
                         },
                         {
-                            "LocalSlot": "ClearCoatNormalInput",
+                            "LocalSlot": "AlbedoInput",
                             "AttachmentRef": {
                                 "Pass": "ForwardPass",
-                                "Attachment": "ClearCoatNormalOutput"
+                                "Attachment": "AlbedoOutput"
                             }
                         },
                         {
@@ -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"
                             }
                         },

+ 6 - 6
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": [
                         {
@@ -208,10 +208,10 @@
                             }
                         },
                         {
-                            "LocalSlot": "ClearCoatNormalInput",
+                            "LocalSlot": "AlbedoInput",
                             "AttachmentRef": {
                                 "Pass": "ForwardPass",
-                                "Attachment": "ClearCoatNormalOutput"
+                                "Attachment": "AlbedoOutput"
                             }
                         },
                         {

+ 10 - 2
Passes/PassTemplates.azasset

@@ -36,6 +36,10 @@
                 "Name": "ForwardMSAAPassTemplate",
                 "Path": "Passes/ForwardMSAA.pass"
             },
+            {
+                "Name": "ForwardSubsurfaceMSAAPassTemplate",
+                "Path": "Passes/ForwardSubsurfaceMSAA.pass"
+            },
             {
                 "Name": "CascadedShadowmapsTemplate",
                 "Path": "Passes/CascadedShadowmaps.pass"
@@ -293,8 +297,8 @@
                 "Path": "Passes/LightCullingRemap.pass"
             },
             {
-                "Name": "SpotLightShadowmapsTemplate",
-                "Path": "Passes/SpotLightShadowmaps.pass"
+                "Name": "ProjectedShadowmapsTemplate",
+                "Path": "Passes/ProjectedShadowmaps.pass"
             },
             {
                 "Name": "EnvironmentCubeMapPipeline",
@@ -508,6 +512,10 @@
                 "Name": "DiffuseProbeGridRelocationPassTemplate",
                 "Path": "Passes/DiffuseProbeGridRelocation.pass"
             },
+            {
+                "Name": "DiffuseProbeGridClassificationPassTemplate",
+                "Path": "Passes/DiffuseProbeGridClassification.pass"
+            },
             {
                 "Name": "DiffuseGlobalIlluminationPassTemplate",
                 "Path": "Passes/DiffuseGlobalIllumination.pass"

+ 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/AutoBrick/brick.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8a3c23e0bb2cd5aa809cf6118eccae44a910ccb224abecbfbb116d7c2f3a25aa
+oid sha256:0ebc37f0c58ed9e772c97a630539f092c80cc9b266bd66b37e7770f6100989b4
 size 2994018

+ 1 - 1
Scripts/ExpectedScreenshots/AutoBrick/tile.ppm

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4db01188d17298a541084c02551257660552b69b6befe532442d1965fb53e004
+oid sha256:3452808970f33471d2de494298df9b96d1d51ae7822a04ddf260e5b5cfd07ca0
 size 2994018

+ 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

Деякі файли не було показано, через те що забагато файлів було змінено