Parcourir la source

Merging changes

Michael Riegger il y a 4 ans
Parent
commit
6823797193
27 fichiers modifiés avec 293 ajouts et 73 suppressions
  1. 2 2
      Config/shader_global_build_options.json
  2. 50 0
      EngineFinder.cmake
  3. 1 1
      Gem/Code/Source/AreaLightExampleComponent.cpp
  4. 6 6
      Gem/Code/Source/Automation/ScriptableImGui.cpp
  5. 3 3
      Gem/Code/Source/Automation/ScriptableImGui.h
  6. 3 1
      Gem/Code/Source/BakedShaderVariantExampleComponent.cpp
  7. 2 2
      Gem/Code/Source/CullingAndLodExampleComponent.cpp
  8. 52 1
      Gem/Code/Source/MeshExampleComponent.cpp
  9. 10 0
      Gem/Code/Source/MeshExampleComponent.h
  10. 28 21
      Gem/Code/Source/ParallaxMappingExampleComponent.cpp
  11. 4 0
      Gem/Code/Source/ParallaxMappingExampleComponent.h
  12. 2 12
      Gem/Code/Source/Platform/Android/BakedShaderVariantExampleComponent_Traits_Platform.h
  13. 13 0
      Gem/Code/Source/Platform/Linux/BakedShaderVariantExampleComponent_Traits_Platform.h
  14. 13 0
      Gem/Code/Source/Platform/Mac/BakedShaderVariantExampleComponent_Traits_Platform.h
  15. 13 0
      Gem/Code/Source/Platform/Windows/BakedShaderVariantExampleComponent_Traits_Platform.h
  16. 13 0
      Gem/Code/Source/Platform/iOS/BakedShaderVariantExampleComponent_Traits_Platform.h
  17. 3 4
      Gem/Code/Source/ShadowExampleComponent.cpp
  18. 2 2
      Gem/Code/Source/ShadowedBistroExampleComponent.cpp
  19. 1 1
      Gem/Code/Source/SkinnedMeshExampleComponent.cpp
  20. 3 0
      Scripts/ExpectedScreenshots/ParallaxTest/screenshot_10_offsetClippingSteep.png
  21. 3 0
      Scripts/ExpectedScreenshots/ParallaxTest/screenshot_8_offset.png
  22. 3 0
      Scripts/ExpectedScreenshots/ParallaxTest/screenshot_9_offsetClipping.png
  23. 3 0
      Scripts/ExpectedScreenshots/StandardPBR/012_parallax_pom_cutout.png
  24. 7 1
      Scripts/MaterialScreenshotTests.bv.lua
  25. 49 12
      Scripts/ParallaxTest.bv.lua
  26. 2 2
      Shaders/StaticMesh.azsl
  27. 2 2
      Standalone/PythonTests/Automated/test_AtomSampleViewer_main_suite.py

+ 2 - 2
Config/shader_global_build_options.json

@@ -5,11 +5,11 @@
     "ClassData": {
         "PreprocessorOptions" : {
             "predefinedMacros": ["AZSL=17"],
-            "projectIncludePaths": [
-                "AtomSampleViewer",
+                // The root of the current project is always the first include path.
                 // These include paths are already part of the automatic include folders list.
                 // By specifying them here, we are boosting the priority of these folders above all the other automatic include folders.
                 // (This is not necessary for the project, but just shown as a usage example.)
+            "projectIncludePaths": [
                 "Gems/Atom/RPI/Assets/ShaderLib",
                 "Gems/Atom/Feature/Common/Assets/ShaderLib"
             ]

+ 50 - 0
EngineFinder.cmake

@@ -0,0 +1,50 @@
+#
+# 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.
+#
+# This file is copied during engine registration. Edits to this file will be lost next
+# time a registration happens.
+
+include_guard()
+
+# Read the engine name from the project_json file
+file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json)
+string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine)
+if(json_error)
+    message(FATAL_ERROR "Unable to read key 'engine' from 'project.json', error: ${json_error}")
+endif()
+
+# Read the list of paths from ~.o3de/o3de_manifest.json
+file(TO_CMAKE_PATH "$ENV{USERPROFILE}" home_directory) # Windows
+if((NOT home_directory) OR (NOT EXISTS ${home_directory}))
+    file(TO_CMAKE_PATH "$ENV{HOME}" home_directory)# Unix
+endif()
+
+if (NOT home_directory)
+    message(FATAL_ERROR "Cannot find user home directory, the o3de manifest cannot be found")
+endif()
+# Set manifest path to path in the user home directory
+set(manifest_path ${home_directory}/.o3de/o3de_manifest.json)
+
+if(EXISTS ${manifest_path})
+    file(READ ${manifest_path} manifest_json)
+    string(JSON engines_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines)
+    if(json_error)
+        message(FATAL_ERROR "Unable to read key 'engines' from '${manifest_path}', error: ${json_error}")
+    endif()
+
+    math(EXPR engines_count "${engines_count}-1")
+    foreach(engine_path_index RANGE ${engines_count})
+        string(JSON engine_path ERROR_VARIABLE json_error GET ${manifest_json} engines ${engine_path_index})
+        if(${json_error})
+            message(FATAL_ERROR "Unable to read engines[${engine_path_index}] '${manifest_path}', error: ${json_error}")
+        endif()
+        list(APPEND CMAKE_MODULE_PATH "${engine_path}/cmake")
+    endforeach()
+endif()

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

@@ -595,7 +595,7 @@ namespace AtomSampleViewer
             ScriptableImGui::EndCombo();
         }
 
