From 9e8e08a8155e575fd42b2838cb3179227d813360 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Wed, 20 Oct 2021 14:10:11 -0700 Subject: [PATCH 01/22] Throwing up Depth of Field WIP so Galib can investigate AP crash with shader processing Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Common/Assets/Passes/NewDepthOfField.pass | 143 +++++++++++++ .../Passes/NewDepthOfFieldComposite.pass | 37 ++++ .../Passes/NewDepthOfFieldDownsample.pass | 72 +++++++ .../Passes/NewDepthOfFieldFilterLarge.pass | 62 ++++++ .../Passes/NewDepthOfFieldFilterSmall.pass | 62 ++++++ .../Assets/Passes/NewDepthOfFieldTile3x3.pass | 57 +++++ .../Passes/NewDepthOfFieldTileReduce.pass | 63 ++++++ .../Assets/Passes/PassTemplates.azasset | 28 +++ .../Assets/Passes/PostProcessParent.pass | 29 ++- .../Shaders/PostProcessing/DepthOfField.azsli | 8 + .../NewDepthOfFieldCommon.azsli | 29 +++ .../NewDepthOfFieldComposite.azsl | 80 +++++++ .../NewDepthOfFieldComposite.shader | 31 +++ .../NewDepthOfFieldDownsample.azsl | 100 +++++++++ .../NewDepthOfFieldDownsample.shader | 22 ++ .../NewDepthOfFieldFilterLarge.azsl | 50 +++++ .../NewDepthOfFieldFilterLarge.shader | 22 ++ .../NewDepthOfFieldFilterSmall.azsl | 74 +++++++ .../NewDepthOfFieldFilterSmall.shader | 22 ++ .../NewDepthOfFieldTile3x3.azsl | 66 ++++++ .../NewDepthOfFieldTile3x3.shader | 22 ++ .../NewDepthOfFieldTileReduce.azsl | 83 ++++++++ .../NewDepthOfFieldTileReduce.shader | 14 ++ .../atom_feature_common_asset_files.cmake | 73 +++++-- .../Code/Source/CommonSystemComponent.cpp | 9 + .../PostProcessing/NewDepthOfFieldPasses.cpp | 196 ++++++++++++++++++ .../PostProcessing/NewDepthOfFieldPasses.h | 117 +++++++++++ .../Code/Source/PostProcessing/TaaPass.cpp | 2 +- .../Code/atom_feature_common_files.cmake | 2 + .../Atom/RHI.Reflect/ShaderInputNameIndex.h | 4 + .../RHI.Reflect/ShaderInputNameIndex.cpp | 6 + .../RPI/Assets/ShaderLib/Atom/RPI/Math.azsli | 40 ++++ .../Atom/RPI.Public/Pass/PassAttachment.h | 8 +- .../Include/Atom/RPI.Public/Pass/RenderPass.h | 2 +- .../RPI.Reflect/Pass/PassAttachmentReflect.h | 7 + .../Source/RPI.Public/Pass/PassAttachment.cpp | 1 + .../Source/RPI.Public/Pass/RenderPass.cpp | 42 +++- .../Pass/PassAttachmentReflect.cpp | 3 +- 38 files changed, 1657 insertions(+), 31 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldComposite.pass create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldDownsample.pass create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterLarge.pass create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterSmall.pass create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTile3x3.pass create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTileReduce.pass create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.shader create mode 100644 Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp create mode 100644 Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass new file mode 100644 index 0000000000..e7c6a23c6c --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass @@ -0,0 +1,143 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "NewDepthOfFieldTemplate", + "PassClass": "NewDepthOfFieldParentPass", + "Slots": [ + { + "Name": "Depth", + "SlotType": "Input" + }, + { + "Name": "LightingBuffer", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "RenderTarget" + } + ], + "PassRequests": [ + { + "Name": "Downsample", + "TemplateName": "NewDepthOfFieldDownsampleTemplate", + + "Connections": [ + { + "LocalSlot": "ColorInput", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "LightingBuffer" + } + }, + { + "LocalSlot": "DepthInput", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "Depth" + } + } + ] + }, + { + "Name": "TileReduce", + "TemplateName": "NewDepthOfFieldTileReduceTemplate", + + "Connections": [ + { + "LocalSlot": "ColorAndCocInput", + "AttachmentRef": { + "Pass": "Downsample", + "Attachment": "OutputColorAndCoC" + } + } + ] + }, + { + "Name": "Tile3x3", + "TemplateName": "NewDepthOfFieldTile3x3Template", + + "Connections": [ + { + "LocalSlot": "Input", + "AttachmentRef": { + "Pass": "TileReduce", + "Attachment": "MinMaxCoC" + } + } + ] + }, + { + "Name": "LargeFilter", + "TemplateName": "NewDepthOfFieldFilterLargeTemplate", + + "Connections": [ + { + "LocalSlot": "ColorAndCoc", + "AttachmentRef": { + "Pass": "Downsample", + "Attachment": "OutputColorAndCoC" + } + }, + { + "LocalSlot": "CocTile", + "AttachmentRef": { + "Pass": "Tile3x3", + "Attachment": "Output" + } + } + ] + }, + { + "Name": "SmallFilter", + "TemplateName": "NewDepthOfFieldFilterSmallTemplate", + + "Connections": [ + { + "LocalSlot": "ColorAndCoc", + "AttachmentRef": { + "Pass": "LargeFilter", + "Attachment": "OutputColorAndCoc" + } + }, + { + "LocalSlot": "CocTile", + "AttachmentRef": { + "Pass": "Tile3x3", + "Attachment": "Output" + } + } + ] + }, + { + "Name": "Composite", + "TemplateName": "NewDepthOfFieldCompositeTemplate", + + "Connections": [ + { + "LocalSlot": "Depth", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "Depth" + } + }, + { + "LocalSlot": "HalfResColorAndCoC", + "AttachmentRef": { + "Pass": "SmallFilter", + "Attachment": "OutputColorAndCoc" + } + }, + { + "LocalSlot": "ColorInputOutput", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "LightingBuffer" + } + } + ] + } + ] + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldComposite.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldComposite.pass new file mode 100644 index 0000000000..522ae78fa5 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldComposite.pass @@ -0,0 +1,37 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "NewDepthOfFieldCompositeTemplate", + "PassClass": "FullScreenTriangle", + "Slots": [ + { + "Name": "Depth", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_fullResDimensions" + }, + { + "Name": "HalfResColorAndCoC", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_halfResDimensions" + }, + { + "Name": "ColorInputOutput", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "RenderTarget" + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/NewDepthOfFieldComposite.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldDownsample.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldDownsample.pass new file mode 100644 index 0000000000..2f1787c6cd --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldDownsample.pass @@ -0,0 +1,72 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "NewDepthOfFieldDownsampleTemplate", + "PassClass": "FullScreenTriangle", + "Slots": [ + { + "Name": "ColorInput", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_inputDimensions" + }, + { + "Name": "DepthInput", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ImageViewDesc": { + "AspectFlags": [ + "Depth" + ] + } + }, + { + "Name": "OutputColorAndCoC", + "SlotType": "Output", + "ScopeAttachmentUsage": "RenderTarget", + "ShaderImageDimensionsConstant": "m_outputDimensions", + "LoadStoreAction": { + "LoadAction": "Clear" + } + } + ], + "ImageAttachments": [ + { + "Name": "OutputAttachment", + "SizeSource": { + "Source": { + "Pass": "This", + "Attachment": "ColorInput" + }, + "Multipliers": { + "WidthMultiplier": 0.5, + "HeightMultiplier": 0.5 + } + }, + "ImageDescriptor": { + "Format": "R16G16B16A16_FLOAT" + } + } + ], + "Connections": [ + { + "LocalSlot": "OutputColorAndCoC", + "AttachmentRef": { + "Pass": "This", + "Attachment": "OutputAttachment" + } + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/NewDepthOfFieldDownsample.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterLarge.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterLarge.pass new file mode 100644 index 0000000000..7b40009cec --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterLarge.pass @@ -0,0 +1,62 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "NewDepthOfFieldFilterLargeTemplate", + "PassClass": "NewDepthOfFieldFilterPass", + "Slots": [ + { + "Name": "ColorAndCoc", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_textureDimensions" + }, + { + "Name": "CocTile", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader" + }, + { + "Name": "OutputColorAndCoc", + "SlotType": "Output", + "ScopeAttachmentUsage": "RenderTarget", + "LoadStoreAction": { + "LoadAction": "Clear" + } + } + ], + "ImageAttachments": [ + { + "Name": "OutputAttachment", + "SizeSource": { + "Source": { + "Pass": "This", + "Attachment": "ColorAndCoc" + } + }, + "ImageDescriptor": { + "Format": "R16G16B16A16_FLOAT" + } + } + ], + "Connections": [ + { + "LocalSlot": "OutputColorAndCoc", + "AttachmentRef": { + "Pass": "This", + "Attachment": "OutputAttachment" + } + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/NewDepthOfFieldFilterLarge.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterSmall.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterSmall.pass new file mode 100644 index 0000000000..35a658a3b1 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldFilterSmall.pass @@ -0,0 +1,62 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "NewDepthOfFieldFilterSmallTemplate", + "PassClass": "NewDepthOfFieldFilterPass", + "Slots": [ + { + "Name": "ColorAndCoc", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_textureDimensions" + }, + { + "Name": "CocTile", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader" + }, + { + "Name": "OutputColorAndCoc", + "SlotType": "Output", + "ScopeAttachmentUsage": "RenderTarget", + "LoadStoreAction": { + "LoadAction": "Clear" + } + } + ], + "ImageAttachments": [ + { + "Name": "OutputAttachment", + "SizeSource": { + "Source": { + "Pass": "This", + "Attachment": "ColorAndCoc" + } + }, + "ImageDescriptor": { + "Format": "R16G16B16A16_FLOAT" + } + } + ], + "Connections": [ + { + "LocalSlot": "OutputColorAndCoc", + "AttachmentRef": { + "Pass": "This", + "Attachment": "OutputAttachment" + } + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/NewDepthOfFieldFilterSmall.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTile3x3.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTile3x3.pass new file mode 100644 index 0000000000..93ae645c83 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTile3x3.pass @@ -0,0 +1,57 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "NewDepthOfFieldTile3x3Template", + "PassClass": "FullScreenTriangle", + "Slots": [ + { + "Name": "Input", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_textureDimensions" + }, + { + "Name": "Output", + "SlotType": "Output", + "ScopeAttachmentUsage": "RenderTarget", + "LoadStoreAction": { + "LoadAction": "Clear" + } + } + ], + "ImageAttachments": [ + { + "Name": "OutputAttachment", + "SizeSource": { + "Source": { + "Pass": "This", + "Attachment": "Input" + } + }, + "ImageDescriptor": { + "Format": "R16G16_SNORM" + } + } + ], + "Connections": [ + { + "LocalSlot": "Output", + "AttachmentRef": { + "Pass": "This", + "Attachment": "OutputAttachment" + } + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/NewDepthOfFieldTile3x3.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTileReduce.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTileReduce.pass new file mode 100644 index 0000000000..2bcf0ef32d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfFieldTileReduce.pass @@ -0,0 +1,63 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "NewDepthOfFieldTileReduceTemplate", + "PassClass": "NewDepthOfFieldTileReducePass", + "Slots": [ + { + "Name": "ColorAndCocInput", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_inputDimensions" + }, + { + "Name": "MinMaxCoC", + "SlotType": "Output", + "ScopeAttachmentUsage": "Shader", + "ShaderImageDimensionsConstant": "m_outputDimensions", + "LoadStoreAction": { + "LoadAction": "Clear" + } + } + ], + "ImageAttachments": [ + { + "Name": "MinMaxCoCAttachment", + "SizeSource": { + "Source": { + "Pass": "This", + "Attachment": "ColorAndCocInput" + }, + "Multipliers": { + // 1/16 = 0.0625 + "WidthMultiplier": 0.0625, + "HeightMultiplier": 0.0625 + } + }, + "ImageDescriptor": { + "Format": "R16G16_SNORM" + } + } + ], + "Connections": [ + { + "LocalSlot": "MinMaxCoC", + "AttachmentRef": { + "Pass": "This", + "Attachment": "MinMaxCoCAttachment" + } + } + ], + "PassData": { + "$type": "ComputePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/NewDepthOfFieldTileReduce.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset index 76285b00c7..355e930237 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset +++ b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset @@ -185,6 +185,34 @@ "Path": "Passes/DepthOfFieldWriteFocusDepthFromGpu.pass" }, { + "Name": "NewDepthOfFieldTemplate", + "Path": "Passes/NewDepthOfField.pass" + }, + { + "Name": "NewDepthOfFieldDownsampleTemplate", + "Path": "Passes/NewDepthOfFieldDownsample.pass" + }, + { + "Name": "NewDepthOfFieldTileReduceTemplate", + "Path": "Passes/NewDepthOfFieldTileReduce.pass" + }, + { + "Name": "NewDepthOfFieldTile3x3Template", + "Path": "Passes/NewDepthOfFieldTile3x3.pass" + }, + { + "Name": "NewDepthOfFieldFilterLargeTemplate", + "Path": "Passes/NewDepthOfFieldFilterLarge.pass" + }, + { + "Name": "NewDepthOfFieldFilterSmallTemplate", + "Path": "Passes/NewDepthOfFieldFilterSmall.pass" + }, + { + "Name": "NewDepthOfFieldCompositeTemplate", + "Path": "Passes/NewDepthOfFieldComposite.pass" + }, + { "Name": "EsmShadowmapsTemplate", "Path": "Passes/EsmShadowmaps.pass" }, diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass index fb27770da3..dc1c0f1664 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass @@ -112,20 +112,41 @@ } ] }, + //{ + // "Name": "DepthOfFieldPass", + // "TemplateName": "DepthOfFieldTemplate", + // "Enabled": true, + // "Connections": [ + // { + // "LocalSlot": "DoFColorInput", + // "AttachmentRef": { + // "Pass": "TaaPass", + // "Attachment": "OutputColor" + // } + // }, + // { + // "LocalSlot": "DoFDepthInput", + // "AttachmentRef": { + // "Pass": "Parent", + // "Attachment": "Depth" + // } + // } + // ] + //}, { "Name": "DepthOfFieldPass", - "TemplateName": "DepthOfFieldTemplate", + "TemplateName": "NewDepthOfFieldTemplate", "Enabled": true, "Connections": [ { - "LocalSlot": "DoFColorInput", + "LocalSlot": "LightingBuffer", "AttachmentRef": { "Pass": "TaaPass", "Attachment": "OutputColor" } }, { - "LocalSlot": "DoFDepthInput", + "LocalSlot": "Depth", "AttachmentRef": { "Pass": "Parent", "Attachment": "Depth" @@ -142,7 +163,7 @@ "LocalSlot": "InputOutput", "AttachmentRef": { "Pass": "DepthOfFieldPass", - "Attachment": "DoFOutput" + "Attachment": "LightingBuffer" } } ] diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfField.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfField.azsli index bc94b4a793..f4c396253f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfField.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfField.azsli @@ -14,6 +14,14 @@ inline float InvertDepth(float depth) return 1.0f - depth; } +inline float4 InvertDepth(float4 depth) +{ + // Convert depth from [1.0 - 0.0] to [0.0 - 1.0]. + // Set the front(near side) to 0.0 and the back(far side) to 1.0. + + return float4(1, 1, 1, 1) - depth; +} + inline float ConvertDofFactor(float depth, float far, float near, float focusDistance) { // dofFactor : The value Calculated from depth. diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli new file mode 100644 index 0000000000..fc98cee055 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli @@ -0,0 +1,29 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + +#include + +#define COC_EPSILON 0.0001 + +#define SAMPLES_LOOP_1 8 +#define SAMPLES_LOOP_2 16 +#define SAMPLES_LOOP_3 24 + +// Must match the struct in NewDepthOfFieldPasses.cpp +struct NewDepthOfFieldConstants +{ + float4 samplePositions[60]; // XY are sample positions (normalized so max lenght is 1) + // Z is the length of XY (0 - 1) + // W is unused + + +}; + + + diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl new file mode 100644 index 0000000000..8a766c71d9 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl @@ -0,0 +1,80 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include "NewDepthOfFieldCommon.azsli" +#include "DepthOfField.azsli" + +#include + +#define COC_EPSILON 0.0001 + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_depth; + Texture2D m_halfResColorAndCoc; + + // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + float4 m_fullResDimensions; + float4 m_halfResDimensions; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +PSOutput MainPS(VSOutput IN) +{ + // Sampling positions + float2 fullResPixelPos = IN.m_position.xy; + float2 halfResPixelPos = fullResPixelPos * 0.5f; + float2 fullResUV = fullResPixelPos * PassSrg::m_fullResDimensions.zw; + float2 halfResUV = halfResPixelPos * PassSrg::m_halfResDimensions.zw; + + // Full res CoC (Circle of Confusion) + float depth = PassSrg::m_depth.Sample(PassSrg::LinearSampler, fullResUV); + float far = ViewSrg::m_dof.m_cameraParameters.x; + float near = ViewSrg::m_dof.m_cameraParameters.y; + float focusDistance = ViewSrg::m_dof.m_cameraParameters.z; + float coc = ConvertDofFactor(InvertDepth(depth), far, near, focusDistance); + + // Calculate Alpha + float cocRadius = abs(coc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; + float maxPixelDist = max(PassSrg::m_halfResDimensions.z, PassSrg::m_halfResDimensions.w); + float alpha = saturate(0.25f * cocRadius / maxPixelDist); + + // Sample half res color and CoC + float4 colorAndCoC = PassSrg::m_halfResColorAndCoc.Sample(PassSrg::LinearSampler, halfResUV); + + + // Make out of focus foreground increasingly blue + float multiplier = saturate(1.0f + coc); + colorAndCoC.r *= multiplier; + colorAndCoC.g *= multiplier; + + // Make out of focus background increasingly red + multiplier = saturate(1.0f - coc); + colorAndCoC.b *= multiplier; + colorAndCoC.g *= multiplier; + + // Output + PSOutput OUT; + OUT.m_color.rgb = colorAndCoC.rgb; + OUT.m_color.a = alpha; + + return OUT; +} + diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.shader new file mode 100644 index 0000000000..f17837b330 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.shader @@ -0,0 +1,31 @@ +{ + "Source" : "NewDepthOfFieldComposite", + + "DepthStencilState" : + { + "Depth" : { "Enable" : false }, + "Stencil" : { "Enable" : false } + }, + + "BlendState" : { + "Enable" : true, + "BlendSource" : "AlphaSource", + "BlendDest" : "AlphaSourceInverse", + "BlendOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl new file mode 100644 index 0000000000..c8070178f0 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl @@ -0,0 +1,100 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include "NewDepthOfFieldCommon.azsli" +#include "DepthOfField.azsli" + +#include + +#define COC_EPSILON 0.0001 + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_colorTexture; + Texture2D m_depth; + + // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + float4 m_inputDimensions; + float4 m_outputDimensions; + + Sampler PointSampler + { + MinFilter = Point; + MagFilter = Point; + MipFilter = Point; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +PSOutput MainPS(VSOutput IN) +{ + // Sampling positions + float2 outputPixelPos = IN.m_position.xy; + float2 inputPixelPos = outputPixelPos * 2.0f; + float2 inputUV = inputPixelPos * PassSrg::m_inputDimensions.zw; + + // Gather Depth + float4 depthGather = PassSrg::m_depth.Gather(PassSrg::PointSampler, inputUV); + depthGather = InvertDepth(depthGather); + + // Calculate CoC (Circle of Confusion) + float far = ViewSrg::m_dof.m_cameraParameters.x; + float near = ViewSrg::m_dof.m_cameraParameters.y; + float focusDistance = ViewSrg::m_dof.m_cameraParameters.z; + + float4 cocGather; + cocGather.x = ConvertDofFactor(depthGather.x, far, near, focusDistance); + cocGather.y = ConvertDofFactor(depthGather.y, far, near, focusDistance); + cocGather.z = ConvertDofFactor(depthGather.z, far, near, focusDistance); + cocGather.w = ConvertDofFactor(depthGather.w, far, near, focusDistance); + + // Clamp CoC + cocGather = clamp(cocGather, -1.0f, 1.0f); + + // Weigh samles by CoC to avoid in foces pixels bleeding into bokeh effect + float4 weights = abs(cocGather) + COC_EPSILON; + weights = weights / (weights.x + weights.y + weights.z + weights.w); + + PSOutput OUT; + + // Red + float4 redGather = PassSrg::m_colorTexture.GatherRed(PassSrg::PointSampler, inputUV); + OUT.m_color.r = dot(redGather, weights); + + // Green + float4 greenGather = PassSrg::m_colorTexture.GatherGreen(PassSrg::PointSampler, inputUV); + OUT.m_color.g = dot(greenGather, weights); + + // Blue + float4 blueGather = PassSrg::m_colorTexture.GatherBlue(PassSrg::PointSampler, inputUV); + OUT.m_color.b = dot(blueGather, weights); + + // CoC - Take the CoC with the maximum absolute value (note CoC can be negative) to get the fullest bokeh effect + // The above weighting by CoC mitigates bokeh bleeding from taking the max CoC + float coc = cocGather.x; + coc = abs(coc) < abs(cocGather.y) ? cocGather.y : coc; + coc = abs(coc) < abs(cocGather.z) ? cocGather.z : coc; + coc = abs(coc) < abs(cocGather.w) ? cocGather.w : coc; + + // CoC weighting #2: we use linear sampling when we compute the CoC blur + // This can lead to in focus pixels bleeding into the bokeh blur + // Pre-multiply the color values by the CoC to avoid this type of bleeding + // Because we then re-multiply by the CoC value after the linear sampling, we want to avoid coc values of 0 + // See http://advances.realtimerendering.com/s2013/Sousa_Graphics_Gems_CryENGINE3.pptx + coc = abs(coc) > COC_EPSILON ? coc : -COC_EPSILON; + OUT.m_color.rgb *= abs(coc); + + OUT.m_color.a = coc; + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.shader new file mode 100644 index 0000000000..00aa89e6d8 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.shader @@ -0,0 +1,22 @@ +{ + "Source" : "NewDepthOfFieldDownsample", + + "DepthStencilState" : { + "Depth" : { "Enable" : false } + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl new file mode 100644 index 0000000000..e566db7880 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl @@ -0,0 +1,50 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "DepthOfField.azsli" +#include "NewDepthOfFieldCommon.azsli" + +#include + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_colorAndCoc; + Texture2D m_minMaxCocTile; + + float4 m_textureDimensions; + + NewDepthOfFieldConstants m_dofConstants; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +PSOutput MainPS(VSOutput IN) +{ + PSOutput OUT = (PSOutput)0; + + float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, IN.m_texCoord); + float3 centerColor = centerSample.rgb; + float centerCoc = centerSample.a; + + centerColor /= centerCoc; + + OUT.m_color.rgb = centerColor; + OUT.m_color.a = centerCoc; + return OUT; +} + diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.shader new file mode 100644 index 0000000000..8f6faedb76 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.shader @@ -0,0 +1,22 @@ +{ + "Source" : "NewDepthOfFieldFilterLarge", + + "DepthStencilState" : { + "Depth" : { "Enable" : false } + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl new file mode 100644 index 0000000000..dadaf57506 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl @@ -0,0 +1,74 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "DepthOfField.azsli" +#include "NewDepthOfFieldCommon.azsli" + +#include + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_colorAndCoc; + Texture2D m_minMaxCocTile; + + float4 m_textureDimensions; + + NewDepthOfFieldConstants m_dofConstants; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +float2 GetOffsetUV(uint index, float radiusMultiplier) +{ + return PassSrg::m_dofConstants.samplePositions[index] * radiusMultiplier * PassSrg::m_textureDimensions.zw; +} + +PSOutput MainPS(VSOutput IN) +{ + // UV of pixel being shaded + float2 pixelUV = IN.m_texCoord.xy; + + // Sample pixel being shaded + float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba; + float centerCoc = centerSample.a; + + // Color and weight accumulation + float3 color = centerSample.rgb; + float totalWeight = 1; + + // Sampling radius + float cocRadius = abs(centerCoc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; + cocRadius *= 0.5f; // This is the small filter, half the sampling radius + + for(uint i = 0; i < SAMPLES_LOOP_1; ++i) + { + float2 offsetUV = GetOffsetUV(i, cocRadius); + float4 sample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba; + float cocDiff = abs(sample.a - centerCoC); + float weight = saturate( 2 - (20 * cocDiff)); + color += sample.rgb * weight; + totalWeight += weight; + } + + // Output + PSOutput OUT; + OUT.m_color.rgb = color / totalWeight; + OUT.m_color.a = centerCoc; + return OUT; +} + diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.shader new file mode 100644 index 0000000000..d05e09be8f --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.shader @@ -0,0 +1,22 @@ +{ + "Source" : "NewDepthOfFieldFilterSmall", + + "DepthStencilState" : { + "Depth" : { "Enable" : false } + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl new file mode 100644 index 0000000000..7238b391aa --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl @@ -0,0 +1,66 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "NewDepthOfFieldCommon.azsli" + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_minMaxSource; + + // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + float4 m_textureDimensions; + + Sampler PointSampler + { + MinFilter = Point; + MagFilter = Point; + MipFilter = Point; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +struct PSOutput +{ + float2 m_color : SV_Target0; +}; + +PSOutput MainPS(VSOutput IN) +{ + // We want the min/max in a 3x3 region. Start sampling up left. + float2 startPixelPos = IN.m_position.xy - float2(1, 1); + + float2 stepSize = PassSrg::m_textureDimensions.zw; + float2 startUV = startPixelPos * stepSize; + + float cocMin = 1.0f; + float cocMax = -1.0f; + + // Gather min/max in 3x3 region + [unroll] + for(float Y = 0.0f; Y < 3.0f; Y += 1.0f) + { + [unroll] + for(float X = 0.0f; X < 3.0f; X += 1.0f) + { + float2 sampleUV = mad(float2(X, Y), stepSize, startUV); + float2 minMax = PassSrg::m_minMaxSource.SampleLevel(PassSrg::PointSampler, sampleUV, 0).xy; + + cocMin = min(cocMin, minMax.x); + cocMax = max(cocMax, minMax.y); + } + } + + PSOutput output; + output.m_color.x = cocMin; + output.m_color.y = cocMax; + return output; +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.shader new file mode 100644 index 0000000000..f7d9cc160e --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.shader @@ -0,0 +1,22 @@ +{ + "Source" : "NewDepthOfFieldTile3x3", + + "DepthStencilState" : { + "Depth" : { "Enable" : false } + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl new file mode 100644 index 0000000000..2705e1fdfd --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl @@ -0,0 +1,83 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "NewDepthOfFieldCommon.azsli" + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + // For this shader we're only interested in the CoC values, which are in the alpha channel + Texture2D m_colorAndCoC; + + // Tiled min/max CoC values + RWTexture2D m_minMaxCoC; + + // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + float4 m_inputDimensions; + float4 m_outputDimensions; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +groupshared uint LDS_MIN_COC[8]; +groupshared uint LDS_MAX_COC[8]; + +[numthreads(8, 8, 1)] +void MainCS(uint3 group_thread_id : SV_GroupThreadID, uint3 group_id : SV_GroupID, uint3 dispatch_id: SV_DispatchThreadID, uint linear_id : SV_GroupIndex) +{ + // Initialize groupshared mem for atomic min/max operations + if(group_thread_id.y == 0) + { + LDS_MIN_COC[group_thread_id.x] = 0xFFFFFFFF; + LDS_MAX_COC[group_thread_id.x] = 0; + } + + // We use gather to get 2x2 values at once, so thread samples are spaced 2 pixels apart (+1 so the sample position is in between the four pixels) + float2 samplePos = float2(dispatch_id.xy) * 2 + float2(1, 1); + float2 sampleUV = samplePos * PassSrg::m_inputDimensions.zw; + + // Gather CoC + float4 cocGather = PassSrg::m_colorAndCoC.GatherAlpha(PassSrg::LinearSampler, sampleUV); + float cocMin = min4(cocGather); + float cocMax = max4(cocGather); + + // For atomic min/max to work with uints, floating point values should be positive + // Map from [-1, 1] range to [0, 2] and cast as uint + InterlockedMin( LDS_MIN_COC[group_thread_id.x], asuint(cocMin + 1) ); + InterlockedMax( LDS_MAX_COC[group_thread_id.x], asuint(cocMax + 1) ); + + // Sync LDS + GroupMemoryBarrierWithGroupSync(); + + if(group_thread_id.y != 0) + { + return; + } + + InterlockedMin( LDS_MIN_COC[0], LDS_MIN_COC[group_thread_id.x] ); + InterlockedMax( LDS_MAX_COC[0], LDS_MAX_COC[group_thread_id.x] ); + + if(group_thread_id.x == 0) + { + // Unpack uints + cocMin = asfloat(LDS_MIN_COC[0]) - 1; + cocMax = asfloat(LDS_MAX_COC[0]) - 1; + + // Output min/max coc of 16x16 region + PassSrg::m_minMaxCoC[group_id.xy] = float2(cocMin, cocMax); + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.shader new file mode 100644 index 0000000000..f2da5305e5 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.shader @@ -0,0 +1,14 @@ +{ + "Source" : "NewDepthOfFieldTileReduce", + + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name" : "MainCS", + "type" : "Compute" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index 60614993b5..d1f94afe3c 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -1,9 +1,8 @@ # -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT # set(FILES @@ -86,7 +85,6 @@ set(FILES Passes/CascadedShadowmaps.pass Passes/CheckerboardResolveColor.pass Passes/CheckerboardResolveDepth.pass - Passes/HDRColorGrading.pass Passes/ContrastAdaptiveSharpening.pass Passes/ConvertToAcescg.pass Passes/DebugOverlayParent.pass @@ -144,6 +142,7 @@ set(FILES Passes/ForwardSubsurfaceMSAA.pass Passes/FullscreenCopy.pass Passes/FullscreenOutputOnly.pass + Passes/HDRColorGrading.pass Passes/ImGui.pass Passes/KawaseShadowBlur.pass Passes/LightAdaptationParent.pass @@ -160,8 +159,6 @@ set(FILES Passes/LuminanceHistogramGenerator.pass Passes/MainPipeline.pass Passes/MainPipelineRenderToTexture.pass - Passes/ThumbnailPipeline.pass - Passes/ThumbnailPipelineRenderToTexture.pass Passes/MeshMotionVector.pass Passes/ModulateTexture.pass Passes/MorphTarget.pass @@ -169,6 +166,13 @@ set(FILES Passes/MSAAResolveColor.pass Passes/MSAAResolveCustom.pass Passes/MSAAResolveDepth.pass + Passes/NewDepthOfField.pass + Passes/NewDepthOfFieldComposite.pass + Passes/NewDepthOfFieldDownsample.pass + Passes/NewDepthOfFieldFilterLarge.pass + Passes/NewDepthOfFieldFilterSmall.pass + Passes/NewDepthOfFieldTile3x3.pass + Passes/NewDepthOfFieldTileReduce.pass Passes/OpaqueParent.pass Passes/PostProcessParent.pass Passes/ProjectedShadowmaps.pass @@ -204,11 +208,17 @@ set(FILES Passes/SsaoParent.pass Passes/SubsurfaceScattering.pass Passes/Taa.pass + Passes/ThumbnailPipeline.pass + Passes/ThumbnailPipelineRenderToTexture.pass Passes/Transparent.pass Passes/TransparentParent.pass Passes/UI.pass Passes/UIParent.pass + Scripts/material_find_overrides_demo.lua Scripts/material_property_overrides_demo.lua + ShaderLib/3rdParty/Features/PostProcessing/KelvinToRgb.azsli + ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli + ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli ShaderLib/Atom/Features/BlendUtility.azsli ShaderLib/Atom/Features/IndirectRendering.azsli ShaderLib/Atom/Features/MatrixUtility.azsli @@ -217,6 +227,8 @@ set(FILES ShaderLib/Atom/Features/SphericalHarmonicsUtility.azsli ShaderLib/Atom/Features/SrgSemantics.azsli ShaderLib/Atom/Features/ColorManagement/TransformColor.azsli + ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCcToAcesCg.azsli + ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCgToAcesCc.azsli ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCg_To_LinearSrgb.azsli ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/Aces_To_AcesCg.azsli ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/CalculateLuminance_AcesCg.azsli @@ -224,8 +236,6 @@ set(FILES ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/LinearSrgb_To_AcesCg.azsli ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/LinearSrgb_To_Srgb.azsli ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/Srgb_To_LinearSrgb.azsli - ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCcToAcesCg.azsli - ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCgToAcesCc.azsli ShaderLib/Atom/Features/CoreLights/PhotometricValue.azsli ShaderLib/Atom/Features/Decals/DecalTextureUtil.azsli ShaderLib/Atom/Features/LightCulling/LightCullingShared.azsli @@ -282,18 +292,23 @@ set(FILES ShaderLib/Atom/Features/PostProcessing/GlyphData.azsli ShaderLib/Atom/Features/PostProcessing/GlyphRender.azsli ShaderLib/Atom/Features/PostProcessing/PostProcessUtil.azsli + ShaderLib/Atom/Features/PostProcessing/Shapers.azsli + ShaderLib/Atom/Features/RayTracing/RayTracingMaterialSrg.azsli + ShaderLib/Atom/Features/RayTracing/RayTracingMaterialUtils.azsli ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli + ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli + ShaderLib/Atom/Features/RayTracing/RayTracingSrgs.azsl + ShaderLib/Atom/Features/RayTracing/RayTracingSrgs.shader ShaderLib/Atom/Features/ScreenSpace/ScreenSpaceUtil.azsli ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli ShaderLib/Atom/Features/Shadow/JitterTablePcf.azsli ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli + ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli ShaderLib/Atom/Features/Shadow/Shadow.azsli ShaderLib/Atom/Features/Shadow/ShadowmapAtlasLib.azsli + ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli ShaderLib/Atom/Features/Vertex/VertexHelper.azsli - ShaderLib/3rdParty/Features/PostProcessing/KelvinToRgb.azsli - ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli - ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli ShaderResourceGroups/SceneSrg.azsli ShaderResourceGroups/SceneSrgAll.azsli ShaderResourceGroups/ViewSrg.azsli @@ -304,6 +319,8 @@ set(FILES ShaderResourceGroups/PostProcessing/SceneSrg.azsli ShaderResourceGroups/PostProcessing/ViewSrg.azsli ShaderResourceGroups/SkyBox/SceneSrg.azsli + Shaders/ForwardPassSrg.azsl + Shaders/ForwardPassSrg.shader Shaders/AuxGeom/AuxGeomObject.azsl Shaders/AuxGeom/AuxGeomObject.shader Shaders/AuxGeom/AuxGeomObjectLit.azsl @@ -318,14 +335,20 @@ set(FILES Shaders/Checkerboard/CheckerboardColorResolveCS.shader Shaders/Depth/DepthPass.azsl Shaders/Depth/DepthPass.shader + Shaders/Depth/DepthPassCommon.azsli + Shaders/Depth/DepthPassSkin.azsl + Shaders/Depth/DepthPassSkin.shader Shaders/Depth/DepthPassTransparentMax.shader Shaders/Depth/DepthPassTransparentMin.shader Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl Shaders/DiffuseGlobalIllumination/DiffuseComposite.shader + Shaders/DiffuseGlobalIllumination/DiffuseComposite_nomsaa.azsl Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.azsl Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.shader + Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen_nomsaa.azsl Shaders/DiffuseGlobalIllumination/DiffuseProbeGridDownsample.azsl Shaders/DiffuseGlobalIllumination/DiffuseProbeGridDownsample.shader + Shaders/DiffuseGlobalIllumination/DiffuseProbeGridDownsample_nomsaa.azsl Shaders/ImGui/ImGui.azsl Shaders/ImGui/ImGui.shader Shaders/LightCulling/LightCulling.azsl @@ -345,6 +368,9 @@ set(FILES Shaders/MotionVector/CameraMotionVector.shader Shaders/MotionVector/MeshMotionVector.azsl Shaders/MotionVector/MeshMotionVector.shader + Shaders/MotionVector/MeshMotionVectorCommon.azsli + Shaders/MotionVector/MeshMotionVectorSkin.azsl + Shaders/MotionVector/MeshMotionVectorSkin.shader Shaders/PostProcessing/AcesOutputTransformLut.azsl Shaders/PostProcessing/AcesOutputTransformLut.shader Shaders/PostProcessing/ApplyShaperLookupTable.azsl @@ -359,6 +385,8 @@ set(FILES Shaders/PostProcessing/BloomCompositeCS.shader Shaders/PostProcessing/BloomDownsampleCS.azsl Shaders/PostProcessing/BloomDownsampleCS.shader + Shaders/PostProcessing/ContrastAdaptiveSharpening.azsl + Shaders/PostProcessing/ContrastAdaptiveSharpening.shader Shaders/PostProcessing/ConvertToAcescg.azsl Shaders/PostProcessing/ConvertToAcescg.shader Shaders/PostProcessing/DepthDownsample.azsl @@ -415,6 +443,18 @@ set(FILES Shaders/PostProcessing/MSAAResolveCustom.shader Shaders/PostProcessing/MSAAResolveDepth.azsl Shaders/PostProcessing/MSAAResolveDepth.shader + Shaders/PostProcessing/NewDepthOfFieldComposite.azsl + Shaders/PostProcessing/NewDepthOfFieldComposite.shader + Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl + Shaders/PostProcessing/NewDepthOfFieldDownsample.shader + Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl + Shaders/PostProcessing/NewDepthOfFieldFilterLarge.shader + Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl + Shaders/PostProcessing/NewDepthOfFieldFilterSmall.shader + Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl + Shaders/PostProcessing/NewDepthOfFieldTile3x3.shader + Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl + Shaders/PostProcessing/NewDepthOfFieldTileReduce.shader Shaders/PostProcessing/OutputTransform.azsl Shaders/PostProcessing/OutputTransform.shader Shaders/PostProcessing/ScreenSpaceSubsurfaceScatteringCS.azsl @@ -431,13 +471,17 @@ set(FILES Shaders/PostProcessing/SMAAUtils.azsli Shaders/PostProcessing/SsaoCompute.azsl Shaders/PostProcessing/SsaoCompute.shader + Shaders/PostProcessing/Taa.azsl + Shaders/PostProcessing/Taa.shader Shaders/PostProcessing/UniformColor.azsl Shaders/PostProcessing/UniformColor.shader Shaders/Reflections/ReflectionCommon.azsli Shaders/Reflections/ReflectionComposite.azsl Shaders/Reflections/ReflectionComposite.shader + Shaders/Reflections/ReflectionComposite_nomsaa.azsl Shaders/Reflections/ReflectionGlobalFullscreen.azsl Shaders/Reflections/ReflectionGlobalFullscreen.shader + Shaders/Reflections/ReflectionGlobalFullscreen_nomsaa.azsl Shaders/Reflections/ReflectionProbeBlendWeight.azsl Shaders/Reflections/ReflectionProbeBlendWeight.shader Shaders/Reflections/ReflectionProbeRenderCommon.azsli @@ -466,6 +510,9 @@ set(FILES Shaders/Shadow/KawaseShadowBlur.shader Shaders/Shadow/Shadowmap.azsl Shaders/Shadow/Shadowmap.shader + Shaders/Shadow/ShadowmapCommon.azsli + Shaders/Shadow/ShadowmapSkin.azsl + Shaders/Shadow/ShadowmapSkin.shader Shaders/SkinnedMesh/LinearSkinningCS.azsl Shaders/SkinnedMesh/LinearSkinningCS.shader Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index 22c5f37ff8..a7891b7907 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -248,6 +249,14 @@ namespace AZ passSystem->AddPassCreator(Name("DepthOfFieldReadBackFocusDepthPass"), &DepthOfFieldReadBackFocusDepthPass::Create); passSystem->AddPassCreator(Name("DepthOfFieldWriteFocusDepthFromGpuPass"), &DepthOfFieldWriteFocusDepthFromGpuPass::Create); + passSystem->AddPassCreator(Name("NewDepthOfFieldParentPass"), &NewDepthOfFieldParentPass::Create); + passSystem->AddPassCreator(Name("NewDepthOfFieldTileReducePass"), &NewDepthOfFieldTileReducePass::Create); + passSystem->AddPassCreator(Name("NewDepthOfFieldFilterPass"), &NewDepthOfFieldFilterPass::Create); + passSystem->AddPassCreator(Name("NewDepthOfFieldCompositePass"), &NewDepthOfFieldCompositePass::Create); + + + + // Add FastDepthAwareBlur passes passSystem->AddPassCreator(Name("FastDepthAwareBlurHorPass"), &FastDepthAwareBlurHorPass::Create); passSystem->AddPassCreator(Name("FastDepthAwareBlurVerPass"), &FastDepthAwareBlurVerPass::Create); diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp new file mode 100644 index 0000000000..7b9e46f6b1 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include + +#include +#include +#include + +namespace AZ +{ + namespace Render + { + + // Must match the struct in NewDepthOfFieldCommon.azsli + struct NewDepthOfFieldConstants + { + static constexpr uint32_t numberOfLoops = 3; + static constexpr float loopCounts[] = { 8.0f, 16.0f, 24.0f }; + + AZStd::array m_samplePositions; // XY are sample positions (normalized so max lenght is 1) + // Z is the length of XY (0 - 1) + // W is unused + }; + + + // --- Depth of Field Parent Pass --- + + RPI::Ptr NewDepthOfFieldParentPass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew NewDepthOfFieldParentPass(descriptor); + return AZStd::move(pass); + } + + NewDepthOfFieldParentPass::NewDepthOfFieldParentPass(const RPI::PassDescriptor& descriptor) + : RPI::ParentPass(descriptor) + { } + + bool NewDepthOfFieldParentPass::IsEnabled() const + { + if (!ParentPass::IsEnabled()) + { + return false; + } + RPI::Scene* scene = GetScene(); + if (!scene) + { + return false; + } + PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor(); + AZ::RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView(); + if (!fp) + { + return false; + } + PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view); + if (!postProcessSettings) + { + return false; + } + DepthOfFieldSettings* dofSettings = postProcessSettings->GetDepthOfFieldSettings(); + return (dofSettings != nullptr) && dofSettings->GetEnabled(); + } + + void NewDepthOfFieldParentPass::FrameBeginInternal(FramePrepareParams params) + { + RPI::Scene* scene = GetScene(); + PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor(); + AZ::RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView(); + if (fp) + { + PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view); + if (postProcessSettings) + { + DepthOfFieldSettings* dofSettings = postProcessSettings->GetDepthOfFieldSettings(); + if (dofSettings) + { + dofSettings->SetValuesToViewSrg(view->GetShaderResourceGroup()); + } + } + } + + ParentPass::FrameBeginInternal(params); + } + + // --- Tile Reduce Pass --- + + RPI::Ptr NewDepthOfFieldTileReducePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew NewDepthOfFieldTileReducePass(descriptor); + return AZStd::move(pass); + } + + NewDepthOfFieldTileReducePass::NewDepthOfFieldTileReducePass(const RPI::PassDescriptor& descriptor) + : RPI::ComputePass(descriptor) + { + // Though this is a fullscreen pass, the algorithm used makes each thread output 3 blurred pixels, so + // it's not a 1-to-1 ratio and requires custom calculation of target thread counts + m_isFullscreenPass = false; + } + + void NewDepthOfFieldTileReducePass::FrameBeginInternal(FramePrepareParams params) + { + AZ_Assert(GetOutputCount() > 0, "NewDepthOfFieldTileReducePass: No output bindings!"); + RPI::PassAttachment* outputAttachment = GetOutputBinding(0).m_attachment.get(); + + AZ_Assert(outputAttachment != nullptr, "NewDepthOfFieldTileReducePass: Output binding has no attachment!"); + RHI::Size outputSize = outputAttachment->m_descriptor.m_image.m_size; + + // The algorithm outputs the min/max CoC values from a 16x16 region using 8x8 threads + u32 targetThreadCountX = outputSize.m_width * 8; + u32 targetThreadCountY = outputSize.m_height * 8; + SetTargetThreadCounts(targetThreadCountX, targetThreadCountY, 1); + + RPI::ComputePass::FrameBeginInternal(params); + } + + + + // --- Filter Pass --- + + RPI::Ptr NewDepthOfFieldFilterPass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew NewDepthOfFieldFilterPass(descriptor); + return AZStd::move(pass); + } + + NewDepthOfFieldFilterPass::NewDepthOfFieldFilterPass(const RPI::PassDescriptor& descriptor) + : RPI::FullscreenTrianglePass(descriptor) + { } + + void NewDepthOfFieldFilterPass::FrameBeginInternal(FramePrepareParams params) + { + NewDepthOfFieldConstants dofConstants; + + uint32_t sampleIndex = 0; + + for (uint32_t loop = 0; loop < NewDepthOfFieldConstants::numberOfLoops; ++loop) + { + float radius = (loop + 1.0f) / float(NewDepthOfFieldConstants::numberOfLoops); + float loopCount = NewDepthOfFieldConstants::loopCounts[loop]; + + for (float i = 0.0f; i < loopCount; ++i) + { + float angle = Constants::TwoPi * i / loopCount; + Vector2 pos = Vector2::CreateFromAngle(angle); + pos = pos * radius; + + dofConstants.m_samplePositions[sampleIndex][0] = pos.GetX(); + dofConstants.m_samplePositions[sampleIndex][1] = pos.GetY(); + dofConstants.m_samplePositions[sampleIndex][2] = radius; + dofConstants.m_samplePositions[sampleIndex][3] = 0.0f; + ++sampleIndex; + } + + } + + m_shaderResourceGroup->SetConstant(m_constantsIndex, dofConstants); + + // TODO HERE + RPI::FullscreenTrianglePass::FrameBeginInternal(params); + } + + + + // --- Composite Pass --- + + RPI::Ptr NewDepthOfFieldCompositePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew NewDepthOfFieldCompositePass(descriptor); + return AZStd::move(pass); + } + + NewDepthOfFieldCompositePass::NewDepthOfFieldCompositePass(const RPI::PassDescriptor& descriptor) + : RPI::ComputePass(descriptor) + { } + + void NewDepthOfFieldCompositePass::FrameBeginInternal(FramePrepareParams params) + { + // TODO HERE + RPI::ComputePass::FrameBeginInternal(params); + } + + + + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h new file mode 100644 index 0000000000..f7a0ee95ca --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include + +#include + +namespace AZ +{ + namespace Render + { + //! + class NewDepthOfFieldParentPass final + : public RPI::ParentPass + { + AZ_RPI_PASS(NewDepthOfFieldParentPass); + + public: + AZ_RTTI(AZ::Render::NewDepthOfFieldParentPass, "{71F4998B-447C-4BAC-A5BE-2D2850FABB57}", AZ::RPI::ParentPass); + AZ_CLASS_ALLOCATOR(NewDepthOfFieldParentPass, SystemAllocator, 0); + virtual ~NewDepthOfFieldParentPass() = default; + + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + bool IsEnabled() const override; + + protected: + // Behavior functions override... + void FrameBeginInternal(FramePrepareParams params) override; + + private: + NewDepthOfFieldParentPass(const RPI::PassDescriptor& descriptor); + }; + + + + //! + class NewDepthOfFieldTileReducePass final + : public RPI::ComputePass + { + AZ_RPI_PASS(NewDepthOfFieldTileReducePass); + + public: + AZ_RTTI(AZ::Render::NewDepthOfFieldTileReducePass, "{2E072695-0847-43A6-9BE4-D6D85CFFBA41}", AZ::RPI::ComputePass); + AZ_CLASS_ALLOCATOR(NewDepthOfFieldTileReducePass, SystemAllocator, 0); + virtual ~NewDepthOfFieldTileReducePass() = default; + + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + protected: + // Behavior functions override... + void FrameBeginInternal(FramePrepareParams params) override; + + private: + NewDepthOfFieldTileReducePass(const RPI::PassDescriptor& descriptor); + }; + + + + //! + class NewDepthOfFieldFilterPass final + : public RPI::FullscreenTrianglePass + { + AZ_RPI_PASS(NewDepthOfFieldFilterPass); + + public: + AZ_RTTI(AZ::Render::NewDepthOfFieldFilterPass, "{F8A98E53-1A50-4178-A6EB-2BD0148C038B}", AZ::RPI::FullscreenTrianglePass); + AZ_CLASS_ALLOCATOR(NewDepthOfFieldFilterPass, SystemAllocator, 0); + virtual ~NewDepthOfFieldFilterPass() = default; + + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + protected: + // Behavior functions override... + void FrameBeginInternal(FramePrepareParams params) override; + + private: + NewDepthOfFieldFilterPass(const RPI::PassDescriptor& descriptor); + + // SRG binding indices... + AZ::RHI::ShaderInputNameIndex m_constantsIndex = "m_dofConstants"; + }; + + + + //! + class NewDepthOfFieldCompositePass final + : public RPI::ComputePass + { + AZ_RPI_PASS(NewDepthOfFieldCompositePass); + + public: + AZ_RTTI(AZ::Render::NewDepthOfFieldCompositePass, "{63270A3A-EAE5-4C0C-98AA-43CA55279613}", AZ::RPI::ComputePass); + AZ_CLASS_ALLOCATOR(NewDepthOfFieldCompositePass, SystemAllocator, 0); + virtual ~NewDepthOfFieldCompositePass() = default; + + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + protected: + // Behavior functions override... + void FrameBeginInternal(FramePrepareParams params) override; + + private: + NewDepthOfFieldCompositePass(const RPI::PassDescriptor& descriptor); + }; + + + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp index 779f02cba0..643d9bb96d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp @@ -168,7 +168,7 @@ namespace AZ::Render // The ImageViewDescriptor must be specified to make sure the frame graph compiler doesn't treat this as a transient image. RHI::ImageViewDescriptor viewDesc = RHI::ImageViewDescriptor::Create(imageDesc.m_format, 0, 0); viewDesc.m_aspectFlags = RHI::ImageAspectFlags::Color; - viewDesc.m_overrideBindFlags = RHI::ImageBindFlags::ShaderReadWrite; + //viewDesc.m_overrideBindFlags = RHI::ImageBindFlags::ShaderReadWrite; // The full path name is needed for the attachment image so it's not deduplicated from accumulation images in different pipelines. AZStd::string imageName = RPI::ConcatPassString(GetPathName(), attachment->m_path); diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 18cdc273d2..23a67ef5db 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -240,6 +240,8 @@ set(FILES Source/PostProcessing/LookModificationTransformPass.h Source/PostProcessing/LuminanceHistogramGeneratorPass.h Source/PostProcessing/LuminanceHistogramGeneratorPass.cpp + Source/PostProcessing/NewDepthOfFieldPasses.cpp + Source/PostProcessing/NewDepthOfFieldPasses.h Source/PostProcessing/PostProcessingShaderOptionBase.cpp Source/PostProcessing/PostProcessingShaderOptionBase.h Source/PostProcessing/SMAABasePass.cpp diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ShaderInputNameIndex.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ShaderInputNameIndex.h index 03062afd52..5e9b1a9c77 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ShaderInputNameIndex.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ShaderInputNameIndex.h @@ -67,6 +67,10 @@ namespace AZ bool IsInitialized() const; void AssetInialized() const; + // Retrieves the underlying name. Should only be used for debug purposes like printing the name when we fail to bind to the SRG. + // All regular functionality should go through the above functions. + const Name& GetNameForDebug() const; + private: enum class IndexType : u32 diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ShaderInputNameIndex.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ShaderInputNameIndex.cpp index 2eb23895f8..b7ed2dbfe7 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ShaderInputNameIndex.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ShaderInputNameIndex.cpp @@ -227,5 +227,11 @@ namespace AZ } + const Name& ShaderInputNameIndex::GetNameForDebug() const + { + AZ_Assert(HasName(), "GetNameForDebug() called on ShaderInputNameIndex that doesn't have a name set. Please initialize it with a name.", m_name.GetCStr()); + return m_name; + } + } } diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli index 80f8a6cc36..6ffdb6e815 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli @@ -31,6 +31,8 @@ void swap(inout float a, inout float b) b = c; } +// ---------- Power ----------- + float Pow2(float x) { return x * x; @@ -48,6 +50,44 @@ float Pow5(float x) { return x * Pow4(x); } + +// ---------- Min & Max ----------- + +float min3(float a, float b, float c) +{ + return min(min(a, b), c); +} +float min4(float a, float b, float c, float d) +{ + return min(min3(a, b, c), d); +} +float max3(float a, float b, float c) +{ + return max(max(a, b), c); +} +float max4(float a, float b, float c, float d) +{ + return max(max3(a, b, c), d); +} + +float min3(float3 abc) +{ + return min3(abc.x, abc.y, abc.z); +} +float min4(float4 abcd) +{ + return min4(abcd.x, abcd.y, abcd.z, abcd.w); +} +float max3(float3 abc) +{ + return max3(abc.x, abc.y, abc.z); +} +float max4(float4 abcd) +{ + return max4(abcd.x, abcd.y, abcd.z, abcd.w); +} + + // ---------- Intersection ----------- // a simple ray sphere intersection function, didn't take limited precision diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassAttachment.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassAttachment.h index babcf752e9..d60a5a8064 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassAttachment.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassAttachment.h @@ -10,6 +10,8 @@ #include #include +#include + #include namespace AZ @@ -145,7 +147,11 @@ namespace AZ //! Name of the SRG member this binds to (see PassSlot::m_shaderInputName for more details) Name m_shaderInputName = Name("AutoBind"); - + + //! Name index of the SRG constant to which, if specified, we automatically calculate + //! and bind the image dimensions (if this binding is of type image) + RHI::ShaderInputNameIndex m_shaderImageDimensionsNameIndex; + //! Whether binding is an input, output or inputOutput PassSlotType m_slotType = PassSlotType::Uninitialized; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RenderPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RenderPass.h index cbff297021..5fb90d044e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RenderPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RenderPass.h @@ -119,7 +119,7 @@ namespace AZ private: // Helper function that binds a single attachment to the pass shader resource group - void BindAttachment(const RHI::FrameGraphCompileContext& context, const PassAttachmentBinding& binding, int16_t& imageIndex, int16_t& bufferIndex); + void BindAttachment(const RHI::FrameGraphCompileContext& context, PassAttachmentBinding& binding, int16_t& imageIndex, int16_t& bufferIndex); // Helper function to get the query by the scope index and query type RHI::Ptr GetQuery(ScopeQueryType queryType); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Pass/PassAttachmentReflect.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Pass/PassAttachmentReflect.h index 1131f2ff70..0de3676abe 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Pass/PassAttachmentReflect.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Pass/PassAttachmentReflect.h @@ -87,6 +87,13 @@ namespace AZ //! The keyword "NoBind" means the slot will not bind it's attachment to the SRG Name m_shaderInputName = Name("AutoBind"); + //! Name of the shader resource group constant (must be float4) to which the pass can automatically bind the following: + //! X component = image width + //! Y component = image height + //! Z component = 1 / image width + //! W component = 1 / image height + Name m_shaderImageDimensionsName; + //! This is to specify an array index if the shader input is an array. //! e.g. Texture2DMS m_color[4]; uint16_t m_shaderInputArrayIndex = 0; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp index e0831381e7..3b4f10a968 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassAttachment.cpp @@ -187,6 +187,7 @@ namespace AZ { m_name = slot.m_name; m_shaderInputName = slot.m_shaderInputName; + m_shaderImageDimensionsNameIndex = slot.m_shaderImageDimensionsName; m_shaderInputArrayIndex = slot.m_shaderInputArrayIndex; m_slotType = slot.m_slotType; m_scopeAttachmentUsage = slot.m_scopeAttachmentUsage; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp index 318ea7d11f..dad511def1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -272,15 +273,8 @@ namespace AZ } } - void RenderPass::BindAttachment(const RHI::FrameGraphCompileContext& context, const PassAttachmentBinding& binding, int16_t& imageIndex, int16_t& bufferIndex) + void RenderPass::BindAttachment(const RHI::FrameGraphCompileContext& context, PassAttachmentBinding& binding, int16_t& imageIndex, int16_t& bufferIndex) { - if (binding.m_shaderInputIndex == PassAttachmentBinding::ShaderInputNoBind || - binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::RenderTarget || - binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil) - { - return; - } - PassAttachment* attachment = binding.m_attachment.get(); if (attachment) { @@ -293,11 +287,39 @@ namespace AZ inputIndex = imageIndex; } const RHI::ImageView* imageView = context.GetImageView(attachment->GetAttachmentId(), binding.m_attachmentUsageIndex); - m_shaderResourceGroup->SetImageView(RHI::ShaderInputImageIndex(inputIndex), imageView, arrayIndex); - ++imageIndex; + + if (binding.m_shaderImageDimensionsNameIndex.HasName()) + { + RHI::Size size = attachment->m_descriptor.m_image.m_size; + + AZ::Vector4 imageDimensions; + imageDimensions.SetX(float(size.m_width)); + imageDimensions.SetY(float(size.m_height)); + imageDimensions.SetZ(1.0f / float(size.m_width)); + imageDimensions.SetW(1.0f / float(size.m_height)); + + bool success = m_shaderResourceGroup->SetConstant(binding.m_shaderImageDimensionsNameIndex, imageDimensions); + AZ_Assert(success, "Pass [%s] Could not find float4 constant [%s] in Shader Resource Group [%s]", + GetPathName().GetCStr(), + binding.m_shaderImageDimensionsNameIndex.GetNameForDebug().GetCStr(), + m_shaderResourceGroup->GetDatabaseName()); + } + + if (binding.m_shaderInputIndex != PassAttachmentBinding::ShaderInputNoBind && + binding.m_scopeAttachmentUsage != RHI::ScopeAttachmentUsage::RenderTarget && + binding.m_scopeAttachmentUsage != RHI::ScopeAttachmentUsage::DepthStencil) + { + m_shaderResourceGroup->SetImageView(RHI::ShaderInputImageIndex(inputIndex), imageView, arrayIndex); + ++imageIndex; + } } else if (attachment->GetAttachmentType() == RHI::AttachmentType::Buffer) { + if (binding.m_shaderInputIndex == PassAttachmentBinding::ShaderInputNoBind) + { + return; + } + if (inputIndex == PassAttachmentBinding::ShaderInputAutoBind) { inputIndex = bufferIndex; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Pass/PassAttachmentReflect.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Pass/PassAttachmentReflect.cpp index 39be08d299..602793ba19 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Pass/PassAttachmentReflect.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Pass/PassAttachmentReflect.cpp @@ -56,9 +56,10 @@ namespace AZ ; serializeContext->Class() - ->Version(1) + ->Version(2) ->Field("Name", &PassSlot::m_name) ->Field("ShaderInputName", &PassSlot::m_shaderInputName) + ->Field("ShaderImageDimensionsConstant", &PassSlot::m_shaderImageDimensionsName) ->Field("ShaderInputArrayIndex", &PassSlot::m_shaderInputArrayIndex) ->Field("SlotType", &PassSlot::m_slotType) ->Field("ScopeAttachmentUsage", &PassSlot::m_scopeAttachmentUsage) From d04d9883bc3c3f5b63ea1bb99725ee715969d002 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 21 Oct 2021 00:42:48 -0700 Subject: [PATCH 02/22] New Depth Of Field working quite well with a small amount of artefacts Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Common/Assets/Passes/NewDepthOfField.pass | 16 ++- .../NewDepthOfFieldCommon.azsli | 2 + .../NewDepthOfFieldComposite.azsl | 23 ++-- .../NewDepthOfFieldDownsample.azsl | 2 +- .../NewDepthOfFieldFilterLarge.azsl | 97 ++++++++++++++-- ...epthOfFieldFilterLarge.azsl~RF1bf9782e.TMP | 105 ++++++++++++++++++ .../NewDepthOfFieldFilterSmall.azsl | 36 ++++-- 7 files changed, 251 insertions(+), 30 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass index e7c6a23c6c..483ce0e49a 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass @@ -67,6 +67,20 @@ } ] }, + { + "Name": "Tile5x5", + "TemplateName": "NewDepthOfFieldTile3x3Template", + + "Connections": [ + { + "LocalSlot": "Input", + "AttachmentRef": { + "Pass": "Tile3x3", + "Attachment": "Output" + } + } + ] + }, { "Name": "LargeFilter", "TemplateName": "NewDepthOfFieldFilterLargeTemplate", @@ -82,7 +96,7 @@ { "LocalSlot": "CocTile", "AttachmentRef": { - "Pass": "Tile3x3", + "Pass": "Tile5x5", "Attachment": "Output" } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli index fc98cee055..a789537819 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli @@ -15,6 +15,8 @@ #define SAMPLES_LOOP_2 16 #define SAMPLES_LOOP_3 24 +#define SAMPLES_LOOP_TOTAL 48 + // Must match the struct in NewDepthOfFieldPasses.cpp struct NewDepthOfFieldConstants { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl index 8a766c71d9..14bc0d3b18 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl @@ -54,22 +54,25 @@ PSOutput MainPS(VSOutput IN) // Calculate Alpha float cocRadius = abs(coc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; float maxPixelDist = max(PassSrg::m_halfResDimensions.z, PassSrg::m_halfResDimensions.w); - float alpha = saturate(0.25f * cocRadius / maxPixelDist); + float alpha = saturate(cocRadius / maxPixelDist); // Sample half res color and CoC float4 colorAndCoC = PassSrg::m_halfResColorAndCoc.Sample(PassSrg::LinearSampler, halfResUV); - // Make out of focus foreground increasingly blue - float multiplier = saturate(1.0f + coc); - colorAndCoC.r *= multiplier; - colorAndCoC.g *= multiplier; + if(false) + { + // Make out of focus foreground increasingly blue + float multiplier = saturate(1.0f + coc); + colorAndCoC.r *= multiplier; + colorAndCoC.g *= multiplier; + + // Make out of focus background increasingly red + multiplier = saturate(1.0f - coc); + colorAndCoC.b *= multiplier; + colorAndCoC.g *= multiplier; + } - // Make out of focus background increasingly red - multiplier = saturate(1.0f - coc); - colorAndCoC.b *= multiplier; - colorAndCoC.g *= multiplier; - // Output PSOutput OUT; OUT.m_color.rgb = colorAndCoC.rgb; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl index c8070178f0..d9972b8400 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl @@ -93,8 +93,8 @@ PSOutput MainPS(VSOutput IN) // See http://advances.realtimerendering.com/s2013/Sousa_Graphics_Gems_CryENGINE3.pptx coc = abs(coc) > COC_EPSILON ? coc : -COC_EPSILON; OUT.m_color.rgb *= abs(coc); - OUT.m_color.a = coc; + return OUT; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl index e566db7880..497d73444b 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl @@ -31,20 +31,103 @@ ShaderResourceGroup PassSrg : SRG_PerPass AddressV = Clamp; AddressW = Clamp; }; + + Sampler PointSampler + { + MinFilter = Point; + MagFilter = Point; + MipFilter = Point; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +float3 GetOffsetUV(uint index, float2 offsetMultiplier) +{ + float3 offset = PassSrg::m_dofConstants.samplePositions[index].xyz; + offset.xy *= offsetMultiplier; + return offset; +} + +float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc) +{ + // The maximum distance for which samples are valid is the min of the sample CoC and the center CoC + float maxRadius = abs(min(sampleCoc, centerCoc)); + + // radius = samplingRadius * offsetRadius; + // falloff = maxRadius - radius; + // weight = 1 + (4 * falloff) + float falloff = mad(-samplingRadius, offsetRadius, maxRadius); + float weight = saturate(mad(4, falloff, 1)); + return weight; } PSOutput MainPS(VSOutput IN) { - PSOutput OUT = (PSOutput)0; + // Get center sample + float2 pixelUV = IN.m_texCoord; + float4 color = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba; + float centerCoc = color.a; + + // Get tile min and max + int2 tile = int2(IN.m_position.xy) / 16; + float minCoc = PassSrg::m_minMaxCocTile[tile].x; + + // Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w + float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w; + + // Sampling radius + float cocRadius = max( abs(centerCoc), -minCoc); + float screenRadius = cocRadius * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; + float2 offsetMultiplier = float2(screenRadius / aspectRatio, screenRadius); - float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, IN.m_texCoord); - float3 centerColor = centerSample.rgb; - float centerCoc = centerSample.a; - centerColor /= centerCoc; + float4 backgroundColor = float4(0, 0, 0, 0); + + { + float backgroundMin = min(0, centerCoc); + color.rgb /= abs(color.a); + color.a = 1; + + for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i) + { + // Calculate sample offset + float3 offset = GetOffsetUV(i, offsetMultiplier); + + // Get sample + float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offset.xy).rgba; + sampleColorCoc.rgb /= abs(sampleColorCoc.a); + + // Calculate weight for sample + float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); + sampleColorCoc.rgb *= weight; + + bool isBackground = (sampleColorCoc.a < backgroundMin); + + // We accumulate weight in alpha channel of color and backgroundColor + sampleColorCoc.a = weight; + + // Accumulate + backgroundColor += isBackground * sampleColorCoc; + color += !isBackground * sampleColorCoc; + } + } + + float backgroundRatio = backgroundColor.a / float(SAMPLES_LOOP_TOTAL); + float alpha = backgroundRatio > abs(centerCoc) ? -backgroundRatio : centerCoc; + + color.rgb /= max(color.a, COC_EPSILON); + backgroundColor.rgb /= max(backgroundColor.a, COC_EPSILON); + + color = color * saturate(1 - backgroundRatio) + backgroundColor * backgroundRatio; + //color.rgb += backgroundColor.rgb; + - OUT.m_color.rgb = centerColor; - OUT.m_color.a = centerCoc; + + PSOutput OUT = (PSOutput)0; + OUT.m_color.rgb = color.rgb; + OUT.m_color.a = alpha; return OUT; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP new file mode 100644 index 0000000000..7c0f32381b --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP @@ -0,0 +1,105 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "DepthOfField.azsli" +#include "NewDepthOfFieldCommon.azsli" + +#include + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_colorAndCoc; + Texture2D m_minMaxCocTile; + + float4 m_textureDimensions; + + NewDepthOfFieldConstants m_dofConstants; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +float2 GetOffsetUV(uint index, float2 offsetMultiplier) +{ + return PassSrg::m_dofConstants.samplePositions[index].xy * offsetMultiplier; +} + +PSOutput MainPS(VSOutput IN) +{ + // Get center sample + float2 pixelUV = IN.m_texCoord; + float4 color = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba; + float centerCoc = color.a; + + // Get tile min and max + int2 tile = int2(IN.m_position.xy) / 16; + float minCoc = PassSrg::m_minMaxCocTile[tile].x; + + // Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w + float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w; + + // Sampling radius + float cocRadius = max( abs(centerCoc), -minCoc); + cocRadius *= ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; + float2 offsetMultiplier = float2(cocRadius / aspectRatio, cocRadius); + + + + float4 negColor = float4(0, 0, 0, 0); + + { + float negMin = min(0, centerCoc); + color.rgb /= abs(color.a); + color.a = 1; + + for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i) + { + // Calculate sample offset + float2 offsetUV = GetOffsetUV(i, offsetMultiplier); + + // Get sample + float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba; + + // Calculate weight and adjust sample + float cocDiff = sampleColorCoc.a - centerCoc; + float weight = saturate( 2 - (20 * cocDiff)); + sampleColorCoc.rgb *= (weight / abs(sampleColorCoc.a)); + // + // bool isNeg = (sampleColorCoc.a < negMin); + // sampleColorCoc.a = weight; + // + // // Accumulate + // negColor += isNeg * sampleColorCoc; + // color += !isNeg * sampleColorCoc; + } + } + + float negRatio = negColor.a / float(SAMPLES_LOOP_TOTAL); + float alpha = negRatio > abs(centerCoc) ? -negRatio : centerCoc; + + color = color * saturate(1 - negRatio) + negColor; + color.rgb /= max(color.a, COC_EPSILON); + color.rgb += negColor.rgb; + + //float alpha = 1.0f; + + PSOutput OUT = (PSOutput)0; + OUT.m_color.rgb = color.rgb; + OUT.m_color.a = alpha; + return OUT; +} + diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl index dadaf57506..440701ded9 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl @@ -33,9 +33,9 @@ ShaderResourceGroup PassSrg : SRG_PerPass }; } -float2 GetOffsetUV(uint index, float radiusMultiplier) +float2 GetOffsetUV(uint index, float2 offsetMultiplier) { - return PassSrg::m_dofConstants.samplePositions[index] * radiusMultiplier * PassSrg::m_textureDimensions.zw; + return PassSrg::m_dofConstants.samplePositions[index].xy * offsetMultiplier; } PSOutput MainPS(VSOutput IN) @@ -47,27 +47,41 @@ PSOutput MainPS(VSOutput IN) float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba; float centerCoc = centerSample.a; - // Color and weight accumulation - float3 color = centerSample.rgb; - float totalWeight = 1; + // Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w + float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w; // Sampling radius float cocRadius = abs(centerCoc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; cocRadius *= 0.5f; // This is the small filter, half the sampling radius + float2 offsetMultiplier = float2(cocRadius / aspectRatio, cocRadius); - for(uint i = 0; i < SAMPLES_LOOP_1; ++i) + // Color and weight accumulation + float3 color = centerSample.rgb; + float totalWeight = 1; + + for(uint i = 0; i < 8; ++i) { - float2 offsetUV = GetOffsetUV(i, cocRadius); - float4 sample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba; - float cocDiff = abs(sample.a - centerCoC); + // Calculate sample offset + float2 offsetUV = GetOffsetUV(i, offsetMultiplier); + + // Get sample + float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba; + + // Calculate weight + float cocDiff = sampleColorCoc.a - centerCoc; float weight = saturate( 2 - (20 * cocDiff)); - color += sample.rgb * weight; + + // Accumulate sample and weight + color += sampleColorCoc.rgb * weight; totalWeight += weight; } + // Normalize accumulated sample + color /= totalWeight; + // Output PSOutput OUT; - OUT.m_color.rgb = color / totalWeight; + OUT.m_color.rgb = color; OUT.m_color.a = centerCoc; return OUT; } From 60148ccc3975bf8bcd1f18fe3298d04a530ef135 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 21 Oct 2021 01:23:43 -0700 Subject: [PATCH 03/22] New Depth of Field - Minor improvements, optimizations, and now works with auto focus Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Common/Assets/Passes/NewDepthOfField.pass | 13 +++++++++ .../NewDepthOfFieldFilterLarge.azsl | 28 +++++++++++++++---- .../NewDepthOfFieldFilterSmall.azsl | 15 ++++++++-- .../PostProcessing/NewDepthOfFieldPasses.cpp | 8 ++++++ 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass index 483ce0e49a..70cebab5a1 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/NewDepthOfField.pass @@ -18,6 +18,19 @@ } ], "PassRequests": [ + { + "Name": "AutoFocus", + "TemplateName": "DepthOfFieldReadBackFocusDepthTemplate", + "Connections": [ + { + "LocalSlot": "DepthInput", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "Depth" + } + } + ] + }, { "Name": "Downsample", "TemplateName": "NewDepthOfFieldDownsampleTemplate", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl index 497d73444b..6ab47b14ea 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl @@ -85,6 +85,24 @@ PSOutput MainPS(VSOutput IN) float4 backgroundColor = float4(0, 0, 0, 0); + if(minCoc >= 0) + { + for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i) + { + // Calculate sample offset + float3 offset = GetOffsetUV(i, offsetMultiplier); + + // Get sample + float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offset.xy).rgba; + + // Calculate weight for sample + float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); + + // Accumulate + color += weight * sampleColorCoc; + } + } + else { float backgroundMin = min(0, centerCoc); color.rgb /= abs(color.a); @@ -112,17 +130,15 @@ PSOutput MainPS(VSOutput IN) backgroundColor += isBackground * sampleColorCoc; color += !isBackground * sampleColorCoc; } + + backgroundColor.rgb /= max(backgroundColor.a, COC_EPSILON); } - float backgroundRatio = backgroundColor.a / float(SAMPLES_LOOP_TOTAL); + float backgroundRatio = saturate( backgroundColor.a / float(SAMPLES_LOOP_TOTAL) ); float alpha = backgroundRatio > abs(centerCoc) ? -backgroundRatio : centerCoc; color.rgb /= max(color.a, COC_EPSILON); - backgroundColor.rgb /= max(backgroundColor.a, COC_EPSILON); - - color = color * saturate(1 - backgroundRatio) + backgroundColor * backgroundRatio; - //color.rgb += backgroundColor.rgb; - + color = lerp(color, backgroundColor, backgroundRatio); PSOutput OUT = (PSOutput)0; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl index 440701ded9..05227cfee7 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl @@ -31,6 +31,16 @@ ShaderResourceGroup PassSrg : SRG_PerPass AddressV = Clamp; AddressW = Clamp; }; + + Sampler PointSampler + { + MinFilter = Point; + MagFilter = Point; + MipFilter = Point; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; } float2 GetOffsetUV(uint index, float2 offsetMultiplier) @@ -44,7 +54,7 @@ PSOutput MainPS(VSOutput IN) float2 pixelUV = IN.m_texCoord.xy; // Sample pixel being shaded - float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba; + float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV).rgba; float centerCoc = centerSample.a; // Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w @@ -65,7 +75,7 @@ PSOutput MainPS(VSOutput IN) float2 offsetUV = GetOffsetUV(i, offsetMultiplier); // Get sample - float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba; + float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offsetUV).rgba; // Calculate weight float cocDiff = sampleColorCoc.a - centerCoc; @@ -85,4 +95,3 @@ PSOutput MainPS(VSOutput IN) OUT.m_color.a = centerCoc; return OUT; } - diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp index 7b9e46f6b1..b69484297a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp @@ -149,6 +149,14 @@ namespace AZ float radius = (loop + 1.0f) / float(NewDepthOfFieldConstants::numberOfLoops); float loopCount = NewDepthOfFieldConstants::loopCounts[loop]; + float angleOffset = 0; + + // Every other loop slightly rotate sample ring so they don't line up + if (loop & 1) + { + angleOffset = Constants::TwoPi * 0.5f / loopCount; + } + for (float i = 0.0f; i < loopCount; ++i) { float angle = Constants::TwoPi * i / loopCount; From 6642850c02d17dc8accfb6636200e2c596d698a9 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 21 Oct 2021 04:44:26 -0700 Subject: [PATCH 04/22] Cleaned up new Depth of Field, ready for PR Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../NewDepthOfFieldCommon.azsli | 4 - .../NewDepthOfFieldComposite.azsl | 80 ++++++++++++++----- .../NewDepthOfFieldFilterLarge.azsl | 44 +++++++--- .../NewDepthOfFieldFilterSmall.azsl | 63 ++++++++++----- .../NewDepthOfFieldTile3x3.azsl | 7 +- .../NewDepthOfFieldTileReduce.azsl | 3 + .../atom_feature_common_asset_files.cmake | 1 + .../Code/Source/CommonSystemComponent.cpp | 4 - .../PostProcessing/NewDepthOfFieldPasses.cpp | 42 ++-------- .../PostProcessing/NewDepthOfFieldPasses.h | 35 ++------ 10 files changed, 155 insertions(+), 128 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli index a789537819..cd0f334f29 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldCommon.azsli @@ -23,9 +23,5 @@ struct NewDepthOfFieldConstants float4 samplePositions[60]; // XY are sample positions (normalized so max lenght is 1) // Z is the length of XY (0 - 1) // W is unused - - }; - - diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl index 14bc0d3b18..b15095535d 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl @@ -51,33 +51,69 @@ PSOutput MainPS(VSOutput IN) float focusDistance = ViewSrg::m_dof.m_cameraParameters.z; float coc = ConvertDofFactor(InvertDepth(depth), far, near, focusDistance); - // Calculate Alpha - float cocRadius = abs(coc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; - float maxPixelDist = max(PassSrg::m_halfResDimensions.z, PassSrg::m_halfResDimensions.w); - float alpha = saturate(cocRadius / maxPixelDist); + // --- Weights based on CoC similarity --- + + // Gather CoCs + float4 cocGather = PassSrg::m_halfResColorAndCoc.GatherAlpha(PassSrg::LinearSampler, halfResUV); + + // Calculate differences + float4 diff = saturate(cocGather - coc); - // Sample half res color and CoC - float4 colorAndCoC = PassSrg::m_halfResColorAndCoc.Sample(PassSrg::LinearSampler, halfResUV); + // Slide differences such that small difference (i.e. most similar CoC) will become 0 + // (which then gets inverted in the next step) + float minDiff = min4(diff); + diff -= minDiff; + // Invert the differences with a slope multiplier of 2 + float4 cocDiffWeights = saturate(1 - (2 * diff)); + + // --- Weights based on pixel proximity --- + + // Based on which pixel we're shading, we'll be closer/further to half res pixels + // Here are the pre-caculated weights, arranged to match the Gather pattern + // + // W Z + // X Y + // + // Note: These weights come down to the same contributions as if we did a linear sample + int2 pixel = int2(fullResPixelPos); + float4 weights = (pixel.x & 1) + ? ( (pixel.y & 1) ? float4(0.1875f, 0.0625f, 0.1875f, 0.5625f) + : float4(0.5625f, 0.1875f, 0.0625f, 0.1875f) ) + : ( (pixel.y & 1) ? float4(0.0625f, 0.1875f, 0.5625f, 0.1875f) + : float4(0.1875f, 0.5625f, 0.1875f, 0.0625f) ); + + // Combine and normalize weights + weights *= cocDiffWeights; + weights /= (weights.x + weights.y + weights.z + weights.w); + + // --- Color --- + + // For each color channel, do a gather and multiply the samples by the weights calculated above + float3 color; + float4 red = PassSrg::m_halfResColorAndCoc.GatherRed(PassSrg::LinearSampler, halfResUV); + color.r = dot(red, weights); + float4 blue = PassSrg::m_halfResColorAndCoc.GatherBlue(PassSrg::LinearSampler, halfResUV); + color.b = dot(blue, weights); + float4 green = PassSrg::m_halfResColorAndCoc.GatherGreen(PassSrg::LinearSampler, halfResUV); + color.g = dot(green, weights); + + + // --- Alpha --- + + // Calculate alpha such that we fully take the half res texture value if the CoC of the full + // resolution pixel is greater than the size of a half resolution pixel + float cocRadius = abs(coc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; + float alpha = saturate(cocRadius / PassSrg::m_halfResDimensions.w); + + // We may have objects in focus (CoC = 0) but that receive contribution from background bokeh + // (which have a negative CoC that we calculated in the large filter). Take the max here. + float minCoc = min4(cocGather); + alpha = max(alpha, -minCoc); - if(false) - { - // Make out of focus foreground increasingly blue - float multiplier = saturate(1.0f + coc); - colorAndCoC.r *= multiplier; - colorAndCoC.g *= multiplier; - - // Make out of focus background increasingly red - multiplier = saturate(1.0f - coc); - colorAndCoC.b *= multiplier; - colorAndCoC.g *= multiplier; - } - - // Output PSOutput OUT; - OUT.m_color.rgb = colorAndCoC.rgb; + OUT.m_color.rgb = color.rgb; OUT.m_color.a = alpha; - return OUT; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl index 6ab47b14ea..ff955493d6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl @@ -18,6 +18,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_colorAndCoc; Texture2D m_minMaxCocTile; + // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height float4 m_textureDimensions; NewDepthOfFieldConstants m_dofConstants; @@ -43,10 +44,10 @@ ShaderResourceGroup PassSrg : SRG_PerPass }; } -float3 GetOffsetUV(uint index, float2 offsetMultiplier) +float3 GetOffset(uint index, float2 offsetUVMultiplier) { float3 offset = PassSrg::m_dofConstants.samplePositions[index].xyz; - offset.xy *= offsetMultiplier; + offset.xy *= offsetUVMultiplier; return offset; } @@ -55,14 +56,19 @@ float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, // The maximum distance for which samples are valid is the min of the sample CoC and the center CoC float maxRadius = abs(min(sampleCoc, centerCoc)); + // Easy human readable calculations: // radius = samplingRadius * offsetRadius; // falloff = maxRadius - radius; - // weight = 1 + (4 * falloff) + // weight = 1 + (4 * falloff) + // + // The same thing in mad form: float falloff = mad(-samplingRadius, offsetRadius, maxRadius); - float weight = saturate(mad(4, falloff, 1)); - return weight; + return saturate(mad(4, falloff, 1)); } +// This shader blurs by sampling 48 pixels in a circle around the center pixel +// See http://advances.realtimerendering.com/s2013/Sousa_Graphics_Gems_CryENGINE3.pptx +// for a detailed explanation. PSOutput MainPS(VSOutput IN) { // Get center sample @@ -70,10 +76,12 @@ PSOutput MainPS(VSOutput IN) float4 color = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba; float centerCoc = color.a; - // Get tile min and max + // Get tile min CoC int2 tile = int2(IN.m_position.xy) / 16; float minCoc = PassSrg::m_minMaxCocTile[tile].x; + // Aspect ratio is needed because sample offsets are calculated in a perfect circle, but + // UV space is stretched due to normalized device coordinates. Correct this with aspect ratio // Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w; @@ -82,15 +90,20 @@ PSOutput MainPS(VSOutput IN) float screenRadius = cocRadius * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; float2 offsetMultiplier = float2(screenRadius / aspectRatio, screenRadius); - + // Background samples are samples behind the current pixel. Because of how depth of field works, + // these pixels can contribute to the center pixel even if they are out of range of the center pixel's CoC + // We accumulate them seperately and calculate a new estimated alpha value based on the ratio of samples + // that were background pixels. float4 backgroundColor = float4(0, 0, 0, 0); + // If there are only positive CoCs in our region, we don't need to consider background blur + // Do the faster and nicer approach if(minCoc >= 0) { for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i) { // Calculate sample offset - float3 offset = GetOffsetUV(i, offsetMultiplier); + float3 offset = GetOffset(i, offsetMultiplier); // Get sample float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offset.xy).rgba; @@ -102,18 +115,22 @@ PSOutput MainPS(VSOutput IN) color += weight * sampleColorCoc; } } - else + else // Some CoCs in the region are negative, need to consider possible background bokeh contribution { + // Distance behind which samples are considered background samples float backgroundMin = min(0, centerCoc); + + // Linear sampling colors pre-multiplied with CoC yields artefacts when combined with this background technique + // We therefore do point sampling and unpack the original color value per sample color.rgb /= abs(color.a); color.a = 1; for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i) { // Calculate sample offset - float3 offset = GetOffsetUV(i, offsetMultiplier); + float3 offset = GetOffset(i, offsetMultiplier); - // Get sample + // Get sample + unpack float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offset.xy).rgba; sampleColorCoc.rgb /= abs(sampleColorCoc.a); @@ -131,16 +148,19 @@ PSOutput MainPS(VSOutput IN) color += !isBackground * sampleColorCoc; } + // Average background samples backgroundColor.rgb /= max(backgroundColor.a, COC_EPSILON); } + // Calculate background ratio. If greater than the current CoC, replace the current CoC with + // background ratio. This is so background bokeh effects will still render on in-focus objects float backgroundRatio = saturate( backgroundColor.a / float(SAMPLES_LOOP_TOTAL) ); float alpha = backgroundRatio > abs(centerCoc) ? -backgroundRatio : centerCoc; + // Average accumulated color samples and combine with background samples color.rgb /= max(color.a, COC_EPSILON); color = lerp(color, backgroundColor, backgroundRatio); - PSOutput OUT = (PSOutput)0; OUT.m_color.rgb = color.rgb; OUT.m_color.a = alpha; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl index 05227cfee7..04bc095a93 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl @@ -18,6 +18,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_colorAndCoc; Texture2D m_minMaxCocTile; + // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height float4 m_textureDimensions; NewDepthOfFieldConstants m_dofConstants; @@ -43,55 +44,77 @@ ShaderResourceGroup PassSrg : SRG_PerPass }; } -float2 GetOffsetUV(uint index, float2 offsetMultiplier) +float3 GetOffset(uint index, float2 offsetUVMultiplier) { - return PassSrg::m_dofConstants.samplePositions[index].xy * offsetMultiplier; + float3 offset = PassSrg::m_dofConstants.samplePositions[index].xyz; + offset.xy *= offsetUVMultiplier; + return offset; } +float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc) +{ + // The maximum distance for which samples are valid is the min of the sample CoC and the center CoC + float maxRadius = abs(min(sampleCoc, centerCoc)); + + // Easy human readable calculations: + // radius = samplingRadius * offsetRadius; + // falloff = maxRadius - radius; + // weight = 1 + (4 * falloff) + // + // The same thing in mad form: + float falloff = mad(-samplingRadius, offsetRadius, maxRadius); + return saturate(mad(4, falloff, 1)); +} + +// This shader attempts to fill the gaps left by the large filter by sampling 8 pixels around the center pixel +// See http://advances.realtimerendering.com/s2013/Sousa_Graphics_Gems_CryENGINE3.pptx +// for a detailed overview of the technique PSOutput MainPS(VSOutput IN) { - // UV of pixel being shaded + // Get center sample float2 pixelUV = IN.m_texCoord.xy; + float4 color = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV).rgba; + float centerCoc = color.a; - // Sample pixel being shaded - float4 centerSample = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV).rgba; - float centerCoc = centerSample.a; + // Get tile min CoC + int2 tile = int2(IN.m_position.xy) / 16; + float minCoc = PassSrg::m_minMaxCocTile[tile].x; + // Aspect ratio is needed because sample offsets are calculated in a perfect circle, but + // UV space is stretched due to normalized device coordinates. Correct this with aspect ratio // Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w; // Sampling radius - float cocRadius = abs(centerCoc) * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; - cocRadius *= 0.5f; // This is the small filter, half the sampling radius - float2 offsetMultiplier = float2(cocRadius / aspectRatio, cocRadius); + float cocRadius = max( abs(centerCoc), -minCoc) * 0.5f; // Small filter pass so half the radius + float screenRadius = cocRadius * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; + float2 offsetMultiplier = float2(screenRadius / aspectRatio, screenRadius); - // Color and weight accumulation - float3 color = centerSample.rgb; + // Weight accumulation. Start with 1 for center pixel. float totalWeight = 1; - for(uint i = 0; i < 8; ++i) + for(uint i = 0; i < SAMPLES_LOOP_1; ++i) { // Calculate sample offset - float2 offsetUV = GetOffsetUV(i, offsetMultiplier); + float3 offset = GetOffset(i, offsetMultiplier); // Get sample - float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offsetUV).rgba; + float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offset.xy).rgba; // Calculate weight - float cocDiff = sampleColorCoc.a - centerCoc; - float weight = saturate( 2 - (20 * cocDiff)); + float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); // Accumulate sample and weight - color += sampleColorCoc.rgb * weight; + color.rgb += sampleColorCoc.rgb * weight; totalWeight += weight; } + // Normalize accumulated sample - color /= totalWeight; + color.rgb /= totalWeight; - // Output PSOutput OUT; - OUT.m_color.rgb = color; + OUT.m_color.rgb = color.rgb; OUT.m_color.a = centerCoc; return OUT; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl index 7238b391aa..e7ce99aae9 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl @@ -33,13 +33,14 @@ struct PSOutput float2 m_color : SV_Target0; }; +// Expands the min and max tiles so each tile contains the min and max of it's 3x3 neighborhood PSOutput MainPS(VSOutput IN) { // We want the min/max in a 3x3 region. Start sampling up left. float2 startPixelPos = IN.m_position.xy - float2(1, 1); - float2 stepSize = PassSrg::m_textureDimensions.zw; - float2 startUV = startPixelPos * stepSize; + float2 pixelSizeInUV = PassSrg::m_textureDimensions.zw; + float2 startUV = startPixelPos * pixelSizeInUV; float cocMin = 1.0f; float cocMax = -1.0f; @@ -51,7 +52,7 @@ PSOutput MainPS(VSOutput IN) [unroll] for(float X = 0.0f; X < 3.0f; X += 1.0f) { - float2 sampleUV = mad(float2(X, Y), stepSize, startUV); + float2 sampleUV = mad(float2(X, Y), pixelSizeInUV, startUV); float2 minMax = PassSrg::m_minMaxSource.SampleLevel(PassSrg::PointSampler, sampleUV, 0).xy; cocMin = min(cocMin, minMax.x); diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl index 2705e1fdfd..740ebabaff 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl @@ -36,6 +36,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass groupshared uint LDS_MIN_COC[8]; groupshared uint LDS_MAX_COC[8]; +// Calculates the min and max CoC (Circle of Confusion) for 16x16 pixel tiles [numthreads(8, 8, 1)] void MainCS(uint3 group_thread_id : SV_GroupThreadID, uint3 group_id : SV_GroupID, uint3 dispatch_id: SV_DispatchThreadID, uint linear_id : SV_GroupIndex) { @@ -68,9 +69,11 @@ void MainCS(uint3 group_thread_id : SV_GroupThreadID, uint3 group_id : SV_GroupI return; } + // Min the mins and max the maxs InterlockedMin( LDS_MIN_COC[0], LDS_MIN_COC[group_thread_id.x] ); InterlockedMax( LDS_MAX_COC[0], LDS_MAX_COC[group_thread_id.x] ); + // Each group write to just one pixel. If we're the last thread in the group, write out if(group_thread_id.x == 0) { // Unpack uints diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index d1f94afe3c..0423741dda 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -443,6 +443,7 @@ set(FILES Shaders/PostProcessing/MSAAResolveCustom.shader Shaders/PostProcessing/MSAAResolveDepth.azsl Shaders/PostProcessing/MSAAResolveDepth.shader + Shaders/PostProcessing/NewDepthOfFieldCommon.azsli Shaders/PostProcessing/NewDepthOfFieldComposite.azsl Shaders/PostProcessing/NewDepthOfFieldComposite.shader Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index a7891b7907..c117cadbde 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -252,10 +252,6 @@ namespace AZ passSystem->AddPassCreator(Name("NewDepthOfFieldParentPass"), &NewDepthOfFieldParentPass::Create); passSystem->AddPassCreator(Name("NewDepthOfFieldTileReducePass"), &NewDepthOfFieldTileReducePass::Create); passSystem->AddPassCreator(Name("NewDepthOfFieldFilterPass"), &NewDepthOfFieldFilterPass::Create); - passSystem->AddPassCreator(Name("NewDepthOfFieldCompositePass"), &NewDepthOfFieldCompositePass::Create); - - - // Add FastDepthAwareBlur passes passSystem->AddPassCreator(Name("FastDepthAwareBlurHorPass"), &FastDepthAwareBlurHorPass::Create); diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp index b69484297a..69ee2a6751 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.cpp @@ -32,7 +32,6 @@ namespace AZ // W is unused }; - // --- Depth of Field Parent Pass --- RPI::Ptr NewDepthOfFieldParentPass::Create(const RPI::PassDescriptor& descriptor) @@ -103,8 +102,8 @@ namespace AZ NewDepthOfFieldTileReducePass::NewDepthOfFieldTileReducePass(const RPI::PassDescriptor& descriptor) : RPI::ComputePass(descriptor) { - // Though this is a fullscreen pass, the algorithm used makes each thread output 3 blurred pixels, so - // it's not a 1-to-1 ratio and requires custom calculation of target thread counts + // Though this is a fullscreen pass, the shader computes 16x16 tiles with groups of 8x8 threads, + // each thread outputting to a single pixel in the tiled min/max texture m_isFullscreenPass = false; } @@ -124,8 +123,6 @@ namespace AZ RPI::ComputePass::FrameBeginInternal(params); } - - // --- Filter Pass --- RPI::Ptr NewDepthOfFieldFilterPass::Create(const RPI::PassDescriptor& descriptor) @@ -144,22 +141,19 @@ namespace AZ uint32_t sampleIndex = 0; + // Calculate all the offset positions for (uint32_t loop = 0; loop < NewDepthOfFieldConstants::numberOfLoops; ++loop) { float radius = (loop + 1.0f) / float(NewDepthOfFieldConstants::numberOfLoops); float loopCount = NewDepthOfFieldConstants::loopCounts[loop]; - float angleOffset = 0; + float angleStep = Constants::TwoPi / loopCount; // Every other loop slightly rotate sample ring so they don't line up - if (loop & 1) - { - angleOffset = Constants::TwoPi * 0.5f / loopCount; - } + float angle = (loop & 1) ? (angleStep * 0.5f) : 0; for (float i = 0.0f; i < loopCount; ++i) { - float angle = Constants::TwoPi * i / loopCount; Vector2 pos = Vector2::CreateFromAngle(angle); pos = pos * radius; @@ -167,38 +161,16 @@ namespace AZ dofConstants.m_samplePositions[sampleIndex][1] = pos.GetY(); dofConstants.m_samplePositions[sampleIndex][2] = radius; dofConstants.m_samplePositions[sampleIndex][3] = 0.0f; + ++sampleIndex; + angle += angleStep; } - } m_shaderResourceGroup->SetConstant(m_constantsIndex, dofConstants); - // TODO HERE RPI::FullscreenTrianglePass::FrameBeginInternal(params); } - - - // --- Composite Pass --- - - RPI::Ptr NewDepthOfFieldCompositePass::Create(const RPI::PassDescriptor& descriptor) - { - RPI::Ptr pass = aznew NewDepthOfFieldCompositePass(descriptor); - return AZStd::move(pass); - } - - NewDepthOfFieldCompositePass::NewDepthOfFieldCompositePass(const RPI::PassDescriptor& descriptor) - : RPI::ComputePass(descriptor) - { } - - void NewDepthOfFieldCompositePass::FrameBeginInternal(FramePrepareParams params) - { - // TODO HERE - RPI::ComputePass::FrameBeginInternal(params); - } - - - } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h index f7a0ee95ca..d529623c0a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h @@ -17,7 +17,9 @@ namespace AZ { namespace Render { - //! + //! Parent pass for the new depth of field technique + //! Main updates the view srg via the depth of field settings + //! And enables/disables all depth of field passes based on component activation class NewDepthOfFieldParentPass final : public RPI::ParentPass { @@ -41,8 +43,7 @@ namespace AZ }; - - //! + //! Need a class for the tile reduce pass because it dispatches a non-trivial number of threads class NewDepthOfFieldTileReducePass final : public RPI::ComputePass { @@ -64,8 +65,9 @@ namespace AZ }; - - //! + //! Filter pass used to render the bokeh blur effect on downsampled image buffer + //! This class is used for both the large filter and the small filter + //! It's main purpose is calculating the sample positions and setting srg constants class NewDepthOfFieldFilterPass final : public RPI::FullscreenTrianglePass { @@ -90,28 +92,5 @@ namespace AZ }; - - //! - class NewDepthOfFieldCompositePass final - : public RPI::ComputePass - { - AZ_RPI_PASS(NewDepthOfFieldCompositePass); - - public: - AZ_RTTI(AZ::Render::NewDepthOfFieldCompositePass, "{63270A3A-EAE5-4C0C-98AA-43CA55279613}", AZ::RPI::ComputePass); - AZ_CLASS_ALLOCATOR(NewDepthOfFieldCompositePass, SystemAllocator, 0); - virtual ~NewDepthOfFieldCompositePass() = default; - - static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); - - protected: - // Behavior functions override... - void FrameBeginInternal(FramePrepareParams params) override; - - private: - NewDepthOfFieldCompositePass(const RPI::PassDescriptor& descriptor); - }; - - } // namespace Render } // namespace AZ From 6e7d2e6dd62bbb26114e20637a1704076553f1fd Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 21 Oct 2021 04:48:45 -0700 Subject: [PATCH 05/22] removing commented line in TAA pass Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp index 643d9bb96d..574d959c07 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp @@ -168,7 +168,6 @@ namespace AZ::Render // The ImageViewDescriptor must be specified to make sure the frame graph compiler doesn't treat this as a transient image. RHI::ImageViewDescriptor viewDesc = RHI::ImageViewDescriptor::Create(imageDesc.m_format, 0, 0); viewDesc.m_aspectFlags = RHI::ImageAspectFlags::Color; - //viewDesc.m_overrideBindFlags = RHI::ImageBindFlags::ShaderReadWrite; // The full path name is needed for the attachment image so it's not deduplicated from accumulation images in different pipelines. AZStd::string imageName = RPI::ConcatPassString(GetPathName(), attachment->m_path); From 58a518ce692f18a1378d6a4d02f252ce56d4ec69 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 21 Oct 2021 04:52:46 -0700 Subject: [PATCH 06/22] removing accidental file Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- ...epthOfFieldFilterLarge.azsl~RF1bf9782e.TMP | 105 ------------------ 1 file changed, 105 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP deleted file mode 100644 index 7c0f32381b..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl~RF1bf9782e.TMP +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include -#include "DepthOfField.azsli" -#include "NewDepthOfFieldCommon.azsli" - -#include - -ShaderResourceGroup PassSrg : SRG_PerPass -{ - Texture2D m_colorAndCoc; - Texture2D m_minMaxCocTile; - - float4 m_textureDimensions; - - NewDepthOfFieldConstants m_dofConstants; - - Sampler LinearSampler - { - MinFilter = Linear; - MagFilter = Linear; - MipFilter = Linear; - AddressU = Clamp; - AddressV = Clamp; - AddressW = Clamp; - }; -} - -float2 GetOffsetUV(uint index, float2 offsetMultiplier) -{ - return PassSrg::m_dofConstants.samplePositions[index].xy * offsetMultiplier; -} - -PSOutput MainPS(VSOutput IN) -{ - // Get center sample - float2 pixelUV = IN.m_texCoord; - float4 color = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV).rgba; - float centerCoc = color.a; - - // Get tile min and max - int2 tile = int2(IN.m_position.xy) / 16; - float minCoc = PassSrg::m_minMaxCocTile[tile].x; - - // Aspect ratio = texture.x / texture.y = dimensions.x * dimensions.w - float aspectRatio = PassSrg::m_textureDimensions.x * PassSrg::m_textureDimensions.w; - - // Sampling radius - float cocRadius = max( abs(centerCoc), -minCoc); - cocRadius *= ViewSrg::m_dof.m_cocToScreenRatio * 0.5f; - float2 offsetMultiplier = float2(cocRadius / aspectRatio, cocRadius); - - - - float4 negColor = float4(0, 0, 0, 0); - - { - float negMin = min(0, centerCoc); - color.rgb /= abs(color.a); - color.a = 1; - - for(uint i = 0; i < SAMPLES_LOOP_TOTAL; ++i) - { - // Calculate sample offset - float2 offsetUV = GetOffsetUV(i, offsetMultiplier); - - // Get sample - float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offsetUV).rgba; - - // Calculate weight and adjust sample - float cocDiff = sampleColorCoc.a - centerCoc; - float weight = saturate( 2 - (20 * cocDiff)); - sampleColorCoc.rgb *= (weight / abs(sampleColorCoc.a)); - // - // bool isNeg = (sampleColorCoc.a < negMin); - // sampleColorCoc.a = weight; - // - // // Accumulate - // negColor += isNeg * sampleColorCoc; - // color += !isNeg * sampleColorCoc; - } - } - - float negRatio = negColor.a / float(SAMPLES_LOOP_TOTAL); - float alpha = negRatio > abs(centerCoc) ? -negRatio : centerCoc; - - color = color * saturate(1 - negRatio) + negColor; - color.rgb /= max(color.a, COC_EPSILON); - color.rgb += negColor.rgb; - - //float alpha = 1.0f; - - PSOutput OUT = (PSOutput)0; - OUT.m_color.rgb = color.rgb; - OUT.m_color.a = alpha; - return OUT; -} - From a1edb2c4ac0e8b56e150be02277a091c27c6fffc Mon Sep 17 00:00:00 2001 From: sweeneys Date: Thu, 21 Oct 2021 11:51:47 -0700 Subject: [PATCH 07/22] Update platform defaults to return a launcher instead of a string Signed-off-by: sweeneys --- .../launchers/launcher_helper.py | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py b/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py index d37623f352..9a75bbe3ee 100755 --- a/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py +++ b/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py @@ -9,14 +9,15 @@ Main launchers module, provides a facade for creating launchers. import logging -import ly_test_tools._internal.managers.workspace import ly_test_tools +import ly_test_tools._internal.managers.workspace as workspace_manager +import ly_test_tools.launchers.platforms.base as base_launcher log = logging.getLogger(__name__) def create_launcher(workspace, launcher_platform=ly_test_tools.HOST_OS_PLATFORM, args=None): - # type: (ly_test_tools.managers.workspace.WorkspaceManager, str, List[str]) -> Launcher + # type: (workspace_manager.AbstractWorkspaceManager, str, list[str]) -> base_launcher.Launcher """ Create a launcher compatible with the specified workspace, if no specific launcher is found return a generic one. @@ -25,12 +26,16 @@ def create_launcher(workspace, launcher_platform=ly_test_tools.HOST_OS_PLATFORM, :param args: List of arguments to pass to the launcher's 'args' argument during construction :return: Launcher instance """ - launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform, ly_test_tools.HOST_OS_PLATFORM) + launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform) + if not launcher_class: + log.warning(f"Using default launcher for '{ly_test_tools.HOST_OS_PLATFORM}' " + f"as no option is available for '{launcher_platform}'") + launcher_class = ly_test_tools.LAUNCHERS.get(ly_test_tools.HOST_OS_PLATFORM) return launcher_class(workspace, args) def create_dedicated_launcher(workspace, launcher_platform=ly_test_tools.HOST_OS_DEDICATED_SERVER, args=None): - # type: (ly_test_tools.managers.workspace.WorkspaceManager, str, List[str]) -> Launcher + # type: (workspace_manager.AbstractWorkspaceManager, str, list[str]) -> base_launcher.Launcher """ Create a dedicated launcher compatible with the specified workspace. Dedicated Launcher is only supported on the Linux and Windows Platform @@ -41,11 +46,15 @@ def create_dedicated_launcher(workspace, launcher_platform=ly_test_tools.HOST_OS :return: Launcher instance """ launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform, ly_test_tools.HOST_OS_DEDICATED_SERVER) + if not launcher_class: + log.warning(f"Using default dedicated launcher for '{ly_test_tools.HOST_OS_PLATFORM}' " + f"as no option is available for '{launcher_platform}'") + launcher_class = ly_test_tools.LAUNCHERS.get(ly_test_tools.HOST_OS_DEDICATED_SERVER) return launcher_class(workspace, args) def create_editor(workspace, launcher_platform=ly_test_tools.HOST_OS_EDITOR, args=None): - # type: (ly_test_tools.managers.workspace.WorkspaceManager, str, List[str]) -> Launcher + # type: (workspace_manager.AbstractWorkspaceManager, str, list[str]) -> base_launcher.Launcher """ Create an Editor compatible with the specified workspace. Editor is only officially supported on the Windows Platform. @@ -56,11 +65,15 @@ def create_editor(workspace, launcher_platform=ly_test_tools.HOST_OS_EDITOR, arg :return: Editor instance """ launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform, ly_test_tools.HOST_OS_EDITOR) + if not launcher_class: + log.warning(f"Using default editor launcher for '{ly_test_tools.HOST_OS_PLATFORM}' " + f"as no option is available for '{launcher_platform}'") + launcher_class = ly_test_tools.LAUNCHERS.get(ly_test_tools.HOST_OS_EDITOR) return launcher_class(workspace, args) def create_generic_launcher(workspace, launcher_platform, exe_file_name, args=None): - # type: (ly_test_tools.managers.workspace.WorkspaceManager, str, str, List[str]) -> Launcher + # type: (workspace_manager.AbstractWorkspaceManager, str, str, list[str]) -> base_launcher.Launcher """ Create a generic launcher compatible with the specified workspace. Allows custom .exe files to serve as the launcher instead of ones listed in the ly_test_tools.LAUNCHERS constant @@ -72,4 +85,8 @@ def create_generic_launcher(workspace, launcher_platform, exe_file_name, args=No :return: Launcher instance. """ launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform, ly_test_tools.HOST_OS_GENERIC_EXECUTABLE) + if not launcher_class: + log.warning(f"Using default generic executable launcher for '{ly_test_tools.HOST_OS_PLATFORM}' " + f"as no option is available for '{launcher_platform}'") + launcher_class = ly_test_tools.LAUNCHERS.get(ly_test_tools.HOST_OS_GENERIC_EXECUTABLE) return launcher_class(workspace, exe_file_name, args) From 7eaf54e48dd272ed2bd34bf03f4f69dbf7c1c213 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 21 Oct 2021 11:52:50 -0700 Subject: [PATCH 08/22] Adding 5361st maybe_unused to the code base to pass AR Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp index dad511def1..b8115dff10 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -298,6 +298,7 @@ namespace AZ imageDimensions.SetZ(1.0f / float(size.m_width)); imageDimensions.SetW(1.0f / float(size.m_height)); + [[maybe_unused]] bool success = m_shaderResourceGroup->SetConstant(binding.m_shaderImageDimensionsNameIndex, imageDimensions); AZ_Assert(success, "Pass [%s] Could not find float4 constant [%s] in Shader Resource Group [%s]", GetPathName().GetCStr(), From ea325d356c736a7cf5544a1b18b42252720c91ae Mon Sep 17 00:00:00 2001 From: sweeneys Date: Thu, 21 Oct 2021 12:05:22 -0700 Subject: [PATCH 09/22] updated defaults in all launchers, with additional unit test Signed-off-by: sweeneys --- .../ly_test_tools/launchers/launcher_helper.py | 12 ++++++------ Tools/LyTestTools/tests/unit/test_launcher_base.py | 7 +++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py b/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py index 9a75bbe3ee..ac4ad621da 100755 --- a/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py +++ b/Tools/LyTestTools/ly_test_tools/launchers/launcher_helper.py @@ -45,9 +45,9 @@ def create_dedicated_launcher(workspace, launcher_platform=ly_test_tools.HOST_OS :param args: List of arguments to pass to the launcher's 'args' argument during construction :return: Launcher instance """ - launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform, ly_test_tools.HOST_OS_DEDICATED_SERVER) + launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform) if not launcher_class: - log.warning(f"Using default dedicated launcher for '{ly_test_tools.HOST_OS_PLATFORM}' " + log.warning(f"Using default dedicated launcher for '{ly_test_tools.HOST_OS_DEDICATED_SERVER}' " f"as no option is available for '{launcher_platform}'") launcher_class = ly_test_tools.LAUNCHERS.get(ly_test_tools.HOST_OS_DEDICATED_SERVER) return launcher_class(workspace, args) @@ -64,9 +64,9 @@ def create_editor(workspace, launcher_platform=ly_test_tools.HOST_OS_EDITOR, arg :param args: List of arguments to pass to the launcher's 'args' argument during construction :return: Editor instance """ - launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform, ly_test_tools.HOST_OS_EDITOR) + launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform) if not launcher_class: - log.warning(f"Using default editor launcher for '{ly_test_tools.HOST_OS_PLATFORM}' " + log.warning(f"Using default editor launcher for '{ly_test_tools.HOST_OS_EDITOR}' " f"as no option is available for '{launcher_platform}'") launcher_class = ly_test_tools.LAUNCHERS.get(ly_test_tools.HOST_OS_EDITOR) return launcher_class(workspace, args) @@ -84,9 +84,9 @@ def create_generic_launcher(workspace, launcher_platform, exe_file_name, args=No :param args: List of arguments to pass to the launcher's 'args' argument during construction :return: Launcher instance. """ - launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform, ly_test_tools.HOST_OS_GENERIC_EXECUTABLE) + launcher_class = ly_test_tools.LAUNCHERS.get(launcher_platform) if not launcher_class: - log.warning(f"Using default generic executable launcher for '{ly_test_tools.HOST_OS_PLATFORM}' " + log.warning(f"Using default generic executable launcher for '{ly_test_tools.HOST_OS_GENERIC_EXECUTABLE}' " f"as no option is available for '{launcher_platform}'") launcher_class = ly_test_tools.LAUNCHERS.get(ly_test_tools.HOST_OS_GENERIC_EXECUTABLE) return launcher_class(workspace, exe_file_name, args) diff --git a/Tools/LyTestTools/tests/unit/test_launcher_base.py b/Tools/LyTestTools/tests/unit/test_launcher_base.py index 1ab9129a7d..5264e1bc28 100755 --- a/Tools/LyTestTools/tests/unit/test_launcher_base.py +++ b/Tools/LyTestTools/tests/unit/test_launcher_base.py @@ -221,3 +221,10 @@ class TestLauncherBuilder(object): under_test = ly_test_tools.launchers.launcher_helper.create_editor( dummy_workspace, ly_test_tools.HOST_OS_GENERIC_EXECUTABLE) assert isinstance(under_test, ly_test_tools.launchers.Launcher) + + def test_CreateEditor_InvalidPlatform_ValidLauncherStillReturned(self): + dummy_workspace = mock.MagicMock() + dummy_workspace.paths.build_directory.return_value = 'dummy' + under_test = ly_test_tools.launchers.launcher_helper.create_editor( + dummy_workspace, 'does not exist') + assert isinstance(under_test, ly_test_tools.launchers.Launcher) From e3cfcd4cc7da7153b5980a03069b3ec774f2740f Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Thu, 21 Oct 2021 16:07:07 -0700 Subject: [PATCH 10/22] Add the ability for Python to pass download progress to Project Manager and to cancel downloads. Signed-off-by: AMZN-Phil --- .../Source/DownloadController.cpp | 29 +++++++--- .../Source/DownloadController.h | 4 +- .../GemCatalog/GemCatalogHeaderWidget.cpp | 11 +++- .../GemCatalog/GemCatalogHeaderWidget.h | 1 + .../ProjectManager/Source/PythonBindings.cpp | 54 +++++++++++++++++++ .../ProjectManager/Source/PythonBindings.h | 1 + .../Source/PythonBindingsInterface.h | 11 ++++ scripts/o3de/o3de/utils.py | 42 ++++++++++++++- 8 files changed, 142 insertions(+), 11 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp index fa3fdb10d1..3ee800bba8 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp @@ -8,10 +8,15 @@ #include #include +#include + +#include #include + + namespace O3DE::ProjectManager { DownloadController::DownloadController(QWidget* parent) @@ -46,6 +51,24 @@ namespace O3DE::ProjectManager } } + void DownloadController::CancelGemDownload(const QString& gemName) + { + auto findResult = AZStd::find(m_gemNames.begin(), m_gemNames.end(), gemName); + + if (findResult != m_gemNames.end()) + { + if (findResult == m_gemNames.begin()) + { + // HandleResults will remove the gem upon cancelling + PythonBindingsInterface::Get()->CancelDownload(); + } + else + { + m_gemNames.erase(findResult); + } + } + } + void DownloadController::UpdateUIProgress(int progress) { m_lastProgress = progress; @@ -75,10 +98,4 @@ namespace O3DE::ProjectManager m_workerThread.wait(); } } - - void DownloadController::HandleCancel() - { - m_workerThread.quit(); - emit Done(false); - } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/DownloadController.h b/Code/Tools/ProjectManager/Source/DownloadController.h index 608d9b1a2b..11ceaacddb 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.h +++ b/Code/Tools/ProjectManager/Source/DownloadController.h @@ -27,7 +27,8 @@ namespace O3DE::ProjectManager explicit DownloadController(QWidget* parent = nullptr); ~DownloadController(); - void AddGemDownload(const QString& m_gemName); + void AddGemDownload(const QString& gemName); + void CancelGemDownload(const QString& gemName); bool IsDownloadQueueEmpty() { @@ -54,7 +55,6 @@ namespace O3DE::ProjectManager public slots: void UpdateUIProgress(int progress); void HandleResults(const QString& result); - void HandleCancel(); signals: void StartGemDownload(const QString& gemName); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 79ff7624b7..875d5ada8c 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -154,6 +154,11 @@ namespace O3DE::ProjectManager update(); } + void CartOverlayWidget::OnCancelDownloadActivated(const QString& gemName) + { + m_downloadController->CancelGemDownload(gemName); + } + void CartOverlayWidget::CreateDownloadSection() { QWidget* widget = new QWidget(); @@ -188,6 +193,8 @@ namespace O3DE::ProjectManager downloadingItemLayout->setAlignment(Qt::AlignTop); downloadingItemWidget->setLayout(downloadingItemLayout); + m_downloadController->AddGemDownload("TestGem"); + auto update = [=](int downloadProgress) { if (m_downloadController->IsDownloadQueueEmpty()) @@ -234,7 +241,9 @@ namespace O3DE::ProjectManager nameProgressLayout->addWidget(progress); QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); nameProgressLayout->addSpacerItem(spacer); - QLabel* cancelText = new QLabel(tr("Cancel")); + QLabel* cancelText = new QLabel(QString("Cancel").arg(downloadQueue[downloadingGemNumber])); + cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse); + connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated); nameProgressLayout->addWidget(cancelText); downloadingItemLayout->addLayout(nameProgressLayout); QProgressBar* downloadProgessBar = new QProgressBar(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h index 8e0eaa13ba..9f1e592d6e 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h @@ -40,6 +40,7 @@ namespace O3DE::ProjectManager using GetTagIndicesCallback = AZStd::function()>; void CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices); void CreateDownloadSection(); + void OnCancelDownloadActivated(const QString& link); QVBoxLayout* m_layout = nullptr; GemModel* m_gemModel = nullptr; diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index bc8773b0c8..8b716666de 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -223,6 +223,50 @@ namespace RedirectOutput } } // namespace RedirectOutput +namespace O3DEProjectManagerPy +{ + using DownloadProgressFunc = AZStd::function; + DownloadProgressFunc currentProgressCallback; + bool requestCancelDownload = false; + + static PyObject* CLICancelDownload(PyObject* /*self*/, PyObject* /*args*/) + { + if (requestCancelDownload) + { + return Py_True; + } + else + { + return Py_False; + } + } + + static PyObject* CLIDownloadProgress(PyObject* /*self*/, PyObject* args) + { + int progress_percentage = 0; + if (!PyArg_ParseTuple(args, "i", &progress_percentage)) + return NULL; + if (currentProgressCallback) + { + currentProgressCallback(progress_percentage); + } + + Py_RETURN_NONE; + } + + static PyMethodDef O3DEPMPyMethods[] = { { "download_progress", CLIDownloadProgress, METH_VARARGS, "Used to call back to the UI to inform of download progress." }, + { "request_cancel_download", CLICancelDownload, METH_NOARGS, "Returns that the UI is requesting that the current download be cancelled." }, + { NULL, NULL, 0, NULL } }; + + static PyModuleDef O3DEPMPyModule = { PyModuleDef_HEAD_INIT, "o3de_projectmanager", NULL, -1, O3DEPMPyMethods, NULL, NULL, NULL, NULL }; + + static PyObject* PyInit_O3DEPMPy(void) + { + return PyModule_Create(&O3DEPMPyModule); + } +} // namespace O3DEProjectManagerPy + + namespace O3DE::ProjectManager { PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath) @@ -270,6 +314,7 @@ namespace O3DE::ProjectManager AZ_TracePrintf("python", "Py_GetProgramFullPath=%ls \n", Py_GetProgramFullPath()); PyImport_AppendInittab("azlmbr_redirect", RedirectOutput::PyInit_RedirectOutput); + PyImport_AppendInittab("o3de_projectmanager", &O3DEProjectManagerPy::PyInit_O3DEPMPy); try { @@ -1080,6 +1125,8 @@ namespace O3DE::ProjectManager AZ::Outcome PythonBindings::DownloadGem(const QString& gemName, std::function gemProgressCallback) { bool downloadSucceeded = false; + O3DEProjectManagerPy::currentProgressCallback = gemProgressCallback; + O3DEProjectManagerPy::requestCancelDownload = false; auto result = ExecuteWithLockErrorHandling( [&] { @@ -1091,6 +1138,8 @@ namespace O3DE::ProjectManager downloadSucceeded = (downloadResult.cast() == 0); }); + O3DEProjectManagerPy::currentProgressCallback = nullptr; + if (!result.IsSuccess()) { return result; @@ -1102,4 +1151,9 @@ namespace O3DE::ProjectManager return AZ::Success(); } + + void PythonBindings::CancelDownload() + { + O3DEProjectManagerPy::requestCancelDownload = true; + } } diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 638ce6b1d4..386268b5b2 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -62,6 +62,7 @@ namespace O3DE::ProjectManager bool RemoveGemRepo(const QString& repoUri) override; AZ::Outcome, AZStd::string> GetAllGemRepoInfos() override; AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) override; + void CancelDownload() override; private: AZ_DISABLE_COPY_MOVE(PythonBindings); diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index 19442540a4..928e9a8d48 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -188,7 +188,18 @@ namespace O3DE::ProjectManager */ virtual AZ::Outcome, AZStd::string> GetAllGemRepoInfos() = 0; + /** + * Downloads and registers a Gem. + * @param gemName the name of the Gem to download + * @param gemProgressCallback a callback function that is called with an int percentage download value + * @return an outcome with a string error message on failure. + */ virtual AZ::Outcome DownloadGem(const QString& gemName, std::function gemProgressCallback) = 0; + + /** + * Cancels the current download. + */ + virtual void CancelDownload() = 0; }; using PythonBindingsInterface = AZ::Interface; diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index c5be21c60f..cce51bbd8f 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -10,15 +10,44 @@ This file contains utility functions """ import sys import uuid +import os import pathlib import shutil import urllib.request import logging import zipfile +try: + import o3de_projectmanager +except ImportError: + pass logger = logging.getLogger() logging.basicConfig() +COPY_BUFSIZE = 64 * 1024 + +def copyfileobj(fsrc, fdst, callback, length=0): + # This is functionally the same as the python shutil copyfileobj but + # allows for a callback to return the download progress in blocks and allows + # to early out to cancel the copy. + if not length: + length = COPY_BUFSIZE + + fsrc_read = fsrc.read + fdst_write = fdst.write + + copied = 0 + while True: + if o3de_projectmanager and o3de_projectmanager.request_cancel_download(): + return 1 + buf = fsrc_read(length) + if not buf: + break + fdst_write(buf) + copied += len(buf) + callback(copied) + return 0 + def validate_identifier(identifier: str) -> bool: """ Determine if the identifier supplied is valid. @@ -93,7 +122,6 @@ def backup_folder(folder: str or pathlib.Path) -> None: if backup_folder_name.is_dir(): renamed = True - def download_file(parsed_uri, download_path: pathlib.Path) -> int: """ :param parsed_uri: uniform resource identifier to zip file to download @@ -103,8 +131,18 @@ def download_file(parsed_uri, download_path: pathlib.Path) -> int: logger.warn(f'File already downloaded to {download_path}.') elif parsed_uri.scheme in ['http', 'https', 'ftp', 'ftps']: with urllib.request.urlopen(parsed_uri.geturl()) as s: + download_file_size = 0 + try: + download_file_size = s.headers['content-length'] + except KeyError: + pass + def download_progress(blocks): + if o3de_projectmanager and download_file_size: + o3de_projectmanager.download_progress(int(blocks/int(download_file_size) * 100)) with download_path.open('wb') as f: - shutil.copyfileobj(s, f) + download_cancelled = copyfileobj(s, f, download_progress) + if download_cancelled: + return 1 else: origin_file = pathlib.Path(parsed_uri.geturl()).resolve() if not origin_file.is_file(): From 5e6ecddbf98c59c491740f0953f9f7a9e227523d Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Thu, 21 Oct 2021 16:11:28 -0700 Subject: [PATCH 11/22] Remove some test code and extra newlines Signed-off-by: AMZN-Phil --- Code/Tools/ProjectManager/Source/DownloadController.cpp | 3 --- .../Source/GemCatalog/GemCatalogHeaderWidget.cpp | 2 -- 2 files changed, 5 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp index 3ee800bba8..224b90299c 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp @@ -14,9 +14,6 @@ #include - - - namespace O3DE::ProjectManager { DownloadController::DownloadController(QWidget* parent) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 875d5ada8c..e62499d963 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -193,8 +193,6 @@ namespace O3DE::ProjectManager downloadingItemLayout->setAlignment(Qt::AlignTop); downloadingItemWidget->setLayout(downloadingItemLayout); - m_downloadController->AddGemDownload("TestGem"); - auto update = [=](int downloadProgress) { if (m_downloadController->IsDownloadQueueEmpty()) From e5c7703aa72339e2a36d5a4fbf977cc6f7040536 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 21 Oct 2021 20:15:39 -0700 Subject: [PATCH 12/22] Addressing review feedback Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Assets/Passes/PostProcessParent.pass | 1 + .../NewDepthOfFieldComposite.azsl | 7 ++-- .../NewDepthOfFieldDownsample.azsl | 3 +- .../NewDepthOfFieldFilterLarge.azsl | 7 ++-- .../NewDepthOfFieldFilterSmall.azsl | 5 +-- .../NewDepthOfFieldTile3x3.azsl | 33 ++++++++++--------- .../NewDepthOfFieldTileReduce.azsl | 3 +- .../PostProcessing/NewDepthOfFieldPasses.h | 23 +++++++++++++ 8 files changed, 56 insertions(+), 26 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass index dc1c0f1664..67c5072513 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/PostProcessParent.pass @@ -112,6 +112,7 @@ } ] }, + // Todo: remove the old depth of field implementation and rename NewDepthOfField -> DepthOfField //{ // "Name": "DepthOfFieldPass", // "TemplateName": "DepthOfFieldTemplate", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl index b15095535d..468f93db78 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldComposite.azsl @@ -22,6 +22,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_halfResColorAndCoc; // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + // Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file float4 m_fullResDimensions; float4 m_halfResDimensions; @@ -69,15 +70,15 @@ PSOutput MainPS(VSOutput IN) // --- Weights based on pixel proximity --- - // Based on which pixel we're shading, we'll be closer/further to half res pixels - // Here are the pre-caculated weights, arranged to match the Gather pattern + // Based on which pixel we're shading, we'll be closer/farther to half res pixels + // Here are the pre-calculated weights, arranged to match the Gather pattern // // W Z // X Y // // Note: These weights come down to the same contributions as if we did a linear sample int2 pixel = int2(fullResPixelPos); - float4 weights = (pixel.x & 1) + float4 weights = (pixel.x & 1) ? ( (pixel.y & 1) ? float4(0.1875f, 0.0625f, 0.1875f, 0.5625f) : float4(0.5625f, 0.1875f, 0.0625f, 0.1875f) ) : ( (pixel.y & 1) ? float4(0.0625f, 0.1875f, 0.5625f, 0.1875f) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl index d9972b8400..01ff4b9493 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldDownsample.azsl @@ -22,6 +22,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_depth; // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + // Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file float4 m_inputDimensions; float4 m_outputDimensions; @@ -61,7 +62,7 @@ PSOutput MainPS(VSOutput IN) // Clamp CoC cocGather = clamp(cocGather, -1.0f, 1.0f); - // Weigh samles by CoC to avoid in foces pixels bleeding into bokeh effect + // Weight samples by CoC to avoid in focus pixels bleeding into bokeh effect float4 weights = abs(cocGather) + COC_EPSILON; weights = weights / (weights.x + weights.y + weights.z + weights.w); diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl index ff955493d6..3b979b9c39 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterLarge.azsl @@ -19,6 +19,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_minMaxCocTile; // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + // Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file float4 m_textureDimensions; NewDepthOfFieldConstants m_dofConstants; @@ -51,7 +52,7 @@ float3 GetOffset(uint index, float2 offsetUVMultiplier) return offset; } -float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc) +float CalculateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc) { // The maximum distance for which samples are valid is the min of the sample CoC and the center CoC float maxRadius = abs(min(sampleCoc, centerCoc)); @@ -109,7 +110,7 @@ PSOutput MainPS(VSOutput IN) float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::LinearSampler, pixelUV + offset.xy).rgba; // Calculate weight for sample - float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); + float weight = CalculateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); // Accumulate color += weight * sampleColorCoc; @@ -135,7 +136,7 @@ PSOutput MainPS(VSOutput IN) sampleColorCoc.rgb /= abs(sampleColorCoc.a); // Calculate weight for sample - float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); + float weight = CalculateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); sampleColorCoc.rgb *= weight; bool isBackground = (sampleColorCoc.a < backgroundMin); diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl index 04bc095a93..38762254a8 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldFilterSmall.azsl @@ -19,6 +19,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_minMaxCocTile; // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + // Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file float4 m_textureDimensions; NewDepthOfFieldConstants m_dofConstants; @@ -51,7 +52,7 @@ float3 GetOffset(uint index, float2 offsetUVMultiplier) return offset; } -float CaclulateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc) +float CalculateWeight(float offsetRadius, float samplingRadius, float sampleCoc, float centerCoc) { // The maximum distance for which samples are valid is the min of the sample CoC and the center CoC float maxRadius = abs(min(sampleCoc, centerCoc)); @@ -102,7 +103,7 @@ PSOutput MainPS(VSOutput IN) float4 sampleColorCoc = PassSrg::m_colorAndCoc.Sample(PassSrg::PointSampler, pixelUV + offset.xy).rgba; // Calculate weight - float weight = CaclulateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); + float weight = CalculateWeight(offset.z, cocRadius, sampleColorCoc.a, centerCoc); // Accumulate sample and weight color.rgb += sampleColorCoc.rgb * weight; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl index e7ce99aae9..6c56b0b79c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTile3x3.azsl @@ -15,6 +15,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_minMaxSource; // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + // Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file float4 m_textureDimensions; Sampler PointSampler @@ -38,28 +39,28 @@ PSOutput MainPS(VSOutput IN) { // We want the min/max in a 3x3 region. Start sampling up left. float2 startPixelPos = IN.m_position.xy - float2(1, 1); - + float2 pixelSizeInUV = PassSrg::m_textureDimensions.zw; float2 startUV = startPixelPos * pixelSizeInUV; - + float cocMin = 1.0f; - float cocMax = -1.0f; - + float cocMax = -1.0f; + // Gather min/max in 3x3 region - [unroll] - for(float Y = 0.0f; Y < 3.0f; Y += 1.0f) + [unroll] + for(float Y = 0.0f; Y < 3.0f; Y += 1.0f) { - [unroll] - for(float X = 0.0f; X < 3.0f; X += 1.0f) - { - float2 sampleUV = mad(float2(X, Y), pixelSizeInUV, startUV); - float2 minMax = PassSrg::m_minMaxSource.SampleLevel(PassSrg::PointSampler, sampleUV, 0).xy; - - cocMin = min(cocMin, minMax.x); - cocMax = max(cocMax, minMax.y); - } + [unroll] + for(float X = 0.0f; X < 3.0f; X += 1.0f) + { + float2 sampleUV = mad(float2(X, Y), pixelSizeInUV, startUV); + float2 minMax = PassSrg::m_minMaxSource.SampleLevel(PassSrg::PointSampler, sampleUV, 0).xy; + + cocMin = min(cocMin, minMax.x); + cocMax = max(cocMax, minMax.y); + } } - + PSOutput output; output.m_color.x = cocMin; output.m_color.y = cocMax; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl index 740ebabaff..6d55648f22 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/NewDepthOfFieldTileReduce.azsl @@ -19,6 +19,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass RWTexture2D m_minMaxCoC; // Texture dimensions. XY channels are width and height and ZW channels are 1 / width and 1 / height + // Auto-filled by the pass system when "ShaderImageDimensionsConstant" is specified in the .pass file float4 m_inputDimensions; float4 m_outputDimensions; @@ -59,7 +60,7 @@ void MainCS(uint3 group_thread_id : SV_GroupThreadID, uint3 group_id : SV_GroupI // For atomic min/max to work with uints, floating point values should be positive // Map from [-1, 1] range to [0, 2] and cast as uint InterlockedMin( LDS_MIN_COC[group_thread_id.x], asuint(cocMin + 1) ); - InterlockedMax( LDS_MAX_COC[group_thread_id.x], asuint(cocMax + 1) ); + InterlockedMax( LDS_MAX_COC[group_thread_id.x], asuint(cocMax + 1) ); // Sync LDS GroupMemoryBarrierWithGroupSync(); diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h index d529623c0a..159f91e744 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/NewDepthOfFieldPasses.h @@ -17,6 +17,29 @@ namespace AZ { namespace Render { + // Technique + // + // 1. This Depth of Field technique starts by downsampling the lighting buffer and calculating + // the circle of confusion (CoC) for each downsampled pixel. + // + // 2. It then computes the min and max CoC for tiles of 16x16 pixels + // + // 3. It expands the min and max in a 3x3 region (twice, so 5x5 at the end) so that each tile + // tile pixel has the min and max CoCs of the 5x5 tile region around it + // + // 4. We perform a 48 tap scatter-as-gather blur around each pixel + // + // 5. We perform a follow up 8 tap scatter-as-gather blur to fill the holes from the first blur + // + // 6. We composite the blurred half resolution image onto the full resolution lighting buffer + // + // See http://advances.realtimerendering.com/s2013/Sousa_Graphics_Gems_CryENGINE3.pptx + // for a more detailed explanation. + // + // Notes: The name NewDepthOfField is in contrast to the previously implemented depth of field method + // That method will be removed in a follow up change and at that point NewDepthOfField will be renamed + // to simple DepthOfField. + //! Parent pass for the new depth of field technique //! Main updates the view srg via the depth of field settings //! And enables/disables all depth of field passes based on component activation From 95c2ee0e9d4da1ced0e796fc0da03c9bd1ef03d7 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Fri, 22 Oct 2021 10:30:48 -0500 Subject: [PATCH 13/22] Added API for finding components based on required/incompatible services. Signed-off-by: Chris Galvan --- .../Component/EditorComponentAPIBus.h | 4 ++ .../Component/EditorComponentAPIComponent.cpp | 30 +++++++++ .../Component/EditorComponentAPIComponent.h | 1 + .../Entity/EditorEntityHelpers.cpp | 62 +++++++++++++++++++ .../Entity/EditorEntityHelpers.h | 10 +++ .../ComponentPalette/ComponentPaletteUtil.cpp | 62 +------------------ .../ComponentPalette/ComponentPaletteUtil.hxx | 12 ---- .../Tests/EntityInspectorTests.cpp | 7 ++- 8 files changed, 112 insertions(+), 76 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIBus.h index f7119f3e14..b639686269 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIBus.h @@ -36,6 +36,10 @@ namespace AzToolsFramework //! the entity type. virtual AZStd::vector FindComponentTypeIdsByEntityType(const AZStd::vector& componentTypeNames, EntityType entityType) = 0; + //! Return a list of type ids for components that match the required services filter, + //! and don't conflict with any of the incompatible services filter + virtual AZStd::vector FindComponentTypeIdsByService(const AZStd::vector& serviceFilter, const AZStd::vector& incompatibleServiceFilter) = 0; + //! Finds the component names from their type ids virtual AZStd::vector FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp index 30a7c603bd..2cca3804ea 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,7 @@ namespace AzToolsFramework serializeContext->Class(); serializeContext->RegisterGenericType>(); + serializeContext->RegisterGenericType>(); } if (auto behaviorContext = azrtti_cast(context)) @@ -99,6 +101,7 @@ namespace AzToolsFramework ->Attribute(AZ::Script::Attributes::Module, "editor") ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Event("FindComponentTypeIdsByEntityType", &EditorComponentAPIRequests::FindComponentTypeIdsByEntityType) + ->Event("FindComponentTypeIdsByService", &EditorComponentAPIRequests::FindComponentTypeIdsByService) ->Event("FindComponentTypeNames", &EditorComponentAPIRequests::FindComponentTypeNames) ->Event("BuildComponentTypeNameListByEntityType", &EditorComponentAPIRequests::BuildComponentTypeNameListByEntityType) ->Event("AddComponentsOfType", &EditorComponentAPIRequests::AddComponentsOfType) @@ -216,6 +219,33 @@ namespace AzToolsFramework return foundTypeIds; } + AZStd::vector EditorComponentAPIComponent::FindComponentTypeIdsByService(const AZStd::vector& serviceFilter, const AZStd::vector& incompatibleServiceFilter) + { + AZStd::vector foundTypeIds; + + m_serializeContext->EnumerateDerived( + [&foundTypeIds, serviceFilter, incompatibleServiceFilter](const AZ::SerializeContext::ClassData* componentClass, const AZ::Uuid& knownType) -> bool + { + AZ_UNUSED(knownType); + + if (componentClass->m_editData) + { + // If none of the required services are offered by this component, or the component + // can not be added by the user, skip to the next component + if (!OffersRequiredServices(componentClass, serviceFilter, incompatibleServiceFilter)) + { + return true; + } + + foundTypeIds.push_back(componentClass->m_typeId); + } + + return true; + }); + + return foundTypeIds; + } + AZStd::vector EditorComponentAPIComponent::FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) { AZStd::vector foundTypeNames; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.h index 2b74ea98c5..3e7eede77f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.h @@ -35,6 +35,7 @@ namespace AzToolsFramework // EditorComponentAPIBus ... AZStd::vector FindComponentTypeIdsByEntityType(const AZStd::vector& componentTypeNames, EditorComponentAPIRequests::EntityType entityType) override; + AZStd::vector FindComponentTypeIdsByService(const AZStd::vector& serviceFilter, const AZStd::vector& incompatibleServiceFilter) override; AZStd::vector FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) override; AZStd::vector BuildComponentTypeNameListByEntityType(EditorComponentAPIRequests::EntityType entityType) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp index 8d40162f52..28d6e2bc08 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp @@ -271,6 +271,68 @@ namespace AzToolsFramework return editorComponentBaseComponent; } + bool OffersRequiredServices( + const AZ::SerializeContext::ClassData* componentClass, + const AZStd::vector& serviceFilter, + const AZStd::vector& incompatibleServiceFilter + ) + { + AZ_Assert(componentClass, "Component class must not be null"); + + if (!componentClass) + { + return false; + } + + AZ::ComponentDescriptor* componentDescriptor = nullptr; + AZ::ComponentDescriptorBus::EventResult( + componentDescriptor, componentClass->m_typeId, &AZ::ComponentDescriptor::GetDescriptor); + if (!componentDescriptor) + { + return false; + } + + // If no services are provided, this function returns true + if (serviceFilter.empty()) + { + return true; + } + + AZ::ComponentDescriptor::DependencyArrayType providedServices; + componentDescriptor->GetProvidedServices(providedServices, nullptr); + + //reject this component if it does not offer any of the required services + if (AZStd::find_first_of( + providedServices.begin(), + providedServices.end(), + serviceFilter.begin(), + serviceFilter.end()) == providedServices.end()) + { + return false; + } + + //reject this component if it does offer any of the incompatible services + if (AZStd::find_first_of( + providedServices.begin(), + providedServices.end(), + incompatibleServiceFilter.begin(), + incompatibleServiceFilter.end()) != providedServices.end()) + { + return false; + } + + return true; + } + + bool OffersRequiredServices( + const AZ::SerializeContext::ClassData* componentClass, + const AZStd::vector& serviceFilter + ) + { + const AZStd::vector incompatibleServices; + return OffersRequiredServices(componentClass, serviceFilter, incompatibleServices); + } + bool ShouldInspectorShowComponent(const AZ::Component* component) { if (!component) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h index 73acb2deb0..c2d693c553 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h @@ -105,6 +105,16 @@ namespace AzToolsFramework AZ::ComponentDescriptor* GetComponentDescriptor(const AZ::Component* component); Components::EditorComponentDescriptor* GetEditorComponentDescriptor(const AZ::Component* component); Components::EditorComponentBase* GetEditorComponent(AZ::Component* component); + // Returns true if the given component provides at least one of the services specified or no services are provided + bool OffersRequiredServices( + const AZ::SerializeContext::ClassData* componentClass, + const AZStd::vector& serviceFilter, + const AZStd::vector& incompatibleServiceFilter + ); + bool OffersRequiredServices( + const AZ::SerializeContext::ClassData* componentClass, + const AZStd::vector& serviceFilter + ); /// Return true if the editor should show this component to users, /// false if the component should be hidden from users. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.cpp index 6f3727bdb4..b6f5b41b65 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.cpp @@ -12,6 +12,7 @@ #include #include #include +#include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags' needs to have dll-interface to be used by clients of class 'QLayoutItem' #include AZ_POP_DISABLE_WARNING @@ -20,67 +21,6 @@ namespace AzToolsFramework { namespace ComponentPaletteUtil { - bool OffersRequiredServices( - const AZ::SerializeContext::ClassData* componentClass, - const AZStd::vector& serviceFilter, - const AZStd::vector& incompatibleServiceFilter - ) - { - AZ_Assert(componentClass, "Component class must not be null"); - - if (!componentClass) - { - return false; - } - - AZ::ComponentDescriptor* componentDescriptor = nullptr; - EBUS_EVENT_ID_RESULT(componentDescriptor, componentClass->m_typeId, AZ::ComponentDescriptorBus, GetDescriptor); - if (!componentDescriptor) - { - return false; - } - - // If no services are provided, this function returns true - if (serviceFilter.empty()) - { - return true; - } - - AZ::ComponentDescriptor::DependencyArrayType providedServices; - componentDescriptor->GetProvidedServices(providedServices, nullptr); - - //reject this component if it does not offer any of the required services - if (AZStd::find_first_of( - providedServices.begin(), - providedServices.end(), - serviceFilter.begin(), - serviceFilter.end()) == providedServices.end()) - { - return false; - } - - //reject this component if it does offer any of the incompatible services - if (AZStd::find_first_of( - providedServices.begin(), - providedServices.end(), - incompatibleServiceFilter.begin(), - incompatibleServiceFilter.end()) != providedServices.end()) - { - return false; - } - - return true; - } - - bool OffersRequiredServices( - const AZ::SerializeContext::ClassData* componentClass, - const AZStd::vector& serviceFilter - ) - { - const AZStd::vector incompatibleServices; - return OffersRequiredServices(componentClass, serviceFilter, incompatibleServices); - } - bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass) { AZ_Assert(componentClass, "component class must not be null"); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.hxx index 2000d72c5c..dffb893c59 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.hxx @@ -26,18 +26,6 @@ namespace AzToolsFramework using ComponentIconTable = AZStd::map; - // Returns true if the given component provides at least one of the services specified or no services are provided - bool OffersRequiredServices( - const AZ::SerializeContext::ClassData* componentClass, - const AZStd::vector& serviceFilter, - const AZStd::vector& incompatibleServiceFilter - ); - - bool OffersRequiredServices( - const AZ::SerializeContext::ClassData* componentClass, - const AZStd::vector& serviceFilter - ); - // Returns true if the given component is addable by the user bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass); diff --git a/Code/Framework/AzToolsFramework/Tests/EntityInspectorTests.cpp b/Code/Framework/AzToolsFramework/Tests/EntityInspectorTests.cpp index 0fbc7eba98..d640a91eab 100644 --- a/Code/Framework/AzToolsFramework/Tests/EntityInspectorTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EntityInspectorTests.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include // Inspector Test Includes @@ -313,17 +314,17 @@ namespace UnitTest AZ_TEST_ASSERT(testComponent1_ProvidedServices.size() == 1); const AZ::SerializeContext::ClassData* testComponent1_ClassData = context->FindClassData(testComponent1_typeId); - EXPECT_TRUE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, testComponent1_ProvidedServices)); + EXPECT_TRUE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, testComponent1_ProvidedServices)); // Verify that OffersRequiredServices returns when given services provided by a different component AZ::ComponentDescriptor::DependencyArrayType testComponent2_ProvidedServices; Inspector_TestComponent2::GetProvidedServices(testComponent2_ProvidedServices); AZ_TEST_ASSERT(testComponent2_ProvidedServices.size() == 1); AZ_TEST_ASSERT(testComponent1_ProvidedServices != testComponent2_ProvidedServices); - EXPECT_FALSE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, testComponent2_ProvidedServices)); + EXPECT_FALSE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, testComponent2_ProvidedServices)); // verify that OffersRequiredServices returns true when provided with an empty list of services - EXPECT_TRUE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, AZ::ComponentDescriptor::DependencyArrayType())); + EXPECT_TRUE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, AZ::ComponentDescriptor::DependencyArrayType())); ////////////////////////////////////////////////////////////////////////// // TEST IsAddableByUser() From 993baeac7bf667a1964f343732db8e8e75afd645 Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Fri, 22 Oct 2021 09:37:04 -0700 Subject: [PATCH 14/22] Add a comment to inform that the process is limited to a single download Signed-off-by: AMZN-Phil --- Code/Tools/ProjectManager/Source/PythonBindings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 8b716666de..0e24d46815 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -1124,6 +1124,7 @@ namespace O3DE::ProjectManager AZ::Outcome PythonBindings::DownloadGem(const QString& gemName, std::function gemProgressCallback) { + // This process is currently limited to download a single gem at a time. bool downloadSucceeded = false; O3DEProjectManagerPy::currentProgressCallback = gemProgressCallback; O3DEProjectManagerPy::requestCancelDownload = false; From 7ba99262022e1b5746f264575f49092ab5722892 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 22 Oct 2021 11:10:37 -0700 Subject: [PATCH 15/22] The .shader file must now include the .azsl extension when referencing a .azsl file. It will no longer be automatically appended. Fixed an issue where the shader builder would incorrectly succeed when the .azsl file is missing. Also renamed some variables for more consistency. Updated all .shader files accordingly. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../AzslShaderBuilderSystemComponent.cpp | 2 +- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 18 +++++++------- .../Source/Editor/ShaderBuilderUtility.cpp | 24 ++++++++++++++----- .../Code/Source/Editor/ShaderBuilderUtility.h | 4 ++-- .../Shaders/AuxGeom/AuxGeomObject.shader | 2 +- .../Shaders/AuxGeom/AuxGeomObjectLit.shader | 2 +- .../Shaders/AuxGeom/AuxGeomWorld.shader | 2 +- .../Shaders/BRDFTexture/BRDFTextureCS.shader | 2 +- .../CheckerboardColorResolveCS.shader | 2 +- .../Shaders/ColorGrading/LutGeneration.shader | 2 +- .../Assets/Shaders/Depth/DepthPassSkin.shader | 2 +- .../DiffuseComposite.shader | 2 +- .../DiffuseGlobalFullscreen.shader | 2 +- .../DiffuseProbeGridDownsample.shader | 2 +- .../Common/Assets/Shaders/ImGui/ImGui.shader | 2 +- .../Shaders/LightCulling/LightCulling.shader | 2 +- .../LightCulling/LightCullingHeatmap.shader | 2 +- .../LightCulling/LightCullingRemap.shader | 2 +- .../LightCullingTilePrepare.shader | 2 +- .../Shaders/LuxCore/RenderTexture.shader | 2 +- .../Shaders/MorphTargets/MorphTargetCS.shader | 2 +- .../MotionVector/CameraMotionVector.shader | 2 +- .../MotionVector/MeshMotionVector.shader | 2 +- .../MotionVector/MeshMotionVectorSkin.shader | 2 +- .../AcesOutputTransformLut.shader | 2 +- .../ApplyShaperLookupTable.shader | 2 +- .../BakeAcesOutputTransformLutCS.shader | 2 +- .../BlendColorGradingLuts.shader | 2 +- .../Shaders/PostProcessing/BloomBlurCS.shader | 2 +- .../PostProcessing/BloomCompositeCS.shader | 2 +- .../PostProcessing/BloomDownsampleCS.shader | 2 +- .../ContrastAdaptiveSharpening.shader | 2 +- .../PostProcessing/ConvertToAcescg.shader | 2 +- .../PostProcessing/DepthDownsample.shader | 2 +- .../DepthOfFieldBlurBokeh.shader | 2 +- .../DepthOfFieldComposite.shader | 2 +- .../DepthOfFieldDownSample.shader | 2 +- .../PostProcessing/DepthOfFieldMask.shader | 2 +- .../PostProcessing/DepthOfFieldPrepare.shader | 2 +- .../DepthOfFieldWriteFocusDepthFromGpu.shader | 2 +- .../PostProcessing/DepthToLinearDepth.shader | 2 +- .../PostProcessing/DepthUpsample.shader | 2 +- .../DiffuseSpecularMerge.shader | 2 +- .../PostProcessing/DisplayMapper.shader | 2 +- .../DisplayMapperOnlyGammaCorrection.shader | 2 +- .../DownsampleLuminanceMinAvgMaxCS.shader | 2 +- .../DownsampleMinAvgMaxCS.shader | 2 +- .../PostProcessing/EyeAdaptation.shader | 2 +- .../FastDepthAwareBlurHor.shader | 2 +- .../FastDepthAwareBlurVer.shader | 2 +- .../PostProcessing/FullscreenCopy.shader | 2 +- .../PostProcessing/HDRColorGrading.shader | 2 +- .../LookModificationTransform.shader | 2 +- .../PostProcessing/LuminanceHeatmap.shader | 2 +- .../LuminanceHistogramGenerator.shader | 2 +- .../PostProcessing/MSAAResolveCustom.shader | 2 +- .../PostProcessing/MSAAResolveDepth.shader | 2 +- .../PostProcessing/ModulateTexture.shader | 2 +- .../PostProcessing/OutputTransform.shader | 2 +- .../SMAABlendingWeightCalculation.shader | 2 +- .../SMAAConvertToPerceptualColor.shader | 2 +- .../PostProcessing/SMAAEdgeDetection.shader | 2 +- .../SMAANeighborhoodBlending.shader | 2 +- .../ScreenSpaceSubsurfaceScatteringCS.shader | 2 +- .../Shaders/PostProcessing/SsaoCompute.shader | 2 +- .../Assets/Shaders/PostProcessing/Taa.shader | 2 +- .../PostProcessing/UniformColor.shader | 2 +- .../Reflections/ReflectionComposite.shader | 2 +- .../ReflectionGlobalFullscreen.shader | 2 +- .../ReflectionProbeBlendWeight.shader | 2 +- .../ReflectionProbeRenderInner.shader | 2 +- .../ReflectionProbeRenderOuter.shader | 2 +- .../Reflections/ReflectionProbeStencil.shader | 2 +- ...ReflectionScreenSpaceBlurHorizontal.shader | 2 +- .../ReflectionScreenSpaceBlurVertical.shader | 2 +- .../ReflectionScreenSpaceComposite.shader | 2 +- .../ReflectionScreenSpaceTrace.shader | 2 +- .../Shaders/Shadow/DepthExponentiation.shader | 2 +- .../Shaders/Shadow/KawaseShadowBlur.shader | 2 +- .../Assets/Shaders/Shadow/Shadowmap.shader | 2 +- .../Shaders/Shadow/ShadowmapSkin.shader | 2 +- .../SkinnedMesh/LinearSkinningCS.shader | 2 +- .../Assets/Shaders/SkyBox/SkyBox.shader | 2 +- .../Shaders/SkyBox/SkyBox_TwoOutputs.shader | 2 +- .../RPI/Assets/Shader/DecomposeMsImage.shader | 2 +- .../RPI/Assets/Shader/ImagePreview.shader | 2 +- .../Assets/Shaders/LyShineUI.shader | 2 +- .../Assets/Shaders/SimpleTextured.shader | 2 +- .../Assets/Shaders/TexturedIcon.shader | 2 +- .../Assets/Shaders/ImGuiAtom/ImGuiAtom.shader | 2 +- .../Shaders/Terrain/Terrain_Shadowmap.shader | 2 +- 91 files changed, 117 insertions(+), 105 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp index ffc5f40ef4..56f2fdec62 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp @@ -81,7 +81,7 @@ namespace AZ // Register Shader Asset Builder AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; - shaderAssetBuilderDescriptor.m_version = 105; // [AZSL] Changing inlineConstant to rootConstant keyword work. + shaderAssetBuilderDescriptor.m_version = 107; // Required .azsl extension in .shader file references // .shader file changes trigger rebuilds shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid(); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 3bc63b89a0..a0205efa72 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -151,11 +151,11 @@ namespace AZ void ShaderAssetBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const { - AZStd::string fullPath; - AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullPath, true); + AZStd::string shaderAssetSourceFileFullPath; + AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), shaderAssetSourceFileFullPath, true); ShaderBuilderUtility::IncludedFilesParser includedFilesParser; - AZ_TracePrintf(ShaderAssetBuilderName, "CreateJobs for Shader \"%s\"\n", fullPath.data()); + AZ_TracePrintf(ShaderAssetBuilderName, "CreateJobs for Shader \"%s\"\n", shaderAssetSourceFileFullPath.data()); // Used to synchronize versions of the ShaderAsset and ShaderVariantTreeAsset, especially during hot-reload. // Note it's probably important for this to be set once outside the platform loop so every platform's ShaderAsset @@ -166,7 +166,7 @@ namespace AZ // Need to get the name of the azsl file from the .shader source asset, to be able to declare a dependency to SRG Layout Job. // and the macro options to preprocess. - auto descriptorParseOutcome = ShaderBuilderUtility::LoadShaderDataJson(fullPath); + auto descriptorParseOutcome = ShaderBuilderUtility::LoadShaderDataJson(shaderAssetSourceFileFullPath); if (!descriptorParseOutcome.IsSuccess()) { AZ_Error( @@ -178,7 +178,7 @@ namespace AZ RPI::ShaderSourceData shaderSourceData = descriptorParseOutcome.TakeValue(); AZStd::string azslFullPath; - ShaderBuilderUtility::GetAbsolutePathToAzslFile(fullPath, shaderSourceData.m_source, azslFullPath); + ShaderBuilderUtility::GetAbsolutePathToAzslFile(shaderAssetSourceFileFullPath, shaderSourceData.m_source, azslFullPath); { // Add the AZSL as source dependency @@ -191,9 +191,9 @@ namespace AZ { AZ_Error( ShaderAssetBuilderName, false, "Shader program listed as the source entry does not exist: %s.", azslFullPath.c_str()); - // Treat as success, so when the azsl file shows up the AP will try to recompile. - response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; - return; + // Even though there was an error here, don't stop, because we need to report the SourceFileDependency so when the azsl + // file shows up the AP will try to recompile. We will go ahead and create the job anyway, and then ProcessJob can + // report the failure. } GlobalBuildOptions buildOptions = ReadBuildOptions(ShaderAssetBuilderName); @@ -229,7 +229,7 @@ namespace AZ } // for all request.m_enabledPlatforms AZ_TracePrintf( - ShaderAssetBuilderName, "CreateJobs for %s took %llu microseconds", fullPath.c_str(), + ShaderAssetBuilderName, "CreateJobs for %s took %llu microseconds", shaderAssetSourceFileFullPath.c_str(), AZStd::GetTimeNowMicroSecond() - shaderAssetBuildTimestamp); response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index 2c87a79068..e6c99630b2 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -70,11 +70,11 @@ namespace AZ return AZ::Success(shaderSourceData); } - void GetAbsolutePathToAzslFile(const AZStd::string& shaderTemplatePathAndFile, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteAzslPath) + void GetAbsolutePathToAzslFile(const AZStd::string& shaderSourceFileFullPath, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteAzslPath) { AZStd::string sourcePath; - AzFramework::StringFunc::Path::GetFullPath(shaderTemplatePathAndFile.data(), sourcePath); + AzFramework::StringFunc::Path::GetFullPath(shaderSourceFileFullPath.c_str(), sourcePath); AzFramework::StringFunc::Path::Normalize(specifiedShaderPathAndName); bool shaderNameHasPath = (specifiedShaderPathAndName.find(AZ_CORRECT_FILESYSTEM_SEPARATOR) != AZStd::string::npos); @@ -82,15 +82,27 @@ namespace AZ // Join will handle overlapping directory structures for us AzFramework::StringFunc::Path::Join(sourcePath.data(), specifiedShaderPathAndName.data(), absoluteAzslPath, shaderNameHasPath /* handle directory overlap? */, false /* be case insensitive? */); - AzFramework::StringFunc::Path::ReplaceExtension(absoluteAzslPath, "azsl"); + // The builders used to automatically set the ".azsl" extension, but no more, because that would make the .shader file confusing to read. + // Here we just detect the issue and instruct the user what to change. + // (There's no need to return a failure code, the builder will eventually fail anyway when it can't find the file). + if (!IO::FileIOBase::GetInstance()->Exists(absoluteAzslPath.c_str())) + { + AZStd::string absoluteAzslPathWithForcedExtension = absoluteAzslPath; + AzFramework::StringFunc::Path::ReplaceExtension(absoluteAzslPathWithForcedExtension, "azsl"); + + if (IO::FileIOBase::GetInstance()->Exists(absoluteAzslPathWithForcedExtension.c_str())) + { + AZ_Error(ShaderBuilderUtilityName, false, "When the .shader file references a .azsl file, it must include the \".azsl\" extension."); + } + } } AZStd::shared_ptr PrepareSourceInput( [[maybe_unused]] const char* builderName, - const AZStd::string& shaderAssetSourcePath, + const AZStd::string& shaderSourceFileFullPath, RPI::ShaderSourceData& sourceAsset) { - auto shaderAssetSourceFileParseOutput = ShaderBuilderUtility::LoadShaderDataJson(shaderAssetSourcePath); + auto shaderAssetSourceFileParseOutput = ShaderBuilderUtility::LoadShaderDataJson(shaderSourceFileFullPath); if (!shaderAssetSourceFileParseOutput.IsSuccess()) { AZ_Error(builderName, false, "Failed to load/parse Shader Descriptor JSON: %s", shaderAssetSourceFileParseOutput.GetError().c_str()); @@ -100,7 +112,7 @@ namespace AZ AZStd::shared_ptr files(new ShaderFiles); const AZStd::string& specifiedAzslName = sourceAsset.m_source; - ShaderBuilderUtility::GetAbsolutePathToAzslFile(shaderAssetSourcePath, specifiedAzslName, files->m_azslSourceFullPath); + ShaderBuilderUtility::GetAbsolutePathToAzslFile(shaderSourceFileFullPath, specifiedAzslName, files->m_azslSourceFullPath); // specifiedAzslName may have a relative path on it so need to strip it AzFramework::StringFunc::Path::GetFileName(specifiedAzslName.c_str(), files->m_azslFileName); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h index 5d45ade9cb..a27eddf2cc 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h @@ -33,12 +33,12 @@ namespace AZ { Outcome LoadShaderDataJson(const AZStd::string& fullPathToJsonFile); - void GetAbsolutePathToAzslFile(const AZStd::string& shaderTemplatePathAndFile, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteShaderPath); + void GetAbsolutePathToAzslFile(const AZStd::string& shaderSourceFileFullPath, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteShaderPath); //! Opens and read the .shader, returns expanded file paths AZStd::shared_ptr PrepareSourceInput( const char* builderName, - const AZStd::string& shaderAssetSourcePath, + const AZStd::string& shaderSourceFileFullPath, RPI::ShaderSourceData& sourceAsset); namespace AzslSubProducts diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObject.shader b/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObject.shader index 88120b3a9d..83012fe13c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObject.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObject.shader @@ -1,5 +1,5 @@ { - "Source" : "AuxGeomObject", + "Source" : "AuxGeomObject.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObjectLit.shader b/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObjectLit.shader index 98ace1da32..b06a0cd662 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObjectLit.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomObjectLit.shader @@ -1,5 +1,5 @@ { - "Source" : "AuxGeomObjectLit", + "Source" : "AuxGeomObjectLit.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomWorld.shader b/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomWorld.shader index ad49848f0f..2d7ff39999 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomWorld.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/AuxGeom/AuxGeomWorld.shader @@ -1,5 +1,5 @@ { - "Source" : "AuxGeomWorld", + "Source" : "AuxGeomWorld.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/BRDFTexture/BRDFTextureCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/BRDFTexture/BRDFTextureCS.shader index 50ce945edd..376e2bb5a3 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/BRDFTexture/BRDFTextureCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/BRDFTexture/BRDFTextureCS.shader @@ -1,5 +1,5 @@ { - "Source": "BRDFTextureCS", + "Source": "BRDFTextureCS.azsl", "ProgramSettings": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Checkerboard/CheckerboardColorResolveCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Checkerboard/CheckerboardColorResolveCS.shader index f21f3e5c01..c08065a550 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Checkerboard/CheckerboardColorResolveCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Checkerboard/CheckerboardColorResolveCS.shader @@ -1,5 +1,5 @@ { - "Source": "CheckerboardColorResolveCS", + "Source": "CheckerboardColorResolveCS.azsl", "CompilerHints": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.shader b/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.shader index 4e2c83db35..9c7e66fbfd 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.shader @@ -1,5 +1,5 @@ { - "Source" : "LutGeneration", + "Source" : "LutGeneration.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader index de6c989223..849c7e3441 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthPassSkin", + "Source" : "DepthPassSkin.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.shader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.shader index 1593f0bb66..ba145cd7cf 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.shader @@ -1,5 +1,5 @@ { - "Source" : "DiffuseComposite", + "Source" : "DiffuseComposite.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.shader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.shader index 3d4b711f63..1279775ad0 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.shader @@ -1,5 +1,5 @@ { - "Source" : "DiffuseGlobalFullscreen", + "Source" : "DiffuseGlobalFullscreen.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridDownsample.shader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridDownsample.shader index dff0f755d0..c3494e6bea 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridDownsample.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridDownsample.shader @@ -1,5 +1,5 @@ { - "Source" : "DiffuseProbeGridDownsample", + "Source" : "DiffuseProbeGridDownsample.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/ImGui/ImGui.shader b/Gems/Atom/Feature/Common/Assets/Shaders/ImGui/ImGui.shader index 4e742f8194..46729ff7f2 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/ImGui/ImGui.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/ImGui/ImGui.shader @@ -1,6 +1,6 @@ { - "Source" : "ImGui", + "Source" : "ImGui.azsl", "RasterState" : { "CullMode" : "None" }, diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.shader b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.shader index 6a4adcaade..24c1184b53 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCulling.shader @@ -1,5 +1,5 @@ { - "Source": "LightCulling", + "Source": "LightCulling.azsl", "CompilerHints": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingHeatmap.shader b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingHeatmap.shader index 99b6c314fb..65e6a205e4 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingHeatmap.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingHeatmap.shader @@ -1,5 +1,5 @@ { - "Source" : "LightCullingHeatmap", + "Source" : "LightCullingHeatmap.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingRemap.shader b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingRemap.shader index d1b52525b6..795f028eba 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingRemap.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingRemap.shader @@ -1,5 +1,5 @@ { - "Source": "LightCullingRemap", + "Source": "LightCullingRemap.azsl", "Compiler": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingTilePrepare.shader b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingTilePrepare.shader index 070bc8e2bc..6a3173da96 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingTilePrepare.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/LightCulling/LightCullingTilePrepare.shader @@ -1,5 +1,5 @@ { - "Source": "LightCullingTilePrepare", + "Source": "LightCullingTilePrepare.azsl", "CompilerHints": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/LuxCore/RenderTexture.shader b/Gems/Atom/Feature/Common/Assets/Shaders/LuxCore/RenderTexture.shader index 32fff758be..6035f98f5d 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/LuxCore/RenderTexture.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/LuxCore/RenderTexture.shader @@ -1,5 +1,5 @@ { - "Source" : "RenderTexture", + "Source" : "RenderTexture.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader index 08b1e7c298..38baa9ab87 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MorphTargets/MorphTargetCS.shader @@ -1,5 +1,5 @@ { - "Source": "MorphTargetCS", + "Source": "MorphTargetCS.azsl", "ProgramSettings": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/CameraMotionVector.shader b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/CameraMotionVector.shader index 4dee7cc702..f4a92a84d7 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/CameraMotionVector.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/CameraMotionVector.shader @@ -1,5 +1,5 @@ { - "Source": "CameraMotionVector", + "Source": "CameraMotionVector.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.shader b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.shader index c585060f3d..2badc21957 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.shader @@ -1,5 +1,5 @@ { - "Source" : "MeshMotionVector", + "Source" : "MeshMotionVector.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader index 9a50e4e2cf..a253c2704b 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader @@ -1,5 +1,5 @@ { - "Source" : "MeshMotionVectorSkin", + "Source" : "MeshMotionVectorSkin.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/AcesOutputTransformLut.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/AcesOutputTransformLut.shader index 69ffb44394..b0f3a81cc9 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/AcesOutputTransformLut.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/AcesOutputTransformLut.shader @@ -1,5 +1,5 @@ { - "Source" : "AcesOutputTransformLut", + "Source" : "AcesOutputTransformLut.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ApplyShaperLookupTable.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ApplyShaperLookupTable.shader index ec18e33e7d..328b4353d8 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ApplyShaperLookupTable.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ApplyShaperLookupTable.shader @@ -1,5 +1,5 @@ { - "Source" : "ApplyShaperLookupTable", + "Source" : "ApplyShaperLookupTable.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BakeAcesOutputTransformLutCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BakeAcesOutputTransformLutCS.shader index 9274fa701e..928360b5ab 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BakeAcesOutputTransformLutCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BakeAcesOutputTransformLutCS.shader @@ -1,5 +1,5 @@ { - "Source": "BakeAcesOutputTransformLutCS", + "Source": "BakeAcesOutputTransformLutCS.azsl", "ProgramSettings": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BlendColorGradingLuts.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BlendColorGradingLuts.shader index 10bccf1d42..ed647d8398 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BlendColorGradingLuts.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BlendColorGradingLuts.shader @@ -1,5 +1,5 @@ { - "Source": "BlendColorGradingLuts", + "Source": "BlendColorGradingLuts.azsl", "DrawList" : "forward", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomBlurCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomBlurCS.shader index 467ccbf867..caaf411d29 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomBlurCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomBlurCS.shader @@ -1,5 +1,5 @@ { - "Source": "BloomBlurCS", + "Source": "BloomBlurCS.azsl", "DrawList" : "forward", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomCompositeCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomCompositeCS.shader index 0be9455da1..26ada282ac 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomCompositeCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomCompositeCS.shader @@ -1,5 +1,5 @@ { - "Source": "BloomCompositeCS", + "Source": "BloomCompositeCS.azsl", "DrawList" : "forward", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomDownsampleCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomDownsampleCS.shader index 7f33a041db..f78c4d4837 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomDownsampleCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/BloomDownsampleCS.shader @@ -1,5 +1,5 @@ { - "Source": "BloomDownsampleCS", + "Source": "BloomDownsampleCS.azsl", "DrawList" : "forward", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ContrastAdaptiveSharpening.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ContrastAdaptiveSharpening.shader index 756ce0ec7a..75407d1095 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ContrastAdaptiveSharpening.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ContrastAdaptiveSharpening.shader @@ -1,5 +1,5 @@ { - "Source": "ContrastAdaptiveSharpening", + "Source": "ContrastAdaptiveSharpening.azsl", "ProgramSettings": { "EntryPoints": [ { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ConvertToAcescg.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ConvertToAcescg.shader index 82a70913d6..f5dae97b16 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ConvertToAcescg.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ConvertToAcescg.shader @@ -1,5 +1,5 @@ { - "Source" : "ConvertToAcescg", + "Source" : "ConvertToAcescg.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthDownsample.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthDownsample.shader index 77ae2b625c..6a66ff875d 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthDownsample.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthDownsample.shader @@ -1,5 +1,5 @@ { - "Source": "DepthDownsample", + "Source": "DepthDownsample.azsl", "ProgramSettings" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldBlurBokeh.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldBlurBokeh.shader index 56dc124196..611f0a917c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldBlurBokeh.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldBlurBokeh.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthOfFieldBlurBokeh", + "Source" : "DepthOfFieldBlurBokeh.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldComposite.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldComposite.shader index a3d5890aa0..581b20d1a6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldComposite.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldComposite.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthOfFieldComposite", + "Source" : "DepthOfFieldComposite.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldDownSample.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldDownSample.shader index 87b0ffc56c..4093ace95b 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldDownSample.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldDownSample.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthOfFieldDownSample", + "Source" : "DepthOfFieldDownSample.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldMask.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldMask.shader index 83c24caa4b..7535e57b5d 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldMask.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldMask.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthOfFieldMask", + "Source" : "DepthOfFieldMask.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldPrepare.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldPrepare.shader index 9d7788a6e2..ec33cbf995 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldPrepare.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldPrepare.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthOfFieldPrepare", + "Source" : "DepthOfFieldPrepare.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldWriteFocusDepthFromGpu.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldWriteFocusDepthFromGpu.shader index de6790c675..92243acb87 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldWriteFocusDepthFromGpu.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthOfFieldWriteFocusDepthFromGpu.shader @@ -1,5 +1,5 @@ { - "Source": "DepthOfFieldWriteFocusDepthFromGpu", + "Source": "DepthOfFieldWriteFocusDepthFromGpu.azsl", "ProgramSettings" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthToLinearDepth.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthToLinearDepth.shader index c8f2e6b48a..92e807fea6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthToLinearDepth.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthToLinearDepth.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthToLinearDepth", + "Source" : "DepthToLinearDepth.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthUpsample.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthUpsample.shader index 8ecf28f8d3..80a4fabb3c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthUpsample.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DepthUpsample.shader @@ -1,5 +1,5 @@ { - "Source": "DepthUpsample", + "Source": "DepthUpsample.azsl", "ProgramSettings" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DiffuseSpecularMerge.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DiffuseSpecularMerge.shader index 87ee6fcb17..fea445335b 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DiffuseSpecularMerge.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DiffuseSpecularMerge.shader @@ -1,5 +1,5 @@ { - "Source" : "DiffuseSpecularMerge", + "Source" : "DiffuseSpecularMerge.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapper.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapper.shader index f9fd37efb7..2b5c9998ef 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapper.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapper.shader @@ -1,5 +1,5 @@ { - "Source" : "DisplayMapper", + "Source" : "DisplayMapper.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapperOnlyGammaCorrection.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapperOnlyGammaCorrection.shader index fdd4b90ef9..51d3b22d12 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapperOnlyGammaCorrection.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DisplayMapperOnlyGammaCorrection.shader @@ -1,5 +1,5 @@ { - "Source" : "DisplayMapperOnlyGammaCorrection", + "Source" : "DisplayMapperOnlyGammaCorrection.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleLuminanceMinAvgMaxCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleLuminanceMinAvgMaxCS.shader index 3b541fe132..ba764ae2f1 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleLuminanceMinAvgMaxCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleLuminanceMinAvgMaxCS.shader @@ -1,5 +1,5 @@ { - "Source": "DownsampleLuminanceMinAvgMaxCS", + "Source": "DownsampleLuminanceMinAvgMaxCS.azsl", "ProgramSettings": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleMinAvgMaxCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleMinAvgMaxCS.shader index a3eb7e6bdb..c7f560c17b 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleMinAvgMaxCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/DownsampleMinAvgMaxCS.shader @@ -1,5 +1,5 @@ { - "Source": "DownsampleMinAvgMaxCS", + "Source": "DownsampleMinAvgMaxCS.azsl", "ProgramSettings": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/EyeAdaptation.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/EyeAdaptation.shader index e6e81b88fe..596af32317 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/EyeAdaptation.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/EyeAdaptation.shader @@ -1,5 +1,5 @@ { - "Source": "EyeAdaptation", + "Source": "EyeAdaptation.azsl", "ProgramSettings" : diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.shader index 74e5eeea42..d649584c44 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.shader @@ -1,5 +1,5 @@ { - "Source": "FastDepthAwareBlurHor", + "Source": "FastDepthAwareBlurHor.azsl", "ProgramSettings" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.shader index eb7b4225bb..b78cd6830a 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.shader @@ -1,5 +1,5 @@ { - "Source": "FastDepthAwareBlurVer", + "Source": "FastDepthAwareBlurVer.azsl", "ProgramSettings" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FullscreenCopy.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FullscreenCopy.shader index b6626cfc87..c82383167b 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FullscreenCopy.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FullscreenCopy.shader @@ -1,5 +1,5 @@ { - "Source" : "FullscreenCopy", + "Source" : "FullscreenCopy.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader index f76f6708b7..8b519b70e7 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader @@ -1,5 +1,5 @@ { - "Source" : "HDRColorGrading", + "Source" : "HDRColorGrading.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LookModificationTransform.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LookModificationTransform.shader index bc9dbda122..5b1d53da89 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LookModificationTransform.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LookModificationTransform.shader @@ -1,5 +1,5 @@ { - "Source" : "LookModificationTransform", + "Source" : "LookModificationTransform.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.shader index 9be5f49cc1..06368ff039 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHeatmap.shader @@ -1,5 +1,5 @@ { - "Source" : "LuminanceHeatmap", + "Source" : "LuminanceHeatmap.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader index f3dd11e11a..23e57b164f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader @@ -1,5 +1,5 @@ { - "Source": "LuminanceHistogramGenerator", + "Source": "LuminanceHistogramGenerator.azsl", "DrawList" : "forward", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveCustom.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveCustom.shader index e23dba6d73..6a08dbaaed 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveCustom.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveCustom.shader @@ -1,5 +1,5 @@ { - "Source": "MSAAResolveCustom", + "Source": "MSAAResolveCustom.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveDepth.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveDepth.shader index c9439d1033..74011db7fa 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveDepth.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/MSAAResolveDepth.shader @@ -1,5 +1,5 @@ { - "Source" : "MSAAResolveDepth", + "Source" : "MSAAResolveDepth.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "Always" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ModulateTexture.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ModulateTexture.shader index d4cd98a5cd..4341d04390 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ModulateTexture.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ModulateTexture.shader @@ -1,5 +1,5 @@ { - "Source": "ModulateTexture", + "Source": "ModulateTexture.azsl", "ProgramSettings" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/OutputTransform.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/OutputTransform.shader index 1a13a21063..5cb652e93d 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/OutputTransform.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/OutputTransform.shader @@ -1,5 +1,5 @@ { - "Source" : "OutputTransform", + "Source" : "OutputTransform.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAABlendingWeightCalculation.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAABlendingWeightCalculation.shader index 119f10fa47..cbca022dca 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAABlendingWeightCalculation.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAABlendingWeightCalculation.shader @@ -1,5 +1,5 @@ { - "Source" : "SMAABlendingWeightCalculation", + "Source" : "SMAABlendingWeightCalculation.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAConvertToPerceptualColor.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAConvertToPerceptualColor.shader index c009c62255..cccccd7418 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAConvertToPerceptualColor.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAConvertToPerceptualColor.shader @@ -1,5 +1,5 @@ { - "Source" : "SMAAConvertToPerceptualColor", + "Source" : "SMAAConvertToPerceptualColor.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAEdgeDetection.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAEdgeDetection.shader index 43110a1944..cb421a7e63 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAEdgeDetection.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAAEdgeDetection.shader @@ -1,5 +1,5 @@ { - "Source" : "SMAAEdgeDetection", + "Source" : "SMAAEdgeDetection.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAANeighborhoodBlending.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAANeighborhoodBlending.shader index b93672b961..caeffcff15 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAANeighborhoodBlending.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAANeighborhoodBlending.shader @@ -1,5 +1,5 @@ { - "Source" : "SMAANeighborhoodBlending", + "Source" : "SMAANeighborhoodBlending.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ScreenSpaceSubsurfaceScatteringCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ScreenSpaceSubsurfaceScatteringCS.shader index a54060f093..f6e89db84f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ScreenSpaceSubsurfaceScatteringCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/ScreenSpaceSubsurfaceScatteringCS.shader @@ -1,5 +1,5 @@ { - "Source": "ScreenSpaceSubsurfaceScatteringCS", + "Source": "ScreenSpaceSubsurfaceScatteringCS.azsl", "ProgramSettings": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.shader index 777400ca97..226f995cb6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.shader @@ -1,5 +1,5 @@ { - "Source": "SsaoCompute", + "Source": "SsaoCompute.azsl", "ProgramSettings" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/Taa.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/Taa.shader index f30ff92f20..fb0d510a8a 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/Taa.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/Taa.shader @@ -1,5 +1,5 @@ { - "Source": "Taa", + "Source": "Taa.azsl", "ProgramSettings": { "EntryPoints": [ { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/UniformColor.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/UniformColor.shader index 422199c420..5db8c97699 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/UniformColor.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/UniformColor.shader @@ -1,5 +1,5 @@ { - "Source" : "UniformColor", + "Source" : "UniformColor.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionComposite.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionComposite.shader index 847bf5e300..91bcd9b1b4 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionComposite.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionComposite.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionComposite", + "Source" : "ReflectionComposite.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.shader index 445a29c74f..f0b962c2eb 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionGlobalFullscreen", + "Source" : "ReflectionGlobalFullscreen.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.shader index 1da653f1e7..0e4cc83413 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionProbeBlendWeight", + "Source" : "ReflectionProbeBlendWeight.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.shader index 76cab60b3c..20dd4bcb56 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionProbeRenderInner", + "Source" : "ReflectionProbeRenderInner.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.shader index 9e60a5faf9..ce7b1c0487 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionProbeRenderOuter", + "Source" : "ReflectionProbeRenderOuter.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeStencil.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeStencil.shader index 538d746fba..7c23487dc1 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeStencil.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeStencil.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionProbeStencil", + "Source" : "ReflectionProbeStencil.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.shader index 013c42da57..aea21136dc 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionScreenSpaceBlurHorizontal", + "Source" : "ReflectionScreenSpaceBlurHorizontal.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurVertical.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurVertical.shader index d5ed94c4a9..dcebb4d2ae 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurVertical.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceBlurVertical.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionScreenSpaceBlurVertical", + "Source" : "ReflectionScreenSpaceBlurVertical.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.shader index d04189b0ba..d23adf898d 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceComposite.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionScreenSpaceComposite", + "Source" : "ReflectionScreenSpaceComposite.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceTrace.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceTrace.shader index a6e0b5df4e..563e0e3276 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceTrace.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionScreenSpaceTrace.shader @@ -1,5 +1,5 @@ { - "Source" : "ReflectionScreenSpaceTrace", + "Source" : "ReflectionScreenSpaceTrace.azsl", "RasterState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.shader index e2f860a169..7d969a491b 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.shader @@ -1,5 +1,5 @@ { - "Source" : "DepthExponentiation", + "Source" : "DepthExponentiation.azsl", "DrawList" : "shadow", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.shader index dacacdafff..4f317b31e6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.shader @@ -1,5 +1,5 @@ { - "Source" : "KawaseShadowBlur", + "Source" : "KawaseShadowBlur.azsl", "DrawList" : "shadow", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.shader index 6ef5be872a..d56f40ccdb 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.shader @@ -1,5 +1,5 @@ { - "Source" : "Shadowmap", + "Source" : "Shadowmap.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "LessEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader index 14c1352c08..40379d9193 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader @@ -1,5 +1,5 @@ { - "Source" : "ShadowmapSkin", + "Source" : "ShadowmapSkin.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "LessEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.shader b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.shader index 6bb4f3c289..a853d61dd8 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/SkinnedMesh/LinearSkinningCS.shader @@ -1,5 +1,5 @@ { - "Source": "LinearSkinningCS", + "Source": "LinearSkinningCS.azsl", "ProgramSettings": { diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox.shader b/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox.shader index 4edd81d07f..ff91e2f104 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox.shader @@ -1,5 +1,5 @@ { - "Source" : "SkyBox", + "Source" : "SkyBox.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox_TwoOutputs.shader b/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox_TwoOutputs.shader index ec80d4a20e..ecd4c5b18e 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox_TwoOutputs.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/SkyBox/SkyBox_TwoOutputs.shader @@ -1,5 +1,5 @@ { - "Source" : "SkyBox_TwoOutputs", + "Source" : "SkyBox_TwoOutputs.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/Atom/RPI/Assets/Shader/DecomposeMsImage.shader b/Gems/Atom/RPI/Assets/Shader/DecomposeMsImage.shader index 424c5ad6e3..943de52767 100644 --- a/Gems/Atom/RPI/Assets/Shader/DecomposeMsImage.shader +++ b/Gems/Atom/RPI/Assets/Shader/DecomposeMsImage.shader @@ -1,5 +1,5 @@ { - "Source": "DecomposeMsImage", + "Source": "DecomposeMsImage.azsl", "ProgramSettings": { diff --git a/Gems/Atom/RPI/Assets/Shader/ImagePreview.shader b/Gems/Atom/RPI/Assets/Shader/ImagePreview.shader index d87a4506a2..9a3594e2dd 100644 --- a/Gems/Atom/RPI/Assets/Shader/ImagePreview.shader +++ b/Gems/Atom/RPI/Assets/Shader/ImagePreview.shader @@ -1,5 +1,5 @@ { - "Source" : "ImagePreview", + "Source" : "ImagePreview.azsl", "DepthStencilState" : { "Depth" : { "Enable" : false, "CompareFunc" : "GreaterEqual" } diff --git a/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shader b/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shader index 9fd3e76813..14088e8c1a 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shader +++ b/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/LyShineUI.shader @@ -1,5 +1,5 @@ { - "Source" : "LyShineUI", + "Source" : "LyShineUI.azsl", "DepthStencilState" : { "Depth" : { diff --git a/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/SimpleTextured.shader b/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/SimpleTextured.shader index 0f4090c08e..0932ea00b7 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/SimpleTextured.shader +++ b/Gems/AtomLyIntegration/AtomBridge/Assets/Shaders/SimpleTextured.shader @@ -1,5 +1,5 @@ { - "Source" : "SimpleTextured", + "Source" : "SimpleTextured.azsl", "DepthStencilState" : { "Depth" : { diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.shader b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.shader index 601a2664b5..3793d9c8ed 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.shader +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.shader @@ -1,5 +1,5 @@ { - "Source" : "TexturedIcon", + "Source" : "TexturedIcon.azsl", "DepthStencilState" : { "Depth" : { diff --git a/Gems/AtomLyIntegration/ImguiAtom/Assets/Shaders/ImGuiAtom/ImGuiAtom.shader b/Gems/AtomLyIntegration/ImguiAtom/Assets/Shaders/ImGuiAtom/ImGuiAtom.shader index db96bfecb7..2f2a81ea3d 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Assets/Shaders/ImGuiAtom/ImGuiAtom.shader +++ b/Gems/AtomLyIntegration/ImguiAtom/Assets/Shaders/ImGuiAtom/ImGuiAtom.shader @@ -1,6 +1,6 @@ { - "Source" : "ImGuiAtom", + "Source" : "ImGuiAtom.azsl", "RasterState" : { "CullMode" : "None" }, diff --git a/Gems/Terrain/Assets/Shaders/Terrain/Terrain_Shadowmap.shader b/Gems/Terrain/Assets/Shaders/Terrain/Terrain_Shadowmap.shader index 290c83bddf..8f163d25cd 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/Terrain_Shadowmap.shader +++ b/Gems/Terrain/Assets/Shaders/Terrain/Terrain_Shadowmap.shader @@ -1,5 +1,5 @@ { - "Source" : "Terrain_DepthPass", + "Source" : "Terrain_DepthPass.azsl", "DepthStencilState" : { "Depth" : { "Enable" : true, "CompareFunc" : "LessEqual" } From ea1284c5810f738f400950bebc24a7d3021db807 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Fri, 22 Oct 2021 12:14:35 -0700 Subject: [PATCH 16/22] fixing up atom_feature_common_asset_files.cmake Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Common/Assets/atom_feature_common_asset_files.cmake | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index a33034a1b3..94b711e86c 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -160,8 +160,6 @@ set(FILES Passes/LutGeneration.pass Passes/MainPipeline.pass Passes/MainPipelineRenderToTexture.pass - Passes/ToolsPipeline.pass - Passes/ToolsPipelineRenderToTexture.pass Passes/MeshMotionVector.pass Passes/ModulateTexture.pass Passes/MorphTarget.pass @@ -211,8 +209,8 @@ set(FILES Passes/SsaoParent.pass Passes/SubsurfaceScattering.pass Passes/Taa.pass - Passes/ThumbnailPipeline.pass - Passes/ThumbnailPipelineRenderToTexture.pass + Passes/ToolsPipeline.pass + Passes/ToolsPipelineRenderToTexture.pass Passes/Transparent.pass Passes/TransparentParent.pass Passes/UI.pass @@ -306,6 +304,7 @@ set(FILES ShaderLib/Atom/Features/ScreenSpace/ScreenSpaceUtil.azsli ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli + ShaderLib/Atom/Features/Shadow/NormalOffsetShadows.azsli ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli ShaderLib/Atom/Features/Shadow/Shadow.azsli From 2fe4524458556e717d7cd6d9c98807bbb6a1ee74 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Fri, 22 Oct 2021 14:22:57 -0500 Subject: [PATCH 17/22] Terrain API cleanups (#4914) * Terrain API fixups Moved SurfaceData definitions in AzFramework out of terrain into separate files. Added some missing API calls: Get*FromVector2, GetSurfacePoint* Changed OrderedSurfaceTagWeightSet to SurfaceTagWeightList Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * PR feedback - remove IsClose check. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed PhysX test compile failures by redcoding a bunch of "dummy terrain" implementation that's unused. It was originally added for the PhysX Terrain component, but that component is long gone and has been superceded by the more generic PhysX Heightfield Collider. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed up failing terrain unit tests. Added API changes, and changed the assumption on where the surface weight sort is taking place. The component is no longer expected to provide the sorted list, it only needs to be sorted at the end coming out of the terrain system, so the unit tests have been modified to reflect that. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../AzFramework/Application/Application.cpp | 3 + .../AzFramework/SurfaceData/SurfaceData.cpp | 59 +++++++++ .../AzFramework/SurfaceData/SurfaceData.h | 72 +++++++++++ .../Terrain/TerrainDataRequestBus.cpp | 71 ++++------- .../Terrain/TerrainDataRequestBus.h | 116 +++++++++--------- .../AzFramework/azframework_files.cmake | 2 + .../Benchmarks/PhysXBenchmarksCommon.cpp | 4 - .../Tests/Benchmarks/PhysXBenchmarksCommon.h | 1 - Gems/PhysX/Code/Tests/EditorTestUtilities.cpp | 4 - Gems/PhysX/Code/Tests/EditorTestUtilities.h | 1 - Gems/PhysX/Code/Tests/PhysXTestFixtures.cpp | 4 - Gems/PhysX/Code/Tests/PhysXTestFixtures.h | 1 - Gems/PhysX/Code/Tests/PhysXTestUtil.h | 64 ---------- .../Ebuses/TerrainAreaSurfaceRequestBus.h | 4 +- Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h | 29 +++-- .../MockTerrainAreaSurfaceRequestBus.h | 2 +- .../TerrainSurfaceDataSystemComponent.cpp | 14 ++- .../TerrainSurfaceGradientListComponent.cpp | 7 +- .../TerrainSurfaceGradientListComponent.h | 2 +- .../Source/TerrainSystem/TerrainSystem.cpp | 111 ++++++++++------- .../Code/Source/TerrainSystem/TerrainSystem.h | 41 +++++-- .../Tests/TerrainSurfaceGradientListTests.cpp | 16 +-- Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 47 ++++--- 23 files changed, 390 insertions(+), 285 deletions(-) create mode 100644 Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp create mode 100644 Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp index 1f99a594fa..f8d0ea8bb1 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -278,6 +279,8 @@ namespace AzFramework AzFramework::RemoteStorageDriveConfig::Reflect(context); Physics::ReflectionUtils::ReflectPhysicsApi(context); + AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context); + AzFramework::SurfaceData::SurfacePoint::Reflect(context); AzFramework::Terrain::TerrainDataRequests::Reflect(context); if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) diff --git a/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp new file mode 100644 index 0000000000..55fec57bb6 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AzFramework::SurfaceData +{ + void SurfaceTagWeight::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType) + ->Field("m_weight", &SurfaceTagWeight::m_weight) + ; + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Category, "SurfaceData") + ->Constructor() + ->Property("surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType)) + ->Property("weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight)) + ; + } + } + + void SurfacePoint::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Field("m_position", &SurfacePoint::m_position) + ->Field("m_normal", &SurfacePoint::m_normal) + ->Field("m_surfaceTags", &SurfacePoint::m_surfaceTags) + ; + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->Class("AzFramework::SurfaceData::SurfacePoint") + ->Attribute(AZ::Script::Attributes::Category, "SurfaceData") + ->Constructor() + ->Property("position", BehaviorValueProperty(&SurfacePoint::m_position)) + ->Property("normal", BehaviorValueProperty(&SurfacePoint::m_normal)) + ->Property("surfaceTags", BehaviorValueProperty(&SurfacePoint::m_surfaceTags)) + ; + } + } + +} // namespace AzFramework::SurfaceData diff --git a/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h new file mode 100644 index 0000000000..77d9ae4239 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include +#include + +namespace AzFramework::SurfaceData +{ + namespace Constants + { + static constexpr const char* s_unassignedTagName = "(unassigned)"; + } + + struct SurfaceTagWeight + { + AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}"); + SurfaceTagWeight() = default; + SurfaceTagWeight(AZ::Crc32 surfaceType, float weight) + : m_surfaceType(surfaceType) + , m_weight(weight) + { + } + + AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName); + float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f] + + static void Reflect(AZ::ReflectContext* context); + }; + + struct SurfaceTagWeightComparator + { + bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const + { + // Return a deterministic sort order for surface tags from highest to lowest weight, with the surface types sorted + // in a predictable order when the weights are equal. The surface type sort order is meaningless since it is sorting CRC + // values, it's really just important for it to be stable. + // For the floating-point weight comparisons we use exact instead of IsClose value comparisons for a similar reason - we + // care about being sorted highest to lowest, but there's no inherent meaning in sorting surface types with *similar* weights + // together. + + if (tagWeight1.m_weight != tagWeight2.m_weight) + { + return tagWeight1.m_weight > tagWeight2.m_weight; + } + else + { + return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType; + } + } + }; + + using SurfaceTagWeightList = AZStd::vector; + + struct SurfacePoint final + { + AZ_TYPE_INFO(SurfacePoint, "{331A3D0E-BB1D-47BF-96A2-249FAA0D720D}"); + + AZ::Vector3 m_position; + AZ::Vector3 m_normal; + SurfaceTagWeightList m_surfaceTags; + + static void Reflect(AZ::ReflectContext* context); + }; +} // namespace AzFramework::SurfaceData diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp index 1fb29cfa30..561408db20 100644 --- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp +++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp @@ -8,56 +8,33 @@ #include "TerrainDataRequestBus.h" #include +#include -namespace AzFramework +namespace AzFramework::Terrain { - namespace SurfaceData + void TerrainDataRequests::Reflect(AZ::ReflectContext* context) { - void SurfaceTagWeight::Reflect(AZ::ReflectContext* context) + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType) - ->Field("m_weight", &SurfaceTagWeight::m_weight) - ; - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class("SurfaceTagWeight") - ->Property("m_surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType)) - ->Property("m_weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight)) - ; - } - } - } //namespace SurfaceData - - namespace Terrain - { - void TerrainDataRequests::Reflect(AZ::ReflectContext* context) - { - AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context); - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("TerrainDataRequestBus") - ->Attribute(AZ::Script::Attributes::Category, "Terrain") - ->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight) - ->Event("GetHeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeightFromFloats) - ->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight) - ->Event("GetMaxSurfaceWeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromFloats) - ->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats) - ->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal) - ->Event("GetNormalFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormalFromFloats) - ->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb) - ->Event("GetTerrainHeightQueryResolution", - &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution) - ; - - } - + behaviorContext->EBus("TerrainDataRequestBus") + ->Attribute(AZ::Script::Attributes::Category, "Terrain") + ->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight) + ->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal) + ->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight) + ->Event("GetMaxSurfaceWeightFromVector2", + &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromVector2) + ->Event("GetSurfaceWeights", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeights) + ->Event("GetSurfaceWeightsFromVector2", + &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeightsFromVector2) + ->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats) + ->Event("GetSurfacePoint", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePoint) + ->Event("GetSurfacePointFromVector2", + &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePointFromVector2) + ->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb) + ->Event("GetTerrainHeightQueryResolution", + &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution) + ; } - } //namespace Terrain -} // namespace AzFramework + } +} // namespace AzFramework::Terrain diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h index 3f6a8f0960..30a2f8e044 100644 --- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h +++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h @@ -8,50 +8,13 @@ #pragma once #include -#include #include #include #include -#include +#include namespace AzFramework { - namespace SurfaceData - { - namespace Constants - { - static const char* s_unassignedTagName = "(unassigned)"; - } - - struct SurfaceTagWeight - { - AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}"); - - AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName); - float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f] - - //! Don't call this directly. TerrainDataRequests::Reflect is doing it already. - static void Reflect(AZ::ReflectContext* context); - }; - - struct SurfaceTagWeightComparator - { - bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const - { - if (!AZ::IsClose(tagWeight1.m_weight, tagWeight2.m_weight)) - { - return tagWeight1.m_weight > tagWeight2.m_weight; - } - else - { - return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType; - } - } - }; - - using OrderedSurfaceTagWeightSet = AZStd::set; - } //namespace SurfaceData - namespace Terrain { @@ -91,49 +54,82 @@ namespace AzFramework //! Returns terrains height in meters at location x,y. //! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will become false, //! otherwise *terrainExistsPtr will become true. - virtual float GetHeight(AZ::Vector3 position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; - virtual float GetHeightFromFloats(float x, float y, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + virtual float GetHeight(const AZ::Vector3& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + virtual float GetHeightFromVector2( + const AZ::Vector2& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + virtual float GetHeightFromFloats( + float x, float y, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + + //! Returns true if there's a hole at location x,y. + //! Also returns true if there's no terrain data at location x,y. + virtual bool GetIsHole(const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR) const = 0; + virtual bool GetIsHoleFromVector2(const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR) const = 0; + virtual bool GetIsHoleFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR) const = 0; + + // Given an XY coordinate, return the surface normal. + //! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a + //! terrain HOLE then *terrainExistsPtr will be set to false, + //! otherwise *terrainExistsPtr will be set to true. + virtual AZ::Vector3 GetNormal( + const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + virtual AZ::Vector3 GetNormalFromVector2( + const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + virtual AZ::Vector3 GetNormalFromFloats( + float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; //! Given an XY coordinate, return the max surface type and weight. //! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false, //! otherwise *terrainExistsPtr will be set to true. - virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; - virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0; - virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight( + const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2( + const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0; + virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats( + float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; //! Given an XY coordinate, return the set of surface types and weights. The Vector3 input position version is defined to ignore //! the input Z value. virtual void GetSurfaceWeights( const AZ::Vector3& inPosition, - SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0; virtual void GetSurfaceWeightsFromVector2( const AZ::Vector2& inPosition, - SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0; virtual void GetSurfaceWeightsFromFloats( float x, float y, - SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0; //! Convenience function for low level systems that can't do a reverse lookup from Crc to string. Everyone else should use GetMaxSurfaceWeight or GetMaxSurfaceWeightFromFloats. //! Not available in the behavior context. //! Returns nullptr if the position is inside a hole or outside of the terrain boundaries. - virtual const char * GetMaxSurfaceName(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; - - //! Returns true if there's a hole at location x,y. - //! Also returns true if there's no terrain data at location x,y. - virtual bool GetIsHoleFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR) const = 0; + virtual const char* GetMaxSurfaceName( + const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; - // Given an XY coordinate, return the surface normal. - //! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false, - //! otherwise *terrainExistsPtr will be set to true. - virtual AZ::Vector3 GetNormal(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; - virtual AZ::Vector3 GetNormalFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; + //! Given an XY coordinate, return all terrain information at that location. The Vector3 input position version is defined + //! to ignore the input Z value. + virtual void GetSurfacePoint( + const AZ::Vector3& inPosition, + SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter = Sampler::DEFAULT, + bool* terrainExistsPtr = nullptr) const = 0; + virtual void GetSurfacePointFromVector2( + const AZ::Vector2& inPosition, + SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter = Sampler::DEFAULT, + bool* terrainExistsPtr = nullptr) const = 0; + virtual void GetSurfacePointFromFloats( + float x, + float y, + SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter = Sampler::DEFAULT, + bool* terrainExistsPtr = nullptr) const = 0; }; using TerrainDataRequestBus = AZ::EBus; @@ -169,6 +165,10 @@ namespace AzFramework } }; using TerrainDataNotificationBus = AZ::EBus; - - } //namespace Terrain + } // namespace Terrain } // namespace AzFramework + +namespace AZ +{ + AZ_TYPE_INFO_SPECIALIZE(AzFramework::Terrain::TerrainDataRequests::Sampler, "{D29BB6D7-3006-4114-858D-355EAA256B86}"); +} // namespace AZ diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index b338dbb0a8..d3196e8517 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -301,6 +301,8 @@ set(FILES Spawnable/SpawnableMonitor.cpp Spawnable/SpawnableSystemComponent.h Spawnable/SpawnableSystemComponent.cpp + SurfaceData/SurfaceData.h + SurfaceData/SurfaceData.cpp Terrain/TerrainDataRequestBus.h Terrain/TerrainDataRequestBus.cpp Thermal/ThermalInfo.h diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.cpp index 70b5aefe14..49dc249d25 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.cpp @@ -61,7 +61,6 @@ namespace PhysX::Benchmarks m_defaultScene = physicsSystem->GetScene(m_testSceneHandle); } - m_dummyTerrainComponentDescriptor = DummyTestTerrainComponent::CreateDescriptor(); Physics::DefaultWorldBus::Handler::BusConnect(); } @@ -80,9 +79,6 @@ namespace PhysX::Benchmarks m_testSceneHandle = AzPhysics::InvalidSceneHandle; TestUtils::ResetPhysXSystem(); - - m_dummyTerrainComponentDescriptor->ReleaseDescriptor(); - m_dummyTerrainComponentDescriptor = nullptr; } AzPhysics::SceneHandle PhysXBaseBenchmarkFixture::CreateDefaultTestScene() diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.h b/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.h index b32298d484..bde4995e27 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.h +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXBenchmarksCommon.h @@ -61,7 +61,6 @@ namespace PhysX::Benchmarks AzPhysics::Scene* m_defaultScene = nullptr; AzPhysics::SceneHandle m_testSceneHandle = AzPhysics::InvalidSceneHandle; - AZ::ComponentDescriptor* m_dummyTerrainComponentDescriptor = nullptr; }; } // namespace PhysX::Benchmarks #endif //HAVE_BENCHMARK diff --git a/Gems/PhysX/Code/Tests/EditorTestUtilities.cpp b/Gems/PhysX/Code/Tests/EditorTestUtilities.cpp index 63a689894c..fa794c58a5 100644 --- a/Gems/PhysX/Code/Tests/EditorTestUtilities.cpp +++ b/Gems/PhysX/Code/Tests/EditorTestUtilities.cpp @@ -52,14 +52,10 @@ namespace PhysXEditorTests m_defaultScene = physicsSystem->GetScene(m_defaultSceneHandle); } Physics::DefaultWorldBus::Handler::BusConnect(); - m_dummyTerrainComponentDescriptor = PhysX::DummyTestTerrainComponent::CreateDescriptor(); } void PhysXEditorFixture::TearDown() { - m_dummyTerrainComponentDescriptor->ReleaseDescriptor(); - m_dummyTerrainComponentDescriptor = nullptr; - Physics::DefaultWorldBus::Handler::BusDisconnect(); // prevents warnings from the undo cache on subsequent tests diff --git a/Gems/PhysX/Code/Tests/EditorTestUtilities.h b/Gems/PhysX/Code/Tests/EditorTestUtilities.h index b05a7561fe..9dfe40f366 100644 --- a/Gems/PhysX/Code/Tests/EditorTestUtilities.h +++ b/Gems/PhysX/Code/Tests/EditorTestUtilities.h @@ -51,7 +51,6 @@ namespace PhysXEditorTests // DefaultWorldBus AzPhysics::SceneHandle GetDefaultSceneHandle() const override; - AZ::ComponentDescriptor* m_dummyTerrainComponentDescriptor = nullptr; AzPhysics::SceneHandle m_defaultSceneHandle = AzPhysics::InvalidSceneHandle; AzPhysics::Scene* m_defaultScene = nullptr; diff --git a/Gems/PhysX/Code/Tests/PhysXTestFixtures.cpp b/Gems/PhysX/Code/Tests/PhysXTestFixtures.cpp index b3f233d388..c5fb2d5092 100644 --- a/Gems/PhysX/Code/Tests/PhysXTestFixtures.cpp +++ b/Gems/PhysX/Code/Tests/PhysXTestFixtures.cpp @@ -41,16 +41,12 @@ namespace PhysX } Physics::DefaultWorldBus::Handler::BusConnect(); - - m_dummyTerrainComponentDescriptor = DummyTestTerrainComponent::CreateDescriptor(); } void PhysXDefaultWorldTest::TearDown() { Physics::DefaultWorldBus::Handler::BusDisconnect(); m_defaultScene = nullptr; - m_dummyTerrainComponentDescriptor->ReleaseDescriptor(); - m_dummyTerrainComponentDescriptor = nullptr; //Clean up the Test scene if (auto* physicsSystem = AZ::Interface::Get()) diff --git a/Gems/PhysX/Code/Tests/PhysXTestFixtures.h b/Gems/PhysX/Code/Tests/PhysXTestFixtures.h index 9b00f7d892..6a8325a66f 100644 --- a/Gems/PhysX/Code/Tests/PhysXTestFixtures.h +++ b/Gems/PhysX/Code/Tests/PhysXTestFixtures.h @@ -33,7 +33,6 @@ namespace PhysX // DefaultWorldBus AzPhysics::SceneHandle GetDefaultSceneHandle() const override; - AZ::ComponentDescriptor* m_dummyTerrainComponentDescriptor = nullptr; AzPhysics::Scene* m_defaultScene = nullptr; AzPhysics::SceneHandle m_testSceneHandle = AzPhysics::InvalidSceneHandle; }; diff --git a/Gems/PhysX/Code/Tests/PhysXTestUtil.h b/Gems/PhysX/Code/Tests/PhysXTestUtil.h index 1c86768de7..d821fb146b 100644 --- a/Gems/PhysX/Code/Tests/PhysXTestUtil.h +++ b/Gems/PhysX/Code/Tests/PhysXTestUtil.h @@ -63,68 +63,4 @@ namespace PhysX AzPhysics::SimulatedBodyEvents::OnTriggerExit::Handler m_onTriggerExitHandler; }; - - //! Dummy component emulating presence of terrain by connecting to TerrainDataRequestBus - //! PhysX Terrain Component skips activation if there's no terrain present, - //! so in order to test it we also add the DummyTestTerrainComponent. - class DummyTestTerrainComponent - : public AZ::Component - , private AzFramework::Terrain::TerrainDataRequestBus::Handler - { - public: - AZ_COMPONENT(DummyTestTerrainComponent, "{EE4ECA23-9C27-4D5D-9C6F-271A19C0333E}"); - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC_CE("TerrainService")); - } - - private: - //////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Activate() override - { - AzFramework::Terrain::TerrainDataRequestBus::Handler::BusConnect(); - } - void Deactivate() override - { - AzFramework::Terrain::TerrainDataRequestBus::Handler::BusDisconnect(); - } - //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // TerrainDataRequestBus interface dummy implementation - AZ::Vector2 GetTerrainHeightQueryResolution() const override - { - return {}; - } - void SetTerrainHeightQueryResolution([[maybe_unused]] AZ::Vector2 queryResolution) override - { - } - - AZ::Aabb GetTerrainAabb() const override - { - return {}; - } - void SetTerrainAabb([[maybe_unused]] const AZ::Aabb& worldBounds) override - { - } - - float GetHeight(AZ::Vector3, Sampler, bool*) const override - { - return {}; - } - float GetHeightFromFloats(float, float, Sampler, bool*) const override { return {}; } - AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(AZ::Vector3, Sampler, bool*) const override { return {}; } - AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(const AZ::Vector2&, Sampler, bool*) const override { return {}; } - AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(float, float, Sampler, bool*) const override { return {}; } - void GetSurfaceWeights(const AZ::Vector3&, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet&, Sampler, bool*) const override {} - void GetSurfaceWeightsFromVector2(const AZ::Vector2&, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet&, Sampler, bool*) const override{}; - void GetSurfaceWeightsFromFloats(float, float, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet&, Sampler, bool*) const override {} - const char* GetMaxSurfaceName(AZ::Vector3, Sampler, bool*) const override { return {}; } - bool GetIsHoleFromFloats(float, float, Sampler) const override { return {}; } - AZ::Vector3 GetNormal(AZ::Vector3, Sampler, bool*) const override { return {}; } - AZ::Vector3 GetNormalFromFloats(float, float, Sampler, bool*) const override { return {}; } - //////////////////////////////////////////////////////////////////////// - }; - } // namespace PhysX diff --git a/Gems/Terrain/Code/Include/Terrain/Ebuses/TerrainAreaSurfaceRequestBus.h b/Gems/Terrain/Code/Include/Terrain/Ebuses/TerrainAreaSurfaceRequestBus.h index 4c04cf1e42..ed352b55df 100644 --- a/Gems/Terrain/Code/Include/Terrain/Ebuses/TerrainAreaSurfaceRequestBus.h +++ b/Gems/Terrain/Code/Include/Terrain/Ebuses/TerrainAreaSurfaceRequestBus.h @@ -27,8 +27,8 @@ namespace Terrain virtual ~TerrainAreaSurfaceRequests() = default; - //! Get the surfaces and weights from a gradient at a given position sorted into descending order of weight. - virtual void GetSurfaceWeights(const AZ::Vector3& inPosition, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights) const = 0; + //! Get the surfaces and weights from a gradient at a given position. + virtual void GetSurfaceWeights(const AZ::Vector3& inPosition, AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights) const = 0; }; using TerrainAreaSurfaceRequestBus = AZ::EBus; diff --git a/Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h b/Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h index bb1fa5683a..53d93be8ea 100644 --- a/Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h +++ b/Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h @@ -107,17 +107,28 @@ namespace UnitTest MOCK_METHOD1(SetTerrainHeightQueryResolution, void(AZ::Vector2)); MOCK_CONST_METHOD0(GetTerrainAabb, AZ::Aabb()); MOCK_METHOD1(SetTerrainAabb, void(const AZ::Aabb&)); - MOCK_CONST_METHOD3(GetHeight, float(AZ::Vector3, Sampler, bool*)); + MOCK_CONST_METHOD3(GetHeight, float(const AZ::Vector3&, Sampler, bool*)); + MOCK_CONST_METHOD3(GetHeightFromVector2, float(const AZ::Vector2&, Sampler, bool*)); MOCK_CONST_METHOD4(GetHeightFromFloats, float(float, float, Sampler, bool*)); - MOCK_CONST_METHOD3(GetMaxSurfaceWeight, AzFramework::SurfaceData::SurfaceTagWeight(AZ::Vector3, Sampler, bool*)); - MOCK_CONST_METHOD3(GetMaxSurfaceWeightFromVector2, AzFramework::SurfaceData::SurfaceTagWeight(const AZ::Vector2&, Sampler, bool*)); - MOCK_CONST_METHOD4(GetMaxSurfaceWeightFromFloats, AzFramework::SurfaceData::SurfaceTagWeight(float, float, Sampler, bool*)); - MOCK_CONST_METHOD4(GetSurfaceWeights, void(const AZ::Vector3&, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet&, Sampler, bool*)); - MOCK_CONST_METHOD4(GetSurfaceWeightsFromVector2, void(const AZ::Vector2&, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet&, Sampler, bool*)); - MOCK_CONST_METHOD5(GetSurfaceWeightsFromFloats, void(float, float, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet&, Sampler, bool*)); - MOCK_CONST_METHOD3(GetMaxSurfaceName, const char*(AZ::Vector3, Sampler, bool*)); + MOCK_CONST_METHOD2(GetIsHole, bool(const AZ::Vector3&, Sampler)); + MOCK_CONST_METHOD2(GetIsHoleFromVector2, bool(const AZ::Vector2&, Sampler)); MOCK_CONST_METHOD3(GetIsHoleFromFloats, bool(float, float, Sampler)); - MOCK_CONST_METHOD3(GetNormal, AZ::Vector3(AZ::Vector3, Sampler, bool*)); + MOCK_CONST_METHOD3(GetNormal, AZ::Vector3(const AZ::Vector3&, Sampler, bool*)); + MOCK_CONST_METHOD3(GetNormalFromVector2, AZ::Vector3(const AZ::Vector2&, Sampler, bool*)); MOCK_CONST_METHOD4(GetNormalFromFloats, AZ::Vector3(float, float, Sampler, bool*)); + MOCK_CONST_METHOD3(GetMaxSurfaceWeight, AzFramework::SurfaceData::SurfaceTagWeight(const AZ::Vector3&, Sampler, bool*)); + MOCK_CONST_METHOD3(GetMaxSurfaceWeightFromVector2, AzFramework::SurfaceData::SurfaceTagWeight(const AZ::Vector2&, Sampler, bool*)); + MOCK_CONST_METHOD4(GetMaxSurfaceWeightFromFloats, AzFramework::SurfaceData::SurfaceTagWeight(float, float, Sampler, bool*)); + MOCK_CONST_METHOD4(GetSurfaceWeights, void(const AZ::Vector3&, AzFramework::SurfaceData::SurfaceTagWeightList&, Sampler, bool*)); + MOCK_CONST_METHOD4( + GetSurfaceWeightsFromVector2, void(const AZ::Vector2&, AzFramework::SurfaceData::SurfaceTagWeightList&, Sampler, bool*)); + MOCK_CONST_METHOD5( + GetSurfaceWeightsFromFloats, void(float, float, AzFramework::SurfaceData::SurfaceTagWeightList&, Sampler, bool*)); + MOCK_CONST_METHOD3(GetMaxSurfaceName, const char*(const AZ::Vector3&, Sampler, bool*)); + MOCK_CONST_METHOD4(GetSurfacePoint, void(const AZ::Vector3&, AzFramework::SurfaceData::SurfacePoint&, Sampler, bool*)); + MOCK_CONST_METHOD4( + GetSurfacePointFromVector2, void(const AZ::Vector2&, AzFramework::SurfaceData::SurfacePoint&, Sampler, bool*)); + MOCK_CONST_METHOD5( + GetSurfacePointFromFloats, void(float, float, AzFramework::SurfaceData::SurfacePoint&, Sampler, bool*)); }; } // namespace UnitTest diff --git a/Gems/Terrain/Code/Mocks/Terrain/MockTerrainAreaSurfaceRequestBus.h b/Gems/Terrain/Code/Mocks/Terrain/MockTerrainAreaSurfaceRequestBus.h index c5a04b4265..665bf581bc 100644 --- a/Gems/Terrain/Code/Mocks/Terrain/MockTerrainAreaSurfaceRequestBus.h +++ b/Gems/Terrain/Code/Mocks/Terrain/MockTerrainAreaSurfaceRequestBus.h @@ -28,7 +28,7 @@ namespace UnitTest MOCK_METHOD0(Activate, void()); MOCK_METHOD0(Deactivate, void()); - MOCK_CONST_METHOD2(GetSurfaceWeights, void(const AZ::Vector3&, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet&)); + MOCK_CONST_METHOD2(GetSurfaceWeights, void(const AZ::Vector3&, AzFramework::SurfaceData::SurfaceTagWeightList&)); }; } // namespace UnitTest diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp index 0346ff7281..7395e66d06 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp @@ -149,13 +149,17 @@ namespace Terrain if (terrain->GetTerrainAabb().Contains(inPosition)) { bool isTerrainValidAtPoint = false; - const float terrainHeight = terrain->GetHeight(inPosition, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR, &isTerrainValidAtPoint); + AzFramework::SurfaceData::SurfacePoint terrainSurfacePoint; + terrain->GetSurfacePoint( + inPosition, terrainSurfacePoint, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR, + &isTerrainValidAtPoint); + const bool isHole = !isTerrainValidAtPoint; SurfaceData::SurfacePoint point; point.m_entityId = GetEntityId(); - point.m_position = AZ::Vector3(inPosition.GetX(), inPosition.GetY(), terrainHeight); - point.m_normal = terrain->GetNormal(inPosition); + point.m_position = terrainSurfacePoint.m_position; + point.m_normal = terrainSurfacePoint.m_normal; // Always add a "terrain" or "terrainHole" tag. const AZ::Crc32 terrainTag = @@ -163,9 +167,7 @@ namespace Terrain SurfaceData::AddMaxValueForMasks(point.m_masks, terrainTag, 1.0f); // Add all of the surface tags that the terrain has at this point. - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet surfaceWeights; - terrain->GetSurfaceWeights(point.m_position, surfaceWeights); - for (auto& tag : surfaceWeights) + for (auto& tag : terrainSurfacePoint.m_surfaceTags) { SurfaceData::AddMaxValueForMasks(point.m_masks, tag.m_surfaceType, tag.m_weight); } diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp index 958e175cf3..5b76f15d74 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp @@ -166,7 +166,7 @@ namespace Terrain void TerrainSurfaceGradientListComponent::GetSurfaceWeights( const AZ::Vector3& inPosition, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights) const + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights) const { outSurfaceWeights.clear(); @@ -178,10 +178,7 @@ namespace Terrain GradientSignal::GradientRequestBus::EventResult(weight, mapping.m_gradientEntityId, &GradientSignal::GradientRequestBus::Events::GetValue, params); - AzFramework::SurfaceData::SurfaceTagWeight tagWeight; - tagWeight.m_surfaceType = mapping.m_surfaceTag; - tagWeight.m_weight = weight; - outSurfaceWeights.emplace(tagWeight); + outSurfaceWeights.emplace_back(mapping.m_surfaceTag, weight); } } diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h index bb30029f35..20851c127f 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h @@ -72,7 +72,7 @@ namespace Terrain bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override; // TerrainAreaSurfaceRequestBus - void GetSurfaceWeights(const AZ::Vector3& inPosition, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights) const override; + void GetSurfaceWeights(const AZ::Vector3& inPosition, AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights) const override; private: ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index 821e0bd2e2..fa1d483a5d 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -241,7 +241,12 @@ float TerrainSystem::GetTerrainAreaHeight(float x, float y, bool& terrainExists) return height; } -float TerrainSystem::GetHeight(AZ::Vector3 position, Sampler sampler, bool* terrainExistsPtr) const +float TerrainSystem::GetHeight(const AZ::Vector3& position, Sampler sampler, bool* terrainExistsPtr) const +{ + return GetHeightSynchronous(position.GetX(), position.GetY(), sampler, terrainExistsPtr); +} + +float TerrainSystem::GetHeightFromVector2(const AZ::Vector2& position, Sampler sampler, bool* terrainExistsPtr) const { return GetHeightSynchronous(position.GetX(), position.GetY(), sampler, terrainExistsPtr); } @@ -251,6 +256,20 @@ float TerrainSystem::GetHeightFromFloats(float x, float y, Sampler sampler, bool return GetHeightSynchronous(x, y, sampler, terrainExistsPtr); } +bool TerrainSystem::GetIsHole(const AZ::Vector3& position, Sampler sampler) const +{ + bool terrainExists = false; + GetHeightSynchronous(position.GetX(), position.GetY(), sampler, &terrainExists); + return !terrainExists; +} + +bool TerrainSystem::GetIsHoleFromVector2(const AZ::Vector2& position, Sampler sampler) const +{ + bool terrainExists = false; + GetHeightSynchronous(position.GetX(), position.GetY(), sampler, &terrainExists); + return !terrainExists; +} + bool TerrainSystem::GetIsHoleFromFloats(float x, float y, Sampler sampler) const { bool terrainExists = false; @@ -287,7 +306,12 @@ AZ::Vector3 TerrainSystem::GetNormalSynchronous(float x, float y, Sampler sample return outNormal; } -AZ::Vector3 TerrainSystem::GetNormal(AZ::Vector3 position, Sampler sampler, bool* terrainExistsPtr) const +AZ::Vector3 TerrainSystem::GetNormal(const AZ::Vector3& position, Sampler sampler, bool* terrainExistsPtr) const +{ + return GetNormalSynchronous(position.GetX(), position.GetY(), sampler, terrainExistsPtr); +} + +AZ::Vector3 TerrainSystem::GetNormalFromVector2(const AZ::Vector2& position, Sampler sampler, bool* terrainExistsPtr) const { return GetNormalSynchronous(position.GetX(), position.GetY(), sampler, terrainExistsPtr); } @@ -299,7 +323,7 @@ AZ::Vector3 TerrainSystem::GetNormalFromFloats(float x, float y, Sampler sampler AzFramework::SurfaceData::SurfaceTagWeight TerrainSystem::GetMaxSurfaceWeight( - const AZ::Vector3 position, Sampler sampleFilter, bool* terrainExistsPtr) const + const AZ::Vector3& position, Sampler sampleFilter, bool* terrainExistsPtr) const { return GetMaxSurfaceWeightFromFloats(position.GetX(), position.GetY(), sampleFilter, terrainExistsPtr); } @@ -317,7 +341,7 @@ AzFramework::SurfaceData::SurfaceTagWeight TerrainSystem::GetMaxSurfaceWeightFro *terrainExistsPtr = true; } - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet weightSet; + AzFramework::SurfaceData::SurfaceTagWeightList weightSet; GetOrderedSurfaceWeights(x, y, sampleFilter, weightSet, terrainExistsPtr); @@ -329,6 +353,38 @@ AzFramework::SurfaceData::SurfaceTagWeight TerrainSystem::GetMaxSurfaceWeightFro return *weightSet.begin(); } +void TerrainSystem::GetSurfacePoint( + const AZ::Vector3& inPosition, + AzFramework::SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter, + bool* terrainExistsPtr) const +{ + outSurfacePoint.m_position = inPosition; + outSurfacePoint.m_position.SetZ(GetHeightSynchronous(inPosition.GetX(), inPosition.GetY(), sampleFilter, terrainExistsPtr)); + outSurfacePoint.m_normal = GetNormalSynchronous(inPosition.GetX(), inPosition.GetY(), sampleFilter, nullptr); + GetSurfaceWeights(inPosition, outSurfacePoint.m_surfaceTags, sampleFilter, nullptr); +} + +void TerrainSystem::GetSurfacePointFromVector2( + const AZ::Vector2& inPosition, + AzFramework::SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter, + bool* terrainExistsPtr) const +{ + GetSurfacePoint(AZ::Vector3(inPosition.GetX(), inPosition.GetY(), 0.0f), outSurfacePoint, sampleFilter, terrainExistsPtr); +} + +void TerrainSystem::GetSurfacePointFromFloats( + float x, + float y, + AzFramework::SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter, + bool* terrainExistsPtr) const +{ + GetSurfacePoint(AZ::Vector3(x, y, 0.0f), outSurfacePoint, sampleFilter, terrainExistsPtr); +} + + AZ::EntityId TerrainSystem::FindBestAreaEntityAtPosition(float x, float y, AZ::Aabb& bounds) const { AZ::Vector3 inPosition = AZ::Vector3(x, y, 0); @@ -354,7 +410,7 @@ void TerrainSystem::GetOrderedSurfaceWeights( const float x, const float y, [[maybe_unused]] Sampler sampler, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, bool* terrainExistsPtr) const { AZ::Aabb bounds; @@ -377,54 +433,40 @@ void TerrainSystem::GetOrderedSurfaceWeights( // Get all the surfaces with weights at the given point. Terrain::TerrainAreaSurfaceRequestBus::Event( bestAreaId, &Terrain::TerrainAreaSurfaceRequestBus::Events::GetSurfaceWeights, inPosition, outSurfaceWeights); + + AZStd::sort(outSurfaceWeights.begin(), outSurfaceWeights.end(), AzFramework::SurfaceData::SurfaceTagWeightComparator()); } void TerrainSystem::GetSurfaceWeights( const AZ::Vector3& inPosition, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter, bool* terrainExistsPtr) const { - if (terrainExistsPtr) - { - *terrainExistsPtr = true; - } - GetOrderedSurfaceWeights(inPosition.GetX(), inPosition.GetY(), sampleFilter, outSurfaceWeights, terrainExistsPtr); } void TerrainSystem::GetSurfaceWeightsFromVector2( const AZ::Vector2& inPosition, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter, bool* terrainExistsPtr) const { - // For now, always set terrainExists to true, as we don't have a way to author data for terrain holes yet. - if (terrainExistsPtr) - { - *terrainExistsPtr = true; - } GetOrderedSurfaceWeights(inPosition.GetX(), inPosition.GetY(), sampleFilter, outSurfaceWeights, terrainExistsPtr); } void TerrainSystem::GetSurfaceWeightsFromFloats( - float x, - float y, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + float x, float y, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter, bool* terrainExistsPtr) const { - // For now, always set terrainExists to true, as we don't have a way to author data for terrain holes yet. - if (terrainExistsPtr) - { - *terrainExistsPtr = true; - } - GetOrderedSurfaceWeights(x, y, sampleFilter, outSurfaceWeights, terrainExistsPtr); } -const char* TerrainSystem::GetMaxSurfaceName([[maybe_unused]] AZ::Vector3 position, [[maybe_unused]] Sampler sampleFilter, [[maybe_unused]] bool* terrainExistsPtr) const +const char* TerrainSystem::GetMaxSurfaceName( + [[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] Sampler sampleFilter, [[maybe_unused]] bool* terrainExistsPtr) const { // For now, always set terrainExists to true, as we don't have a way to author data for terrain holes yet. if (terrainExistsPtr) @@ -436,21 +478,6 @@ const char* TerrainSystem::GetMaxSurfaceName([[maybe_unused]] AZ::Vector3 positi } /* -void TerrainSystem::GetSurfacePoint( - const AZ::Vector3& inPosition, [[maybe_unused]] Sampler sampleFilter, SurfaceData::SurfacePoint& outSurfacePoint) -{ - // TODO: Handle sampleFilter - - float sampleX = inPosition.GetX(); - float sampleY = inPosition.GetY(); - - GetHeight(inPosition, sampleFilter, outSurfacePoint.m_position); - //outSurfacePoint.m_position = AZ::Vector3(sampleX, sampleY, GetHeightSynchronous(sampleX, sampleY)); - outSurfacePoint.m_normal = GetNormalSynchronous(sampleX, sampleY); -} - - - void TerrainSystem::ProcessHeightsFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, Sampler sampleFilter, SurfacePointRegionFillCallback perPositionCallback, TerrainDataReadyCallback onComplete) { diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index 66c48850ef..956424f048 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -62,7 +62,8 @@ namespace Terrain //! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain //! HOLE then *terrainExistsPtr will become false, //! otherwise *terrainExistsPtr will become true. - float GetHeight(AZ::Vector3 position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; + float GetHeight(const AZ::Vector3& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; + float GetHeightFromVector2(const AZ::Vector2& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; float GetHeightFromFloats(float x, float y, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; //! Given an XY coordinate, return the max surface type and weight. @@ -70,7 +71,7 @@ namespace Terrain //! HOLE then *terrainExistsPtr will be set to false, //! otherwise *terrainExistsPtr will be set to true. AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight( - const AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; + const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2( const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const override; AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats( @@ -78,18 +79,18 @@ namespace Terrain void GetSurfaceWeights( const AZ::Vector3& inPosition, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const override; void GetSurfaceWeightsFromVector2( const AZ::Vector2& inPosition, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const override; void GetSurfaceWeightsFromFloats( float x, float y, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const override; @@ -97,10 +98,12 @@ namespace Terrain //! GetMaxSurfaceWeight or GetMaxSurfaceWeightFromFloats. Not available in the behavior context. Returns nullptr if the position is //! inside a hole or outside of the terrain boundaries. const char* GetMaxSurfaceName( - AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; + const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; //! Returns true if there's a hole at location x,y. //! Also returns true if there's no terrain data at location x,y. + bool GetIsHole(const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR) const override; + bool GetIsHoleFromVector2(const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR) const override; bool GetIsHoleFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR) const override; // Given an XY coordinate, return the surface normal. @@ -108,10 +111,30 @@ namespace Terrain //! HOLE then *terrainExistsPtr will be set to false, //! otherwise *terrainExistsPtr will be set to true. AZ::Vector3 GetNormal( - AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; + const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; + AZ::Vector3 GetNormalFromVector2( + const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; AZ::Vector3 GetNormalFromFloats( float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; + void GetSurfacePoint( + const AZ::Vector3& inPosition, + AzFramework::SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter = Sampler::DEFAULT, + bool* terrainExistsPtr = nullptr) const override; + void GetSurfacePointFromVector2( + const AZ::Vector2& inPosition, + AzFramework::SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter = Sampler::DEFAULT, + bool* terrainExistsPtr = nullptr) const override; + void GetSurfacePointFromFloats( + float x, + float y, + AzFramework::SurfaceData::SurfacePoint& outSurfacePoint, + Sampler sampleFilter = Sampler::DEFAULT, + bool* terrainExistsPtr = nullptr) const override; + + private: void ClampPosition(float x, float y, AZ::Vector2& outPosition, AZ::Vector2& normalizedDelta) const; @@ -120,11 +143,11 @@ namespace Terrain const float x, const float y, Sampler sampler, - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, + AzFramework::SurfaceData::SurfaceTagWeightList& outSurfaceWeights, bool* terrainExistsPtr) const; float GetHeightSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; float GetTerrainAreaHeight(float x, float y, bool& terrainExists) const; - AZ::Vector3 GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; + AZ::Vector3 GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; // AZ::TickBus::Handler overrides ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; diff --git a/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp b/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp index 2a645b3f94..dea861bda5 100644 --- a/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSurfaceGradientListTests.cpp @@ -91,10 +91,10 @@ namespace UnitTest } }; - TEST_F(TerrainSurfaceGradientListTest, SurfaceGradientReturnsSurfaceWeightsInOrder) + TEST_F(TerrainSurfaceGradientListTest, SurfaceGradientReturnsSurfaceWeights) { - // When there is more that one surface/weight defined and added to the component, they should all - // be returned in descending weight order. + // When there is more than one surface/weight defined and added to the component, they should all + // be returned. The component isn't required to return them in descending order. AddSurfaceGradientListToEntities(); m_entity->Activate(); @@ -109,15 +109,15 @@ namespace UnitTest NiceMock mockGradientRequests2(m_gradientEntity2->GetId()); ON_CALL(mockGradientRequests2, GetValue).WillByDefault(Return(gradient2Value)); - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet weightSet; + AzFramework::SurfaceData::SurfaceTagWeightList weightList; Terrain::TerrainAreaSurfaceRequestBus::Event( - m_entity->GetId(), &Terrain::TerrainAreaSurfaceRequestBus::Events::GetSurfaceWeights, AZ::Vector3::CreateZero(), weightSet); + m_entity->GetId(), &Terrain::TerrainAreaSurfaceRequestBus::Events::GetSurfaceWeights, AZ::Vector3::CreateZero(), weightList); - AZ::Crc32 expectedCrcList[] = { AZ::Crc32(surfaceTag2), AZ::Crc32(surfaceTag1) }; - const float expectedWeightList[] = { gradient2Value, gradient1Value }; + AZ::Crc32 expectedCrcList[] = { AZ::Crc32(surfaceTag1), AZ::Crc32(surfaceTag2) }; + const float expectedWeightList[] = { gradient1Value, gradient2Value }; int index = 0; - for (const auto& surfaceWeight : weightSet) + for (const auto& surfaceWeight : weightList) { EXPECT_EQ(surfaceWeight.m_surfaceType, expectedCrcList[index]); EXPECT_NEAR(surfaceWeight.m_weight, expectedWeightList[index], 0.01f); diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp index f273a85e26..4d149e8527 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -475,8 +475,10 @@ namespace UnitTest } } - TEST_F(TerrainSystemTest, GetSurfaceWeightsReturnsAllValidSurfaceWeights) + TEST_F(TerrainSystemTest, GetSurfaceWeightsReturnsAllValidSurfaceWeightsInOrder) { + // When there is more than one surface/weight defined, they should all be returned in descending weight order. + CreateAndActivateTerrainSystem(); const AZ::Aabb aabb = AZ::Aabb::CreateFromMinMax(AZ::Vector3::CreateZero(), AZ::Vector3::CreateOne()); @@ -490,32 +492,41 @@ namespace UnitTest const AZ::Crc32 tag1("tag1"); const AZ::Crc32 tag2("tag2"); + const AZ::Crc32 tag3("tag3"); + const float tag1Weight = 0.8f; + const float tag2Weight = 1.0f; + const float tag3Weight = 0.5f; - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet orderedSurfaceWeights; - - AzFramework::SurfaceData::SurfaceTagWeight tagWeight1; - tagWeight1.m_surfaceType = tag1; - tagWeight1.m_weight = 1.0f; - orderedSurfaceWeights.emplace(tagWeight1); - - AzFramework::SurfaceData::SurfaceTagWeight tagWeight2; - tagWeight2.m_surfaceType = tag2; - tagWeight2.m_weight = 0.8f; - orderedSurfaceWeights.emplace(tagWeight2); + AzFramework::SurfaceData::SurfaceTagWeightList orderedSurfaceWeights + { + { tag1, tag1Weight }, { tag2, tag2Weight }, { tag3, tag3Weight } + }; NiceMock mockSurfaceRequests(entity->GetId()); ON_CALL(mockSurfaceRequests, GetSurfaceWeights).WillByDefault(SetArgReferee<1>(orderedSurfaceWeights)); - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet outSurfaceWeights; + AzFramework::SurfaceData::SurfaceTagWeightList outSurfaceWeights; // Asking for values outside the layer spawner bounds, should result in no results. m_terrainSystem->GetSurfaceWeights(aabb.GetMax() + AZ::Vector3::CreateOne(), outSurfaceWeights); EXPECT_TRUE(outSurfaceWeights.empty()); - // Inside the layer spawner box should give us both the added surface weights. + // Inside the layer spawner box should give us all of the added surface weights. m_terrainSystem->GetSurfaceWeights(aabb.GetCenter(), outSurfaceWeights); - EXPECT_EQ(outSurfaceWeights.size(), 2); + EXPECT_EQ(outSurfaceWeights.size(), 3); + + // The weights should be returned in decreasing order. + AZ::Crc32 expectedCrcList[] = { tag2, tag1, tag3 }; + const float expectedWeightList[] = { tag2Weight, tag1Weight, tag3Weight }; + + int index = 0; + for (const auto& surfaceWeight : outSurfaceWeights) + { + EXPECT_EQ(surfaceWeight.m_surfaceType, expectedCrcList[index]); + EXPECT_NEAR(surfaceWeight.m_weight, expectedWeightList[index], 0.01f); + index++; + } } TEST_F(TerrainSystemTest, GetMaxSurfaceWeightsReturnsBiggestValidSurfaceWeight) @@ -534,17 +545,17 @@ namespace UnitTest const AZ::Crc32 tag1("tag1"); const AZ::Crc32 tag2("tag2"); - AzFramework::SurfaceData::OrderedSurfaceTagWeightSet orderedSurfaceWeights; + AzFramework::SurfaceData::SurfaceTagWeightList orderedSurfaceWeights; AzFramework::SurfaceData::SurfaceTagWeight tagWeight1; tagWeight1.m_surfaceType = tag1; tagWeight1.m_weight = 1.0f; - orderedSurfaceWeights.emplace(tagWeight1); + orderedSurfaceWeights.emplace_back(tagWeight1); AzFramework::SurfaceData::SurfaceTagWeight tagWeight2; tagWeight2.m_surfaceType = tag2; tagWeight2.m_weight = 0.8f; - orderedSurfaceWeights.emplace(tagWeight2); + orderedSurfaceWeights.emplace_back(tagWeight2); NiceMock mockSurfaceRequests(entity->GetId()); ON_CALL(mockSurfaceRequests, GetSurfaceWeights).WillByDefault(SetArgReferee<1>(orderedSurfaceWeights)); From 243532c5debc7c65c20b11cb066eee593cbd8485 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Fri, 22 Oct 2021 14:33:36 -0500 Subject: [PATCH 18/22] Addressed feedback from PR 4874. (#4915) * Addressed feedback from PR 4874. * Removed second copy of HeightfieldProviderBus.h from cmake file * Changed CookedMeshShapeConfiguration and HeightfieldShapeConfiguration to have less messy implementations, instead opting for the slightly less messy const_cast inside of Utils.cpp and DebugDraw.cpp. * Changed InitHeightfieldShapeConfiguraiton to CreateHeightfieldShapeConfiguration with a better API signature. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed indentation Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../Physics/ShapeConfiguration.cpp | 21 +++++++++--- .../AzFramework/Physics/ShapeConfiguration.h | 14 ++++---- .../AzFramework/azframework_files.cmake | 1 - Gems/PhysX/Code/Editor/DebugDraw.cpp | 6 +++- .../EditorHeightfieldColliderComponent.cpp | 4 +-- .../Source/HeightfieldColliderComponent.cpp | 2 +- Gems/PhysX/Code/Source/Utils.cpp | 32 +++++++++++++------ Gems/PhysX/Code/Source/Utils.h | 2 +- 8 files changed, 54 insertions(+), 28 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp index 9bf00d9707..db8004d83a 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp +++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp @@ -286,12 +286,17 @@ namespace Physics return m_type; } - void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const + const void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const { return m_cachedNativeMesh; } - void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh) const + void* CookedMeshShapeConfiguration::GetCachedNativeMesh() + { + return m_cachedNativeMesh; + } + + void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh) { m_cachedNativeMesh = cachedNativeMesh; } @@ -353,12 +358,17 @@ namespace Physics return *this; } - void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const + const void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const { return m_cachedNativeHeightfield; } - void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield) const + void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() + { + return m_cachedNativeHeightfield; + } + + void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield) { if (m_cachedNativeHeightfield) { @@ -427,4 +437,5 @@ namespace Physics { m_maxHeightBounds = maxBounds; } -} +} // namespace Physics + diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h index 3bcf336af6..bd9d6a6aa7 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h @@ -187,8 +187,9 @@ namespace Physics MeshType GetMeshType() const; - void* GetCachedNativeMesh() const; - void SetCachedNativeMesh(void* cachedNativeMesh) const; + void* GetCachedNativeMesh(); + const void* GetCachedNativeMesh() const; + void SetCachedNativeMesh(void* cachedNativeMesh); private: void ReleaseCachedNativeMesh(); @@ -197,7 +198,7 @@ namespace Physics MeshType m_type = MeshType::TriangleMesh; //! Cached native mesh object (e.g. PxConvexMesh or PxTriangleMesh). This data is not serialized. - mutable void* m_cachedNativeMesh = nullptr; + void* m_cachedNativeMesh = nullptr; }; class HeightfieldShapeConfiguration @@ -217,8 +218,9 @@ namespace Physics return ShapeType::Heightfield; } - void* GetCachedNativeHeightfield() const; - void SetCachedNativeHeightfield(void* cachedNativeHeightfield) const; + const void* GetCachedNativeHeightfield() const; + void* GetCachedNativeHeightfield(); + void SetCachedNativeHeightfield(void* cachedNativeHeightfield); AZ::Vector2 GetGridResolution() const; void SetGridResolution(const AZ::Vector2& gridSpacing); int32_t GetNumColumns() const; @@ -246,6 +248,6 @@ namespace Physics //! The grid of sample points for the heightfield. AZStd::vector m_samples; //! An optional storage pointer for the physics system to cache its native heightfield representation. - mutable void* m_cachedNativeHeightfield{ nullptr }; + void* m_cachedNativeHeightfield{ nullptr }; }; } // namespace Physics diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index d3196e8517..e03d166cfc 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -252,7 +252,6 @@ set(FILES Physics/Shape.h Physics/ShapeConfiguration.h Physics/ShapeConfiguration.cpp - Physics/HeightfieldProviderBus.h Physics/SystemBus.h Physics/ColliderComponentBus.h Physics/RagdollPhysicsBus.h diff --git a/Gems/PhysX/Code/Editor/DebugDraw.cpp b/Gems/PhysX/Code/Editor/DebugDraw.cpp index 734557205a..90a1eb6004 100644 --- a/Gems/PhysX/Code/Editor/DebugDraw.cpp +++ b/Gems/PhysX/Code/Editor/DebugDraw.cpp @@ -264,7 +264,11 @@ namespace PhysX case Physics::ShapeType::CookedMesh: { const auto& cookedMeshConfig = static_cast(shapeConfig); - physx::PxBase* meshData = static_cast(cookedMeshConfig.GetCachedNativeMesh()); + const physx::PxBase* constMeshData = static_cast(cookedMeshConfig.GetCachedNativeMesh()); + + // Specifically removing the const from the meshData pointer because the physx APIs expect this pointer to be non-const. + physx::PxBase* meshData = const_cast(constMeshData); + if (meshData) { if (meshData->is()) diff --git a/Gems/PhysX/Code/Source/EditorHeightfieldColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorHeightfieldColliderComponent.cpp index 96b1bd51f5..0f09258524 100644 --- a/Gems/PhysX/Code/Source/EditorHeightfieldColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorHeightfieldColliderComponent.cpp @@ -201,9 +201,7 @@ namespace PhysX void EditorHeightfieldColliderComponent::InitHeightfieldShapeConfiguration() { - Physics::HeightfieldShapeConfiguration& configuration = static_cast(*m_shapeConfig); - - Utils::InitHeightfieldShapeConfiguration(GetEntityId(), configuration); + *m_shapeConfig = Utils::CreateHeightfieldShapeConfiguration(GetEntityId()); } void EditorHeightfieldColliderComponent::RefreshHeightfield() diff --git a/Gems/PhysX/Code/Source/HeightfieldColliderComponent.cpp b/Gems/PhysX/Code/Source/HeightfieldColliderComponent.cpp index 9bc209982d..c1fa09f21f 100644 --- a/Gems/PhysX/Code/Source/HeightfieldColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/HeightfieldColliderComponent.cpp @@ -139,7 +139,7 @@ namespace PhysX { Physics::HeightfieldShapeConfiguration& configuration = static_cast(*m_shapeConfig.second); - Utils::InitHeightfieldShapeConfiguration(GetEntityId(), configuration); + configuration = Utils::CreateHeightfieldShapeConfiguration(GetEntityId()); } void HeightfieldColliderComponent::RefreshHeightfield() diff --git a/Gems/PhysX/Code/Source/Utils.cpp b/Gems/PhysX/Code/Source/Utils.cpp index 72e17aff70..b4e1e768c3 100644 --- a/Gems/PhysX/Code/Source/Utils.cpp +++ b/Gems/PhysX/Code/Source/Utils.cpp @@ -67,7 +67,7 @@ namespace PhysX } void CreatePxGeometryFromHeightfield( - const Physics::HeightfieldShapeConfiguration& heightfieldConfig, physx::PxGeometryHolder& pxGeometry) + Physics::HeightfieldShapeConfiguration& heightfieldConfig, physx::PxGeometryHolder& pxGeometry) { physx::PxHeightField* heightfield = nullptr; @@ -264,9 +264,14 @@ namespace PhysX } case Physics::ShapeType::CookedMesh: { - const Physics::CookedMeshShapeConfiguration& cookedMeshShapeConfig = + const Physics::CookedMeshShapeConfiguration& constCookedMeshShapeConfig = static_cast(shapeConfiguration); + // We are deliberately removing the const off of the ShapeConfiguration here because we're going to change the cached + // native mesh pointer that gets stored in the configuration. + Physics::CookedMeshShapeConfiguration& cookedMeshShapeConfig = + const_cast(constCookedMeshShapeConfig); + physx::PxBase* nativeMeshObject = nullptr; // Use the cached mesh object if it is there, otherwise create one and save in the shape configuration @@ -303,13 +308,18 @@ namespace PhysX return false; } case Physics::ShapeType::Heightfield: - { - const Physics::HeightfieldShapeConfiguration& heightfieldConfig = - static_cast(shapeConfiguration); + { + const Physics::HeightfieldShapeConfiguration& constHeightfieldConfig = + static_cast(shapeConfiguration); - CreatePxGeometryFromHeightfield(heightfieldConfig, pxGeometry); - break; - } + // We are deliberately removing the const off of the ShapeConfiguration here because we're going to change the cached + // native heightfield pointer that gets stored in the configuration. + Physics::HeightfieldShapeConfiguration& heightfieldConfig = + const_cast(constHeightfieldConfig); + + CreatePxGeometryFromHeightfield(heightfieldConfig, pxGeometry); + break; + } default: AZ_Warning("PhysX Rigid Body", false, "Shape not supported in PhysX. Shape Type: %d", shapeType); return false; @@ -1518,9 +1528,9 @@ namespace PhysX return entityWorldTransformWithoutScale * jointLocalTransformWithoutScale; } - void InitHeightfieldShapeConfiguration(AZ::EntityId entityId, Physics::HeightfieldShapeConfiguration& configuration) + Physics::HeightfieldShapeConfiguration CreateHeightfieldShapeConfiguration(AZ::EntityId entityId) { - configuration = Physics::HeightfieldShapeConfiguration(); + Physics::HeightfieldShapeConfiguration configuration; AZ::Vector2 gridSpacing(1.0f); Physics::HeightfieldProviderRequestsBus::EventResult( @@ -1549,6 +1559,8 @@ namespace PhysX samples, entityId, &Physics::HeightfieldProviderRequestsBus::Events::GetHeightsAndMaterials); configuration.SetSamples(samples); + + return configuration; } } // namespace Utils diff --git a/Gems/PhysX/Code/Source/Utils.h b/Gems/PhysX/Code/Source/Utils.h index 54a81bb28d..525db03315 100644 --- a/Gems/PhysX/Code/Source/Utils.h +++ b/Gems/PhysX/Code/Source/Utils.h @@ -188,7 +188,7 @@ namespace PhysX //! Returns defaultValue if the input is infinite or NaN, otherwise returns the input unchanged. const AZ::Vector3& Sanitize(const AZ::Vector3& input, const AZ::Vector3& defaultValue = AZ::Vector3::CreateZero()); - void InitHeightfieldShapeConfiguration(AZ::EntityId entityId, Physics::HeightfieldShapeConfiguration& configuration); + Physics::HeightfieldShapeConfiguration CreateHeightfieldShapeConfiguration(AZ::EntityId entityId); namespace Geometry { From 45926d0dbddc3bb8a294bb407cb07ade47bdd37b Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Fri, 22 Oct 2021 12:37:43 -0700 Subject: [PATCH 19/22] LYN-7539 + LYN-7541 | Focus Mode - Show prefab names and dirty markers instead of instance names in breadcrumbs (#4850) * Change Prefab Focus breadcrumb widget to display template filename instead of instance container entity name. Also display dirty state for the template (*) and refresh it in real time. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Streamline path creation code; fix stem retrieval to ensure extension is cut correctly; delay refresh one frame when path is clicked to correctly refresh it. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Remove test code. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Simplify code to use Native directly. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor variable renaming and comment adjustments to make them clearer. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Prefab/PrefabFocusHandler.cpp | 57 ++++++++++++++++--- .../Prefab/PrefabFocusHandler.h | 5 +- .../Prefab/PrefabPublicNotificationBus.h | 4 ++ .../Prefab/PrefabSystemComponent.cpp | 11 ++-- .../Prefab/PrefabViewportFocusPathHandler.cpp | 5 ++ 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index 8bc258fef9..5ba7382831 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace AzToolsFramework::Prefab { @@ -79,7 +80,7 @@ namespace AzToolsFramework::Prefab auto editUndo = aznew PrefabFocusUndo("Edit Prefab"); editUndo->Capture(entityId); editUndo->SetParent(undoBatch.GetUndoBatch()); - ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, editUndo); + FocusOnPrefabInstanceOwningEntityId(entityId); } return AZ::Success(); @@ -94,9 +95,7 @@ namespace AzToolsFramework::Prefab InstanceOptionalReference focusedInstance = m_instanceFocusHierarchy[index]; - FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId()); - - return AZ::Success(); + return FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId()); } PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) @@ -255,7 +254,7 @@ namespace AzToolsFramework::Prefab void PrefabFocusHandler::OnEntityInfoUpdatedName(AZ::EntityId entityId, [[maybe_unused]]const AZStd::string& name) { - // Determine if the entityId is the container for any of the instances in the vector + // Determine if the entityId is the container for any of the instances in the vector. auto result = AZStd::find_if( m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(), [entityId](const InstanceOptionalReference& instance) @@ -279,6 +278,25 @@ namespace AzToolsFramework::Prefab PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged); } + void PrefabFocusHandler::OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, [[maybe_unused]] bool status) + { + // Determine if the templateId matches any of the instances in the vector. + auto result = AZStd::find_if( + m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(), + [templateId](const InstanceOptionalReference& instance) + { + return (instance->get().GetTemplateId() == templateId); + } + ); + + if (result != m_instanceFocusHierarchy.end()) + { + // Refresh the path and notify changes. + RefreshInstanceFocusPath(); + PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged); + } + } + void PrefabFocusHandler::RefreshInstanceFocusList() { m_instanceFocusHierarchy.clear(); @@ -293,17 +311,42 @@ namespace AzToolsFramework::Prefab currentInstance = currentInstance->get().GetParentInstance(); } - // Invert the vector, since we need the top instance to be at index 0 + // Invert the vector, since we need the top instance to be at index 0. AZStd::reverse(m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end()); } void PrefabFocusHandler::RefreshInstanceFocusPath() { + auto prefabSystemComponentInterface = AZ::Interface::Get(); + m_instanceFocusPath.clear(); + size_t index = 0; + size_t maxIndex = m_instanceFocusHierarchy.size() - 1; + for (const InstanceOptionalReference& instance : m_instanceFocusHierarchy) { - m_instanceFocusPath.Append(instance->get().GetContainerEntity()->get().GetName()); + AZStd::string prefabName; + + if (index < maxIndex) + { + // Get the filename without the extension (stem). + prefabName = instance->get().GetTemplateSourcePath().Stem().Native(); + } + else + { + // Get the full filename. + prefabName = instance->get().GetTemplateSourcePath().Filename().Native(); + } + + if (prefabSystemComponentInterface->IsTemplateDirty(instance->get().GetTemplateId())) + { + prefabName += "*"; + } + + m_instanceFocusPath.Append(prefabName); + + ++index; } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index cb8165e7f0..9decaed1ec 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -64,8 +64,9 @@ namespace AzToolsFramework::Prefab void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& name) override; // PrefabPublicNotifications overrides ... - void OnPrefabInstancePropagationEnd(); - + void OnPrefabInstancePropagationEnd() override; + void OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, bool status) override; + private: PrefabFocusOperationResult FocusOnPrefabInstance(InstanceOptionalReference focusedInstance); void RefreshInstanceFocusList(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicNotificationBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicNotificationBus.h index 65725b04de..8b0d446f51 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicNotificationBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicNotificationBus.h @@ -9,6 +9,7 @@ #pragma once #include +#include namespace AzToolsFramework { @@ -22,6 +23,9 @@ namespace AzToolsFramework virtual void OnPrefabInstancePropagationBegin() {} virtual void OnPrefabInstancePropagationEnd() {} + + virtual void OnPrefabTemplateDirtyFlagUpdated( + [[maybe_unused]] TemplateId templateId, [[maybe_unused]] bool status) {} }; using PrefabPublicNotificationBus = AZ::EBus; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index b1fdf9784d..c930c66786 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -185,7 +185,7 @@ namespace AzToolsFramework if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal) { templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator()); - templateToUpdate->get().MarkAsDirty(true); + SetTemplateDirtyFlag(templateId, true); PropagateTemplateChanges(templateId); } } @@ -813,11 +813,12 @@ namespace AzToolsFramework void PrefabSystemComponent::SetTemplateDirtyFlag(TemplateId templateId, bool dirty) { - auto templateRef = FindTemplate(templateId); - - if (templateRef.has_value()) + if (auto templateReference = FindTemplate(templateId); templateReference.has_value()) { - templateRef->get().MarkAsDirty(dirty); + templateReference->get().MarkAsDirty(dirty); + + PrefabPublicNotificationBus::Broadcast( + &PrefabPublicNotificationBus::Events::OnPrefabTemplateDirtyFlagUpdated, templateId, dirty); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp index 21ada94184..52cf3279a4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp @@ -10,6 +10,8 @@ #include +#include + namespace AzToolsFramework::Prefab { PrefabViewportFocusPathHandler::PrefabViewportFocusPathHandler() @@ -47,6 +49,9 @@ namespace AzToolsFramework::Prefab [&](const QString&, int linkIndex) { m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex); + + // Manually refresh path + QTimer::singleShot(0, [&]() { OnPrefabFocusChanged(); }); } ); From a4e0d69e8326ec101417db020b49745c48a0ce5a Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Fri, 22 Oct 2021 12:46:06 -0700 Subject: [PATCH 20/22] Update Splashscreen and About Us dialogs for General Availability (#4901) * Add new image for splashscreen. Layout changes incoming. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Adapt layouts to new splashscreen style with transparent background. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Ensure cropping logic works correctly when screen scaling is used. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Remove old image. Replace new image with new version with more readable credits. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- Code/Editor/AboutDialog.cpp | 14 ++++---- Code/Editor/AboutDialog.h | 6 ++-- Code/Editor/AboutDialog.ui | 12 +++---- Code/Editor/StartupLogoDialog.cpp | 5 +-- Code/Editor/StartupLogoDialog.h | 4 +-- Code/Editor/StartupLogoDialog.qrc | 2 +- Code/Editor/StartupLogoDialog.ui | 35 ++++++++++++++----- .../splashscreen_background_2021_11.jpg | 3 ++ ...ashscreen_background_developer_preview.jpg | 3 -- .../Utilities/PixmapScaleUtilities.cpp | 17 +++++++++ .../Utilities/PixmapScaleUtilities.h | 2 ++ 11 files changed, 71 insertions(+), 32 deletions(-) create mode 100644 Code/Editor/splashscreen_background_2021_11.jpg delete mode 100644 Code/Editor/splashscreen_background_developer_preview.jpg diff --git a/Code/Editor/AboutDialog.cpp b/Code/Editor/AboutDialog.cpp index 2c76526731..c0fd39e1ae 100644 --- a/Code/Editor/AboutDialog.cpp +++ b/Code/Editor/AboutDialog.cpp @@ -6,10 +6,7 @@ * */ - - #include "EditorDefs.h" - #include "AboutDialog.h" // Qt @@ -47,14 +44,17 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }"); // Prepare background image - m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi( - QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")), - screen(), - QSize(m_enforcedWidth, m_enforcedHeight), + QPixmap image = AzQtComponents::ScalePixmapForScreenDpi( + QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")), + screen(), QSize(m_imageWidth, m_imageHeight), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); + // Crop image to cut out transparent border + QRect cropRect((m_imageWidth - m_enforcedWidth) / 2, (m_imageHeight - m_enforcedHeight) / 2, m_enforcedWidth, m_enforcedHeight); + m_backgroundImage = AzQtComponents::CropPixmapForScreenDpi(image, screen(), cropRect); + // Draw the Open 3D Engine logo from svg m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); diff --git a/Code/Editor/AboutDialog.h b/Code/Editor/AboutDialog.h index 229675901e..db079a6ec7 100644 --- a/Code/Editor/AboutDialog.h +++ b/Code/Editor/AboutDialog.h @@ -38,7 +38,9 @@ private: QScopedPointer m_ui; QPixmap m_backgroundImage; - int m_enforcedWidth = 600; - int m_enforcedHeight = 400; + const int m_imageWidth = 668; + const int m_imageHeight = 368; + const int m_enforcedWidth = 600; + const int m_enforcedHeight = 300; }; diff --git a/Code/Editor/AboutDialog.ui b/Code/Editor/AboutDialog.ui index 9341a00d48..a6c5bb5d52 100644 --- a/Code/Editor/AboutDialog.ui +++ b/Code/Editor/AboutDialog.ui @@ -7,7 +7,7 @@ 0 0 600 - 360 + 300 @@ -19,13 +19,13 @@ 600 - 360 + 300 - 600 - 360 + 608 + 300 @@ -69,7 +69,7 @@ 11 - 12 + 10 12 @@ -125,7 +125,7 @@ - Developer Preview + General Availability Qt::AutoText diff --git a/Code/Editor/StartupLogoDialog.cpp b/Code/Editor/StartupLogoDialog.cpp index ab251b1564..135c76cf7f 100644 --- a/Code/Editor/StartupLogoDialog.cpp +++ b/Code/Editor/StartupLogoDialog.cpp @@ -34,11 +34,12 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy m_ui->setupUi(this); s_pLogoWindow = this; - setFixedSize(QSize(600, 300)); + setFixedSize(QSize(m_enforcedWidth, m_enforcedHeight)); + setAttribute(Qt::WA_TranslucentBackground, true); // Prepare background image m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi( - QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")), + QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")), screen(), QSize(m_enforcedWidth, m_enforcedHeight), Qt::IgnoreAspectRatio, diff --git a/Code/Editor/StartupLogoDialog.h b/Code/Editor/StartupLogoDialog.h index af80ab7e90..072ad6a905 100644 --- a/Code/Editor/StartupLogoDialog.h +++ b/Code/Editor/StartupLogoDialog.h @@ -50,7 +50,7 @@ private: QScopedPointer m_ui; QPixmap m_backgroundImage; - const int m_enforcedWidth = 600; - const int m_enforcedHeight = 300; + const int m_enforcedWidth = 668; + const int m_enforcedHeight = 368; }; diff --git a/Code/Editor/StartupLogoDialog.qrc b/Code/Editor/StartupLogoDialog.qrc index 38d1d1da2a..2d7dd81e87 100644 --- a/Code/Editor/StartupLogoDialog.qrc +++ b/Code/Editor/StartupLogoDialog.qrc @@ -1,6 +1,6 @@ o3de_logo.svg - splashscreen_background_developer_preview.jpg + splashscreen_background_2021_11.jpg diff --git a/Code/Editor/StartupLogoDialog.ui b/Code/Editor/StartupLogoDialog.ui index 60969f7f7f..c0b8115cb0 100644 --- a/Code/Editor/StartupLogoDialog.ui +++ b/Code/Editor/StartupLogoDialog.ui @@ -6,13 +6,22 @@ 0 0 - 600 - 300 + 668 + 368 + + 50 + + + 42 + + + 42 + - 9 + 42 10 @@ -29,7 +38,7 @@ - 250 + 300 20 @@ -53,7 +62,7 @@ 1 - 28 + 20 24 @@ -94,7 +103,7 @@ - Developer Preview + General Availability @@ -153,20 +162,28 @@ 290 - 0 + 32 290 - 16777215 + 32 + + + 8 + + Starting Editor... + + Qt::PlainText + - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop diff --git a/Code/Editor/splashscreen_background_2021_11.jpg b/Code/Editor/splashscreen_background_2021_11.jpg new file mode 100644 index 0000000000..703884fc53 --- /dev/null +++ b/Code/Editor/splashscreen_background_2021_11.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffcb7614bed0790bf58a2bb7b2d70958289cb2edf562acc8fc841f4c50a55445 +size 2974586 diff --git a/Code/Editor/splashscreen_background_developer_preview.jpg b/Code/Editor/splashscreen_background_developer_preview.jpg deleted file mode 100644 index 59f05a64df..0000000000 --- a/Code/Editor/splashscreen_background_developer_preview.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7105ec99477f124a8ac8d588f2dfc4ee7bb54f39386c8131b7703c86754c0cb8 -size 248690 diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp index fa32b708d7..95c0289f16 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp @@ -28,4 +28,21 @@ namespace AzQtComponents return scaledPixmap; } + + QPixmap CropPixmapForScreenDpi( + QPixmap pixmap, QScreen* screen, QRect rect) + { + qreal screenDpiFactor = QHighDpiScaling::factor(screen); + pixmap.setDevicePixelRatio(screenDpiFactor); + + QRect cropRect( + aznumeric_cast(aznumeric_cast(rect.left()) * screenDpiFactor), + aznumeric_cast(aznumeric_cast(rect.top()) * screenDpiFactor), + aznumeric_cast(aznumeric_cast(rect.width()) * screenDpiFactor), + aznumeric_cast(aznumeric_cast(rect.height()) * screenDpiFactor) + ); + + QPixmap croppedPixmap = pixmap.copy(cropRect); + return croppedPixmap; + } } diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h index 4b083855d5..4462e3c9a7 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h @@ -11,9 +11,11 @@ #include #include +#include #include namespace AzQtComponents { AZ_QT_COMPONENTS_API QPixmap ScalePixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode); + AZ_QT_COMPONENTS_API QPixmap CropPixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QRect rect); }; // namespace AzQtComponents From b609dbbbbbb654397a315dc8e28e38703f9853ac Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Fri, 22 Oct 2021 14:07:32 -0700 Subject: [PATCH 21/22] Pass a callback instead of weak linking a module Signed-off-by: AMZN-Phil --- .../ProjectManager/Source/PythonBindings.cpp | 60 ++++--------------- .../ProjectManager/Source/PythonBindings.h | 2 + scripts/o3de/o3de/download.py | 30 ++++++---- scripts/o3de/o3de/utils.py | 20 +++---- 4 files changed, 39 insertions(+), 73 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 0e24d46815..269ddee445 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -223,49 +223,6 @@ namespace RedirectOutput } } // namespace RedirectOutput -namespace O3DEProjectManagerPy -{ - using DownloadProgressFunc = AZStd::function; - DownloadProgressFunc currentProgressCallback; - bool requestCancelDownload = false; - - static PyObject* CLICancelDownload(PyObject* /*self*/, PyObject* /*args*/) - { - if (requestCancelDownload) - { - return Py_True; - } - else - { - return Py_False; - } - } - - static PyObject* CLIDownloadProgress(PyObject* /*self*/, PyObject* args) - { - int progress_percentage = 0; - if (!PyArg_ParseTuple(args, "i", &progress_percentage)) - return NULL; - if (currentProgressCallback) - { - currentProgressCallback(progress_percentage); - } - - Py_RETURN_NONE; - } - - static PyMethodDef O3DEPMPyMethods[] = { { "download_progress", CLIDownloadProgress, METH_VARARGS, "Used to call back to the UI to inform of download progress." }, - { "request_cancel_download", CLICancelDownload, METH_NOARGS, "Returns that the UI is requesting that the current download be cancelled." }, - { NULL, NULL, 0, NULL } }; - - static PyModuleDef O3DEPMPyModule = { PyModuleDef_HEAD_INIT, "o3de_projectmanager", NULL, -1, O3DEPMPyMethods, NULL, NULL, NULL, NULL }; - - static PyObject* PyInit_O3DEPMPy(void) - { - return PyModule_Create(&O3DEPMPyModule); - } -} // namespace O3DEProjectManagerPy - namespace O3DE::ProjectManager { @@ -314,7 +271,6 @@ namespace O3DE::ProjectManager AZ_TracePrintf("python", "Py_GetProgramFullPath=%ls \n", Py_GetProgramFullPath()); PyImport_AppendInittab("azlmbr_redirect", RedirectOutput::PyInit_RedirectOutput); - PyImport_AppendInittab("o3de_projectmanager", &O3DEProjectManagerPy::PyInit_O3DEPMPy); try { @@ -1126,20 +1082,26 @@ namespace O3DE::ProjectManager { // This process is currently limited to download a single gem at a time. bool downloadSucceeded = false; - O3DEProjectManagerPy::currentProgressCallback = gemProgressCallback; - O3DEProjectManagerPy::requestCancelDownload = false; + + m_requestCancelDownload = false; auto result = ExecuteWithLockErrorHandling( [&] { auto downloadResult = m_download.attr("download_gem")( QString_To_Py_String(gemName), // gem name pybind11::none(), // destination path - false// skip auto register + false, // skip auto register + pybind11::cpp_function( + [this, gemProgressCallback](int progress) + { + gemProgressCallback(progress); + + return m_requestCancelDownload; + }) // Callback for download progress and cancelling ); downloadSucceeded = (downloadResult.cast() == 0); }); - O3DEProjectManagerPy::currentProgressCallback = nullptr; if (!result.IsSuccess()) { @@ -1155,6 +1117,6 @@ namespace O3DE::ProjectManager void PythonBindings::CancelDownload() { - O3DEProjectManagerPy::requestCancelDownload = true; + m_requestCancelDownload = true; } } diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 386268b5b2..73970021a6 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -91,5 +91,7 @@ namespace O3DE::ProjectManager pybind11::handle m_editProjectProperties; pybind11::handle m_download; pybind11::handle m_pathlib; + + bool m_requestCancelDownload = false; }; } diff --git a/scripts/o3de/o3de/download.py b/scripts/o3de/o3de/download.py index f8868dd460..98f5d051a4 100644 --- a/scripts/o3de/o3de/download.py +++ b/scripts/o3de/o3de/download.py @@ -90,7 +90,8 @@ def get_downloadable(engine_name: str = None, def download_o3de_object(object_name: str, default_folder_name: str, dest_path: str or pathlib.Path, - object_type: str, downloadable_kwarg_key, skip_auto_register: bool) -> int: + object_type: str, downloadable_kwarg_key, skip_auto_register: bool, + download_progress_callback = None) -> int: download_path = manifest.get_o3de_cache_folder() / default_folder_name / object_name download_path.mkdir(parents=True, exist_ok=True) @@ -104,7 +105,7 @@ def download_o3de_object(object_name: str, default_folder_name: str, dest_path: origin_uri = downloadable_object_data['originuri'] parsed_uri = urllib.parse.urlparse(origin_uri) - download_zip_result = utils.download_zip_file(parsed_uri, download_zip_path) + download_zip_result = utils.download_zip_file(parsed_uri, download_zip_path, download_progress_callback) if download_zip_result != 0: return download_zip_result @@ -147,33 +148,38 @@ def download_o3de_object(object_name: str, default_folder_name: str, dest_path: def download_engine(engine_name: str, dest_path: str or pathlib.Path, - skip_auto_register: bool) -> int: - return download_o3de_object(engine_name, 'engines', dest_path, 'engine', 'engine_name', skip_auto_register) + skip_auto_register: bool, + download_progress_callback = None) -> int: + return download_o3de_object(engine_name, 'engines', dest_path, 'engine', 'engine_name', skip_auto_register, download_progress_callback) def download_project(project_name: str, dest_path: str or pathlib.Path, - skip_auto_register: bool) -> int: - return download_o3de_object(project_name, 'projects', dest_path, 'project', 'project_name', skip_auto_register) + skip_auto_register: bool, + download_progress_callback = None) -> int: + return download_o3de_object(project_name, 'projects', dest_path, 'project', 'project_name', skip_auto_register, download_progress_callback) def download_gem(gem_name: str, dest_path: str or pathlib.Path, - skip_auto_register: bool) -> int: - return download_o3de_object(gem_name, 'gems', dest_path, 'gem', 'gem_name', skip_auto_register) + skip_auto_register: bool, + download_progress_callback = None) -> int: + return download_o3de_object(gem_name, 'gems', dest_path, 'gem', 'gem_name', skip_auto_register, download_progress_callback) def download_template(template_name: str, dest_path: str or pathlib.Path, - skip_auto_register: bool) -> int: - return download_o3de_object(template_name, 'templates', dest_path, 'template', 'template_name', skip_auto_register) + skip_auto_register: bool, + download_progress_callback = None) -> int: + return download_o3de_object(template_name, 'templates', dest_path, 'template', 'template_name', skip_auto_register, download_progress_callback) def download_restricted(restricted_name: str, dest_path: str or pathlib.Path, - skip_auto_register: bool) -> int: - return download_o3de_object(restricted_name, 'restricted', dest_path, 'restricted', 'restricted_name', skip_auto_register) + skip_auto_register: bool, + download_progress_callback = None) -> int: + return download_o3de_object(restricted_name, 'restricted', dest_path, 'restricted', 'restricted_name', skip_auto_register, download_progress_callback) def _run_download(args: argparse) -> int: diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index cce51bbd8f..c07793fd1b 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -16,10 +16,6 @@ import shutil import urllib.request import logging import zipfile -try: - import o3de_projectmanager -except ImportError: - pass logger = logging.getLogger() logging.basicConfig() @@ -38,14 +34,13 @@ def copyfileobj(fsrc, fdst, callback, length=0): copied = 0 while True: - if o3de_projectmanager and o3de_projectmanager.request_cancel_download(): - return 1 buf = fsrc_read(length) if not buf: break fdst_write(buf) copied += len(buf) - callback(copied) + if callback(copied): + return 1 return 0 def validate_identifier(identifier: str) -> bool: @@ -122,11 +117,12 @@ def backup_folder(folder: str or pathlib.Path) -> None: if backup_folder_name.is_dir(): renamed = True -def download_file(parsed_uri, download_path: pathlib.Path) -> int: +def download_file(parsed_uri, download_path: pathlib.Path, download_progress_callback = None) -> int: """ :param parsed_uri: uniform resource identifier to zip file to download :param download_path: location path on disk to download file """ + logger.warn(f'File about to downloaded to {download_path}.') if download_path.is_file(): logger.warn(f'File already downloaded to {download_path}.') elif parsed_uri.scheme in ['http', 'https', 'ftp', 'ftps']: @@ -137,8 +133,8 @@ def download_file(parsed_uri, download_path: pathlib.Path) -> int: except KeyError: pass def download_progress(blocks): - if o3de_projectmanager and download_file_size: - o3de_projectmanager.download_progress(int(blocks/int(download_file_size) * 100)) + if download_progress_callback and download_file_size: + return download_progress_callback(int(blocks/int(download_file_size) * 100)) with download_path.open('wb') as f: download_cancelled = copyfileobj(s, f, download_progress) if download_cancelled: @@ -152,12 +148,12 @@ def download_file(parsed_uri, download_path: pathlib.Path) -> int: return 0 -def download_zip_file(parsed_uri, download_zip_path: pathlib.Path) -> int: +def download_zip_file(parsed_uri, download_zip_path: pathlib.Path, download_progress_callback = None) -> int: """ :param parsed_uri: uniform resource identifier to zip file to download :param download_zip_path: path to output zip file """ - download_file_result = download_file(parsed_uri, download_zip_path) + download_file_result = download_file(parsed_uri, download_zip_path, download_progress_callback) if download_file_result != 0: return download_file_result From e1b46b7e5c08bb934c82daf8ec909e8389b923bf Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Fri, 22 Oct 2021 14:23:55 -0700 Subject: [PATCH 22/22] Add comment about additional callback function and be explicit on return value. Signed-off-by: AMZN-Phil --- scripts/o3de/o3de/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index c07793fd1b..8663502a3f 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -121,8 +121,8 @@ def download_file(parsed_uri, download_path: pathlib.Path, download_progress_cal """ :param parsed_uri: uniform resource identifier to zip file to download :param download_path: location path on disk to download file + :download_progress_callback: callback called with the download progress as a percentage, returns true to request to cancel the download """ - logger.warn(f'File about to downloaded to {download_path}.') if download_path.is_file(): logger.warn(f'File already downloaded to {download_path}.') elif parsed_uri.scheme in ['http', 'https', 'ftp', 'ftps']: @@ -135,6 +135,7 @@ def download_file(parsed_uri, download_path: pathlib.Path, download_progress_cal def download_progress(blocks): if download_progress_callback and download_file_size: return download_progress_callback(int(blocks/int(download_file_size) * 100)) + return False with download_path.open('wb') as f: download_cancelled = copyfileobj(s, f, download_progress) if download_cancelled: