From 61f915366a92a02f57e3a3b53b7f30ada76eddbf Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Fri, 4 Feb 2022 11:53:37 -0700 Subject: [PATCH 1/7] Shader refactor (no functional changes) The purpose of this shader refactor is to split various material type shaders into disparate pieces: 1. The original material type shaders now include an external file with the actual shader entry points and structure of the algorithm (e.g. depth pass, shadow pass, forward pass) but continue to specify the SRGs used 2. Common functionality used across multiple shaders was consolidated into routines implemented in the MaterialFunctions folder (Materials/Types/MaterialFunctions) 3. The implementation shaders rely on common routines to be included/imported prior to inclusion, and by design, make no references to any Draw, Object, or Material SRG. This refactor only includes the Standard and Enhanced material types, and is, for the most part, a non-functional change. However, the Surface definition needed to be augmented to include information needed by lighting later. Modifying the Surface structure enables the lighting loops to avoid any references to the Material SRG. This completes the decoupling needed to support future Material canvas work, as well as a future Material pipeline abstraction (where by the implementation shaders can be injected by the user, customized per platform, and in general, are simply decoupled from the materials themselves). Signed-off-by: Jeremy Ong --- .../Materials/Types/BasePBR_ForwardPass.azsl | 6 +- .../Materials/Types/DepthPass_WithPS.azsl | 124 ++++++ .../Types/EnhancedPBR_DepthPass_WithPS.azsl | 91 +--- .../Types/EnhancedPBR_ForwardPass.azsl | 417 +----------------- .../Types/EnhancedPBR_Shadowmap_WithPS.azsl | 91 +--- .../Types/EnhancedSurface_ForwardPass.azsl | 317 +++++++++++++ .../EnhancedParallaxDepth.azsli | 41 ++ .../EvaluateEnhancedSurface.azsli | 149 +++++++ .../EvaluateStandardSurface.azsli | 95 ++++ .../EvaluateTangentFrame.azsli | 33 ++ .../MultilayerParallaxDepth.azsli | 35 ++ .../MaterialFunctions/ParallaxDepth.azsli | 51 +++ .../MaterialFunctions/StandardGetAlpha.azsli | 17 + .../StandardGetNormalToWorld.azsli | 12 + .../StandardGetObjectToWorld.azsli | 12 + .../MaterialFunctions/StandardMaybeClip.azsli | 14 + .../StandardTransformDetailUvs.azsli | 18 + .../StandardTransformUvs.azsli | 14 + .../Materials/Types/ShadowMap_WithPS.azsl | 127 ++++++ ...tandardMultilayerPBR_DepthPass_WithPS.azsl | 109 +---- .../StandardMultilayerPBR_ForwardPass.azsl | 10 +- ...tandardMultilayerPBR_Shadowmap_WithPS.azsl | 108 +---- .../Types/StandardPBR_DepthPass_WithPS.azsl | 94 +--- .../Types/StandardPBR_ForwardPass.azsl | 340 +------------- .../Types/StandardPBR_Shadowmap_WithPS.azsl | 93 +--- .../Types/StandardSurface_ForwardPass.azsl | 306 +++++++++++++ .../PBR/Surfaces/EnhancedSurface.azsli | 27 +- .../PBR/Surfaces/StandardSurface.azsli | 22 +- .../Types/AutoBrick_ForwardPass.azsl | 16 +- .../Types/MinimalPBR_ForwardPass.azsl | 6 +- 30 files changed, 1492 insertions(+), 1303 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlpha.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl index 96318f2284..b887761917 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl @@ -116,19 +116,19 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace) float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); - float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); + surface.baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); // ------- Metallic ------- float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex]; - float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + surface.metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); // ------- Specular ------- float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex]; float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); + surface.SetAlbedoAndSpecularF0(specularF0Factor); // ------- Roughness ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl new file mode 100644 index 0000000000..9b017222b1 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl @@ -0,0 +1,124 @@ +/* + * 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 + * + */ + +struct VSInput +{ + float3 m_position : POSITION; + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; + + // only used for parallax depth calculation + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + +#ifdef MULTILAYER + // This gets set automatically by the system at runtime only if it's available. + // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. + // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). + // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. + float4 m_optional_blendMask : COLOR0; +#endif +}; + +struct VSDepthOutput +{ + // "centroid" is needed for SV_Depth to compile + precise linear centroid float4 m_position : SV_Position; + float2 m_uv[UvSetCount] : UV1; + + // only used for parallax depth calculation + float3 m_normal : NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + +#ifdef MULTILAYER + float3 m_blendMask : UV3; +#endif +}; + +VSDepthOutput MainVS(VSInput IN) +{ + VSDepthOutput OUT; + + float4x4 objectToWorld = GetObjectToWorld(); + float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); + + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); + + float2 uvs[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformUvs(uvs, OUT.m_uv); + + if(ShouldHandleParallaxInDepthShaders()) + { + OUT.m_worldPosition = worldPosition.xyz; + + float3x3 objectToWorldIT = GetNormalToWorld(); + ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); + } + +#ifdef MULTILAYER + if(o_blendMask_isBound) + { + OUT.m_blendMask = IN.m_optional_blendMask.rgb; + } + else + { + OUT.m_blendMask = float3(0,0,0); + } +#endif + + return OUT; +} + +struct PSDepthOutput +{ + precise float m_depth : SV_Depth; +}; + +PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + PSDepthOutput OUT; + + OUT.m_depth = IN.m_position.z; + + if(ShouldHandleParallaxInDepthShaders()) + { + float3 tangents[UvSetCount] = { IN.m_tangent, IN.m_tangent }; + float3 bitangents[UvSetCount] = { IN.m_bitangent, IN.m_bitangent }; + + for (int i = 0; i != UvSetCount; ++i) + { + EvaluateTangentFrame( + IN.m_normal, + IN.m_worldPosition, + isFrontFace, + IN.m_uv[i], + i, + IN.m_tangent, + IN.m_bitangent, + tangents[i], + bitangents[i]); + } + +#ifdef MULTILAYER + MultilayerSetPixelDepth(IN.m_blendMask, IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); +#else + SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); +#endif + + } + +#ifndef MULTILAYER + float alpha = GetAlpha(IN.m_uv); + MaybeClip(alpha, IN.m_uv); +#endif + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl index 08642decc0..2f7a5b94f9 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -8,88 +8,13 @@ #include "./EnhancedPBR_Common.azsli" #include -#include -#include -#include "MaterialInputs/AlphaInput.azsli" -#include "MaterialInputs/ParallaxInput.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetAlpha.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardMaybeClip.azsli" -struct VSInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VSDepthOutput -{ - precise linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VSDepthOutput MainVS(VSInput IN) -{ - VSDepthOutput OUT; - - float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); - - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - return OUT; -} - -struct PSDepthOutput -{ - precise float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - } - - // Clip Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#include "DepthPass_WithPS.azsl" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 8458ca11a2..bac97fed64 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -10,21 +10,6 @@ // SRGs #include -#include - -// Pass Output -#include - -// Utility -#include -#include - -// Custom Surface & Lighting -#include - -// Decals -#include - // ---------- Material Parameters ---------- @@ -49,397 +34,13 @@ COMMON_OPTIONS_DETAIL_MAPS() #include "MaterialInputs/TransmissionInput.azsli" -// ---------- Vertex Shader ---------- - -struct VSInput -{ - // Base fields (required by the template azsli file)... - float3 m_position : POSITION; - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; -}; - -struct VSOutput -{ - // Base fields (required by the template azsli file)... - precise linear centroid float4 m_position : SV_Position; - float3 m_normal: NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV5; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv[UvSetCount] : UV1; - float2 m_detailUv[UvSetCount] : UV3; -}; - -#include - -VSOutput EnhancedPbr_ForwardPassVS(VSInput IN) -{ - VSOutput OUT; - - float3 worldPosition = mul(ObjectSrg::GetWorldMatrix(), float4(IN.m_position, 1.0)).xyz; - - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - // As seen above our standard practice is to only transform the first UV as that's the one we expect to be used for - // tiling. But for detail maps you could actually use either UV stream for tiling. There is no concern about applying - // the same transform to both UV sets because the detail map feature forces the same UV set to be used for all detail maps. - // Note we might be able to combine these into a single UV similar to what Skin.materialtype does, - // but we would need to address how it works with the parallax code below that indexes into the m_detailUV array. - OUT.m_detailUv[0] = mul(MaterialSrg::m_detailUvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_detailUv[1] = mul(MaterialSrg::m_detailUvMatrix, float3(IN.m_uv1, 1.0)).xy; - - // Shadow coords will be calculated in the pixel shader in this case - bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; - - VertexHelper(IN, OUT, worldPosition, skipShadowCoords); - - return OUT; -} - - -// ---------- Pixel Shader ---------- - -PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth) -{ - const float3 vertexNormal = normalize(IN.m_normal); - - // ------- Tangents & Bitangets ------- - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture) || o_detail_normal_useTexture) - { - PrepareGeneratedTangent(vertexNormal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - } - - // ------- Depth & Parallax ------- - - depth = IN.m_position.z; - - bool displacementIsClipped = false; - - // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scatteirng is enabled - if(ShouldHandleParallax()) - { - // GetParallaxInput applies an tangent offset to the UV. We want to apply the same offset to the detailUv (note: this needs to be tested with content) - // The math is: offset = newUv - oldUv; detailUv += offset; - // This is the same as: detailUv -= oldUv; detailUv += newUv; - IN.m_detailUv[MaterialSrg::m_parallaxUvIndex] -= IN.m_uv[MaterialSrg::m_parallaxUvIndex]; - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(vertexNormal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, IN.m_position.w, displacementIsClipped); - - // Apply second part of the offset to the detail UV (see comment above) - IN.m_detailUv[MaterialSrg::m_parallaxUvIndex] -= IN.m_uv[MaterialSrg::m_parallaxUvIndex]; - - // Adjust directional light shadow coorinates for parallax correction - if(o_parallax_enablePixelDepthOffset) - { - const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; - if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) - { - DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); - } - } - } - - Surface surface; - surface.position = IN.m_worldPosition; - - // ------- Alpha & Clip ------- - - float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUv = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = GetAlphaInputAndClip(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUv, opacityUv, MaterialSrg::m_sampler, MaterialSrg::m_opacityFactor, o_opacity_source); - - // ------- Detail Layer Setup ------- - - const float2 detailUv = IN.m_detailUv[MaterialSrg::m_detail_allMapsUvIndex]; - - // When the detail maps and the detail blend mask are on the same UV, they both use the transformed detail UVs because they are 'attached' to each other - const float2 detailBlendMaskUv = (MaterialSrg::m_detail_blendMask_uvIndex == MaterialSrg::m_detail_allMapsUvIndex) ? - IN.m_detailUv[MaterialSrg::m_detail_blendMask_uvIndex] : - IN.m_uv[MaterialSrg::m_detail_blendMask_uvIndex]; - - const float detailLayerBlendFactor = GetDetailLayerBlendFactor( - MaterialSrg::m_detail_blendMask_texture, - MaterialSrg::m_sampler, - detailBlendMaskUv, - o_detail_blendMask_useTexture, - MaterialSrg::m_detail_blendFactor); - - // ------- Normal ------- - - float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex]; - float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. - float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor; - surface.vertexNormal = vertexNormal; - surface.normal = GetDetailedNormalInputWS( - isFrontFace, IN.m_normal, - tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture, - tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, detailUv, detailLayerNormalFactor, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY, MaterialSrg::m_detailUvMatrix, o_detail_normal_useTexture); - - //--------------------- Base Color ---------------------- - - // [GFX TODO][ATOM-1761] Figure out how we want our base material to expect channels to be encoded, and apply that to the way we pack alpha. - - float detailLayerBaseColorFactor = MaterialSrg::m_detail_baseColor_factor * detailLayerBlendFactor; - - float3 baseColor = GetDetailedBaseColorInput( - MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, o_baseColor_useTexture, MaterialSrg::m_baseColor, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, - MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, detailUv, o_detail_baseColor_useTexture, detailLayerBaseColorFactor); - - if(o_parallax_highlightClipping && displacementIsClipped) - { - ApplyParallaxClippingHighlight(baseColor); - } - - // ------- Metallic ------- - - float metallic = 0; - if(!o_enableSubsurfaceScattering) // If subsurface scattering is enabled skip texture lookup for metallic, as this quantity won't be used anyway - { - float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex]; - metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); - } - - // ------- Specular ------- - - float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex]; - float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); - - // ------- Roughness ------- - - float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex]; - surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, - MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); - surface.CalculateRoughnessA(); - - // ------- Subsurface ------- - - float2 subsurfaceUv = IN.m_uv[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex]; - float surfaceScatteringFactor = GetSubsurfaceInput(MaterialSrg::m_subsurfaceScatteringInfluenceMap, MaterialSrg::m_sampler, subsurfaceUv, MaterialSrg::m_subsurfaceScatteringFactor); - - // ------- Transmission ------- - - float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex]; - float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness); - surface.transmission.tint = transmissionTintThickness.rgb; - surface.transmission.thickness = transmissionTintThickness.w; - surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams; - surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance; - - // ------- Anisotropy ------- - - if (o_enableAnisotropy) - { - // Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI] - const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI; - const float anisotropyFactor = MaterialSrg::m_anisotropicFactor; - surface.anisotropy.Init(surface.normal, IN.m_tangent, IN.m_bitangent, anisotropyAngle, anisotropyFactor, surface.roughnessA); - } - - // ------- Lighting Data ------- - - LightingData lightingData; - - // Light iterator - lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); - lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); - - // Directional light shadow coordinates - lightingData.shadowCoords = IN.m_shadowCoords; - - // ------- Emissive ------- - - float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex]; - lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); - - // ------- Occlusion ------- - - lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); - lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); - - // ------- Thin Object Light Transmission ------- - - // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection - lightingData.shrinkFactor = surface.transmission.transmissionParams.x; - - // Angle offset for subsurface scattering through thin objects - lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y; - - // Attenuation applied to hide artifacts due to low-res shadow maps - lightingData.distanceAttenuation = surface.transmission.transmissionParams.z; - - // ------- Clearcoat ------- - - // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags - if(o_clearCoat_feature_enabled) - { - if(o_clearCoat_enabled) - { - float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, - MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, - MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, - uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], - MaterialSrg::m_sampler, isFrontFace, - surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); - } - - // manipulate base layer f0 if clear coat is enabled - // modify base layer's normal incidence reflectance - // for the derivation of the following equation please refer to: - // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification - float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); - surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); - } - - // Diffuse and Specular response (used in IBL calculations) - lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); - lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; - - if(o_clearCoat_feature_enabled) - { - // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 - lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); - } - - // ------- Multiscatter ------- - - lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); - - // ------- Lighting Calculation ------- - - // Apply Decals - ApplyDecals(lightingData.tileIterator, surface); - - // Apply Direct Lighting - ApplyDirectLighting(surface, lightingData); - - // Apply Image Based Lighting (IBL) - ApplyIBL(surface, lightingData); - - // Finalize Lighting - lightingData.FinalizeLighting(surface.transmission.tint); - - PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); - - // ------- Opacity ------- - - if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) - { - // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. - // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface - // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor - // values close to 1.0, that indicates the absence of a surface entirely, so this effect should - // not apply. - float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; - alpha = lerp(fresnelAlpha, alpha, MaterialSrg::m_opacityAffectsSpecularFactor); - } - - // Note: lightingOutput rendertargets are not always used as named, particularly m_diffuseColor (target 0) and - // m_specularColor (target 1). Comments below describe the differences when appropriate. - - if (o_opacity_mode == OpacityMode::Blended) - { - // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when - // specular is being added to diffuse just because we're calling render target 0 "diffuse". - - // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular - // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. - // It's done this way because surface transparency doesn't really change specular response (eg, glass). - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_diffuseColor.w = alpha; - } - else if (o_opacity_mode == OpacityMode::TintedTransparent) - { - // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting - // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength - // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, - // absorption, and interior color to be specified. - // - // The technique uses dual source blending to allow two separate sources to be part of the blending equation - // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and - // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). - // - // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then - // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_specularColor.rgb = baseColor * (1.0 - alpha); - } - else - { - // Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961 - uint factorAndQuality = dot(round(float2(saturate(surfaceScatteringFactor), MaterialSrg::m_subsurfaceScatteringQuality) * 255), float2(256, 1)); - lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0); - lightingOutput.m_scatterDistance = MaterialSrg::m_scatterDistance; - } - - return lightingOutput; -} - -ForwardPassOutputWithDepth EnhancedPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutputWithDepth OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); - - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; - OUT.m_scatterDistance = lightingOutput.m_scatterDistance; - OUT.m_depth = depth; - return OUT; -} - -[earlydepthstencil] -ForwardPassOutput EnhancedPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutput OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); - - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; - OUT.m_scatterDistance = lightingOutput.m_scatterDistance; +#include "MaterialFunctions/EvaluateEnhancedSurface.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/EnhancedParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardMaybeClip.azsli" +#include "MaterialFunctions/StandardTransformDetailUvs.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" - return OUT; -} +#include "EnhancedSurface_ForwardPass.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl index 0f2457fcd8..6c01a63a7c 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl @@ -16,85 +16,12 @@ #include "MaterialInputs/AlphaInput.azsli" #include "MaterialInputs/ParallaxInput.azsli" -struct VertexInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VertexOutput -{ - float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VertexOutput MainVS(VertexInput IN) -{ - const float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - VertexOutput OUT; - - const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - - OUT.m_depth += PdoShadowMapBias; - } - - // Clip Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetAlpha.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardMaybeClip.azsli" + +#include "ShadowMap_WithPS.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl new file mode 100644 index 0000000000..ceb9379f28 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl @@ -0,0 +1,317 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +// SRGs +#include + +// Pass Output +#include + +// Utility +#include + +// Custom Surface & Lighting +#include + +// Decals +#include + +// ---------- Vertex Shader ---------- + +struct VSInput +{ + // Base fields (required by the template azsli file)... + float3 m_position : POSITION; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; +}; + +struct VSOutput +{ + // Base fields (required by the template azsli file)... + precise linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV5; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv[UvSetCount] : UV1; + float2 m_detailUv[UvSetCount] : UV3; +}; + +VSOutput EnhancedPbr_ForwardPassVS(VSInput IN) +{ + VSOutput OUT; + + float4x4 objectToWorld = GetObjectToWorld(); + float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); + OUT.m_worldPosition = worldPosition.xyz; + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); + + float2 uv[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformUvs(uv, OUT.m_uv); + + float2 detailUv[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformDetailUvs(detailUv, OUT.m_detailUv); + + // Shadow coords will be calculated in the pixel shader in this case + bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; + + float3x3 objectToWorldIT = GetNormalToWorld(); + ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); + + // directional light shadow + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && !skipShadowCoords && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords( + shadowIndex, + worldPosition, + OUT.m_normal, + OUT.m_shadowCoords); + } + + return OUT; +} + + +// ---------- Pixel Shader ---------- + +PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth) +{ + const float3 vertexNormal = normalize(IN.m_normal); + + // ------- Tangents & Bitangets ------- + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + + if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture) || o_detail_normal_useTexture) + { + for (int i = 0; i != UvSetCount; ++i) + { + EvaluateTangentFrame( + IN.m_normal, + IN.m_worldPosition, + isFrontFace, + IN.m_uv[i], + i, + IN.m_tangent, + IN.m_bitangent, + tangents[i], + bitangents[i]); + } + } + + // ------- Depth & Parallax ------- + + depth = IN.m_position.z; + + bool displacementIsClipped = false; + + // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scatteirng is enabled + if(ShouldHandleParallax()) + { + EnhancedSetPixelDepth( + IN.m_worldPosition, + IN.m_normal, + tangents, + bitangents, + IN.m_uv, + isFrontFace, + IN.m_detailUv, + IN.m_position.w, + depth, + displacementIsClipped); + + // Adjust directional light shadow coorinates for parallax correction + if(o_parallax_enablePixelDepthOffset) + { + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); + } + } + } + + Surface surface; + surface.vertexNormal = vertexNormal; + surface.position = IN.m_worldPosition; + + // ------- Alpha & Clip ------- + // TODO: this often invokes a separate sample of the base color texture which is wasteful + float alpha = GetAlpha(IN.m_uv); + MaybeClip(alpha, IN.m_uv); + + EvaluateEnhancedSurface(IN.m_normal, IN.m_uv, IN.m_detailUv, tangents, bitangents, isFrontFace, displacementIsClipped, surface); + + // ------- Lighting Data ------- + + LightingData lightingData; + + // Light iterator + lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); + lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); + + // Directional light shadow coordinates + lightingData.shadowCoords = IN.m_shadowCoords; + + lightingData.emissiveLighting = surface.emissiveLighting; + lightingData.diffuseAmbientOcclusion = surface.diffuseAmbientOcclusion; + lightingData.specularOcclusion = surface.specularOcclusion; + + // Diffuse and Specular response (used in IBL calculations) + lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); + lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; + + // ------- Thin Object Light Transmission ------- + + // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection + lightingData.shrinkFactor = surface.transmission.transmissionParams.x; + + // Angle offset for subsurface scattering through thin objects + lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y; + + // Attenuation applied to hide artifacts due to low-res shadow maps + lightingData.distanceAttenuation = surface.transmission.transmissionParams.z; + + if(o_clearCoat_feature_enabled) + { + // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 + lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); + } + + // ------- Multiscatter ------- + + lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); + + // ------- Lighting Calculation ------- + + // Apply Decals + ApplyDecals(lightingData.tileIterator, surface); + + // Apply Direct Lighting + ApplyDirectLighting(surface, lightingData); + + // Apply Image Based Lighting (IBL) + ApplyIBL(surface, lightingData); + + // Finalize Lighting + lightingData.FinalizeLighting(surface.transmission.tint); + + PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); + + // ------- Opacity ------- + + if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) + { + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; + alpha = lerp(fresnelAlpha, alpha, surface.opacityAffectsSpecularFactor); + } + + // Note: lightingOutput rendertargets are not always used as named, particularly m_diffuseColor (target 0) and + // m_specularColor (target 1). Comments below describe the differences when appropriate. + + if (o_opacity_mode == OpacityMode::Blended) + { + // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when + // specular is being added to diffuse just because we're calling render target 0 "diffuse". + + // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular + // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. + // It's done this way because surface transparency doesn't really change specular response (eg, glass). + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_diffuseColor.w = alpha; + } + else if (o_opacity_mode == OpacityMode::TintedTransparent) + { + // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting + // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength + // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, + // absorption, and interior color to be specified. + // + // The technique uses dual source blending to allow two separate sources to be part of the blending equation + // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and + // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). + // + // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then + // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_specularColor.rgb = surface.baseColor * (1.0 - alpha); + } + else + { + // Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961 + uint factorAndQuality = dot(round(float2(saturate(surface.subsurfaceScatteringFactor), surface.subsurfaceScatteringQuality) * 255), float2(256, 1)); + lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0); + lightingOutput.m_scatterDistance = surface.scatterDistance; + } + + return lightingOutput; +} + +ForwardPassOutputWithDepth EnhancedPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutputWithDepth OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; + OUT.m_scatterDistance = lightingOutput.m_scatterDistance; + OUT.m_depth = depth; + return OUT; +} + +[earlydepthstencil] +ForwardPassOutput EnhancedPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutput OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; + OUT.m_scatterDistance = lightingOutput.m_scatterDistance; + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli new file mode 100644 index 0000000000..e89afd6f37 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli @@ -0,0 +1,41 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include "../MaterialInputs/ParallaxInput.azsli" +#include + + void EnhancedSetPixelDepth( + float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + float2 uvs[UvSetCount], + bool isFrontFace, + inout float2 detailUv[UvSetCount], + inout float depthCS, + out float depth, + out bool isClipped) +{ + // GetParallaxInput applies an tangent offset to the UV. We want to apply the same offset to the detailUv (note: this needs to be tested with content) + // The math is: offset = newUv - oldUv; detailUv += offset; + // This is the same as: detailUv -= oldUv; detailUv += newUv; + detailUv[MaterialSrg::m_parallaxUvIndex] -= uvs[MaterialSrg::m_parallaxUvIndex]; + + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depth, depthCS, isClipped); + + // Apply second part of the offset to the detail UV (see comment above) + detailUv[MaterialSrg::m_parallaxUvIndex] -= uvs[MaterialSrg::m_parallaxUvIndex]; +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli new file mode 100644 index 0000000000..9cc3e05789 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli @@ -0,0 +1,149 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "StandardGetAlpha.azsli" + +void EvaluateEnhancedSurface( + float3 normal, + float2 uvs[UvSetCount], + float2 detailUvs[UvSetCount], + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + bool isFrontFace, + bool displacementIsClipped, + inout Surface surface) +{ + // ------- Detail Layer Setup ------- + + const float2 detailUv = detailUvs[MaterialSrg::m_detail_allMapsUvIndex]; + + // When the detail maps and the detail blend mask are on the same UV, they both use the transformed detail UVs because they are 'attached' to each other + const float2 detailBlendMaskUv = (MaterialSrg::m_detail_blendMask_uvIndex == MaterialSrg::m_detail_allMapsUvIndex) ? + detailUvs[MaterialSrg::m_detail_blendMask_uvIndex] : + uvs[MaterialSrg::m_detail_blendMask_uvIndex]; + + const float detailLayerBlendFactor = GetDetailLayerBlendFactor( + MaterialSrg::m_detail_blendMask_texture, + MaterialSrg::m_sampler, + detailBlendMaskUv, + o_detail_blendMask_useTexture, + MaterialSrg::m_detail_blendFactor); + + // ------- Normal ------- + + float2 normalUv = uvs[MaterialSrg::m_normalMapUvIndex]; + float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. + float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor; + surface.normal = GetDetailedNormalInputWS( + isFrontFace, normal, + tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture, + tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, detailUv, detailLayerNormalFactor, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY, MaterialSrg::m_detailUvMatrix, o_detail_normal_useTexture); + + //--------------------- Base Color ---------------------- + + // [GFX TODO][ATOM-1761] Figure out how we want our base material to expect channels to be encoded, and apply that to the way we pack alpha. + + float detailLayerBaseColorFactor = MaterialSrg::m_detail_baseColor_factor * detailLayerBlendFactor; + float2 baseColorUv = uvs[MaterialSrg::m_baseColorMapUvIndex]; + + surface.baseColor = GetDetailedBaseColorInput( + MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, o_baseColor_useTexture, MaterialSrg::m_baseColor, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, + MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, detailUv, o_detail_baseColor_useTexture, detailLayerBaseColorFactor); + + if(o_parallax_highlightClipping && displacementIsClipped) + { + ApplyParallaxClippingHighlight(surface.baseColor); + } + + // ------- Metallic ------- + + surface.metallic = 0; + if(!o_enableSubsurfaceScattering) // If subsurface scattering is enabled skip texture lookup for metallic, as this quantity won't be used anyway + { + float2 metallicUv = uvs[MaterialSrg::m_metallicMapUvIndex]; + surface.metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + } + + // ------- Specular ------- + + float2 specularUv = uvs[MaterialSrg::m_specularF0MapUvIndex]; + float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); + + surface.SetAlbedoAndSpecularF0(specularF0Factor); + + // ------- Roughness ------- + + float2 roughnessUv = uvs[MaterialSrg::m_roughnessMapUvIndex]; + surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, + MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); + surface.CalculateRoughnessA(); + + // ------- Subsurface ------- + + float2 subsurfaceUv = uvs[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex]; + surface.subsurfaceScatteringFactor = GetSubsurfaceInput(MaterialSrg::m_subsurfaceScatteringInfluenceMap, MaterialSrg::m_sampler, subsurfaceUv, MaterialSrg::m_subsurfaceScatteringFactor); + surface.subsurfaceScatteringQuality = MaterialSrg::m_subsurfaceScatteringQuality; + surface.scatterDistance = MaterialSrg::m_scatterDistance; + + // ------- Transmission ------- + + float2 transmissionUv = uvs[MaterialSrg::m_transmissionThicknessMapUvIndex]; + float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness); + surface.transmission.tint = transmissionTintThickness.rgb; + surface.transmission.thickness = transmissionTintThickness.w; + surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams; + surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance; + + // ------- Anisotropy ------- + + if (o_enableAnisotropy) + { + // Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI] + const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI; + const float anisotropyFactor = MaterialSrg::m_anisotropicFactor; + surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA); + } + + // ------- Emissive ------- + + float2 emissiveUv = uvs[MaterialSrg::m_emissiveMapUvIndex]; + surface.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); + + // ------- Occlusion ------- + + surface.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvs[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + surface.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, uvs[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + + // ------- Clearcoat ------- + + // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags + if(o_clearCoat_feature_enabled) + { + if(o_clearCoat_enabled) + { + float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, uvs[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, + MaterialSrg::m_clearCoatRoughnessMap, uvs[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, + MaterialSrg::m_clearCoatNormalMap, uvs[MaterialSrg::m_clearCoatNormalMapUvIndex], normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, + uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], + MaterialSrg::m_sampler, isFrontFace, + surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); + } + + // manipulate base layer f0 if clear coat is enabled + // modify base layer's normal incidence reflectance + // for the derivation of the following equation please refer to: + // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification + float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); + surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); + } + + surface.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli new file mode 100644 index 0000000000..54a4a2462a --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli @@ -0,0 +1,95 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "StandardGetAlpha.azsli" + +void EvaluateStandardSurface( + float3 normal, + float2 uv[UvSetCount], + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + bool isFrontFace, + bool displacementIsClipped, + inout Surface surface) +{ + // ------- Normal ------- + + float2 normalUv = uv[MaterialSrg::m_normalMapUvIndex]; + float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. + surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, normal, + tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor); + + // ------- Base Color ------- + + float2 baseColorUv = uv[MaterialSrg::m_baseColorMapUvIndex]; + float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); + surface.baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); + + if(o_parallax_highlightClipping && displacementIsClipped) + { + ApplyParallaxClippingHighlight(surface.baseColor); + } + + // ------- Metallic ------- + + float2 metallicUv = uv[MaterialSrg::m_metallicMapUvIndex]; + surface.metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + + // ------- Specular ------- + + float2 specularUv = uv[MaterialSrg::m_specularF0MapUvIndex]; + float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); + + surface.SetAlbedoAndSpecularF0(specularF0Factor); + + // ------- Roughness ------- + + float2 roughnessUv = uv[MaterialSrg::m_roughnessMapUvIndex]; + surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, + MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); + surface.CalculateRoughnessA(); + + // ------- Emissive ------- + + float2 emissiveUv = uv[MaterialSrg::m_emissiveMapUvIndex]; + surface.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); + + // ------- Occlusion ------- + + surface.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + surface.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + + // ------- Clearcoat ------- + + // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags + if(o_clearCoat_feature_enabled) + { + if(o_clearCoat_enabled) + { + float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, + MaterialSrg::m_clearCoatRoughnessMap, uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, + MaterialSrg::m_clearCoatNormalMap, uv[MaterialSrg::m_clearCoatNormalMapUvIndex], normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, + uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], + MaterialSrg::m_sampler, isFrontFace, + surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); + } + + // manipulate base layer f0 if clear coat is enabled + // modify base layer's normal incidence reflectance + // for the derivation of the following equation please refer to: + // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification + float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); + surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); + } + + // ------- Opacity ------- + surface.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli new file mode 100644 index 0000000000..2aad5f257d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli @@ -0,0 +1,33 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +// The built-in tangent frame evaluation forwards the tangent frame interpolanted from the vertex +// data streams for UV-index 0. For UV-index 1, the tangent frame is computed from UV surface gradients. +void EvaluateTangentFrame( + float3 normal, + float3 worldPosition, + bool isFrontFace, + float2 uv, + int uvIndex, + // The input tangent and bitangent vectors are optional and used to forward data from interpolants + float3 IN_tangent, + float3 IN_bitangent, + float3 OUT_tangent, + float3 OUT_bitangent) +{ + if (DrawSrg::GetTangentAtUv(uvIndex) == 0) + { + OUT_tangent = IN_tangent; + OUT_bitangent = IN_bitangent; + } + else + { + SurfaceGradientNormalMapping_Init(normal, worldPosition, !isFrontFace); \ + SurfaceGradientNormalMapping_GenerateTB(uv, OUT_tangent, OUT_bitangent); \ + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli new file mode 100644 index 0000000000..5ee527b9a4 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli @@ -0,0 +1,35 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include "../MaterialInputs/ParallaxInput.azsli" +#include + + void MultilayerSetPixelDepth( + float blendMask, + float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + float2 uvs[UvSetCount], + bool isFrontFace, + out float depth) +{ + s_blendMaskFromVertexStream = blendMask; + + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + float parallaxOverallOffset = MaterialSrg::m_displacementMax; + float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin; + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + parallaxOverallFactor, parallaxOverallOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depth); +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli new file mode 100644 index 0000000000..0298656375 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli @@ -0,0 +1,51 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include "../MaterialInputs/ParallaxInput.azsli" +#include + + void SetPixelDepth( + inout float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + inout float2 uvs[UvSetCount], + bool isFrontFace, + inout float depthNDC) +{ + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depthNDC); +} + + void SetPixelDepth( + inout float3 worldPosition, + float3 normal, + float3 tangents[UvSetCount], + float3 bitangents[UvSetCount], + inout float2 uvs[UvSetCount], + bool isFrontFace, + inout float depthCS, + inout float depthNDC, + out bool isClipped) +{ + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); + float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); + + GetParallaxInput( + normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], + MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, + ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, + uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depthNDC, depthCS, isClipped); +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlpha.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlpha.azsli new file mode 100644 index 0000000000..90f8e417e1 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlpha.azsli @@ -0,0 +1,17 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "../MaterialInputs/AlphaInput.azsli" + +float GetAlpha(float2 uvs[UvSetCount]) +{ + // Alpha + float2 baseColorUV = uvs[MaterialSrg::m_baseColorMapUvIndex]; + float2 opacityUV = uvs[MaterialSrg::m_opacityMapUvIndex]; + return MaterialSrg::m_opacityFactor * SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli new file mode 100644 index 0000000000..b79b5b3418 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli @@ -0,0 +1,12 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +float3x3 GetNormalToWorld() +{ + return ObjectSrg::GetWorldMatrixInverseTranspose(); +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli new file mode 100644 index 0000000000..435326215b --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli @@ -0,0 +1,12 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +float4x4 GetObjectToWorld() +{ + return ObjectSrg::GetWorldMatrix(); +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli new file mode 100644 index 0000000000..2dabf9ba1e --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli @@ -0,0 +1,14 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +void MaybeClip(float alpha, float2 uvs[UvSetCount]) +{ + CheckClipping(alpha, MaterialSrg::m_opacityFactor); +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli new file mode 100644 index 0000000000..60ab575a2d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli @@ -0,0 +1,18 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +void TransformDetailUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount]) +{ + // Our standard practice is to only transform the first UV as that's the one we expect to be used for + // tiling. But for detail maps you could actually use either UV stream for tiling. There is no concern about applying + // the same transform to both UV sets because the detail map feature forces the same UV set to be used for all detail maps. + // Note we might be able to combine these into a single UV similar to what Skin.materialtype does, + // but we would need to address how it works with the parallax code below that indexes into the m_detailUV array. + OUT[0] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[0], 1.0)).xy; + OUT[1] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[1], 1.0)).xy; +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli new file mode 100644 index 0000000000..dd77f99ac3 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli @@ -0,0 +1,14 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +void TransformUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount]) +{ + // By design, only UV0 is allowed to apply transforms. + OUT[0] = mul(MaterialSrg::m_uvMatrix, float3(IN[0], 1.0)).xy; + OUT[1] = IN[1]; +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl new file mode 100644 index 0000000000..dd0665efe7 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl @@ -0,0 +1,127 @@ +/* + * 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 + +struct VertexInput +{ + float3 m_position : POSITION; + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; + + // only used for parallax depth calculation + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + +#ifdef MULTILAYER + // This gets set automatically by the system at runtime only if it's available. + // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. + // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). + // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. + float4 m_optional_blendMask : COLOR0; +#endif +}; + +struct VertexOutput +{ + // "centroid" is needed for SV_Depth to compile + linear centroid float4 m_position : SV_Position; + float2 m_uv[UvSetCount] : UV1; + + // only used for parallax depth calculation + float3 m_normal : NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + +#ifdef MULTILAYER + float3 m_blendMask : UV3; +#endif +}; + +VertexOutput MainVS(VertexInput IN) +{ + const float4x4 objectToWorld = GetObjectToWorld(); + VertexOutput OUT; + + const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); + + float2 uv[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformUvs(uv, OUT.m_uv); + + if(ShouldHandleParallaxInDepthShaders()) + { + OUT.m_worldPosition = worldPosition.xyz; + + float3x3 objectToWorldIT = GetNormalToWorld(); + ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); + } + +#ifdef MULTILAYER + if(o_blendMask_isBound) + { + OUT.m_blendMask = IN.m_optional_blendMask.rgb; + } + else + { + OUT.m_blendMask = float3(0,0,0); + } +#endif + + return OUT; +} + +struct PSDepthOutput +{ + float m_depth : SV_Depth; +}; + +PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + PSDepthOutput OUT; + + OUT.m_depth = IN.m_position.z; + + if(ShouldHandleParallaxInDepthShaders()) + { + float3 tangents[UvSetCount] = { IN.m_tangent, IN.m_tangent }; + float3 bitangents[UvSetCount] = { IN.m_bitangent, IN.m_bitangent }; + + for (int i = 0; i != UvSetCount; ++i) + { + EvaluateTangentFrame( + IN.m_normal, + IN.m_worldPosition, + isFrontFace, + IN.m_uv[i], + i, + IN.m_tangent, + IN.m_bitangent, + tangents[i], + bitangents[i]); + } + +#ifdef MULTILAYER + MultilayerSetPixelDepth(IN.m_blendMask, IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); +#else + SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); +#endif + + OUT.m_depth += PdoShadowMapBias; + } + +#ifndef MULTILAYER + float alpha = GetAlpha(IN.m_uv); + MaybeClip(alpha, IN.m_uv); +#endif + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl index 7875457489..d1a488ec0a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl @@ -21,104 +21,11 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "./StandardMultilayerPBR_Common.azsli" -struct VSInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // This gets set automatically by the system at runtime only if it's available. - // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. - // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). - // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. - float4 m_optional_blendMask : COLOR0; -}; - -struct VSDepthOutput -{ - precise linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_blendMask : UV3; -}; - -VSDepthOutput MainVS(VSInput IN) -{ - VSDepthOutput OUT; - - float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); - - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); - - // By design, only UV0 is allowed to apply transforms. - // Note there are additional UV transforms that happen for each layer, but we defer that step to the pixel shader to avoid bloating the vertex output buffer. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - if(o_blendMask_isBound) - { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendMask = float3(0,0,0); - } - - return OUT; -} - -struct PSDepthOutput -{ - precise float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - s_blendMaskFromVertexStream = IN.m_blendMask; - - float depth; - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - float parallaxOverallOffset = MaterialSrg::m_displacementMax; - float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin; - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], parallaxOverallFactor, parallaxOverallOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth); - - OUT.m_depth = depth; - } - - return OUT; -} +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/StandardTransformUVs.azsli" +#include "MaterialFunctions/MultilayerParallaxDepth.azsli" + +#define MULTILAYER +#include "DepthPass_WithPS.azsl" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 3617b7fb04..2fe9990862 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -450,16 +450,16 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Combine Albedo, roughness, specular, roughness --------- - float3 baseColor = BlendLayers(lightingInputLayer1.m_baseColor, lightingInputLayer2.m_baseColor, lightingInputLayer3.m_baseColor, blendWeights); - float3 specularF0Factor = BlendLayers(lightingInputLayer1.m_specularF0Factor, lightingInputLayer2.m_specularF0Factor, lightingInputLayer3.m_specularF0Factor, blendWeights); - float3 metallic = BlendLayers(lightingInputLayer1.m_metallic, lightingInputLayer2.m_metallic, lightingInputLayer3.m_metallic, blendWeights); + surface.baseColor = BlendLayers(lightingInputLayer1.m_baseColor, lightingInputLayer2.m_baseColor, lightingInputLayer3.m_baseColor, blendWeights); + float specularF0Factor = BlendLayers(lightingInputLayer1.m_specularF0Factor, lightingInputLayer2.m_specularF0Factor, lightingInputLayer3.m_specularF0Factor, blendWeights); + surface.metallic = BlendLayers(lightingInputLayer1.m_metallic, lightingInputLayer2.m_metallic, lightingInputLayer3.m_metallic, blendWeights); if(o_parallax_highlightClipping && displacementIsClipped) { - ApplyParallaxClippingHighlight(baseColor); + ApplyParallaxClippingHighlight(surface.baseColor); } - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); + surface.SetAlbedoAndSpecularF0(specularF0Factor); surface.roughnessLinear = BlendLayers(lightingInputLayer1.m_roughness, lightingInputLayer2.m_roughness, lightingInputLayer3.m_roughness, blendWeights); surface.CalculateRoughnessA(); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl index 45d8ed94b3..84b44512f0 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ - + #include #include #include @@ -21,103 +21,11 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "StandardMultilayerPBR_Common.azsli" -struct VertexInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // This gets set automatically by the system at runtime only if it's available. - // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. - // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). - // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. - float4 m_optional_blendMask : COLOR0; -}; - -struct VertexOutput -{ - float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_blendMask : UV3; -}; - -VertexOutput MainVS(VertexInput IN) -{ - const float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - VertexOutput OUT; - - const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - - // By design, only UV0 is allowed to apply transforms. - // Note there are additional UV transforms that happen for each layer, but we defer that step to the pixel shader to avoid bloating the vertex output buffer. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - if(o_blendMask_isBound) - { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendMask = float3(0,0,0); - } - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - s_blendMaskFromVertexStream = IN.m_blendMask; - - float depthNDC; - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - float parallaxOverallOffset = MaterialSrg::m_displacementMax; - float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin; - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], parallaxOverallFactor, parallaxOverallOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC); +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/MultilayerParallaxDepth.azsli" - OUT.m_depth = depthNDC; - } - - return OUT; -} +#define MULTILAYER +#include "ShadowMap_WithPS.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl index 04fd104407..fe46d9bfba 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl @@ -8,91 +8,13 @@ #include "./StandardPBR_Common.azsli" #include -#include -#include -#include "MaterialInputs/AlphaInput.azsli" -#include "MaterialInputs/ParallaxInput.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetAlpha.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardMaybeClip.azsli" -struct VSInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VSDepthOutput -{ - // "centroid" is needed for SV_Depth to compile - precise linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VSDepthOutput MainVS(VSInput IN) -{ - VSDepthOutput OUT; - - float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); - - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - return OUT; -} - -struct PSDepthOutput -{ - precise float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - } - - // Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#include "DepthPass_WithPS.azsl" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index b99ea734af..1a5e92b1d3 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -10,23 +10,7 @@ #include "StandardPBR_Common.azsli" -// SRGs #include -#include - -// Pass Output -#include - -// Utility -#include -#include - -// Custom Surface & Lighting -#include - -// Decals -#include - // ---------- Material Parameters ---------- @@ -43,320 +27,12 @@ COMMON_OPTIONS_EMISSIVE() // Alpha #include "MaterialInputs/AlphaInput.azsli" -// ---------- Vertex Shader ---------- - -struct VSInput -{ - // Base fields (required by the template azsli file)... - float3 m_position : POSITION; - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; -}; - -struct VSOutput -{ - // Base fields (required by the template azsli file)... - // "centroid" is needed for SV_Depth to compile - precise linear centroid float4 m_position : SV_Position; - float3 m_normal: NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV3; - - // Extended fields (only referenced in this azsl file)... - float2 m_uv[UvSetCount] : UV1; -}; - -#include - -VSOutput StandardPbr_ForwardPassVS(VSInput IN) -{ - VSOutput OUT; - - float3 worldPosition = mul(ObjectSrg::GetWorldMatrix(), float4(IN.m_position, 1.0)).xyz; - - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - // Shadow coords will be calculated in the pixel shader in this case - bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; - - VertexHelper(IN, OUT, worldPosition, skipShadowCoords); - - return OUT; -} - - -// ---------- Pixel Shader ---------- - -PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) -{ - const float3 vertexNormal = normalize(IN.m_normal); - - // ------- Tangents & Bitangets ------- - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - - if (ShouldHandleParallax() || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture)) - { - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - } - - // ------- Depth & Parallax ------- - - depthNDC = IN.m_position.z; - - bool displacementIsClipped = false; - - if(ShouldHandleParallax()) - { - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC, IN.m_position.w, displacementIsClipped); - - // Adjust directional light shadow coordinates for parallax correction - if(o_parallax_enablePixelDepthOffset) - { - const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; - if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) - { - DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); - } - } - } - - Surface surface; - surface.position = IN.m_worldPosition.xyz; - - // ------- Alpha & Clip ------- - - float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUv = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = GetAlphaInputAndClip(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUv, opacityUv, MaterialSrg::m_sampler, MaterialSrg::m_opacityFactor, o_opacity_source); - - // ------- Normal ------- - - float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex]; - float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. - surface.vertexNormal = vertexNormal; - surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, IN.m_normal, - tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor); - - // ------- Base Color ------- - - float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); - float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); - - if(o_parallax_highlightClipping && displacementIsClipped) - { - ApplyParallaxClippingHighlight(baseColor); - } - - // ------- Metallic ------- - - float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex]; - float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); - - // ------- Specular ------- - - float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex]; - float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); - - // ------- Roughness ------- - - float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex]; - surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, - MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); - surface.CalculateRoughnessA(); - - // ------- Lighting Data ------- - - LightingData lightingData; - - // Light iterator - lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); - lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); - - // Directional light shadow coordinates - lightingData.shadowCoords = IN.m_shadowCoords; - - // ------- Emissive ------- - - float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex]; - lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); - - // ------- Occlusion ------- - - lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); - lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); - - // ------- Clearcoat ------- - - // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags - if(o_clearCoat_feature_enabled) - { - if(o_clearCoat_enabled) - { - float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture, - MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture, - MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength, - uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex], - MaterialSrg::m_sampler, isFrontFace, - surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal); - } - - // manipulate base layer f0 if clear coat is enabled - // modify base layer's normal incidence reflectance - // for the derivation of the following equation please refer to: - // https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification - float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0)); - surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); - } - - // Diffuse and Specular response (used in IBL calculations) - lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); - lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; - - if(o_clearCoat_feature_enabled) - { - // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 - lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); - } - - // ------- Multiscatter ------- - - lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); - - // ------- Lighting Calculation ------- - - // Apply Decals - ApplyDecals(lightingData.tileIterator, surface); - - // Apply Direct Lighting - ApplyDirectLighting(surface, lightingData); - - // Apply Image Based Lighting (IBL) - ApplyIBL(surface, lightingData); - - // Finalize Lighting - lightingData.FinalizeLighting(); - - PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); - - // ------- Opacity ------- - - if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) - { - // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. - // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface - // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor - // values close to 1.0, that indicates the absence of a surface entirely, so this effect should - // not apply. - float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; - alpha = lerp(fresnelAlpha, alpha, MaterialSrg::m_opacityAffectsSpecularFactor); - } - - if (o_opacity_mode == OpacityMode::Blended) - { - // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when - // specular is being added to diffuse just because we're calling render target 0 "diffuse". - - // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular - // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. - // It's done this way because surface transparency doesn't really change specular response (eg, glass). - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_diffuseColor.w = alpha; - } - else if (o_opacity_mode == OpacityMode::TintedTransparent) - { - // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting - // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength - // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, - // absorption, and interior color to be specified. - // - // The technique uses dual source blending to allow two separate sources to be part of the blending equation - // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and - // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). - // - // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then - // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. - - lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - - // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. - float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); - lightingOutput.m_diffuseColor.rgb += specular; - - lightingOutput.m_specularColor.rgb = baseColor * (1.0 - alpha); - } - else - { - lightingOutput.m_diffuseColor.w = -1; // Disable subsurface scattering - } - - return lightingOutput; -} - -ForwardPassOutputWithDepth StandardPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutputWithDepth OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); - -#ifdef UNIFIED_FORWARD_OUTPUT - OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; - OUT.m_color.a = lightingOutput.m_diffuseColor.a; - OUT.m_depth = depth; -#else - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; - OUT.m_depth = depth; -#endif - return OUT; -} - -[earlydepthstencil] -ForwardPassOutput StandardPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - ForwardPassOutput OUT; - float depth; - - PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); +#include "MaterialFunctions/EvaluateStandardSurface.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardMaybeClip.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" -#ifdef UNIFIED_FORWARD_OUTPUT - OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; - OUT.m_color.a = lightingOutput.m_diffuseColor.a; -#else - OUT.m_diffuseColor = lightingOutput.m_diffuseColor; - OUT.m_specularColor = lightingOutput.m_specularColor; - OUT.m_specularF0 = lightingOutput.m_specularF0; - OUT.m_albedo = lightingOutput.m_albedo; - OUT.m_normal = lightingOutput.m_normal; -#endif - return OUT; -} +#include "StandardSurface_ForwardPass.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl index 02f1cd0389..e8aeb20871 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl @@ -9,93 +9,16 @@ #include #include "StandardPBR_Common.azsli" #include -#include -#include -#include #include "MaterialInputs/AlphaInput.azsli" #include "MaterialInputs/ParallaxInput.azsli" -struct VertexInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetAlpha.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardMaybeClip.azsli" - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; -}; - -struct VertexOutput -{ - // "centroid" is needed for SV_Depth to compile - linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; -}; - -VertexOutput MainVS(VertexInput IN) -{ - const float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - VertexOutput OUT; - - const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - // By design, only UV0 is allowed to apply transforms. - OUT.m_uv[0] = mul(MaterialSrg::m_uvMatrix, float3(IN.m_uv0, 1.0)).xy; - OUT.m_uv[1] = IN.m_uv1; - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); - - float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); - float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); - - GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, - ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, - IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth); - - OUT.m_depth += PdoShadowMapBias; - } - - // Alpha - float2 baseColorUV = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; - float2 opacityUV = IN.m_uv[MaterialSrg::m_opacityMapUvIndex]; - float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); - - CheckClipping(alpha, MaterialSrg::m_opacityFactor); - - return OUT; -} +#include "ShadowMap_WithPS.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl new file mode 100644 index 0000000000..1d3fa29991 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl @@ -0,0 +1,306 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +// Pass Output +#include + +// Utility +#include +#include + +// Custom Surface & Lighting +#include + +// Decals +#include + + +// ---------- Vertex Shader ---------- + +struct VSInput +{ + // Base fields (required by the template azsli file)... + float3 m_position : POSITION; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv0 : UV0; + float2 m_uv1 : UV1; +}; + +struct VSOutput +{ + // Base fields (required by the template azsli file)... + // "centroid" is needed for SV_Depth to compile + precise linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV3; + + // Extended fields (only referenced in this azsl file)... + float2 m_uv[UvSetCount] : UV1; +}; + +#include + +VSOutput StandardPbr_ForwardPassVS(VSInput IN) +{ + VSOutput OUT; + + float4x4 objectToWorld = GetObjectToWorld(); + float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); + OUT.m_worldPosition = worldPosition.xyz; + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); + + float2 uvs[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; + TransformUvs(uvs, OUT.m_uv); + + // Shadow coords will be calculated in the pixel shader in this case + bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; + + float3x3 objectToWorldIT = GetNormalToWorld(); + ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); + + // directional light shadow + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && !skipShadowCoords && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords( + shadowIndex, + worldPosition, + OUT.m_normal, + OUT.m_shadowCoords); + } + + return OUT; +} + + +// ---------- Pixel Shader ---------- + +PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) +{ + const float3 vertexNormal = normalize(IN.m_normal); + + // ------- Tangents & Bitangents ------- + float3 tangents[UvSetCount] = { IN.m_tangent, IN.m_tangent }; + float3 bitangents[UvSetCount] = { IN.m_bitangent, IN.m_bitangent }; + + if (ShouldHandleParallax() || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture)) + { + for (int i = 0; i != UvSetCount; ++i) + { + EvaluateTangentFrame( + IN.m_normal, + IN.m_worldPosition, + isFrontFace, + IN.m_uv[i], + i, + IN.m_tangent, + IN.m_bitangent, + tangents[i], + bitangents[i]); + } + } + + // ------- Depth & Parallax ------- + + depthNDC = IN.m_position.z; + bool displacementIsClipped = false; + + if(ShouldHandleParallax()) + { + SetPixelDepth( + IN.m_worldPosition, + IN.m_normal, + tangents, + bitangents, + IN.m_uv, + isFrontFace, + IN.m_position.w, + depthNDC, + displacementIsClipped); + + // Adjust directional light shadow coordinates for parallax correction + if(o_parallax_enablePixelDepthOffset) + { + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) + { + DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords); + } + } + } + + Surface surface; + surface.vertexNormal = vertexNormal; + surface.position = IN.m_worldPosition.xyz; + + // ------- Alpha & Clip ------- + // TODO: this often invokes a separate sample of the base color texture which is wasteful + float alpha = GetAlpha(IN.m_uv); + MaybeClip(alpha, IN.m_uv); + + EvaluateStandardSurface(IN.m_normal, IN.m_uv, tangents, bitangents, isFrontFace, displacementIsClipped, surface); + + // ------- Lighting Data ------- + + LightingData lightingData; + + // Light iterator + lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData); + lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); + + // Directional light shadow coordinates + lightingData.shadowCoords = IN.m_shadowCoords; + + // Surface lighting properties + lightingData.emissiveLighting = surface.emissiveLighting; + lightingData.diffuseAmbientOcclusion = surface.diffuseAmbientOcclusion; + lightingData.specularOcclusion = surface.specularOcclusion; + + // Diffuse and Specular response (used in IBL calculations) + lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); + lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; + + if(o_clearCoat_feature_enabled) + { + // Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04 + lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor); + } + + // ------- Multiscatter ------- + + lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); + + // ------- Lighting Calculation ------- + + // Apply Decals + ApplyDecals(lightingData.tileIterator, surface); + + // Apply Direct Lighting + ApplyDirectLighting(surface, lightingData); + + // Apply Image Based Lighting (IBL) + ApplyIBL(surface, lightingData); + + // Finalize Lighting + lightingData.FinalizeLighting(); + + PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); + + // ------- Opacity ------- + + if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) + { + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; + alpha = lerp(fresnelAlpha, alpha, surface.opacityAffectsSpecularFactor); + } + + if (o_opacity_mode == OpacityMode::Blended) + { + // [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when + // specular is being added to diffuse just because we're calling render target 0 "diffuse". + + // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular + // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. + // It's done this way because surface transparency doesn't really change specular response (eg, glass). + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_diffuseColor.w = alpha; + } + else if (o_opacity_mode == OpacityMode::TintedTransparent) + { + // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting + // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength + // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, + // absorption, and interior color to be specified. + // + // The technique uses dual source blending to allow two separate sources to be part of the blending equation + // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and + // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). + // + // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then + // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + + lightingOutput.m_specularColor.rgb = surface.baseColor * (1.0 - alpha); + } + else + { + lightingOutput.m_diffuseColor.w = -1; // Disable subsurface scattering + } + + return lightingOutput; +} + +ForwardPassOutputWithDepth StandardPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutputWithDepth OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + +#ifdef UNIFIED_FORWARD_OUTPUT + OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; + OUT.m_color.a = lightingOutput.m_diffuseColor.a; + OUT.m_depth = depth; +#else + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; + OUT.m_depth = depth; +#endif + return OUT; +} + +[earlydepthstencil] +ForwardPassOutput StandardPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + ForwardPassOutput OUT; + float depth; + + PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth); + +#ifdef UNIFIED_FORWARD_OUTPUT + OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb; + OUT.m_color.a = lightingOutput.m_diffuseColor.a; +#else + OUT.m_diffuseColor = lightingOutput.m_diffuseColor; + OUT.m_specularColor = lightingOutput.m_specularColor; + OUT.m_specularF0 = lightingOutput.m_specularF0; + OUT.m_albedo = lightingOutput.m_albedo; + OUT.m_normal = lightingOutput.m_normal; +#endif + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli index eb8c33cdce..21f55ea259 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli @@ -24,12 +24,31 @@ class Surface float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space float3 vertexNormal; //!< Vertex normal in world-space - float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value - float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 baseColor; //!< Surface base color + float3 metallic; //!< Surface metallic property float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance + //! Subsurface scattering parameters + float subsurfaceScatteringFactor; + float subsurfaceScatteringQuality; + float3 scatterDistance; + + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float opacityAffectsSpecularFactor; + + //! Surface lighting inputs + float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value + float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 emissiveLighting; //!< Emissive lighting + float diffuseAmbientOcclusion; //!< Diffuse ambient occlusion factor - [0, 1] :: [Dark, Bright] + float specularOcclusion; //!< Specular occlusion factor - [0, 1] :: [Dark, Bright] + //! Applies specular anti-aliasing to roughnessA2 void ApplySpecularAA(); @@ -37,7 +56,7 @@ class Surface void CalculateRoughnessA(); //! Sets albedo and specularF0 using metallic workflow - void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic); + void SetAlbedoAndSpecularF0(float specularF0Factor); }; @@ -76,7 +95,7 @@ void Surface::CalculateRoughnessA() } } -void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic) +void Surface::SetAlbedoAndSpecularF0(float specularF0Factor) { float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli index cf4edba923..9d4abeb0f6 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli @@ -25,12 +25,26 @@ class Surface precise float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space float3 vertexNormal; //!< Vertex normal in world-space - float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value - float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 baseColor; //!< Surface base color + float metallic; //!< Surface metallic property float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float opacityAffectsSpecularFactor; + + //! Surface lighting data + float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value + float3 specularF0; //!< Fresnel f0 spectral value of the surface + float3 emissiveLighting; //!< Emissive lighting + float diffuseAmbientOcclusion; //!< Diffuse ambient occlusion factor - [0, 1] :: [Dark, Bright] + float specularOcclusion; //!< Specular occlusion factor - [0, 1] :: [Dark, Bright] + //! Applies specular anti-aliasing to roughnessA2 void ApplySpecularAA(); @@ -38,7 +52,7 @@ class Surface void CalculateRoughnessA(); //! Sets albedo and specularF0 using metallic workflow - void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic); + void SetAlbedoAndSpecularF0(float specularF0Factor); }; // Specular Anti-Aliasing technique from this paper: @@ -75,7 +89,7 @@ void Surface::CalculateRoughnessA() } } -void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic) +void Surface::SetAlbedoAndSpecularF0(float specularF0Factor) { float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor; diff --git a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl index 13f1e33ef7..3c4388350e 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl @@ -144,18 +144,20 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) identityUvMatrix); IN.m_uv += tangentOffset.m_offsetTS.xy; + + Surface surface; - float3 baseColor = float3(1,1,1); + surface.baseColor = float3(1,1,1); const float noise = AutoBrickSrg::m_noise.Sample(AutoBrickSrg::m_sampler, IN.m_uv).r; float distanceFromBrick = GetNormalizedDistanceFromBrick(IN.m_uv); if(distanceFromBrick > AutoBrickSrg::m_brickColorBleed) { - baseColor = AutoBrickSrg::m_lineColor * lerp(1.0, noise, AutoBrickSrg::m_lineNoiseFactor); + surface.baseColor = AutoBrickSrg::m_lineColor * lerp(1.0, noise, AutoBrickSrg::m_lineNoiseFactor); } else { - baseColor = AutoBrickSrg::m_brickColor * lerp(1.0, noise, AutoBrickSrg::m_brickNoiseFactor); + surface.baseColor = AutoBrickSrg::m_brickColor * lerp(1.0, noise, AutoBrickSrg::m_brickNoiseFactor); } float surfaceDepth; @@ -164,8 +166,6 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) const float3 normal = TangentSpaceToWorld(surfaceNormal, normalize(IN.m_normal), normalize(IN.m_tangent), normalize(IN.m_bitangent)); // ------- Surface ------- - - Surface surface; // Position, Normal, Roughness surface.position = IN.m_worldPosition.xyz; @@ -175,9 +175,9 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) surface.CalculateRoughnessA(); // Albedo, SpecularF0 - const float metallic = 0.0f; - const float specularF0Factor = 0.5f; - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); + surface.metallic = 0.0f; + float specularF0Factor = 0.5f; + surface.SetAlbedoAndSpecularF0(specularF0Factor); // Clear Coat surface.clearCoat.InitializeToZero(); diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl index 140fc57961..503c0107db 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl @@ -68,8 +68,10 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN) surface.CalculateRoughnessA(); // Albedo, SpecularF0 - const float specularF0Factor = 0.5f; - surface.SetAlbedoAndSpecularF0(MinimalPBRSrg::m_baseColor, specularF0Factor, MinimalPBRSrg::m_metallic); + surface.baseColor = MinimalPBRSrg::m_baseColor; + surface.metallic = MinimalPBRSrg::m_metallic; + float specularF0Factor = 0.5f; + surface.SetAlbedoAndSpecularF0(specularF0Factor); // Clear Coat surface.clearCoat.InitializeToZero(); From 7aace39c2fe63757c3ac966452b030842511e734 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Fri, 4 Feb 2022 13:37:42 -0700 Subject: [PATCH 2/7] Consolidate alpha retrieval and clip Signed-off-by: Jeremy Ong --- .../Assets/Materials/Types/DepthPass_WithPS.azsl | 3 +-- .../Types/EnhancedPBR_DepthPass_WithPS.azsl | 3 +-- .../Materials/Types/EnhancedPBR_ForwardPass.azsl | 2 +- .../Types/EnhancedPBR_Shadowmap_WithPS.azsl | 3 +-- .../Types/EnhancedSurface_ForwardPass.azsl | 3 +-- .../EvaluateEnhancedSurface.azsli | 1 - .../EvaluateStandardSurface.azsli | 1 - .../MaterialFunctions/EvaluateTangentFrame.azsli | 4 ++-- ...etAlpha.azsli => StandardGetAlphaAndClip.azsli} | 6 ++++-- .../MaterialFunctions/StandardMaybeClip.azsli | 14 -------------- .../Assets/Materials/Types/ShadowMap_WithPS.azsl | 3 +-- .../Types/StandardPBR_DepthPass_WithPS.azsl | 3 +-- .../Materials/Types/StandardPBR_ForwardPass.azsl | 2 +- .../Types/StandardPBR_Shadowmap_WithPS.azsl | 3 +-- .../Types/StandardSurface_ForwardPass.azsl | 3 +-- 15 files changed, 16 insertions(+), 38 deletions(-) rename Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/{StandardGetAlpha.azsli => StandardGetAlphaAndClip.azsli} (57%) delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl index 9b017222b1..59d10f28f9 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl @@ -116,8 +116,7 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) } #ifndef MULTILAYER - float alpha = GetAlpha(IN.m_uv); - MaybeClip(alpha, IN.m_uv); + GetAlphaAndClip(IN.m_uv); #endif return OUT; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl index 2f7a5b94f9..f5ca5c5cde 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -11,10 +11,9 @@ #include "MaterialFunctions/StandardGetObjectToWorld.azsli" #include "MaterialFunctions/StandardGetNormalToWorld.azsli" -#include "MaterialFunctions/StandardGetAlpha.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/EvaluateTangentFrame.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" -#include "MaterialFunctions/StandardMaybeClip.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" #include "DepthPass_WithPS.azsl" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index bac97fed64..3e2bd4588b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -39,7 +39,7 @@ COMMON_OPTIONS_DETAIL_MAPS() #include "MaterialFunctions/EnhancedParallaxDepth.azsli" #include "MaterialFunctions/StandardGetNormalToWorld.azsli" #include "MaterialFunctions/StandardGetObjectToWorld.azsli" -#include "MaterialFunctions/StandardMaybeClip.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" #include "MaterialFunctions/StandardTransformDetailUvs.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl index 6c01a63a7c..3a9f8a7417 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl @@ -18,10 +18,9 @@ #include "MaterialFunctions/StandardGetObjectToWorld.azsli" #include "MaterialFunctions/StandardGetNormalToWorld.azsli" -#include "MaterialFunctions/StandardGetAlpha.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/EvaluateTangentFrame.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" -#include "MaterialFunctions/StandardMaybeClip.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" #include "ShadowMap_WithPS.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl index ceb9379f28..ef08b928cf 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl @@ -152,8 +152,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Alpha & Clip ------- // TODO: this often invokes a separate sample of the base color texture which is wasteful - float alpha = GetAlpha(IN.m_uv); - MaybeClip(alpha, IN.m_uv); + float alpha = GetAlphaAndClip(IN.m_uv); EvaluateEnhancedSurface(IN.m_normal, IN.m_uv, IN.m_detailUv, tangents, bitangents, isFrontFace, displacementIsClipped, surface); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli index 9cc3e05789..c8d59363ea 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli @@ -8,7 +8,6 @@ #include #include -#include "StandardGetAlpha.azsli" void EvaluateEnhancedSurface( float3 normal, diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli index 54a4a2462a..c58f0534b3 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli @@ -8,7 +8,6 @@ #include #include -#include "StandardGetAlpha.azsli" void EvaluateStandardSurface( float3 normal, diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli index 2aad5f257d..643a2d29ca 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli @@ -17,8 +17,8 @@ void EvaluateTangentFrame( // The input tangent and bitangent vectors are optional and used to forward data from interpolants float3 IN_tangent, float3 IN_bitangent, - float3 OUT_tangent, - float3 OUT_bitangent) + out float3 OUT_tangent, + out float3 OUT_bitangent) { if (DrawSrg::GetTangentAtUv(uvIndex) == 0) { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlpha.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli similarity index 57% rename from Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlpha.azsli rename to Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli index 90f8e417e1..81380e8c07 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlpha.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli @@ -8,10 +8,12 @@ #include "../MaterialInputs/AlphaInput.azsli" -float GetAlpha(float2 uvs[UvSetCount]) +float GetAlphaAndClip(float2 uvs[UvSetCount]) { // Alpha float2 baseColorUV = uvs[MaterialSrg::m_baseColorMapUvIndex]; float2 opacityUV = uvs[MaterialSrg::m_opacityMapUvIndex]; - return MaterialSrg::m_opacityFactor * SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); + float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); + CheckClipping(alpha, MaterialSrg::m_opacityFactor); + return MaterialSrg::m_opacityFactor * alpha; } \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli deleted file mode 100644 index 2dabf9ba1e..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardMaybeClip.azsli +++ /dev/null @@ -1,14 +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 - -void MaybeClip(float alpha, float2 uvs[UvSetCount]) -{ - CheckClipping(alpha, MaterialSrg::m_opacityFactor); -} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl index dd0665efe7..3dc2cf5d77 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl @@ -119,8 +119,7 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) } #ifndef MULTILAYER - float alpha = GetAlpha(IN.m_uv); - MaybeClip(alpha, IN.m_uv); + GetAlphaAndClip(IN.m_uv); #endif return OUT; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl index fe46d9bfba..62dcddf2a6 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl @@ -11,10 +11,9 @@ #include "MaterialFunctions/StandardGetObjectToWorld.azsli" #include "MaterialFunctions/StandardGetNormalToWorld.azsli" -#include "MaterialFunctions/StandardGetAlpha.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" #include "MaterialFunctions/EvaluateTangentFrame.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" -#include "MaterialFunctions/StandardMaybeClip.azsli" #include "DepthPass_WithPS.azsl" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index 1a5e92b1d3..5dc1148370 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -32,7 +32,7 @@ COMMON_OPTIONS_EMISSIVE() #include "MaterialFunctions/ParallaxDepth.azsli" #include "MaterialFunctions/StandardGetNormalToWorld.azsli" #include "MaterialFunctions/StandardGetObjectToWorld.azsli" -#include "MaterialFunctions/StandardMaybeClip.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" #include "StandardSurface_ForwardPass.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl index e8aeb20871..7acc121036 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl @@ -15,10 +15,9 @@ #include "MaterialFunctions/StandardGetObjectToWorld.azsli" #include "MaterialFunctions/StandardGetNormalToWorld.azsli" -#include "MaterialFunctions/StandardGetAlpha.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/EvaluateTangentFrame.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" -#include "MaterialFunctions/StandardMaybeClip.azsli" #include "ShadowMap_WithPS.azsl" \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl index 1d3fa29991..b60f789cf5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl @@ -149,8 +149,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Alpha & Clip ------- // TODO: this often invokes a separate sample of the base color texture which is wasteful - float alpha = GetAlpha(IN.m_uv); - MaybeClip(alpha, IN.m_uv); + float alpha = GetAlphaAndClip(IN.m_uv); EvaluateStandardSurface(IN.m_normal, IN.m_uv, tangents, bitangents, isFrontFace, displacementIsClipped, surface); From 4bcc83e7ac66f7c8631aa45fb9b6796d80e634c2 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Fri, 4 Feb 2022 23:59:45 -0700 Subject: [PATCH 3/7] Address PR feedback, ensure all ASV tests pass Signed-off-by: Jeremy Ong --- .../Materials/Types/BasePBR_ForwardPass.azsl | 6 +- ...ass_WithPS.azsl => DepthPass_WithPS.azsli} | 9 +- .../Types/EnhancedPBR_DepthPass_WithPS.azsl | 2 +- .../Types/EnhancedPBR_ForwardPass.azsl | 2 +- .../Types/EnhancedPBR_Shadowmap_WithPS.azsl | 3 +- ...azsl => EnhancedSurface_ForwardPass.azsli} | 13 +- .../EnhancedParallaxDepth.azsli | 2 +- .../EvaluateEnhancedSurface.azsli | 19 +-- .../EvaluateStandardSurface.azsli | 15 ++- .../EvaluateTangentFrame.azsli | 6 +- .../MultilayerParallaxDepth.azsli | 6 +- .../MaterialFunctions/ParallaxDepth.azsli | 2 +- .../StandardGetAlphaAndClip.azsli | 2 +- .../StandardGetNormalToWorld.azsli | 2 +- .../StandardGetObjectToWorld.azsli | 2 +- .../StandardTransformDetailUvs.azsli | 2 +- .../StandardTransformUvs.azsli | 2 +- .../Materials/Types/ShadowMap_WithPS.azsl | 126 ------------------ ...tandardMultilayerPBR_DepthPass_WithPS.azsl | 3 +- .../StandardMultilayerPBR_ForwardPass.azsl | 8 +- ...tandardMultilayerPBR_Shadowmap_WithPS.azsl | 3 +- .../Types/StandardPBR_DepthPass_WithPS.azsl | 2 +- .../Types/StandardPBR_ForwardPass.azsl | 2 +- .../Types/StandardPBR_LowEndForward.azsl | 13 -- .../Types/StandardPBR_LowEndForward.shader | 4 +- .../StandardPBR_LowEndForward_EDS.shader | 4 +- .../Types/StandardPBR_Shadowmap_WithPS.azsl | 3 +- ...azsl => StandardSurface_ForwardPass.azsli} | 9 +- .../PBR/Surfaces/EnhancedSurface.azsli | 33 +++-- .../PBR/Surfaces/StandardSurface.azsli | 22 ++- .../atom_feature_common_asset_files.cmake | 15 ++- .../Types/AutoBrick_ForwardPass.azsl | 16 +-- .../Types/MinimalPBR_ForwardPass.azsl | 6 +- 33 files changed, 137 insertions(+), 227 deletions(-) rename Gems/Atom/Feature/Common/Assets/Materials/Types/{DepthPass_WithPS.azsl => DepthPass_WithPS.azsli} (95%) rename Gems/Atom/Feature/Common/Assets/Materials/Types/{EnhancedSurface_ForwardPass.azsl => EnhancedSurface_ForwardPass.azsli} (96%) delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.azsl rename Gems/Atom/Feature/Common/Assets/Materials/Types/{StandardSurface_ForwardPass.azsl => StandardSurface_ForwardPass.azsli} (97%) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl index b887761917..96318f2284 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/BasePBR_ForwardPass.azsl @@ -116,19 +116,19 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace) float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex]; float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); - surface.baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); + float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); // ------- Metallic ------- float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex]; - surface.metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); // ------- Specular ------- float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex]; float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - surface.SetAlbedoAndSpecularF0(specularF0Factor); + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); // ------- Roughness ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli similarity index 95% rename from Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl rename to Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli index 59d10f28f9..70d7b65b9b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli @@ -6,6 +6,10 @@ * */ +#ifdef SHADOWS +#include +#endif + struct VSInput { float3 m_position : POSITION; @@ -113,9 +117,12 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); #endif +#ifdef SHADOW + OUT.m_depth += PdoShadowMapBias; +#endif } -#ifndef MULTILAYER +#ifndef DEACTIVATE_ALPHA_CLIP GetAlphaAndClip(IN.m_uv); #endif diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl index f5ca5c5cde..a13d04bdb8 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -16,4 +16,4 @@ #include "MaterialFunctions/ParallaxDepth.azsli" #include "MaterialFunctions/StandardGetAlphaAndClip.azsli" -#include "DepthPass_WithPS.azsl" +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 3e2bd4588b..640ada8bd8 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -43,4 +43,4 @@ COMMON_OPTIONS_DETAIL_MAPS() #include "MaterialFunctions/StandardTransformDetailUvs.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" -#include "EnhancedSurface_ForwardPass.azsl" \ No newline at end of file +#include "EnhancedSurface_ForwardPass.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl index 3a9f8a7417..e5a7b3eb3c 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl @@ -23,4 +23,5 @@ #include "MaterialFunctions/ParallaxDepth.azsli" #include "MaterialFunctions/StandardGetAlphaAndClip.azsli" -#include "ShadowMap_WithPS.azsl" \ No newline at end of file +#define SHADOWS +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsli similarity index 96% rename from Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl rename to Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsli index ef08b928cf..8bc9802443 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedSurface_ForwardPass.azsli @@ -146,6 +146,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float } } + SurfaceSettings surfaceSettings; Surface surface; surface.vertexNormal = vertexNormal; surface.position = IN.m_worldPosition; @@ -154,7 +155,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // TODO: this often invokes a separate sample of the base color texture which is wasteful float alpha = GetAlphaAndClip(IN.m_uv); - EvaluateEnhancedSurface(IN.m_normal, IN.m_uv, IN.m_detailUv, tangents, bitangents, isFrontFace, displacementIsClipped, surface); + EvaluateEnhancedSurface(IN.m_normal, IN.m_uv, IN.m_detailUv, tangents, bitangents, isFrontFace, displacementIsClipped, surface, surfaceSettings); // ------- Lighting Data ------- @@ -222,7 +223,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // values close to 1.0, that indicates the absence of a surface entirely, so this effect should // not apply. float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; - alpha = lerp(fresnelAlpha, alpha, surface.opacityAffectsSpecularFactor); + alpha = lerp(fresnelAlpha, alpha, surfaceSettings.opacityAffectsSpecularFactor); } // Note: lightingOutput rendertargets are not always used as named, particularly m_diffuseColor (target 0) and @@ -241,7 +242,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); lightingOutput.m_diffuseColor.rgb += specular; lightingOutput.m_diffuseColor.w = alpha; @@ -264,7 +265,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); lightingOutput.m_diffuseColor.rgb += specular; lightingOutput.m_specularColor.rgb = surface.baseColor * (1.0 - alpha); @@ -272,9 +273,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float else { // Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961 - uint factorAndQuality = dot(round(float2(saturate(surface.subsurfaceScatteringFactor), surface.subsurfaceScatteringQuality) * 255), float2(256, 1)); + uint factorAndQuality = dot(round(float2(saturate(surface.subsurfaceScatteringFactor), surfaceSettings.subsurfaceScatteringQuality) * 255), float2(256, 1)); lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0); - lightingOutput.m_scatterDistance = surface.scatterDistance; + lightingOutput.m_scatterDistance = surfaceSettings.scatterDistance; } return lightingOutput; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli index e89afd6f37..449c789d01 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli @@ -38,4 +38,4 @@ // Apply second part of the offset to the detail UV (see comment above) detailUv[MaterialSrg::m_parallaxUvIndex] -= uvs[MaterialSrg::m_parallaxUvIndex]; -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli index c8d59363ea..d1cb52004a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli @@ -17,7 +17,8 @@ void EvaluateEnhancedSurface( float3 bitangents[UvSetCount], bool isFrontFace, bool displacementIsClipped, - inout Surface surface) + inout Surface surface, + out SurfaceSettings surfaceSettings) { // ------- Detail Layer Setup ------- @@ -52,22 +53,22 @@ void EvaluateEnhancedSurface( float detailLayerBaseColorFactor = MaterialSrg::m_detail_baseColor_factor * detailLayerBlendFactor; float2 baseColorUv = uvs[MaterialSrg::m_baseColorMapUvIndex]; - surface.baseColor = GetDetailedBaseColorInput( + float3 baseColor = GetDetailedBaseColorInput( MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, o_baseColor_useTexture, MaterialSrg::m_baseColor, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, detailUv, o_detail_baseColor_useTexture, detailLayerBaseColorFactor); if(o_parallax_highlightClipping && displacementIsClipped) { - ApplyParallaxClippingHighlight(surface.baseColor); + ApplyParallaxClippingHighlight(baseColor); } // ------- Metallic ------- - surface.metallic = 0; + float metallic = 0; if(!o_enableSubsurfaceScattering) // If subsurface scattering is enabled skip texture lookup for metallic, as this quantity won't be used anyway { float2 metallicUv = uvs[MaterialSrg::m_metallicMapUvIndex]; - surface.metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); } // ------- Specular ------- @@ -75,7 +76,7 @@ void EvaluateEnhancedSurface( float2 specularUv = uvs[MaterialSrg::m_specularF0MapUvIndex]; float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - surface.SetAlbedoAndSpecularF0(specularF0Factor); + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); // ------- Roughness ------- @@ -88,8 +89,8 @@ void EvaluateEnhancedSurface( float2 subsurfaceUv = uvs[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex]; surface.subsurfaceScatteringFactor = GetSubsurfaceInput(MaterialSrg::m_subsurfaceScatteringInfluenceMap, MaterialSrg::m_sampler, subsurfaceUv, MaterialSrg::m_subsurfaceScatteringFactor); - surface.subsurfaceScatteringQuality = MaterialSrg::m_subsurfaceScatteringQuality; - surface.scatterDistance = MaterialSrg::m_scatterDistance; + surfaceSettings.subsurfaceScatteringQuality = MaterialSrg::m_subsurfaceScatteringQuality; + surfaceSettings.scatterDistance = MaterialSrg::m_scatterDistance; // ------- Transmission ------- @@ -144,5 +145,5 @@ void EvaluateEnhancedSurface( surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor); } - surface.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; + surfaceSettings.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; } diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli index c58f0534b3..da24bb3937 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli @@ -16,7 +16,8 @@ void EvaluateStandardSurface( float3 bitangents[UvSetCount], bool isFrontFace, bool displacementIsClipped, - inout Surface surface) + inout Surface surface, + out SurfaceSettings surfaceSettings) { // ------- Normal ------- @@ -29,24 +30,24 @@ void EvaluateStandardSurface( float2 baseColorUv = uv[MaterialSrg::m_baseColorMapUvIndex]; float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); - surface.baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); + float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); if(o_parallax_highlightClipping && displacementIsClipped) { - ApplyParallaxClippingHighlight(surface.baseColor); + ApplyParallaxClippingHighlight(baseColor); } // ------- Metallic ------- float2 metallicUv = uv[MaterialSrg::m_metallicMapUvIndex]; - surface.metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); + float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture); // ------- Specular ------- float2 specularUv = uv[MaterialSrg::m_specularF0MapUvIndex]; float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture); - surface.SetAlbedoAndSpecularF0(specularF0Factor); + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); // ------- Roughness ------- @@ -90,5 +91,5 @@ void EvaluateStandardSurface( } // ------- Opacity ------- - surface.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; -} \ No newline at end of file + surfaceSettings.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor; +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli index 643a2d29ca..0045d18e47 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli @@ -27,7 +27,7 @@ void EvaluateTangentFrame( } else { - SurfaceGradientNormalMapping_Init(normal, worldPosition, !isFrontFace); \ - SurfaceGradientNormalMapping_GenerateTB(uv, OUT_tangent, OUT_bitangent); \ + SurfaceGradientNormalMapping_Init(normal, worldPosition, !isFrontFace); + SurfaceGradientNormalMapping_GenerateTB(uv, OUT_tangent, OUT_bitangent); } -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli index 5ee527b9a4..3f8b87c942 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli @@ -11,7 +11,7 @@ #include void MultilayerSetPixelDepth( - float blendMask, + float3 blendMask, float3 worldPosition, float3 normal, float3 tangents[UvSetCount], @@ -21,7 +21,7 @@ out float depth) { s_blendMaskFromVertexStream = blendMask; - + float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); @@ -32,4 +32,4 @@ parallaxOverallFactor, parallaxOverallOffset, ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depth); -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli index 0298656375..645e3a4c2d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/ParallaxDepth.azsli @@ -48,4 +48,4 @@ MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset, ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse, uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depthNDC, depthCS, isClipped); -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli index 81380e8c07..c588b4423b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli @@ -16,4 +16,4 @@ float GetAlphaAndClip(float2 uvs[UvSetCount]) float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source); CheckClipping(alpha, MaterialSrg::m_opacityFactor); return MaterialSrg::m_opacityFactor * alpha; -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli index b79b5b3418..f55f1b2078 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli @@ -9,4 +9,4 @@ float3x3 GetNormalToWorld() { return ObjectSrg::GetWorldMatrixInverseTranspose(); -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli index 435326215b..f02677658d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli @@ -9,4 +9,4 @@ float4x4 GetObjectToWorld() { return ObjectSrg::GetWorldMatrix(); -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli index 60ab575a2d..e6bb26ddc5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli @@ -15,4 +15,4 @@ void TransformDetailUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount]) // but we would need to address how it works with the parallax code below that indexes into the m_detailUV array. OUT[0] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[0], 1.0)).xy; OUT[1] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[1], 1.0)).xy; -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli index dd77f99ac3..39d77c7a93 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialFunctions/StandardTransformUvs.azsli @@ -11,4 +11,4 @@ void TransformUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount]) // By design, only UV0 is allowed to apply transforms. OUT[0] = mul(MaterialSrg::m_uvMatrix, float3(IN[0], 1.0)).xy; OUT[1] = IN[1]; -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl deleted file mode 100644 index 3dc2cf5d77..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/ShadowMap_WithPS.azsl +++ /dev/null @@ -1,126 +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 - -struct VertexInput -{ - float3 m_position : POSITION; - float2 m_uv0 : UV0; - float2 m_uv1 : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float4 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - -#ifdef MULTILAYER - // This gets set automatically by the system at runtime only if it's available. - // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. - // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). - // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. - float4 m_optional_blendMask : COLOR0; -#endif -}; - -struct VertexOutput -{ - // "centroid" is needed for SV_Depth to compile - linear centroid float4 m_position : SV_Position; - float2 m_uv[UvSetCount] : UV1; - - // only used for parallax depth calculation - float3 m_normal : NORMAL; - float3 m_tangent : TANGENT; - float3 m_bitangent : BITANGENT; - float3 m_worldPosition : UV0; - -#ifdef MULTILAYER - float3 m_blendMask : UV3; -#endif -}; - -VertexOutput MainVS(VertexInput IN) -{ - const float4x4 objectToWorld = GetObjectToWorld(); - VertexOutput OUT; - - const float3 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - - float2 uv[UvSetCount] = { IN.m_uv0, IN.m_uv1 }; - TransformUvs(uv, OUT.m_uv); - - if(ShouldHandleParallaxInDepthShaders()) - { - OUT.m_worldPosition = worldPosition.xyz; - - float3x3 objectToWorldIT = GetNormalToWorld(); - ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); - } - -#ifdef MULTILAYER - if(o_blendMask_isBound) - { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendMask = float3(0,0,0); - } -#endif - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - float3 tangents[UvSetCount] = { IN.m_tangent, IN.m_tangent }; - float3 bitangents[UvSetCount] = { IN.m_bitangent, IN.m_bitangent }; - - for (int i = 0; i != UvSetCount; ++i) - { - EvaluateTangentFrame( - IN.m_normal, - IN.m_worldPosition, - isFrontFace, - IN.m_uv[i], - i, - IN.m_tangent, - IN.m_bitangent, - tangents[i], - bitangents[i]); - } - -#ifdef MULTILAYER - MultilayerSetPixelDepth(IN.m_blendMask, IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); -#else - SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); -#endif - - OUT.m_depth += PdoShadowMapBias; - } - -#ifndef MULTILAYER - GetAlphaAndClip(IN.m_uv); -#endif - - return OUT; -} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl index d1a488ec0a..a185aae106 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl @@ -28,4 +28,5 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "MaterialFunctions/MultilayerParallaxDepth.azsli" #define MULTILAYER -#include "DepthPass_WithPS.azsl" +#define DEACTIVATE_ALPHA_CLIP +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 2fe9990862..48d3cb4739 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -450,16 +450,16 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Combine Albedo, roughness, specular, roughness --------- - surface.baseColor = BlendLayers(lightingInputLayer1.m_baseColor, lightingInputLayer2.m_baseColor, lightingInputLayer3.m_baseColor, blendWeights); + float3 baseColor = BlendLayers(lightingInputLayer1.m_baseColor, lightingInputLayer2.m_baseColor, lightingInputLayer3.m_baseColor, blendWeights); float specularF0Factor = BlendLayers(lightingInputLayer1.m_specularF0Factor, lightingInputLayer2.m_specularF0Factor, lightingInputLayer3.m_specularF0Factor, blendWeights); - surface.metallic = BlendLayers(lightingInputLayer1.m_metallic, lightingInputLayer2.m_metallic, lightingInputLayer3.m_metallic, blendWeights); + float metallic = BlendLayers(lightingInputLayer1.m_metallic, lightingInputLayer2.m_metallic, lightingInputLayer3.m_metallic, blendWeights); if(o_parallax_highlightClipping && displacementIsClipped) { - ApplyParallaxClippingHighlight(surface.baseColor); + ApplyParallaxClippingHighlight(baseColor); } - surface.SetAlbedoAndSpecularF0(specularF0Factor); + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); surface.roughnessLinear = BlendLayers(lightingInputLayer1.m_roughness, lightingInputLayer2.m_roughness, lightingInputLayer3.m_roughness, blendWeights); surface.CalculateRoughnessA(); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl index 84b44512f0..331fa76b16 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl @@ -28,4 +28,5 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "MaterialFunctions/MultilayerParallaxDepth.azsli" #define MULTILAYER -#include "ShadowMap_WithPS.azsl" \ No newline at end of file +#define DEACTIVATE_ALPHA_CLIP +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl index 62dcddf2a6..cf0b7b7311 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl @@ -16,4 +16,4 @@ #include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" -#include "DepthPass_WithPS.azsl" +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index 5dc1148370..4240c291da 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -35,4 +35,4 @@ COMMON_OPTIONS_EMISSIVE() #include "MaterialFunctions/StandardGetAlphaAndClip.azsli" #include "MaterialFunctions/StandardTransformUvs.azsli" -#include "StandardSurface_ForwardPass.azsl" \ No newline at end of file +#include "StandardSurface_ForwardPass.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.azsl deleted file mode 100644 index 02e9e93ba2..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.azsl +++ /dev/null @@ -1,13 +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 - * - */ - -// NOTE: This file is a temporary workaround until .shader files can #define macros for their .azsl files - -#define QUALITY_LOW_END 1 - -#include "StandardPBR_ForwardPass.azsl" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader index 44139608ca..511749c6ae 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward.shader @@ -5,7 +5,9 @@ // DrawListTag. If your pipeline doesn't have a "lowEndForward" DrawListTag, no draw items // for this shader will be created. - "Source" : "./StandardPBR_LowEndForward.azsl", + "Source" : "./StandardPBR_ForwardPass.azsl", + + "Definitions": [ "QUALITY_LOW_END=1" ], "DepthStencilState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader index 9faa1d3698..6dc4004b07 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_LowEndForward_EDS.shader @@ -5,7 +5,9 @@ // DrawListTag. If your pipeline doesn't have a "lowEndForward" DrawListTag, no draw items // for this shader will be created. - "Source" : "./StandardPBR_LowEndForward.azsl", + "Source" : "./StandardPBR_ForwardPass.azsl", + + "Definitions": [ "QUALITY_LOW_END=1" ], "DepthStencilState" : { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl index 7acc121036..665c85c02e 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl @@ -20,4 +20,5 @@ #include "MaterialFunctions/EvaluateTangentFrame.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" -#include "ShadowMap_WithPS.azsl" \ No newline at end of file +#define SHADOWS +#include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsli similarity index 97% rename from Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl rename to Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsli index b60f789cf5..5f89fc704b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardSurface_ForwardPass.azsli @@ -143,6 +143,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float } } + SurfaceSettings surfaceSettings; Surface surface; surface.vertexNormal = vertexNormal; surface.position = IN.m_worldPosition.xyz; @@ -151,7 +152,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // TODO: this often invokes a separate sample of the base color texture which is wasteful float alpha = GetAlphaAndClip(IN.m_uv); - EvaluateStandardSurface(IN.m_normal, IN.m_uv, tangents, bitangents, isFrontFace, displacementIsClipped, surface); + EvaluateStandardSurface(IN.m_normal, IN.m_uv, tangents, bitangents, isFrontFace, displacementIsClipped, surface, surfaceSettings); // ------- Lighting Data ------- @@ -209,7 +210,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // values close to 1.0, that indicates the absence of a surface entirely, so this effect should // not apply. float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; - alpha = lerp(fresnelAlpha, alpha, surface.opacityAffectsSpecularFactor); + alpha = lerp(fresnelAlpha, alpha, surfaceSettings.opacityAffectsSpecularFactor); } if (o_opacity_mode == OpacityMode::Blended) @@ -225,7 +226,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); lightingOutput.m_diffuseColor.rgb += specular; lightingOutput.m_diffuseColor.w = alpha; @@ -248,7 +249,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. float3 specular = lightingOutput.m_specularColor.rgb; - specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surface.opacityAffectsSpecularFactor); + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor); lightingOutput.m_diffuseColor.rgb += specular; lightingOutput.m_specularColor.rgb = surface.baseColor * (1.0 - alpha); diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli index 21f55ea259..c12cd2834b 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli @@ -13,6 +13,21 @@ #include #include +// This data varies across different surfaces, but is uniform within a surface +class SurfaceSettings +{ + //! Subsurface scattering parameters + float subsurfaceScatteringQuality; + float3 scatterDistance; + + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float opacityAffectsSpecularFactor; +}; + class Surface { AnisotropicSurfaceData anisotropy; @@ -29,18 +44,7 @@ class Surface float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance - - //! Subsurface scattering parameters float subsurfaceScatteringFactor; - float subsurfaceScatteringQuality; - float3 scatterDistance; - - // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. - // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface - // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor - // values close to 1.0, that indicates the absence of a surface entirely, so this effect should - // not apply. - float opacityAffectsSpecularFactor; //! Surface lighting inputs float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value @@ -56,7 +60,7 @@ class Surface void CalculateRoughnessA(); //! Sets albedo and specularF0 using metallic workflow - void SetAlbedoAndSpecularF0(float specularF0Factor); + void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic); }; @@ -95,12 +99,13 @@ void Surface::CalculateRoughnessA() } } -void Surface::SetAlbedoAndSpecularF0(float specularF0Factor) +void Surface::SetAlbedoAndSpecularF0(float3 newBaseColor, float specularF0Factor, float newMetallic) { + baseColor = newBaseColor; + metallic = newMetallic; float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor; // Compute albedo and specularF0 based on metalness albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic); specularF0 = lerp(dielectricSpecularF0, baseColor, metallic); } - diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli index 9d4abeb0f6..9a8d5cfd54 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli @@ -8,11 +8,21 @@ #pragma once -#include #include #include #include +// This data varies across different surfaces, but is uniform within a surface +class SurfaceSettings +{ + // Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor. + // For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface + // like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor + // values close to 1.0, that indicates the absence of a surface entirely, so this effect should + // not apply. + float opacityAffectsSpecularFactor; +}; + class Surface { @@ -51,8 +61,8 @@ class Surface //! Calculates roughnessA and roughnessA2 after roughness has been set void CalculateRoughnessA(); - //! Sets albedo and specularF0 using metallic workflow - void SetAlbedoAndSpecularF0(float specularF0Factor); + //! Sets albedo, base color, specularF0, and metallic properties using metallic workflow + void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic); }; // Specular Anti-Aliasing technique from this paper: @@ -89,12 +99,14 @@ void Surface::CalculateRoughnessA() } } -void Surface::SetAlbedoAndSpecularF0(float specularF0Factor) +void Surface::SetAlbedoAndSpecularF0(float3 newBaseColor, float specularF0Factor, float newMetallic) { + baseColor = newBaseColor; + metallic = newMetallic; + float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor; // Compute albedo and specularF0 based on metalness albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic); specularF0 = lerp(dielectricSpecularF0, baseColor, metallic); } - diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index e6ad71bde3..00d437acd1 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -10,12 +10,24 @@ set(FILES Materials/Special/ShadowCatcher.azsl Materials/Special/ShadowCatcher.materialtype Materials/Special/ShadowCatcher.shader + Materials/Types/MaterialFunctions/EnhancedParallaxDepth.azsli + Materials/Types/MaterialFunctions/EvaluateEnhancedSurface.azsli + Materials/Types/MaterialFunctions/EvaluateStandardSurface.azsli + Materials/Types/MaterialFunctions/EvaluateTangentFrame.azsli + Materials/Types/MaterialFunctions/MultilayerParallaxDepth.azsli + Materials/Types/MaterialFunctions/ParallaxDepth.azsli + Materials/Types/MaterialFunctions/StandardGetAlphaAndClip.azsli + Materials/Types/MaterialFunctions/StandardGetNormalToWorld.azsli + Materials/Types/MaterialFunctions/StandardGetObjectToWorld.azsli + Materials/Types/MaterialFunctions/StandardTransformDetailUvs.azsli + Materials/Types/MaterialFunctions/StandardTransformUvs.azsli Materials/Types/BasePBR.materialtype Materials/Types/BasePBR_Common.azsli Materials/Types/BasePBR_ForwardPass.azsl Materials/Types/BasePBR_ForwardPass.shader Materials/Types/BasePBR_LowEndForward.azsl Materials/Types/BasePBR_LowEndForward.shader + Materials/Types/DepthPass_WithPS.azsli Materials/Types/EnhancedPBR.materialtype Materials/Types/EnhancedPBR_Common.azsli Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -26,6 +38,7 @@ set(FILES Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl Materials/Types/EnhancedPBR_Shadowmap_WithPS.shader Materials/Types/EnhancedPBR_SubsurfaceState.lua + Materials/Types/EnhancedSurface_ForwardPass.azsli Materials/Types/Skin.azsl Materials/Types/Skin.materialtype Materials/Types/Skin.shader @@ -56,7 +69,6 @@ set(FILES Materials/Types/StandardPBR_ForwardPass_EDS.shader Materials/Types/StandardPBR_HandleOpacityDoubleSided.lua Materials/Types/StandardPBR_HandleOpacityMode.lua - Materials/Types/StandardPBR_LowEndForward.azsl Materials/Types/StandardPBR_LowEndForward.shader Materials/Types/StandardPBR_LowEndForward_EDS.shader Materials/Types/StandardPBR_Metallic.lua @@ -65,6 +77,7 @@ set(FILES Materials/Types/StandardPBR_ShaderEnable.lua Materials/Types/StandardPBR_Shadowmap_WithPS.azsl Materials/Types/StandardPBR_Shadowmap_WithPS.shader + Materials/Types/StandardSurface_ForwardPass.azsli Materials/Types/MaterialInputs/AlphaInput.azsli Materials/Types/MaterialInputs/BaseColorInput.azsli Materials/Types/MaterialInputs/ClearCoatInput.azsli diff --git a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl index 3c4388350e..13f1e33ef7 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl @@ -144,20 +144,18 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) identityUvMatrix); IN.m_uv += tangentOffset.m_offsetTS.xy; - - Surface surface; - surface.baseColor = float3(1,1,1); + float3 baseColor = float3(1,1,1); const float noise = AutoBrickSrg::m_noise.Sample(AutoBrickSrg::m_sampler, IN.m_uv).r; float distanceFromBrick = GetNormalizedDistanceFromBrick(IN.m_uv); if(distanceFromBrick > AutoBrickSrg::m_brickColorBleed) { - surface.baseColor = AutoBrickSrg::m_lineColor * lerp(1.0, noise, AutoBrickSrg::m_lineNoiseFactor); + baseColor = AutoBrickSrg::m_lineColor * lerp(1.0, noise, AutoBrickSrg::m_lineNoiseFactor); } else { - surface.baseColor = AutoBrickSrg::m_brickColor * lerp(1.0, noise, AutoBrickSrg::m_brickNoiseFactor); + baseColor = AutoBrickSrg::m_brickColor * lerp(1.0, noise, AutoBrickSrg::m_brickNoiseFactor); } float surfaceDepth; @@ -166,6 +164,8 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) const float3 normal = TangentSpaceToWorld(surfaceNormal, normalize(IN.m_normal), normalize(IN.m_tangent), normalize(IN.m_bitangent)); // ------- Surface ------- + + Surface surface; // Position, Normal, Roughness surface.position = IN.m_worldPosition.xyz; @@ -175,9 +175,9 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) surface.CalculateRoughnessA(); // Albedo, SpecularF0 - surface.metallic = 0.0f; - float specularF0Factor = 0.5f; - surface.SetAlbedoAndSpecularF0(specularF0Factor); + const float metallic = 0.0f; + const float specularF0Factor = 0.5f; + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); // Clear Coat surface.clearCoat.InitializeToZero(); diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl index 503c0107db..71c1621f7f 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl @@ -68,10 +68,10 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN) surface.CalculateRoughnessA(); // Albedo, SpecularF0 - surface.baseColor = MinimalPBRSrg::m_baseColor; - surface.metallic = MinimalPBRSrg::m_metallic; + float3 baseColor = MinimalPBRSrg::m_baseColor; + float metallic = MinimalPBRSrg::m_metallic; float specularF0Factor = 0.5f; - surface.SetAlbedoAndSpecularF0(specularF0Factor); + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); // Clear Coat surface.clearCoat.InitializeToZero(); From 9ed9bcbb2f3324949bf774f56cb37c7ed91159cf Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Sat, 5 Feb 2022 12:31:03 -0700 Subject: [PATCH 4/7] Fix incorrect include header casing Signed-off-by: Jeremy Ong --- .../Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl index a185aae106..7edea547ac 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl @@ -24,7 +24,7 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "MaterialFunctions/StandardGetObjectToWorld.azsli" #include "MaterialFunctions/StandardGetNormalToWorld.azsli" #include "MaterialFunctions/EvaluateTangentFrame.azsli" -#include "MaterialFunctions/StandardTransformUVs.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/MultilayerParallaxDepth.azsli" #define MULTILAYER From 86d8ececfbf1e1b197acc4c2157f59b5b31f4b02 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Mon, 7 Feb 2022 10:54:31 -0700 Subject: [PATCH 5/7] Resolve incorrect SHADOWS definitions Signed-off-by: Jeremy Ong --- .../Common/Assets/Materials/Types/DepthPass_WithPS.azsli | 2 +- .../Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli index 70d7b65b9b..3dd3792102 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli @@ -117,7 +117,7 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); #endif -#ifdef SHADOW +#ifdef SHADOWS OUT.m_depth += PdoShadowMapBias; #endif } diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl index 331fa76b16..8d7314640b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl @@ -29,4 +29,5 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #define MULTILAYER #define DEACTIVATE_ALPHA_CLIP +#define SHADOWS #include "DepthPass_WithPS.azsli" From faa65bca1bee49a6ae607d209d391788e668540a Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Tue, 8 Feb 2022 11:51:16 -0700 Subject: [PATCH 6/7] Refactor shader definitions to be more consistent with other shaders Signed-off-by: Jeremy Ong --- .../Materials/Types/DepthPass_WithPS.azsli | 24 ++++++++++++++----- .../Types/EnhancedPBR_DepthPass_WithPS.azsl | 1 + .../Types/EnhancedPBR_Shadowmap_WithPS.azsl | 3 ++- ...tandardMultilayerPBR_DepthPass_WithPS.azsl | 4 ++-- ...tandardMultilayerPBR_Shadowmap_WithPS.azsl | 6 ++--- .../Types/StandardPBR_DepthPass_WithPS.azsl | 1 + .../Types/StandardPBR_Shadowmap_WithPS.azsl | 3 ++- .../PBR/Surfaces/EnhancedSurface.azsli | 2 +- 8 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli index 3dd3792102..a1318bf383 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/DepthPass_WithPS.azsli @@ -10,6 +10,18 @@ #include #endif +#ifndef MULTILAYER +#define MULTILAYER 0 +#endif + +#ifndef ENABLE_ALPHA_CLIP +#define ENABLE_ALPHA_CLIP 0 +#endif + +#ifndef SHADOWS +#define SHADOWS 0 +#endif + struct VSInput { float3 m_position : POSITION; @@ -21,7 +33,7 @@ struct VSInput float4 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; -#ifdef MULTILAYER +#if MULTILAYER // This gets set automatically by the system at runtime only if it's available. // There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available. // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). @@ -42,7 +54,7 @@ struct VSDepthOutput float3 m_bitangent : BITANGENT; float3 m_worldPosition : UV0; -#ifdef MULTILAYER +#if MULTILAYER float3 m_blendMask : UV3; #endif }; @@ -67,7 +79,7 @@ VSDepthOutput MainVS(VSInput IN) ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent); } -#ifdef MULTILAYER +#if MULTILAYER if(o_blendMask_isBound) { OUT.m_blendMask = IN.m_optional_blendMask.rgb; @@ -111,18 +123,18 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) bitangents[i]); } -#ifdef MULTILAYER +#if MULTILAYER MultilayerSetPixelDepth(IN.m_blendMask, IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); #else SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth); #endif -#ifdef SHADOWS +#if SHADOWS OUT.m_depth += PdoShadowMapBias; #endif } -#ifndef DEACTIVATE_ALPHA_CLIP +#if ENABLE_ALPHA_CLIP GetAlphaAndClip(IN.m_uv); #endif diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl index a13d04bdb8..eb220faec6 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -16,4 +16,5 @@ #include "MaterialFunctions/ParallaxDepth.azsli" #include "MaterialFunctions/StandardGetAlphaAndClip.azsli" +#define ENABLE_ALPHA_CLIP 1 #include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl index e5a7b3eb3c..be350a3ce7 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl @@ -23,5 +23,6 @@ #include "MaterialFunctions/ParallaxDepth.azsli" #include "MaterialFunctions/StandardGetAlphaAndClip.azsli" -#define SHADOWS +#define SHADOWS 1 +#define ENABLE_ALPHA_CLIP 1 #include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl index 7edea547ac..0f000fba98 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl @@ -27,6 +27,6 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/MultilayerParallaxDepth.azsli" -#define MULTILAYER -#define DEACTIVATE_ALPHA_CLIP +#define MULTILAYER 1 +#define ENABLE_ALPHA_CLIP 0 #include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl index 8d7314640b..9d64916444 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl @@ -27,7 +27,7 @@ COMMON_OPTIONS_PARALLAX(o_layer3_) #include "MaterialFunctions/EvaluateTangentFrame.azsli" #include "MaterialFunctions/MultilayerParallaxDepth.azsli" -#define MULTILAYER -#define DEACTIVATE_ALPHA_CLIP -#define SHADOWS +#define MULTILAYER 1 +#define ENABLE_ALPHA_CLIP 0 +#define SHADOWS 1 #include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl index cf0b7b7311..b848ba03ba 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl @@ -16,4 +16,5 @@ #include "MaterialFunctions/StandardTransformUvs.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" +#define ENABLE_ALPHA_CLIP 1 #include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl index 665c85c02e..634d23daa1 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl @@ -20,5 +20,6 @@ #include "MaterialFunctions/EvaluateTangentFrame.azsli" #include "MaterialFunctions/ParallaxDepth.azsli" -#define SHADOWS +#define SHADOWS 1 +#define ENABLE_ALPHA_CLIP 1 #include "DepthPass_WithPS.azsli" diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli index c12cd2834b..961fbd49f9 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli @@ -40,7 +40,7 @@ class Surface float3 normal; //!< Normal in world-space float3 vertexNormal; //!< Vertex normal in world-space float3 baseColor; //!< Surface base color - float3 metallic; //!< Surface metallic property + float metallic; //!< Surface metallic property float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance From 5f914e8e1aa1da1235784b26cb355a7189859b98 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Tue, 8 Feb 2022 12:03:28 -0700 Subject: [PATCH 7/7] Add README to describe upcoming material type changes Signed-off-by: Jeremy Ong --- .../Common/Assets/Materials/Types/README.md | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/README.md diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/README.md b/Gems/Atom/Feature/Common/Assets/Materials/Types/README.md new file mode 100644 index 0000000000..e176f6d7dc --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/README.md @@ -0,0 +1,98 @@ +# Upcoming material system changes + +Currently, `.materialtype` files specify a set of shaders for each pass in the rendering pipeline. +For example, the `StandardPBR.materialtype` asset specifies the following shaders: + +```json +[ + { + "file": "./StandardPBR_ForwardPass.shader", + "tag": "ForwardPass" + }, + { + "file": "./StandardPBR_ForwardPass_EDS.shader", + "tag": "ForwardPass_EDS" + }, + { + "file": "./StandardPBR_LowEndForward.shader", + "tag": "LowEndForward" + }, + { + "file": "./StandardPBR_LowEndForward_EDS.shader", + "tag": "LowEndForward_EDS" + }, + { + "file": "Shaders/Shadow/Shadowmap.shader", + "tag": "Shadowmap" + }, + { + "file": "./StandardPBR_Shadowmap_WithPS.shader", + "tag": "Shadowmap_WithPS" + }, + { + "file": "Shaders/Depth/DepthPass.shader", + "tag": "DepthPass" + }, + { + "file": "./StandardPBR_DepthPass_WithPS.shader", + "tag": "DepthPass_WithPS" + }, + { + "file": "Shaders/MotionVector/MeshMotionVector.shader", + "tag": "MeshMotionVector" + }, + { + "file": "Shaders/Depth/DepthPassTransparentMin.shader", + "tag": "DepthPassTransparentMin" + }, + { + "file": "Shaders/Depth/DepthPassTransparentMax.shader", + "tag": "DepthPassTransparentMax" + } +] +``` + +**This will be changing in a future release** to a material type description that specifies shader snippets (aka material functions) +instead of explicit shaders. + +## Why is it changing? + +There are two primary reasons to move to a different scheme. + +1. Material types are strongly coupled to the rendering pipeline. If a user wants to change the pipeline, or the engine wants to use, for example, a custom pipeline for mobile, or VR, this isn't possible today without cloning existing material types and changing the shader array. +2. The material canvas work that has been prioritized to allow artist-driven material customization benefits from a more modular construction of materials. For example, we'd like to apply a "wind graph" and mix and match that with a "foliage graph" to describe the appearance of some foliage. The current material type description couples all the geometric passes with the material and lighting passes, which makes this sort of decomposition difficult. + +## What is it changing to? + +The best way to understand how this is changing is to inspect the current structure of `EnhancedPBR_ForwardPass.azsl` and `StandardPBR_ForwardPass.azsl`. +These shaders start with a number of includes to specify the SRG as follows: + +```hlsl +#include "StandardPBR_Common.azsli" +#include +``` + +Later, it includes a number of material functions, for example: + +```hlsl +#include "MaterialFunctions/EvaluateStandardSurface.azsli" +#include "MaterialFunctions/EvaluateTangentFrame.azsli" +#include "MaterialFunctions/ParallaxDepth.azsli" +#include "MaterialFunctions/StandardGetNormalToWorld.azsli" +#include "MaterialFunctions/StandardGetObjectToWorld.azsli" +#include "MaterialFunctions/StandardGetAlphaAndClip.azsli" +#include "MaterialFunctions/StandardTransformUvs.azsli" +``` + +The material function headers define functions that may later be overridden using material graphs. + +Finally, in the case of the standard surface shader, it includes an implementation file: + +```hlsl +#include "StandardSurface_ForwardPass.azsli" +``` + +This file, if you inspect it, _makes no reference to `MaterialSrg`_, and furthermore, does not include files needed to implement any of the material functions. +In other words, the structure of the standard pbr forward shader is such that it can be assembled with different components, specifing the SRG, material functions, and implementation. + +In the future, a material pipeline abstraction will allow the `materialtype` asset to specify _only_ the material function files, and the tuple of `materialtype` and `materialpipeline` will allow the material builder to assemble the shader on behalf of the user. The final piece to the puzzle is that (again, in the future), material canvas (in active development) can produce material functions to replace the built-in ones.