-        if (ScriptableImGui::SliderFloat("Lumens", &m_config.m_intensity, 0.0f, 1000.0f, "%.3f", 2.0f))
+        if (ScriptableImGui::SliderFloat("Lumens", &m_config.m_intensity, 0.0f, 1000.0f, "%.3f", ImGuiSliderFlags_Logarithmic))
         {
             lightsNeedUpdate = true;
         }

+ 6 - 6
Gem/Code/Source/Automation/ScriptableImGui.cpp

@@ -338,11 +338,11 @@ namespace AtomSampleViewer
         return ActionHelper<float>(label, imguiAction, reportScriptableAction, handleScriptedAction);
     }
 
-    bool ScriptableImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power)
+    bool ScriptableImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
     {
         auto imguiAction = [&]()
         {
-            return ImGui::SliderFloat(label, v, v_min, v_max, format, power);
+            return ImGui::SliderFloat(label, v, v_min, v_max, format, flags);
         };
 
         auto reportScriptableAction = [&](const AZStd::string& pathToImGuiItem)
@@ -359,11 +359,11 @@ namespace AtomSampleViewer
         return ActionHelper<float>(label, imguiAction, reportScriptableAction, handleScriptedAction);
     }
 
-    bool ScriptableImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power)
+    bool ScriptableImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
     {
         auto imguiAction = [&]()
         {
-            return ImGui::SliderFloat2(label, v, v_min, v_max, format, power);
+            return ImGui::SliderFloat2(label, v, v_min, v_max, format, flags);
         };
 
         auto reportScriptableAction = [&](const AZStd::string& pathToImGuiItem)
@@ -400,11 +400,11 @@ namespace AtomSampleViewer
         return ActionHelper<AZ::Vector3>(label, imguiAction, reportScriptableAction, handleScriptedAction);
     }
 
-    bool ScriptableImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power)
+    bool ScriptableImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
     {
         auto imguiAction = [&]()
         {
-            return ImGui::SliderFloat3(label, v, v_min, v_max, format, power);
+            return ImGui::SliderFloat3(label, v, v_min, v_max, format, flags);
         };
 
         return ThreeComponentHelper(label, v, imguiAction);

+ 3 - 3
Gem/Code/Source/Automation/ScriptableImGui.h

@@ -72,9 +72,9 @@ namespace AtomSampleViewer
         static bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);
 
         static bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d");
-        static bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
-        static bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
-        static bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
+        static bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+        static bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+        static bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
         static bool SliderAngle(const char* label, float* v, float v_min = -360.0f, float v_max = 360.0f, const char* format = "%.0f deg");
 
         static bool ColorEdit3(const char* label, float v[3], ImGuiColorEditFlags flags);

+ 3 - 1
Gem/Code/Source/BakedShaderVariantExampleComponent.cpp

@@ -32,6 +32,8 @@
 
 #include <RHI/BasicRHIComponent.h>
 
+#include <BakedShaderVariantExampleComponent_Traits_Platform.h>
+
 namespace AtomSampleViewer
 {
     using namespace AZ;
@@ -95,7 +97,7 @@ namespace AtomSampleViewer
         m_meshFeatureProcessor->SetTransform(m_meshHandle, meshTransform);
 
         AZStd::vector<AZStd::string> passHierarchy;
-        passHierarchy.push_back("ForwardMSAAPass");
+        passHierarchy.push_back(ATOMSAMPLEVIEWER_TRAIT_BAKED_SHADERVARIANT_SAMPLE_PASS_NAME);
         AZ::RPI::PassHierarchyFilter passFilter(passHierarchy);
         AZStd::vector<AZ::RPI::Pass*> foundPasses = AZ::RPI::PassSystemInterface::Get()->FindPasses(passFilter);
         m_forwardPass = foundPasses[0];

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

@@ -338,7 +338,7 @@ namespace AtomSampleViewer
             const auto lightTrans = Transform::CreateRotationZ(m_directionalLightYaw) * Transform::CreateRotationX(m_directionalLightPitch);
             m_directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, lightTrans.GetBasis(1));
 
-            if (ImGui::SliderFloat("Intensity##directional", &m_directionalLightIntensity, 0.f, 20.f, "%.1f", 2.f))
+            if (ImGui::SliderFloat("Intensity##directional", &m_directionalLightIntensity, 0.f, 20.f, "%.1f", ImGuiSliderFlags_Logarithmic))
             {
                 m_directionalLightFeatureProcessor->SetRgbIntensity(
                     m_directionalLightHandle,
@@ -432,7 +432,7 @@ namespace AtomSampleViewer
                 UpdateDiskLightCount(diskLightCount);
             }
 
-            if (ImGui::SliderFloat("Intensity##disk", &m_diskLightIntensity, 0.f, 100000.f, "%.1f", 4.f))
+            if (ImGui::SliderFloat("Intensity##disk", &m_diskLightIntensity, 0.f, 100000.f, "%.1f", ImGuiSliderFlags_Logarithmic))
             {
                 for (const DiskLight& light : m_diskLights)
                 {

+ 52 - 1
Gem/Code/Source/MeshExampleComponent.cpp

@@ -75,6 +75,8 @@ namespace AtomSampleViewer
                 // This handler will be connected to the feature processor so that when the model is updated, the camera
                 // controller will reset. This ensures the camera is a reasonable distance from the model when it resizes.
                 ResetCameraController();
+
+                UpdateGroundPlane();
             }
         };
     }
@@ -111,6 +113,10 @@ namespace AtomSampleViewer
 
         InitLightingPresets(true);
 
+        AZ::Data::Asset<AZ::RPI::MaterialAsset> groundPlaneMaterialAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::MaterialAsset>(DefaultPbrMaterialPath, AZ::RPI::AssetUtils::TraceLevel::Error);
+        m_groundPlaneMaterial = AZ::RPI::Material::FindOrCreate(groundPlaneMaterialAsset);
+        m_groundPlaneModelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/plane.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
+
         AZ::TickBus::Handler::BusConnect();
     }
 
@@ -124,10 +130,12 @@ namespace AtomSampleViewer
         m_modelBrowser.Deactivate();
 
         RemoveController();
-
+        
         GetMeshFeatureProcessor()->ReleaseMesh(m_meshHandle);
+        GetMeshFeatureProcessor()->ReleaseMesh(m_groundPlandMeshHandle);
 
         m_modelAsset = {};
+        m_groundPlaneModelAsset = {};
 
         m_materialOverrideInstance = nullptr;
 
@@ -146,6 +154,19 @@ namespace AtomSampleViewer
 
             modelNeedsUpdate |= ScriptableImGui::Checkbox("Enable Material Override", &m_enableMaterialOverride);
            
+            if (ScriptableImGui::Checkbox("Show Ground Plane", &m_showGroundPlane))
+            {
+                if (m_showGroundPlane)
+                {
+                    CreateGroundPlane();
+                    UpdateGroundPlane();
+                }
+                else
+                {
+                    RemoveGroundPlane();
+                }
+            }
+
             if (ScriptableImGui::Checkbox("Show Model Materials", &m_showModelMaterials))
             {
                 modelNeedsUpdate = true;
@@ -285,6 +306,36 @@ namespace AtomSampleViewer
             GetMeshFeatureProcessor()->SetMaterialAssignmentMap(m_meshHandle, m_materialOverrideInstance);
         }
     }
+    
+    void MeshExampleComponent::CreateGroundPlane()
+    {
+        m_groundPlandMeshHandle = GetMeshFeatureProcessor()->AcquireMesh(m_groundPlaneModelAsset, m_groundPlaneMaterial);
+    }
+
+    void MeshExampleComponent::UpdateGroundPlane()
+    {
+        if (m_groundPlandMeshHandle.IsValid())
+        {
+            AZ::Transform groundPlaneTransform = AZ::Transform::CreateIdentity();
+
+            AZ::Vector3 modelCenter;
+            float modelRadius;
+            m_modelAsset->GetAabb().GetAsSphere(modelCenter, modelRadius);
+
+            static const float GroundPlaneRelativeScale = 4.0f;
+            static const float GroundPlaneOffset = 0.01f;
+
+            groundPlaneTransform.SetScale(AZ::Vector3(GroundPlaneRelativeScale * modelRadius));
+            groundPlaneTransform.SetTranslation(AZ::Vector3(0.0f, 0.0f, m_modelAsset->GetAabb().GetMin().GetZ() - GroundPlaneOffset));
+
+            GetMeshFeatureProcessor()->SetTransform(m_groundPlandMeshHandle, groundPlaneTransform);
+        }
+    }
+
+    void MeshExampleComponent::RemoveGroundPlane()
+    {
+        GetMeshFeatureProcessor()->ReleaseMesh(m_groundPlandMeshHandle);
+    }
 
     void MeshExampleComponent::OnEntityDestruction(const AZ::EntityId& entityId)
     {

+ 10 - 0
Gem/Code/Source/MeshExampleComponent.h

@@ -52,6 +52,10 @@ namespace AtomSampleViewer
 
         void ModelChange();
 
+        void CreateGroundPlane();
+        void UpdateGroundPlane();
+        void RemoveGroundPlane();
+
         void UseArcBallCameraController();
         void UseNoClipCameraController();
         void RemoveController();
@@ -87,12 +91,18 @@ namespace AtomSampleViewer
         // be shown in the material list.
         bool m_showModelMaterials = false;
 
+        bool m_showGroundPlane = false;
+
         bool m_cameraControllerDisabled = false;
 
         AZ::Data::Instance<AZ::RPI::Material> m_materialOverrideInstance; //< Holds a copy of the material instance being used when m_enableMaterialOverride is true.
         AZ::Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle;
         AZ::Data::Asset<AZ::RPI::ModelAsset> m_modelAsset;
 
+        AZ::Data::Asset<AZ::RPI::ModelAsset> m_groundPlaneModelAsset;
+        AZ::Render::MeshFeatureProcessorInterface::MeshHandle m_groundPlandMeshHandle;
+        AZ::Data::Instance<AZ::RPI::Material> m_groundPlaneMaterial;
+
         ImGuiSidebar m_imguiSidebar;
         ImGuiMaterialDetails m_imguiMaterialDetails;
         ImGuiAssetBrowser m_materialBrowser;

+ 28 - 21
Gem/Code/Source/ParallaxMappingExampleComponent.cpp

@@ -28,6 +28,8 @@ namespace AtomSampleViewer
     static const char* ParallaxEnableName = "parallax.enable";
     static const char* PdoEnableName = "parallax.pdo";
     static const char* ParallaxFactorName = "parallax.factor";
+    static const char* ParallaxHeightOffsetName = "parallax.offset";
+    static const char* ParallaxShowClippingName = "parallax.showClipping";
     static const char* ParallaxAlgorithmName = "parallax.algorithm";
     static const char* ParallaxQualityName = "parallax.quality";
     static const char* ParallaxUvIndexName = "parallax.textureMapUv";
@@ -89,6 +91,8 @@ namespace AtomSampleViewer
         // Material index
         m_parallaxEnableIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxEnableName));
         m_parallaxFactorIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxFactorName));
+        m_parallaxOffsetIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxHeightOffsetName));
+        m_parallaxShowClippingIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxShowClippingName));
         m_parallaxAlgorithmIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxAlgorithmName));
         m_parallaxQualityIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxQualityName));
         m_parallaxUvIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxUvIndexName));
@@ -323,48 +327,53 @@ namespace AtomSampleViewer
                 ImGui::Text("Parallax Setting");
                 ImGui::Indent();
                 {
-                    bool parallaxEnableChanged = false;
-                    bool pdoEnableChanged = false;
-                    bool factorChanged = false;
-                    bool algorithmChanged = false;
-                    bool qualityChanged = false;
-                    bool uvChanged = false;
-
-                    parallaxEnableChanged = ScriptableImGui::Checkbox("Enable Parallax", &m_parallaxEnable);
-                    if (parallaxEnableChanged)
+                    if (ScriptableImGui::Checkbox("Enable Parallax", &m_parallaxEnable))
                     {
+                        parallaxSettingChanged = true;
                         m_parallaxMaterial->SetPropertyValue(m_parallaxEnableIndex, m_parallaxEnable);
                     }
 
                     if (m_parallaxEnable)
                     {
-                        pdoEnableChanged = ScriptableImGui::Checkbox("Enable Pdo", &m_pdoEnable);
-                        if (pdoEnableChanged)
+                        if (ScriptableImGui::Checkbox("Enable Pdo", &m_pdoEnable))
                         {
+                            parallaxSettingChanged = true;
                             m_parallaxMaterial->SetPropertyValue(m_pdoEnableIndex, m_pdoEnable);
                         }
 
-                        factorChanged = ScriptableImGui::SliderFloat("Factor", &m_parallaxFactor, 0.0f, 0.1f);
-                        if (factorChanged)
+                        if (ScriptableImGui::SliderFloat("Heightmap Scale", &m_parallaxFactor, 0.0f, 0.1f))
                         {
+                            parallaxSettingChanged = true;
                             m_parallaxMaterial->SetPropertyValue(m_parallaxFactorIndex, m_parallaxFactor);
                         }
+                        
+                        if (ScriptableImGui::SliderFloat("Offset", &m_parallaxOffset, -0.1f, 0.1f))
+                        {
+                            parallaxSettingChanged = true;
+                            m_parallaxMaterial->SetPropertyValue(m_parallaxOffsetIndex, m_parallaxOffset);
+                        }
+                        
+                        if (ScriptableImGui::Checkbox("Show Clipping", &m_parallaxShowClipping))
+                        {
+                            parallaxSettingChanged = true;
+                            m_parallaxMaterial->SetPropertyValue(m_parallaxShowClippingIndex, m_parallaxShowClipping);
+                        }
 
-                        algorithmChanged = ScriptableImGui::Combo("Algorithm", &m_parallaxAlgorithm, ParallaxAlgorithmList, AZ_ARRAY_SIZE(ParallaxAlgorithmList));
-                        if (algorithmChanged)
+                        if (ScriptableImGui::Combo("Algorithm", &m_parallaxAlgorithm, ParallaxAlgorithmList, AZ_ARRAY_SIZE(ParallaxAlgorithmList)))
                         {
+                            parallaxSettingChanged = true;
                             m_parallaxMaterial->SetPropertyValue(m_parallaxAlgorithmIndex, static_cast<uint32_t>(m_parallaxAlgorithm));
                         }
 
-                        qualityChanged = ScriptableImGui::Combo("Quality", &m_parallaxQuality, ParallaxQualityList, AZ_ARRAY_SIZE(ParallaxQualityList));
-                        if (qualityChanged)
+                        if (ScriptableImGui::Combo("Quality", &m_parallaxQuality, ParallaxQualityList, AZ_ARRAY_SIZE(ParallaxQualityList)))
                         {
+                            parallaxSettingChanged = true;
                             m_parallaxMaterial->SetPropertyValue(m_parallaxQualityIndex, static_cast<uint32_t>(m_parallaxQuality));
                         }
 
-                        uvChanged = ScriptableImGui::Combo("UV", &m_parallaxUv, ParallaxUvSetList, AZ_ARRAY_SIZE(ParallaxUvSetList));
-                        if (uvChanged)
+                        if (ScriptableImGui::Combo("UV", &m_parallaxUv, ParallaxUvSetList, AZ_ARRAY_SIZE(ParallaxUvSetList)))
                         {
+                            parallaxSettingChanged = true;
                             m_parallaxMaterial->SetPropertyValue(m_parallaxUvIndex, static_cast<uint32_t>(m_parallaxUv));
                             m_parallaxMaterial->SetPropertyValue(m_ambientOcclusionUvIndex, static_cast<uint32_t>(m_parallaxUv));
                             m_parallaxMaterial->SetPropertyValue(m_baseColorUvIndex, static_cast<uint32_t>(m_parallaxUv));
@@ -372,8 +381,6 @@ namespace AtomSampleViewer
                             m_parallaxMaterial->SetPropertyValue(m_roughnessUvIndex, static_cast<uint32_t>(m_parallaxUv));
                         }
                     }
-
-                    parallaxSettingChanged = parallaxEnableChanged || pdoEnableChanged || factorChanged || algorithmChanged || qualityChanged || uvChanged;
                 }
                 ImGui::Unindent();
             }

+ 4 - 0
Gem/Code/Source/ParallaxMappingExampleComponent.h

@@ -82,6 +82,8 @@ namespace AtomSampleViewer
 
         AZ::RPI::MaterialPropertyIndex m_parallaxEnableIndex;
         AZ::RPI::MaterialPropertyIndex m_parallaxFactorIndex;
+        AZ::RPI::MaterialPropertyIndex m_parallaxOffsetIndex;
+        AZ::RPI::MaterialPropertyIndex m_parallaxShowClippingIndex;
         AZ::RPI::MaterialPropertyIndex m_parallaxAlgorithmIndex;
         AZ::RPI::MaterialPropertyIndex m_parallaxQualityIndex;
         AZ::RPI::MaterialPropertyIndex m_parallaxUvIndex;
@@ -105,6 +107,8 @@ namespace AtomSampleViewer
         bool m_parallaxEnable = true;
         bool m_pdoEnable = true;
         float m_parallaxFactor = 0.05f;
+        float m_parallaxOffset = 0.0f;
+        bool m_parallaxShowClipping = false;
         // see StandardPbr.materialtype for the full enum list.
         int m_parallaxAlgorithm = 2; // POM
         int m_parallaxQuality = 2;   // High

+ 2 - 12
ShaderLib/raytracingscenesrg.srgi → Gem/Code/Source/Platform/Android/BakedShaderVariantExampleComponent_Traits_Platform.h

@@ -10,15 +10,5 @@
 *
 */
 
-#pragma once
-
-#include <Atom/Features/SrgSemantics.azsli>
-
-partial ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
-{
-/* Intentionally Empty. Helps define the SrgSemantic for RayTracingSceneSrg once.*/
-};
-
-#define AZ_COLLECTING_PARTIAL_SRGS
-#include <Atom/Feature/Common/Assets/ShaderResourceGroups/RayTracingSceneSrgAll.azsli>
-#undef AZ_COLLECTING_PARTIAL_SRGS
+// [ATOM-15361] Mobile pipeline uses no-msaa forward pass, need to differentiate this while getting the pass in the sample
+#define ATOMSAMPLEVIEWER_TRAIT_BAKED_SHADERVARIANT_SAMPLE_PASS_NAME     "ForwardPass"

+ 13 - 0
Gem/Code/Source/Platform/Linux/BakedShaderVariantExampleComponent_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_BAKED_SHADERVARIANT_SAMPLE_PASS_NAME     "ForwardMSAAPass"

+ 13 - 0
Gem/Code/Source/Platform/Mac/BakedShaderVariantExampleComponent_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_BAKED_SHADERVARIANT_SAMPLE_PASS_NAME     "ForwardMSAAPass"

+ 13 - 0
Gem/Code/Source/Platform/Windows/BakedShaderVariantExampleComponent_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_BAKED_SHADERVARIANT_SAMPLE_PASS_NAME     "ForwardMSAAPass"

+ 13 - 0
Gem/Code/Source/Platform/iOS/BakedShaderVariantExampleComponent_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_BAKED_SHADERVARIANT_SAMPLE_PASS_NAME     "ForwardMSAAPass"

+ 3 - 4
Gem/Code/Source/ShadowExampleComponent.cpp

@@ -219,10 +219,10 @@ namespace AtomSampleViewer
 
     AZ::Transform ShadowExampleComponent::GetTransformForLight(const uint32_t index) const
     {
-        constexpr float lightDist = 5.f;
+        constexpr float diskLightDist = 5.f;
         using namespace AZ;
         const float angle = m_positionalLightRotationAngle + index * Constants::TwoPi / 3;
-        const auto location = Vector3(lightDist * sinf(angle), lightDist * cosf(angle), m_positionalLightHeights[index]);
+        const auto location = Vector3(diskLightDist * sinf(angle), diskLightDist * cosf(angle), m_positionalLightHeights[index]);
         const auto transform = Transform::CreateLookAt(location, Vector3::CreateZero());
         return transform;
     }
@@ -501,7 +501,7 @@ namespace AtomSampleViewer
         ImGui::Indent();
         if (ImGui::CollapsingHeader("Directional Light", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
         {
-            ImGui::SliderFloat("Height##Directional", &m_directionalLightHeight, 1.f, 30.f, "%.1f", ImGuiSliderFlags_Logarithmic);
+            ScriptableImGui::SliderFloat("Height##Directional", &m_directionalLightHeight, 1.f, 30.f, "%.1f", ImGuiSliderFlags_Logarithmic);
 
             ScriptableImGui::Checkbox("Auto Rotation##Directional", &m_isDirectionalLightAutoRotate);
             ScriptableImGui::SliderAngle("Direction##Directional", &m_directionalLightRotationAngle, 0, 360);
@@ -650,7 +650,6 @@ namespace AtomSampleViewer
 
             ImGui::Spacing();
 
-
             ImGui::Text("Control Target");
             ScriptableImGui::RadioButton("Red", &m_controlTargetPositionalLightIndex, 0);
             ImGui::SameLine();

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

@@ -410,7 +410,7 @@ namespace AtomSampleViewer
             ScriptableImGui::SliderAngle("Pitch", &m_directionalLightPitch, -90.0f, 0.f);
             ScriptableImGui::SliderAngle("Yaw", &m_directionalLightYaw, 0.f, 360.f);
 
-            if (ScriptableImGui::SliderFloat("Intensity##directional", &m_directionalLightIntensity, 0.f, 20.f, "%.1f", 2.f))
+            if (ScriptableImGui::SliderFloat("Intensity##directional", &m_directionalLightIntensity, 0.f, 20.f, "%.1f", ImGuiSliderFlags_Logarithmic))
             {
                 AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux> lightColor(DirectionalLightColor * m_directionalLightIntensity);
                 m_directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, lightColor);
@@ -551,7 +551,7 @@ namespace AtomSampleViewer
                 UpdateDiskLightCount(diskLightCount);
             }
 
-            if (ScriptableImGui::SliderFloat("Intensity##spot", &m_diskLightIntensity, 0.f, 100000.f, "%.1f", 4.f))
+            if (ScriptableImGui::SliderFloat("Intensity##spot", &m_diskLightIntensity, 0.f, 100000.f, "%.1f", ImGuiSliderFlags_Logarithmic))
             {
                 for (const DiskLight& light : m_diskLights)
                 {

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

@@ -115,7 +115,7 @@ namespace AtomSampleViewer
 
         // Imgui limits slider range to half the natural range of the type
         float segmentCountFloat = static_cast<float>(config.m_segmentCount);
-        configWasModified |= ScriptableImGui::SliderFloat("Segments Per-Mesh", &segmentCountFloat, 2.0f, 2048.0f, "%.0f", 2.0f);
+        configWasModified |= ScriptableImGui::SliderFloat("Segments Per-Mesh", &segmentCountFloat, 2.0f, 2048.0f, "%.0f", ImGuiSliderFlags_Logarithmic);
         configWasModified |= ScriptableImGui::SliderInt("Vertices Per-Segment", &config.m_verticesPerSegment, 4, 2048);
         configWasModified |= ScriptableImGui::SliderInt("Bones Per-Mesh", &config.m_boneCount, 2, 256);
         configWasModified |= ScriptableImGui::SliderInt("Influences Per-Vertex", &config.m_influencesPerVertex, 1, 4);

+ 3 - 0
Scripts/ExpectedScreenshots/ParallaxTest/screenshot_10_offsetClippingSteep.png

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

+ 3 - 0
Scripts/ExpectedScreenshots/ParallaxTest/screenshot_8_offset.png

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

+ 3 - 0
Scripts/ExpectedScreenshots/ParallaxTest/screenshot_9_offsetClipping.png

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

+ 3 - 0
Scripts/ExpectedScreenshots/StandardPBR/012_parallax_pom_cutout.png

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

+ 7 - 1
Scripts/MaterialScreenshotTests.bv.lua

@@ -40,6 +40,9 @@ function GenerateMaterialScreenshot(imageComparisonThresholdLevel, materialName,
     if not (type(options.screenshotFilename) == "string") then
         options.screenshotFilename = materialName
     end
+    if not (type(options.showGroundPlane) == "boolean") then
+        options.showGroundPlane = false
+    end
 
     Print("MODEL: " .. options.model)
 
@@ -52,6 +55,8 @@ function GenerateMaterialScreenshot(imageComparisonThresholdLevel, materialName,
     else
         SetImguiValue('Lighting Preset##SampleBase/Neutral Urban (Alt)', true)
     end
+    
+    SetImguiValue('Show Ground Plane', options.showGroundPlane)
 
     -- The sample resets the camera position after loading the model and we need to
     -- make sure that happens before moving the camera below
@@ -109,6 +114,7 @@ GenerateMaterialScreenshot('Level G', '010_SpecularOcclusion', {lighting="Palerm
 GenerateMaterialScreenshot('Level G', '010_BothOcclusion', {lighting="Palermo Sidewalk (Alt)"})
 GenerateMaterialScreenshot('Level G', '011_Emissive')
 GenerateMaterialScreenshot('Level I', '012_Parallax_POM', {model=g_cubeModel, cameraHeading=-35.0, cameraPitch=35.0})
+GenerateMaterialScreenshot('Level I', '012_Parallax_POM_Cutout', {model=g_cubeModel, cameraHeading=-130.0, cameraPitch=35.0, cameraDistance=3.5, lighting="Goegap (Alt)", showGroundPlane=true})
 GenerateMaterialScreenshot('Level I', '013_SpecularAA_Off', {lighting="Dark Test Lighting"})
 GenerateMaterialScreenshot('Level J', '013_SpecularAA_On', {lighting="Dark Test Lighting"})
 GenerateMaterialScreenshot('Level G', '014_ClearCoat', {lighting="Neutral Urban"})
@@ -167,7 +173,7 @@ Print('Saving screenshots to ' .. NormalizePath(g_screenshotOutputFolder))
 
 -- We should eventually replace this with realistic skin test cases, these are just placeholders for regression testing
 GenerateMaterialScreenshot('Level D', '001_lucy_regression_test',    {model=g_modelLucy, cameraHeading=-26.0, cameraPitch=15.0, cameraDistance=2.0, cameraZ=0.7})
-GenerateMaterialScreenshot('Level E', '002_wrinkle_regression_test', {model=g_modelWithLayerMask, cameraHeading=-135.0, cameraPitch=15.0, cameraZ=-0.3, cameraDistance=3.5})
+GenerateMaterialScreenshot('Level G', '002_wrinkle_regression_test', {model=g_modelWithLayerMask, cameraHeading=-135.0, cameraPitch=15.0, cameraZ=-0.3, cameraDistance=3.5})
 
 ----------------------------------------------------------------------
 -- MinimalPBR Materials...

+ 49 - 12
Scripts/ParallaxTest.bv.lua

@@ -18,15 +18,16 @@ Print('Saving screenshots to ' .. NormalizePath(g_screenshotOutputFolder))
 OpenSample('Features/Parallax')
 ResizeViewport(1600, 900)
 SelectImageComparisonToleranceLevel("Level I")
+
+-- Test with PDO off...
 SetImguiValue('Lighting/Auto Rotation', false)
 SetImguiValue('Lighting/Direction', DegToRad(110))
-SetImguiValue('Parallax Setting/Factor', 0.05)
-
+SetImguiValue('Parallax Setting/Heightmap Scale', 0.05)
 SetImguiValue('Parallax Setting/Enable Pdo', false)
 IdleFrames(2)
--- Disable Pdo
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_1.png')
 
+-- Test alternate UV streams...
 -- Purpose of 2 shots
 -- First: regression test verifying using the 2nd UV is stable
 -- Second: diff test that compares UV0 (direct tangent) to UV1 (generated tangent), UV values are the same
@@ -38,13 +39,13 @@ CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_2ndUv_1.png')
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_2ndUv_2.png')
 SetImguiValue('Parallax Setting/UV', "UV0")
 
+-- Test with PDO on, also Plane rotated...
 SetImguiValue('Parallax Setting/Enable Pdo', true)
--- Plane rotate 45 degree
 SetImguiValue('Plane Setting/Rotation', DegToRad(45))
 IdleFrames(1)
--- Directional Light 0 degree, algorithm POM
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_2.png')
 
+-- Algorithm "Relief", also Directional Light at 120 degrees and uv parameters changed
 ArcBallCameraController_SetHeading(DegToRad(120))
 SetImguiValue('Parallax Setting/Algorithm', "Relief")
 SetImguiValue('Plane Setting/Center U', 0.8)
@@ -56,9 +57,9 @@ SetImguiValue('Plane Setting/Offset V', 0.6)
 SetImguiValue('Plane Setting/Rotation UV', 275)
 SetImguiValue('Plane Setting/Scale UV', 0.6)
 IdleFrames(1)
--- Directional Light 120 degree with uv parameter changed, algorithm Relief
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_3.png')
 
+-- Algorithm Contact Refinement, also Directional Light at 240 degrees with uv parameters changed again 
 ArcBallCameraController_SetHeading(DegToRad(240))
 SetImguiValue('Parallax Setting/Algorithm', "ContactRefinement")
 SetImguiValue('Plane Setting/Center U', -0.5)
@@ -70,19 +71,17 @@ SetImguiValue('Plane Setting/Offset V', -0.6)
 SetImguiValue('Plane Setting/Rotation UV', 138)
 SetImguiValue('Plane Setting/Scale UV', 1.6)
 IdleFrames(1)
--- Directional Light 240 degree with uv parameter changed, algorithm Contact Refinement
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_4.png')
 
-
+-- Algorithm "POM", switch to Spot Light 0 degree, also Plate rotated again 
 ArcBallCameraController_SetHeading(DegToRad(0))
 SetImguiValue('Lighting/Spot Light', true)
 SetImguiValue('Parallax Setting/Algorithm', "POM")
--- Plane rotate 135 degree
 SetImguiValue('Plane Setting/Rotation', DegToRad(135))
 IdleFrames(1)
--- Spot Light 0 degree, algorithm POM
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_5.png')
 
+-- Algorithm "Relief", also Spot Light rotated with uv parameters changed again
 ArcBallCameraController_SetHeading(DegToRad(120))
 SetImguiValue('Parallax Setting/Algorithm', "Relief")
 SetImguiValue('Plane Setting/Center U', -0.8)
@@ -94,9 +93,9 @@ SetImguiValue('Plane Setting/Offset V', 0.2)
 SetImguiValue('Plane Setting/Rotation UV', 125)
 SetImguiValue('Plane Setting/Scale UV', 0.3)
 IdleFrames(1)
--- Spot Light 120 degree with uv parameter changed, algorithm Relief
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_6.png')
 
+-- Algorithm "Contact Refinement" Spot Light rotated again, with uv parameter changed again
 ArcBallCameraController_SetHeading(DegToRad(240))
 SetImguiValue('Parallax Setting/Algorithm', "ContactRefinement")
 SetImguiValue('Plane Setting/Center U', 0.1)
@@ -108,7 +107,45 @@ SetImguiValue('Plane Setting/Offset V', -0.3)
 SetImguiValue('Plane Setting/Rotation UV', 74)
 SetImguiValue('Plane Setting/Scale UV', 1.3)
 IdleFrames(1)
--- Spot Light 240 degree with uv parameter changed, algorithm Contact Refinement
 CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_7.png')
 
+-- Test offset
+ArcBallCameraController_SetHeading(DegToRad(-135))
+ArcBallCameraController_SetPitch(DegToRad(-25))
+SetImguiValue('Lighting/Directional Light', true)
+SetImguiValue('Lighting/Direction', DegToRad(350))
+SetImguiValue('Parallax Setting/Heightmap Scale', 0.1)
+SetImguiValue('Parallax Setting/Offset', -0.1)
+IdleFrames(1)
+CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_8_offset.png')
+
+-- Test offset clipping
+ArcBallCameraController_SetPitch(DegToRad(-15)) -- Use a harsh angle as that could reveal artifacts we've seen in the past and fixed.
+SetImguiValue('Parallax Setting/Offset', 0.05)
+SetImguiValue('Parallax Setting/Show Clipping', true)
+IdleFrames(1)
+CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_9_offsetClipping.png')
+
+-- Testing a specific case where offset clamping was not calculated correctly, and clamped a bit below the surface instead of right on the surface.
+SetImguiValue('Parallax Setting/Offset', 0.06)
+SetImguiValue('Parallax Setting/Heightmap Scale', 0.1)
+SetImguiValue('Parallax Setting/Algorithm', "Steep")
+SetImguiValue('Parallax Setting/Show Clipping', true)
+CaptureScreenshot(g_screenshotOutputFolder .. '/screenshot_10_offsetClippingSteep.png')
+
+-- Test some different combinations that might result in divide-by-0 related crashes (which did happen at one point)
+SetImguiValue('Parallax Setting/Offset', 0.0)
+IdleFrames(1)
+SetImguiValue('Parallax Setting/Heightmap Scale', 0.01)
+IdleFrames(1)
+SetImguiValue('Parallax Setting/Heightmap Scale', 0.0)
+IdleFrames(1)
+SetImguiValue('Parallax Setting/Offset', 0.01)
+IdleFrames(1)
+SetImguiValue('Parallax Setting/Offset', -0.01)
+IdleFrames(1)
+ArcBallCameraController_SetPitch(DegToRad(0))
+IdleFrames(1)
+
+
 OpenSample(nil)

+ 2 - 2
Shaders/StaticMesh.azsl

@@ -133,7 +133,7 @@ PixelOutput MainPS(VertexOutput input)
             debugInfo);
     }
     
-    output.m_diffuse = float4(diffuse.rgb, baseColor.a);
-    output.m_specular = float4(specular.rgb, baseColor.a);
+    output.m_diffuse = float4(diffuse.rgb, saturate(baseColor.a));
+    output.m_specular = float4(specular.rgb, saturate(baseColor.a));
     return output;
 }

+ 2 - 2
Standalone/PythonTests/Automated/test_AtomSampleViewer_main_suite.py

@@ -34,7 +34,7 @@ class TestAutomationMainSuite:
     def test_AutomatedReviewTestSuite(self, request, workspace, launcher_platform, rhi, atomsampleviewer_log_monitor):
         # Script call setup.
         test_script = '_AutomatedReviewTestSuite_.bv.lua'
-        test_script_path = os.path.join(workspace.paths.engine_root(), 'AtomSampleViewer', 'Scripts', test_script)
+        test_script_path = os.path.join(workspace.paths.project(), 'Scripts', test_script)
         if not os.path.exists(test_script_path):
             raise AtomSampleViewerException(f'Test script does not exist in path: {test_script_path}')
         cmd = os.path.join(workspace.paths.build_directory(),
@@ -57,7 +57,7 @@ class TestAutomationMainSuite:
                 unexpected_lines=unexpected_lines, halt_on_unexpected=True, timeout=200)
         except ly_test_tools.log.log_monitor.LogMonitorException as e:
             expected_screenshots_path = os.path.join(
-                workspace.paths.engine_root(), "AtomSampleViewer", "Scripts", "ExpectedScreenshots")
+                workspace.paths.project(), "Scripts", "ExpectedScreenshots")
             test_screenshots_path = os.path.join(
                 workspace.paths.project(), "user", "Scripts", "Screenshots")
             raise AtomSampleViewerException(