From 4b2802d8db09dd8ccbf3f0be181d91d98987ca40 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 7 May 2021 21:26:50 -0700 Subject: [PATCH 01/14] ATOM-14676 Depth Based Layer Blending Added new "Displacment" blend source option that blends between layers based on which displaced height is higher. For now it simply picks the higher of the three. In subsequent commits I'll improve on the blending to allow for some transition. Recactored GetLayerDepthValues(), GetBlendWeights(), and GetBlendWeightsFromLayerDepthValues() to optimize parallax searches so that the displacment maps are sampled once and used for both parallax and the calculating the blend weights. Renamed several layer blending types and variables to be more clear. --- .../Types/StandardMultilayerPBR.materialtype | 8 +- .../Types/StandardMultilayerPBR_Common.azsli | 130 ++++++++++++------ ...tandardMultilayerPBR_DepthPass_WithPS.azsl | 8 +- .../StandardMultilayerPBR_ForwardPass.azsl | 46 +++---- .../Types/StandardMultilayerPBR_Parallax.lua | 8 +- ...tandardMultilayerPBR_Shadowmap_WithPS.azsl | 8 +- .../003_Debug_BlendMaskValues.material | 2 +- ...al => 003_Debug_DisplacementMaps.material} | 2 +- .../005_UseDisplacement.material | 70 ++++++++++ .../cc0/Ground033_1K_AmbientOcclusion.jpg | 3 + .../Textures/cc0/Ground033_1K_Color.jpg | 3 + .../cc0/Ground033_1K_Displacement.jpg | 3 + .../Textures/cc0/Ground033_1K_Normal.jpg | 3 + .../Textures/cc0/Ground033_1K_Roughness.jpg | 3 + .../cc0/Rocks002_1K_AmbientOcclusion.jpg | 3 + .../Textures/cc0/Rocks002_1K_Color.jpg | 3 + .../Textures/cc0/Rocks002_1K_Displacement.jpg | 3 + .../Textures/cc0/Rocks002_1K_Normal.jpg | 3 + .../Textures/cc0/Rocks002_1K_Roughness.jpg | 3 + 19 files changed, 228 insertions(+), 84 deletions(-) rename Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/{003_Debug_DepthMaps.material => 003_Debug_DisplacementMaps.material} (85%) create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Color.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Displacement.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Normal.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Roughness.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Color.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Displacement.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Normal.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Roughness.jpg diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index e2119dcf12..f57a4f9b90 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -204,7 +204,7 @@ "displayName": "Debug Draw Mode", "description": "Enables various debug view features.", "type": "Enum", - "enumValues": [ "None", "BlendMaskValues", "DepthMaps" ], + "enumValues": [ "None", "BlendWeights", "DisplacementMaps" ], "defaultValue": "None", "connection": { "type": "ShaderOption", @@ -305,11 +305,11 @@ "displayName": "Blend Source", "description": "The source to use for defining the blend mask. Note VertexColors mode will still use the texture as a fallback if the mesh does not have a COLOR0 stream.", "type": "Enum", - "enumValues": ["TextureMap", "VertexColors"], - "defaultValue": "TextureMap", + "enumValues": ["BlendMask", "VertexColors", "Displacement"], + "defaultValue": "BlendMask", "connection": { "type": "ShaderOption", - "id": "o_blendSource" + "id": "o_layerBlendSource" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index ba0eaf2ac1..8e6986535b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -62,8 +62,8 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial uint m_parallaxUvIndex; // These are used to limit the heightmap intersection search range to the narrowest band possible, to give the best quality result. - float m_displacementMin; // The lowest displacement value possible from all layers combined - float m_displacementMax; // The highest displacement value possible from all layers combined + float m_displacementMin; // The lowest displacement value possible from all layers combined (negative values are below the surface) + float m_displacementMax; // The highest displacement value possible from all layers combined (negative values are below the surface) float3x3 m_uvMatrix; float4 m_pad4; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. @@ -113,11 +113,11 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial // ------ Shader Options ---------------------------------------- -enum class DebugDrawMode { None, BlendMaskValues, DepthMaps }; +enum class DebugDrawMode { None, BlendWeights, DisplacementMaps }; option DebugDrawMode o_debugDrawMode; -enum class BlendMaskSource { TextureMap, VertexColors, Fallback }; -option BlendMaskSource o_blendSource; +enum class LayerBlendSource { BlendMask, VertexColors, Displacement, Fallback }; +option LayerBlendSource o_layerBlendSource; // Indicates whether the vertex input struct's "m_optional_blendMask" is bound. If false, it is not safe to read from m_optional_blendMask. // This option gets set automatically by the system at runtime; there is a soft naming convention that associates it with m_optional_blendMask. @@ -127,64 +127,100 @@ option bool o_blendMask_isBound; // ------ Blend Utilities ---------------------------------------- -//! Returns the BlendMaskSource that will actually be used when rendering (not necessarily the same BlendMaskSource specified by the user) -BlendMaskSource GetFinalBlendMaskSource() +//! Returns the LayerBlendSource that will actually be used when rendering (not necessarily the same LayerBlendSource specified by the user) +LayerBlendSource GetFinalLayerBlendSource() { - if(o_blendSource == BlendMaskSource::TextureMap) + if(o_layerBlendSource == LayerBlendSource::BlendMask) { - return BlendMaskSource::TextureMap; + return LayerBlendSource::BlendMask; } - else if(o_blendSource == BlendMaskSource::VertexColors) + else if(o_layerBlendSource == LayerBlendSource::VertexColors) { if(o_blendMask_isBound) { - return BlendMaskSource::VertexColors; + return LayerBlendSource::VertexColors; } else { - return BlendMaskSource::TextureMap; + return LayerBlendSource::BlendMask; } } + else if(o_layerBlendSource == LayerBlendSource::Displacement) + { + return LayerBlendSource::Displacement; + } else { - return BlendMaskSource::Fallback; + return LayerBlendSource::Fallback; } } +//! Returns blend weights given the depth values for each layer +float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues) +{ + float highestPoint = min(layerDepthValues.x, min(layerDepthValues.y, layerDepthValues.z)); + float3 blendWeights = float3(layerDepthValues.x <= highestPoint ? 1.0 : 0.0, + layerDepthValues.y <= highestPoint ? 1.0 : 0.0, + layerDepthValues.z <= highestPoint ? 1.0 : 0.0); + return blendWeights; +} + +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); + +//! Return the final blend mask values to be used for rendering, based on the available data and configuration. +//! @param vertexBlendWeights - the blend weights that came from the vertex input, relevant for LayerBlendSource::VertexColors +//! @param layerDepthValues - the per-layer depth values as provided by GetLayerDepthValues() +float3 GetBlendWeights(float2 uv, float3 vertexBlendWeights, float3 layerDepthValues) +{ + float3 blendWeightValues; + + switch(GetFinalLayerBlendSource()) + { + case LayerBlendSource::BlendMask: + blendWeightValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; + break; + case LayerBlendSource::VertexColors: + blendWeightValues = vertexBlendWeights; + break; + case LayerBlendSource::Displacement: + blendWeightValues = GetBlendWeightsFromLayerDepthValues(layerDepthValues); + break; + case LayerBlendSource::Fallback: + blendWeightValues = float3(1,1,1); + break; + } + + blendWeightValues = blendWeightValues / (blendWeightValues.r + blendWeightValues.g + blendWeightValues.b); + + return blendWeightValues; +} + //! Return the final blend mask values to be used for rendering, based on the available data and configuration. -float3 GetBlendMaskValues(float2 uv, float3 vertexBlendMask) +//! Note this will sample the displacement maps in the case of LayerBlendSource::Displacement. If you have already +//! called GetLayerDepthValues(), use the GetBlendWeights() overlad that takes layerDepthValues instead. +float3 GetBlendWeights(float2 uv, float3 vertexBlendWeights) { - float3 blendMaskValues; + float3 layerDepthValues = float3(0,0,0); - switch(GetFinalBlendMaskSource()) + if(GetFinalLayerBlendSource() == LayerBlendSource::Displacement) { - case BlendMaskSource::TextureMap: - blendMaskValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; - break; - case BlendMaskSource::VertexColors: - blendMaskValues = vertexBlendMask; - break; - case BlendMaskSource::Fallback: - blendMaskValues = float3(1,1,1); - break; + layerDepthValues = GetLayerDepthValues(uv, ddx_fine(uv), ddy_fine(uv)); } - blendMaskValues = blendMaskValues / (blendMaskValues.r + blendMaskValues.g + blendMaskValues.b); - - return blendMaskValues; + return GetBlendWeights(uv, vertexBlendWeights, layerDepthValues); } -float BlendLayers(float layer1, float layer2, float layer3, float3 blendMaskValues) +float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeightValues) { - return dot(float3(layer1, layer2, layer3), blendMaskValues); + return dot(float3(layer1, layer2, layer3), blendWeightValues); } -float2 BlendLayers(float2 layer1, float2 layer2, float2 layer3, float3 blendMaskValues) +float2 BlendLayers(float2 layer1, float2 layer2, float2 layer3, float3 blendWeightValues) { - return layer1 * blendMaskValues.r + layer2 * blendMaskValues.g + layer3 * blendMaskValues.b; + return layer1 * blendWeightValues.r + layer2 * blendWeightValues.g + layer3 * blendWeightValues.b; } -float3 BlendLayers(float3 layer1, float3 layer2, float3 layer3, float3 blendMaskValues) +float3 BlendLayers(float3 layer1, float3 layer2, float3 layer3, float3 blendWeightValues) { - return layer1 * blendMaskValues.r + layer2 * blendMaskValues.g + layer3 * blendMaskValues.b; + return layer1 * blendWeightValues.r + layer2 * blendWeightValues.g + layer3 * blendWeightValues.b; } // ------ Parallax Utilities ---------------------------------------- @@ -204,17 +240,17 @@ bool ShouldHandleParallaxInDepthShaders() } // These static values are used to pass extra data to the GetDepth callback function during the parallax depth search. -static float3 s_blendMaskFromVertexStream; +static float3 s_blendWeightsFromVertexStream; //! Setup static variables that are needed by the GetDepth callback function -//! @param vertexBlendMask the blend mask values from the vertex input stream. -void GetDepth_Setup(float3 vertexBlendMask) +//! @param vertexBlendWeights - the blend weights from the vertex input stream. +void GetDepth_Setup(float3 vertexBlendWeights) { - s_blendMaskFromVertexStream = vertexBlendMask; + s_blendWeightsFromVertexStream = vertexBlendWeights; } -// Callback function for ParallaxMapping.azsli -DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) +//! Returns the depth values for each layer +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) { float3 layerDepthValues = float3(0,0,0); @@ -256,12 +292,20 @@ DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; layerDepthValues.b -= MaterialSrg::m_layer3_m_depthOffset; } + + return layerDepthValues; +} + +//! Callback function for ParallaxMapping.azsli +DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) +{ + float3 layerDepthValues = GetLayerDepthValues(uv, uv_ddx, uv_ddy); - // Note, when the blend source is BlendMaskSource::VertexColors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values + // Note, when the blend source is LayerBlendSource::VertexColors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be so noticeable as long as // you have a small depth factor relative to the size of the blend transition. - float3 blendMaskValues = GetBlendMaskValues(uv, s_blendMaskFromVertexStream); + float3 blendWeightValues = GetBlendWeights(uv, s_blendWeightsFromVertexStream, layerDepthValues); - float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendMaskValues); + float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); return DepthResultAbsolute(depth); } 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 ae156d7313..00ef53a33a 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 @@ -53,7 +53,7 @@ struct VSDepthOutput float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; float3 m_worldPosition : UV0; - float3 m_blendMask : UV3; + float3 m_blendWeights : UV3; }; VSDepthOutput MainVS(VSInput IN) @@ -80,11 +80,11 @@ VSDepthOutput MainVS(VSInput IN) if(o_blendMask_isBound) { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; + OUT.m_blendWeights = IN.m_optional_blendMask.rgb; } else { - OUT.m_blendMask = float3(1,1,1); + OUT.m_blendWeights = float3(1,1,1); } return OUT; @@ -108,7 +108,7 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); - GetDepth_Setup(IN.m_blendMask); + GetDepth_Setup(IN.m_blendWeights); float depth; 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 a83ea629e4..518528f964 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -95,7 +95,7 @@ struct VSOutput // Extended fields (only referenced in this azsl file)... float2 m_uv[UvSetCount] : UV1; - float3 m_blendMask : UV7; + float3 m_blendWeights : UV7; }; #include @@ -113,11 +113,11 @@ VSOutput ForwardPassVS(VSInput IN) if(o_blendMask_isBound) { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; + OUT.m_blendWeights = IN.m_optional_blendMask.rgb; } else { - OUT.m_blendMask = float3(1,1,1); + OUT.m_blendWeights = float3(1,1,1); } // Shadow coords will be calculated in the pixel shader in this case @@ -156,15 +156,15 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Debug Modes ------- - if(o_debugDrawMode == DebugDrawMode::BlendMaskValues) + if(o_debugDrawMode == DebugDrawMode::BlendWeights) { - float3 blendMaskValues = GetBlendMaskValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); - return DebugOutput(blendMaskValues); + float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendWeights); + return DebugOutput(blendWeights); } - if(o_debugDrawMode == DebugDrawMode::DepthMaps) + if(o_debugDrawMode == DebugDrawMode::DisplacementMaps) { - GetDepth_Setup(IN.m_blendMask); + GetDepth_Setup(IN.m_blendWeights); float depth = GetNormalizedDepth(-MaterialSrg::m_displacementMax, -MaterialSrg::m_displacementMin, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); return DebugOutput(float3(depth,depth,depth)); } @@ -176,7 +176,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scatteirng is enabled if(ShouldHandleParallax()) { - GetDepth_Setup(IN.m_blendMask); + GetDepth_Setup(IN.m_blendWeights); float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); @@ -218,13 +218,13 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Calculate Layer Blend Mask Values ------- // Now that any parallax has been calculated, we calculate the blend factors for any layers that are impacted by the parallax. - float3 blendMaskValues = GetBlendMaskValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); + float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendWeights); // ------- Normal ------- - float3 layer1_normalFactor = MaterialSrg::m_layer1_m_normalFactor * blendMaskValues.r; - float3 layer2_normalFactor = MaterialSrg::m_layer2_m_normalFactor * blendMaskValues.g; - float3 layer3_normalFactor = MaterialSrg::m_layer3_m_normalFactor * blendMaskValues.b; + float3 layer1_normalFactor = MaterialSrg::m_layer1_m_normalFactor * blendWeights.r; + float3 layer2_normalFactor = MaterialSrg::m_layer2_m_normalFactor * blendWeights.g; + float3 layer3_normalFactor = MaterialSrg::m_layer3_m_normalFactor * blendWeights.b; float3x3 layer1_uvMatrix = MaterialSrg::m_layer1_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer1_m_uvMatrix : CreateIdentity3x3(); float3x3 layer2_uvMatrix = MaterialSrg::m_layer2_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer2_m_uvMatrix : CreateIdentity3x3(); float3x3 layer3_uvMatrix = MaterialSrg::m_layer3_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer3_m_uvMatrix : CreateIdentity3x3(); @@ -249,7 +249,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float3 layer1_baseColor = BlendBaseColor(layer1_sampledColor, MaterialSrg::m_layer1_m_baseColor.rgb, MaterialSrg::m_layer1_m_baseColorFactor, o_layer1_o_baseColorTextureBlendMode, o_layer1_o_baseColor_useTexture); float3 layer2_baseColor = BlendBaseColor(layer2_sampledColor, MaterialSrg::m_layer2_m_baseColor.rgb, MaterialSrg::m_layer2_m_baseColorFactor, o_layer2_o_baseColorTextureBlendMode, o_layer2_o_baseColor_useTexture); float3 layer3_baseColor = BlendBaseColor(layer3_sampledColor, MaterialSrg::m_layer3_m_baseColor.rgb, MaterialSrg::m_layer3_m_baseColorFactor, o_layer3_o_baseColorTextureBlendMode, o_layer3_o_baseColor_useTexture); - float3 baseColor = BlendLayers(layer1_baseColor, layer2_baseColor, layer3_baseColor, blendMaskValues); + float3 baseColor = BlendLayers(layer1_baseColor, layer2_baseColor, layer3_baseColor, blendWeights); if(o_parallax_highlightClipping && displacementIsClipped) { @@ -264,7 +264,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float layer1_metallic = GetMetallicInput(MaterialSrg::m_layer1_m_metallicMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_metallicMapUvIndex], MaterialSrg::m_layer1_m_metallicFactor, o_layer1_o_metallic_useTexture); float layer2_metallic = GetMetallicInput(MaterialSrg::m_layer2_m_metallicMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_metallicMapUvIndex], MaterialSrg::m_layer2_m_metallicFactor, o_layer2_o_metallic_useTexture); float layer3_metallic = GetMetallicInput(MaterialSrg::m_layer3_m_metallicMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_metallicMapUvIndex], MaterialSrg::m_layer3_m_metallicFactor, o_layer3_o_metallic_useTexture); - metallic = BlendLayers(layer1_metallic, layer2_metallic, layer3_metallic, blendMaskValues); + metallic = BlendLayers(layer1_metallic, layer2_metallic, layer3_metallic, blendWeights); } // ------- Specular ------- @@ -272,7 +272,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float layer1_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer1_m_specularF0Map, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularF0MapUvIndex], MaterialSrg::m_layer1_m_specularF0Factor, o_layer1_o_specularF0_useTexture); float layer2_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer2_m_specularF0Map, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularF0MapUvIndex], MaterialSrg::m_layer2_m_specularF0Factor, o_layer2_o_specularF0_useTexture); float layer3_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer3_m_specularF0Map, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularF0MapUvIndex], MaterialSrg::m_layer3_m_specularF0Factor, o_layer3_o_specularF0_useTexture); - float specularF0Factor = BlendLayers(layer1_specularF0Factor, layer2_specularF0Factor, layer3_specularF0Factor, blendMaskValues); + float specularF0Factor = BlendLayers(layer1_specularF0Factor, layer2_specularF0Factor, layer3_specularF0Factor, blendWeights); surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); @@ -281,7 +281,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float layer1_roughness = GetRoughnessInput(MaterialSrg::m_layer1_m_roughnessMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_roughnessMapUvIndex], MaterialSrg::m_layer1_m_roughnessFactor, MaterialSrg::m_layer1_m_roughnessLowerBound, MaterialSrg::m_layer1_m_roughnessUpperBound, o_layer1_o_roughness_useTexture); float layer2_roughness = GetRoughnessInput(MaterialSrg::m_layer2_m_roughnessMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_roughnessMapUvIndex], MaterialSrg::m_layer2_m_roughnessFactor, MaterialSrg::m_layer2_m_roughnessLowerBound, MaterialSrg::m_layer2_m_roughnessUpperBound, o_layer2_o_roughness_useTexture); float layer3_roughness = GetRoughnessInput(MaterialSrg::m_layer3_m_roughnessMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_roughnessMapUvIndex], MaterialSrg::m_layer3_m_roughnessFactor, MaterialSrg::m_layer3_m_roughnessLowerBound, MaterialSrg::m_layer3_m_roughnessUpperBound, o_layer3_o_roughness_useTexture); - surface.roughnessLinear = BlendLayers(layer1_roughness, layer2_roughness, layer3_roughness, blendMaskValues); + surface.roughnessLinear = BlendLayers(layer1_roughness, layer2_roughness, layer3_roughness, blendWeights); surface.CalculateRoughnessA(); @@ -314,19 +314,19 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float3 layer1_emissive = GetEmissiveInput(MaterialSrg::m_layer1_m_emissiveMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_emissiveMapUvIndex], MaterialSrg::m_layer1_m_emissiveIntensity, MaterialSrg::m_layer1_m_emissiveColor.rgb, o_layer1_o_emissiveEnabled, o_layer1_o_emissive_useTexture); float3 layer2_emissive = GetEmissiveInput(MaterialSrg::m_layer2_m_emissiveMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_emissiveMapUvIndex], MaterialSrg::m_layer2_m_emissiveIntensity, MaterialSrg::m_layer2_m_emissiveColor.rgb, o_layer2_o_emissiveEnabled, o_layer2_o_emissive_useTexture); float3 layer3_emissive = GetEmissiveInput(MaterialSrg::m_layer3_m_emissiveMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_emissiveMapUvIndex], MaterialSrg::m_layer3_m_emissiveIntensity, MaterialSrg::m_layer3_m_emissiveColor.rgb, o_layer3_o_emissiveEnabled, o_layer3_o_emissive_useTexture); - lightingData.emissiveLighting = BlendLayers(layer1_emissive, layer2_emissive, layer3_emissive, blendMaskValues); + lightingData.emissiveLighting = BlendLayers(layer1_emissive, layer2_emissive, layer3_emissive, blendWeights); // ------- Occlusion ------- float layer1_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer1_m_diffuseOcclusionFactor, o_layer1_o_diffuseOcclusion_useTexture); float layer2_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer2_m_diffuseOcclusionFactor, o_layer2_o_diffuseOcclusion_useTexture); float layer3_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer3_m_diffuseOcclusionFactor, o_layer3_o_diffuseOcclusion_useTexture); - lightingData.diffuseAmbientOcclusion = BlendLayers(layer1_diffuseAmbientOcclusion, layer2_diffuseAmbientOcclusion, layer3_diffuseAmbientOcclusion, blendMaskValues); + lightingData.diffuseAmbientOcclusion = BlendLayers(layer1_diffuseAmbientOcclusion, layer2_diffuseAmbientOcclusion, layer3_diffuseAmbientOcclusion, blendWeights); float layer1_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer1_m_specularOcclusionFactor, o_layer1_o_specularOcclusion_useTexture); float layer2_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer2_m_specularOcclusionFactor, o_layer2_o_specularOcclusion_useTexture); float layer3_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer3_m_specularOcclusionFactor, o_layer3_o_specularOcclusion_useTexture); - lightingData.specularOcclusion = BlendLayers(layer1_specularOcclusion, layer2_specularOcclusion, layer3_specularOcclusion, blendMaskValues); + lightingData.specularOcclusion = BlendLayers(layer1_specularOcclusion, layer2_specularOcclusion, layer3_specularOcclusion, blendWeights); // ------- Clearcoat ------- @@ -385,11 +385,11 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // --- Blend Layers --- - surface.clearCoat.factor = BlendLayers(layer1_clearCoatFactor, layer2_clearCoatFactor, layer3_clearCoatFactor, blendMaskValues); - surface.clearCoat.roughness = BlendLayers(layer1_clearCoatRoughness, layer2_clearCoatRoughness, layer3_clearCoatRoughness, blendMaskValues); + surface.clearCoat.factor = BlendLayers(layer1_clearCoatFactor, layer2_clearCoatFactor, layer3_clearCoatFactor, blendWeights); + surface.clearCoat.roughness = BlendLayers(layer1_clearCoatRoughness, layer2_clearCoatRoughness, layer3_clearCoatRoughness, blendWeights); // [GFX TODO][ATOM-14592] This is not the right way to blend the normals. We need to use ReorientTangentSpaceNormal(), and that requires GetClearCoatInputs() to return the normal in TS instead of WS. - surface.clearCoat.normal = BlendLayers(layer1_clearCoatNormal, layer2_clearCoatNormal, layer3_clearCoatNormal, blendMaskValues); + surface.clearCoat.normal = BlendLayers(layer1_clearCoatNormal, layer2_clearCoatNormal, layer3_clearCoatNormal, blendWeights); surface.clearCoat.normal = normalize(surface.clearCoat.normal); // manipulate base layer f0 if clear coat is enabled diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua index 8880a4b842..24e596d877 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua @@ -33,7 +33,7 @@ function GetShaderOptionDependencies() return {"o_parallax_feature_enabled"} end -function MergeRange(heightMinMax, offset, factor) +function GetMergedHeightRange(heightMinMax, offset, factor) top = offset bottom = offset - factor @@ -68,9 +68,9 @@ function Process(context) local offsetLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.offset") local heightMinMax = {nil, nil} - if(enable1) then MergeRange(heightMinMax, offsetLayer1, factorLayer1) end - if(enable2) then MergeRange(heightMinMax, offsetLayer2, factorLayer2) end - if(enable3) then MergeRange(heightMinMax, offsetLayer3, factorLayer3) end + if(enable1) then GetMergedHeightRange(heightMinMax, offsetLayer1, factorLayer1) end + if(enable2) then GetMergedHeightRange(heightMinMax, offsetLayer2, factorLayer2) end + if(enable3) then GetMergedHeightRange(heightMinMax, offsetLayer3, factorLayer3) end if(heightMinMax[1] - heightMinMax[0] < 0.0001) then context:SetShaderOptionValue_bool("o_parallax_feature_enabled", false) 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 325937b228..12698a8967 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 @@ -53,7 +53,7 @@ struct VertexOutput float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; float3 m_worldPosition : UV0; - float3 m_blendMask : UV3; + float3 m_blendWeights : UV3; }; VertexOutput MainVS(VertexInput IN) @@ -79,11 +79,11 @@ VertexOutput MainVS(VertexInput IN) if(o_blendMask_isBound) { - OUT.m_blendMask = IN.m_optional_blendMask.rgb; + OUT.m_blendWeights = IN.m_optional_blendMask.rgb; } else { - OUT.m_blendMask = float3(1,1,1); + OUT.m_blendWeights = float3(1,1,1); } return OUT; @@ -107,7 +107,7 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); - GetDepth_Setup(IN.m_blendMask); + GetDepth_Setup(IN.m_blendWeights); float depth; diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMaskValues.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMaskValues.material index 94a1ec6a30..23bbae9943 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMaskValues.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMaskValues.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "general": { - "debugDrawMode": "BlendMaskValues" + "debugDrawMode": "BlendWeights" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DepthMaps.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DisplacementMaps.material similarity index 85% rename from Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DepthMaps.material rename to Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DisplacementMaps.material index d41e116067..eb2d01cef2 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DepthMaps.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DisplacementMaps.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "general": { - "debugDrawMode": "DepthMaps" + "debugDrawMode": "DisplacementMaps" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material new file mode 100644 index 0000000000..c29dddc623 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -0,0 +1,70 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "blendSource": "Displacement" + }, + "layer1_baseColor": { + "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" + }, + "layer1_normal": { + "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" + }, + "layer1_occlusion": { + "diffuseTextureMap": "TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg" + }, + "layer1_parallax": { + "enable": true, + "factor": 0.10000000149011612, + "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" + }, + "layer1_roughness": { + "textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg" + }, + "layer2_baseColor": { + "textureMap": "TestData/Textures/cc0/Ground033_1K_Color.jpg" + }, + "layer2_normal": { + "textureMap": "TestData/Textures/cc0/Ground033_1K_Normal.jpg" + }, + "layer2_occlusion": { + "diffuseTextureMap": "TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg" + }, + "layer2_parallax": { + "enable": true, + "factor": 0.014999999664723874, + "offset": -0.024000000208616258, + "textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg" + }, + "layer2_roughness": { + "textureMap": "TestData/Textures/cc0/Ground033_1K_Roughness.jpg" + }, + "layer3_baseColor": { + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Color.jpg" + }, + "layer3_normal": { + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Normal.jpg" + }, + "layer3_parallax": { + "enable": true, + "factor": 0.027000000700354577, + "offset": -0.02199999988079071, + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Displacement.jpg" + }, + "layer3_roughness": { + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Roughness.jpg" + }, + "layer3_uv": { + "scale": 1.600000023841858 + }, + "parallax": { + "algorithm": "Relief", + "enable": true, + "pdo": true, + "quality": "Low" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg new file mode 100644 index 0000000000..04d871dd2b --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9ec269d03a9552c0ecf24778912fa6190c412b006433db8b7c40e1c0c83e6f7 +size 516915 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Color.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Color.jpg new file mode 100644 index 0000000000..d41658d177 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Color.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b53c4aca020d5833618a5b73b6578c8693dd14e603eb32681e2c7ecc90f59047 +size 1020622 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Displacement.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Displacement.jpg new file mode 100644 index 0000000000..913b35875c --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Displacement.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46ea8a9406ce6df21ce3a6045aac5b1421ce119919ff050951277dd76464ee2c +size 258716 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Normal.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Normal.jpg new file mode 100644 index 0000000000..7c216001a9 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Normal.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac1ad9bea240374bfc6aaaacc42e24eadfbf93c7185617fc1c52e610cb45cb69 +size 1292910 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Roughness.jpg new file mode 100644 index 0000000000..5ac9e78409 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Roughness.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fce266a7445a4d4b5bb3fbf7cb3330e0580b058aeaf2ef7f265a01641dbbdc4 +size 637326 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg new file mode 100644 index 0000000000..772529329e --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca54f762bcddc10ab2d609f10864328cb5a567c43efb8c9bcfe9cb2955db9577 +size 433887 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Color.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Color.jpg new file mode 100644 index 0000000000..8d1d23451d --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Color.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b5f5ff297aef6470045d087cf0c3341f7782e36a750965a052d49d03dd37426 +size 1595449 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Displacement.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Displacement.jpg new file mode 100644 index 0000000000..22304c19dd --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Displacement.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8753448320e0916a70036ef77a06bce746bfa45c14e62b2fbda0987a13bfbb3 +size 277114 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Normal.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Normal.jpg new file mode 100644 index 0000000000..129ecbb1b7 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Normal.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ea23ea8d85d1fffa119e481e6ac85ad3a3096470a5e12f252d37e1b293e5e37 +size 2119669 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Roughness.jpg new file mode 100644 index 0000000000..dc5f8c20a9 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Roughness.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:caa6e94f904135461da4d200fc6c21c86dc99cc7d413ea740e678f7758b2b156 +size 555680 From 9dafc54fc08bd66ef4159171cb7a5c08af9613b6 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Thu, 13 May 2021 14:57:16 -0700 Subject: [PATCH 02/14] Got things working again after merging my depth-based-blend changes together with the new layering model. Updated the terminology (yet again) to hopefully be a bit more clear and consistent. "Blend mask" means the R and G channels that mask layers 2-3. These can come from multipls source, including a "blend mask texture" or "blend mask vertex colors". "Blend weights" are the final RGB channels that are multiplied and added with layer properties to do the final blend. "Blend source" is the combination of data that is used to produce the blend weights, which could be a combination of displacement maps, blend mask texture, vertex colors, or others in the future. Added another debug render mode, so now we can show either the blend mask and the final blend weights. --- .../Types/StandardMultilayerPBR.materialtype | 8 +- .../StandardMultilayerPBR.materialtype.orig | 3126 +++++++++++++++++ .../Types/StandardMultilayerPBR_Common.azsli | 102 +- .../StandardMultilayerPBR_Common.azsli.orig | 401 +++ ...tandardMultilayerPBR_DepthPass_WithPS.azsl | 6 +- ...rdMultilayerPBR_DepthPass_WithPS.azsl.orig | 132 + .../StandardMultilayerPBR_ForwardPass.azsl | 24 +- ...tandardMultilayerPBR_ForwardPass.azsl.orig | 710 ++++ ...tandardMultilayerPBR_Shadowmap_WithPS.azsl | 6 +- ...rdMultilayerPBR_Shadowmap_WithPS.azsl.orig | 131 + ....material => 003_Debug_BlendMask.material} | 2 +- .../003_Debug_BlendWeights.material | 11 + ...terial => 003_Debug_Displacement.material} | 2 +- .../005_UseDisplacement.material | 4 +- 14 files changed, 4608 insertions(+), 57 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig rename Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/{003_Debug_BlendSource.material => 003_Debug_BlendMask.material} (86%) create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material rename Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/{003_Debug_DisplacementMaps.material => 003_Debug_Displacement.material} (85%) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index 96fb4eeea8..f6c0cc3ad3 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -199,7 +199,7 @@ "displayName": "Debug Draw Mode", "description": "Enables various debug view features.", "type": "Enum", - "enumValues": [ "None", "BlendSource", "DisplacementMaps" ], + "enumValues": [ "None", "BlendMask", "Displacement", "FinalBlendWeights" ], "defaultValue": "None", "connection": { "type": "ShaderOption", @@ -322,8 +322,8 @@ "displayName": "Blend Source", "description": "The source to use for defining the blend mask. Note VertexColors mode will still use the texture as a fallback if the mesh does not have a COLOR0 stream.", "type": "Enum", - "enumValues": ["BlendMask", "VertexColors", "Displacement"], - "defaultValue": "BlendMask", + "enumValues": ["TextureMap", "VertexColors", "Displacement"], + "defaultValue": "TextureMap", "connection": { "type": "ShaderOption", "id": "o_layerBlendSource" @@ -331,7 +331,7 @@ }, { "id": "textureMap", - "displayName": "Blend Mask", + "displayName": "Blend Mask Texture", "description": "RGB image where each channel is the blend mask for one of the three available layers.", "type": "Image", "defaultValue": "Textures/DefaultBlendMask_layers.png", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig new file mode 100644 index 0000000000..d185eecddf --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig @@ -0,0 +1,3126 @@ +{ + "description": "Similar to StandardPBR but supports multiple layers blended together.", + "propertyLayout": { + "version": 3, + "groups": [ + { + "id": "general", + "displayName": "General", + "description": "General settings." + }, + { + "id": "blend", + "displayName": "Blend Settings", + "description": "Properties for configuring how layers are blended together." + }, + { + "id": "parallax", + "displayName": "Parallax Settings", + "description": "Properties for configuring the parallax effect, applied to all layers." + }, + { + "id": "uv", + "displayName": "UVs", + "description": "Properties for configuring UV transforms for the entire material, including the blend masks." + }, + { + // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader + "id": "irradiance", + "displayName": "Irradiance", + "description": "Properties for configuring the irradiance used in global illumination." + }, + //############################################################################################## + // Layer 1 Groups + //############################################################################################## + { + "id": "layer1_baseColor", + "displayName": "Layer 1: Base Color", + "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." + }, + { + "id": "layer1_metallic", + "displayName": "Layer 1: Metallic", + "description": "Properties for configuring whether the surface is metallic or not." + }, + { + "id": "layer1_roughness", + "displayName": "Layer 1: Roughness", + "description": "Properties for configuring how rough the surface appears." + }, + { + "id": "layer1_specularF0", + "displayName": "Layer 1: Specular Reflectance f0", + "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." + }, + { + "id": "layer1_normal", + "displayName": "Layer 1: Normal", + "description": "Properties related to configuring surface normal." + }, + { + "id": "layer1_clearCoat", + "displayName": "Layer 1: Clear Coat", + "description": "Properties for configuring gloss clear coat" + }, + { + "id": "layer1_occlusion", + "displayName": "Layer 1: Occlusion", + "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." + }, + { + "id": "layer1_emissive", + "displayName": "Layer 1: Emissive", + "description": "Properties to add light emission, independent of other lights in the scene." + }, + { + "id": "layer1_parallax", + "displayName": "Layer 1: Parallax Mapping", + "description": "Properties for parallax effect produced by depthmap." + }, + { + "id": "layer1_uv", + "displayName": "Layer 1: UVs", + "description": "Properties for configuring UV transforms." + }, + //############################################################################################## + // Layer 2 Groups + //############################################################################################## + { + "id": "layer2_baseColor", + "displayName": "Layer 2: Base Color", + "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." + }, + { + "id": "layer2_metallic", + "displayName": "Layer 2: Metallic", + "description": "Properties for configuring whether the surface is metallic or not." + }, + { + "id": "layer2_roughness", + "displayName": "Layer 2: Roughness", + "description": "Properties for configuring how rough the surface appears." + }, + { + "id": "layer2_specularF0", + "displayName": "Layer 2: Specular Reflectance f0", + "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." + }, + { + "id": "layer2_normal", + "displayName": "Layer 2: Normal", + "description": "Properties related to configuring surface normal." + }, + { + "id": "layer2_clearCoat", + "displayName": "Layer 2: Clear Coat", + "description": "Properties for configuring gloss clear coat" + }, + { + "id": "layer2_occlusion", + "displayName": "Layer 2: Occlusion", + "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." + }, + { + "id": "layer2_emissive", + "displayName": "Layer 2: Emissive", + "description": "Properties to add light emission, independent of other lights in the scene." + }, + { + "id": "layer2_parallax", + "displayName": "Layer 2: Parallax Mapping", + "description": "Properties for parallax effect produced by depthmap." + }, + { + "id": "layer2_uv", + "displayName": "Layer 2: UVs", + "description": "Properties for configuring UV transforms." + }, + //############################################################################################## + // Layer 3 Groups + //############################################################################################## + { + "id": "layer3_baseColor", + "displayName": "Layer 3: Base Color", + "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." + }, + { + "id": "layer3_metallic", + "displayName": "Layer 3: Metallic", + "description": "Properties for configuring whether the surface is metallic or not." + }, + { + "id": "layer3_roughness", + "displayName": "Layer 3: Roughness", + "description": "Properties for configuring how rough the surface appears." + }, + { + "id": "layer3_specularF0", + "displayName": "Layer 3: Specular Reflectance f0", + "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." + }, + { + "id": "layer3_normal", + "displayName": "Layer 3: Normal", + "description": "Properties related to configuring surface normal." + }, + { + "id": "layer3_clearCoat", + "displayName": "Layer 3: Clear Coat", + "description": "Properties for configuring gloss clear coat" + }, + { + "id": "layer3_occlusion", + "displayName": "Layer 3: Occlusion", + "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." + }, + { + "id": "layer3_emissive", + "displayName": "Layer 3: Emissive", + "description": "Properties to add light emission, independent of other lights in the scene." + }, + { + "id": "layer3_parallax", + "displayName": "Layer 3: Parallax Mapping", + "description": "Properties for parallax effect produced by depthmap." + }, + { + "id": "layer3_uv", + "displayName": "Layer 3: UVs", + "description": "Properties for configuring UV transforms." + } + ], + "properties": { + //############################################################################################## + // General Properties + //############################################################################################## + "general": [ + { + "id": "debugDrawMode", + "displayName": "Debug Draw Mode", + "description": "Enables various debug view features.", + "type": "Enum", +<<<<<<< HEAD + "enumValues": [ "None", "BlendSource", "DepthMaps" ], +======= + "enumValues": [ "None", "BlendWeights", "DisplacementMaps" ], +>>>>>>> Atom/santorac/MultilayerPbrImprovements + "defaultValue": "None", + "connection": { + "type": "ShaderOption", + "id": "o_debugDrawMode" + } + }, + { + "id": "applySpecularAA", + "displayName": "Apply Specular AA", + "description": "Whether to apply specular anti-aliasing in the shader.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_applySpecularAA" + } + }, + { + "id": "enableMultiScatterCompensation", + "displayName": "Multiscattering Compensation", + "description": "Whether to enable multiple scattering compensation.", + "type": "Bool", + "connection": { + "type": "ShaderOption", + "id": "o_specularF0_enableMultiScatterCompensation" + } + }, + { + "id": "enableShadows", + "displayName": "Enable Shadows", + "description": "Whether to use the shadow maps.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "id": "o_enableShadows" + } + }, + { + "id": "enableDirectionalLights", + "displayName": "Enable Directional Lights", + "description": "Whether to use directional lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "id": "o_enableDirectionalLights" + } + }, + { + "id": "enablePunctualLights", + "displayName": "Enable Punctual Lights", + "description": "Whether to use punctual lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "id": "o_enablePunctualLights" + } + }, + { + "id": "enableAreaLights", + "displayName": "Enable Area Lights", + "description": "Whether to use area lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "id": "o_enableAreaLights" + } + }, + { + "id": "enableIBL", + "displayName": "Enable IBL", + "description": "Whether to use Image Based Lighting (IBL).", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "id": "o_enableIBL" + } + }, + { + "id": "forwardPassIBLSpecular", + "displayName": "Forward Pass IBL Specular", + "description": "Whether to apply IBL specular in the forward pass.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_materialUseForwardPassIBLSpecular" + } + } + ], + "blend": [ + { + "id": "enableLayer2", + "displayName": "Enable Layer 2", + "description": "Whether to enable layer 2.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_layer2_enabled" + } + }, + { + "id": "enableLayer3", + "displayName": "Enable Layer 3", + "description": "Whether to enable layer 3.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_layer3_enabled" + } + }, + { + "id": "blendSource", + "displayName": "Blend Source", + "description": "The source to use for defining the blend mask. Note VertexColors mode will still use the texture as a fallback if the mesh does not have a COLOR0 stream.", + "type": "Enum", + "enumValues": ["TextureMap", "VertexColors", "Displacement"], + "defaultValue": "TextureMap", + "connection": { + "type": "ShaderOption", + "id": "o_layerBlendSource" + } + }, + { + "id": "textureMap", + "displayName": "Blend Mask", + "description": "RGB image where each channel is the blend mask for one of the three available layers.", + "type": "Image", + "defaultValue": "Textures/DefaultBlendMask_layers.png", + "connection": { + "type": "ShaderInput", + "id": "m_blendMaskTexture" + } + }, + { + "id": "textureMapUv", + "displayName": "Blend Mask UV", + "description": "Blend Mask UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_blendMaskUvIndex" + } + } + ], + "parallax": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Whether to enable the parallax feature for this material.", + "type": "Bool", + "defaultValue": false + }, + { + "id": "parallaxUv", + "displayName": "UV", + "description": "UV set that supports parallax mapping.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_parallaxUvIndex" + } + }, + { + "id": "algorithm", + "displayName": "Algorithm", + "description": "Select the algorithm to use for parallax mapping.", + "type": "Enum", + "enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ], + "defaultValue": "POM", + "connection": { + "type": "ShaderOption", + "id": "o_parallax_algorithm" + } + }, + { + "id": "quality", + "displayName": "Quality", + "description": "Quality of parallax mapping.", + "type": "Enum", + "enumValues": [ "Low", "Medium", "High", "Ultra" ], + "defaultValue": "Medium", + "connection": { + "type": "ShaderOption", + "id": "o_parallax_quality" + } + }, + { + "id": "pdo", + "displayName": "Pixel Depth Offset", + "description": "Whether to enable the pixel depth offset feature.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_parallax_enablePixelDepthOffset" + } + }, + { + "id": "showClipping", + "displayName": "Show Clipping", + "description": "Highlight areas where the heightmap is clipped by the mesh surface.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_parallax_highlightClipping" + } + } + ], + "uv": [ + { + "id": "center", + "displayName": "Center", + "description": "Center point for scaling and rotation transformations.", + "type": "vector2", + "vectorLabels": [ "U", "V" ], + "defaultValue": [ 0.0, 0.0 ] + }, + { + "id": "tileU", + "displayName": "Tile U", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "tileV", + "displayName": "Tile V", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "offsetU", + "displayName": "Offset U", + "description": "Offsets texture coordinates in the U direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "offsetV", + "displayName": "Offset V", + "description": "Offsets texture coordinates in the V direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "rotateDegrees", + "displayName": "Rotate", + "description": "Rotates the texture coordinates (degrees).", + "type": "float", + "defaultValue": 0.0, + "min": -180.0, + "max": 180.0, + "step": 1.0 + }, + { + "id": "scale", + "displayName": "Scale", + "description": "Scales texture coordinates in both U and V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + } + ], + "irradiance": [ + // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader + { + "id": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ] + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0 + } + ], + //############################################################################################## + // Layer 1 Properties + //############################################################################################## + "layer1_baseColor": [ + { + "id": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_baseColor" + } + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_baseColorFactor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Base color texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_baseColorMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Base color texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_baseColorMapUvIndex" + } + }, + { + "id": "textureBlendMode", + "displayName": "Texture Blend Mode", + "description": "Selects the equation to use when combining Color, Factor, and Texture Map.", + "type": "Enum", + "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], + "defaultValue": "Multiply", + "connection": { + "type": "ShaderOption", + "id": "o_layer1_o_baseColorTextureBlendMode" + } + } + ], + "layer1_metallic": [ + { + "id": "factor", + "displayName": "Factor", + "description": "This value is linear, black is non-metal and white means raw metal.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_metallicFactor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_metallicMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Metallic texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_metallicMapUvIndex" + } + } + ], + "layer1_roughness": [ + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface roughness.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_roughnessMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Roughness texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_roughnessMapUvIndex" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "lowerBound", + "displayName": "Lower Bound", + "description": "The roughness value that corresponds to black in the texture map.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_roughnessLowerBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "upperBound", + "displayName": "Upper Bound", + "description": "The roughness value that corresponds to white in the texture map.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_roughnessUpperBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "factor", + "displayName": "Factor", + "description": "Controls the roughness value", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_roughnessFactor" + } + } + ], + "layer1_specularF0": [ + { + "id": "factor", + "displayName": "Factor", + "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", + "type": "Float", + "defaultValue": 0.5, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularF0Factor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface reflectance.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularF0Map" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Specular reflection texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularF0MapUvIndex" + } + } + ], + "layer1_normal": [ + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface normal direction.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_normalMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just rely on vertex normals.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Normal texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_normalMapUvIndex" + } + }, + { + "id": "flipX", + "displayName": "Flip X Channel", + "description": "Flip tangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_flipNormalX" + } + }, + { + "id": "flipY", + "displayName": "Flip Y Channel", + "description": "Flip bitangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_flipNormalY" + } + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the values", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_normalFactor" + } + } + ], + "layer1_clearCoat": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Enable clear coat", + "type": "Bool", + "defaultValue": false + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the percentage of effect applied", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatFactor" + } + }, + { + "id": "influenceMap", + "displayName": " Influence Map", + "description": "Strength factor texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatInfluenceMap" + } + }, + { + "id": "useInfluenceMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "influenceMapUv", + "displayName": " UV", + "description": "Strength factor texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatInfluenceMapUvIndex" + } + }, + { + "id": "roughness", + "displayName": "Roughness", + "description": "Clear coat layer roughness", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatRoughness" + } + }, + { + "id": "roughnessMap", + "displayName": " Roughness Map", + "description": "Roughness texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatRoughnessMap" + } + }, + { + "id": "useRoughnessMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the roughness value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "roughnessMapUv", + "displayName": " UV", + "description": "Roughness texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatRoughnessMapUvIndex" + } + }, + { + "id": "normalStrength", + "displayName": "Normal Strength", + "description": "Scales the impact of the clear coat normal map", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatNormalStrength" + } + }, + { + "id": "normalMap", + "displayName": "Normal Map", + "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatNormalMap" + } + }, + { + "id": "useNormalMap", + "displayName": " Use Texture", + "description": "Whether to use the normal map", + "type": "Bool", + "defaultValue": true + }, + { + "id": "normalMapUv", + "displayName": " UV", + "description": "Normal texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_clearCoatNormalMapUvIndex" + } + } + ], + "layer1_occlusion": [ + { + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_diffuseOcclusionMap" + } + }, + { + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_diffuseOcclusionMapUvIndex" + } + }, + { + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularOcclusionFactor" + } + } + ], + "layer1_emissive": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Enable the emissive group", + "type": "Bool", + "defaultValue": false + }, + { + "id": "unit", + "displayName": "Units", + "description": "The photometric units of the Intensity property.", + "type": "Enum", + "enumValues": ["Ev100"], + "defaultValue": "Ev100" + }, + { + "id": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_emissiveColor" + } + }, + { + "id": "intensity", + "displayName": "Intensity", + "description": "The amount of energy emitted.", + "type": "Float", + "defaultValue": 4, + "min": -10, + "max": 20, + "softMin": -6, + "softMax": 16 + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining emissive area.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_emissiveMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Emissive texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_emissiveMapUvIndex" + } + } + ], + "layer1_parallax": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Whether to enable the parallax feature.", + "type": "Bool", + "defaultValue": false + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Depthmap to create parallax effect.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_depthMap" + } + }, + { + "id": "factor", + "displayName": "Heightmap Scale", + "description": "The total height of the heightmap in local model units.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_depthFactor" + } + }, + { + "id": "offset", + "displayName": "Offset", + "description": "Adjusts the overall displacement amount in local model units.", + "type": "Float", + "defaultValue": 0.0, + "softMin": -0.1, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_depthOffset" + } + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert to depthmap if the texture is heightmap", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_depthInverted" + } + } + ], + "layer1_uv": [ + { + "id": "center", + "displayName": "Center", + "description": "Center point for scaling and rotation transformations.", + "type": "vector2", + "vectorLabels": [ "U", "V" ], + "defaultValue": [ 0.0, 0.0 ] + }, + { + "id": "tileU", + "displayName": "Tile U", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "tileV", + "displayName": "Tile V", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "offsetU", + "displayName": "Offset U", + "description": "Offsets texture coordinates in the U direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "offsetV", + "displayName": "Offset V", + "description": "Offsets texture coordinates in the V direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "rotateDegrees", + "displayName": "Rotate", + "description": "Rotates the texture coordinates (degrees).", + "type": "float", + "defaultValue": 0.0, + "min": -180.0, + "max": 180.0, + "step": 1.0 + }, + { + "id": "scale", + "displayName": "Scale", + "description": "Scales texture coordinates in both U and V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + } + ], + //############################################################################################## + // Layer 2 Properties + //############################################################################################## + "layer2_baseColor": [ + { + "id": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_baseColor" + } + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_baseColorFactor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Base color texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_baseColorMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Base color texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_baseColorMapUvIndex" + } + }, + { + "id": "textureBlendMode", + "displayName": "Texture Blend Mode", + "description": "Selects the equation to use when combining Color, Factor, and Texture Map.", + "type": "Enum", + "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], + "defaultValue": "Multiply", + "connection": { + "type": "ShaderOption", + "id": "o_layer2_o_baseColorTextureBlendMode" + } + } + ], + "layer2_metallic": [ + { + "id": "factor", + "displayName": "Factor", + "description": "This value is linear, black is non-metal and white means raw metal.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_metallicFactor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_metallicMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Metallic texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_metallicMapUvIndex" + } + } + ], + "layer2_roughness": [ + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface roughness.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_roughnessMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Roughness texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_roughnessMapUvIndex" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "lowerBound", + "displayName": "Lower Bound", + "description": "The roughness value that corresponds to black in the texture map.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_roughnessLowerBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "upperBound", + "displayName": "Upper Bound", + "description": "The roughness value that corresponds to white in the texture map.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_roughnessUpperBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "factor", + "displayName": "Factor", + "description": "Controls the roughness value", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_roughnessFactor" + } + } + ], + "layer2_specularF0": [ + { + "id": "factor", + "displayName": "Factor", + "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", + "type": "Float", + "defaultValue": 0.5, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularF0Factor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface reflectance.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularF0Map" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Specular reflection texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularF0MapUvIndex" + } + } + ], + "layer2_normal": [ + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface normal direction.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_normalMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just rely on vertex normals.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Normal texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_normalMapUvIndex" + } + }, + { + "id": "flipX", + "displayName": "Flip X Channel", + "description": "Flip tangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_flipNormalX" + } + }, + { + "id": "flipY", + "displayName": "Flip Y Channel", + "description": "Flip bitangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_flipNormalY" + } + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the values", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_normalFactor" + } + } + ], + "layer2_clearCoat": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Enable clear coat", + "type": "Bool", + "defaultValue": false + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the percentage of effect applied", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatFactor" + } + }, + { + "id": "influenceMap", + "displayName": " Influence Map", + "description": "Strength factor texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatInfluenceMap" + } + }, + { + "id": "useInfluenceMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "influenceMapUv", + "displayName": " UV", + "description": "Strength factor texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatInfluenceMapUvIndex" + } + }, + { + "id": "roughness", + "displayName": "Roughness", + "description": "Clear coat layer roughness", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatRoughness" + } + }, + { + "id": "roughnessMap", + "displayName": " Roughness Map", + "description": "Roughness texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatRoughnessMap" + } + }, + { + "id": "useRoughnessMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the roughness value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "roughnessMapUv", + "displayName": " UV", + "description": "Roughness texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatRoughnessMapUvIndex" + } + }, + { + "id": "normalStrength", + "displayName": "Normal Strength", + "description": "Scales the impact of the clear coat normal map", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatNormalStrength" + } + }, + { + "id": "normalMap", + "displayName": "Normal Map", + "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatNormalMap" + } + }, + { + "id": "useNormalMap", + "displayName": " Use Texture", + "description": "Whether to use the normal map", + "type": "Bool", + "defaultValue": true + }, + { + "id": "normalMapUv", + "displayName": " UV", + "description": "Normal texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_clearCoatNormalMapUvIndex" + } + } + ], + "layer2_occlusion": [ + { + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_diffuseOcclusionMap" + } + }, + { + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_diffuseOcclusionMapUvIndex" + } + }, + { + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularOcclusionFactor" + } + } + ], + "layer2_emissive": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Enable the emissive group", + "type": "Bool", + "defaultValue": false + }, + { + "id": "unit", + "displayName": "Units", + "description": "The photometric units of the Intensity property.", + "type": "Enum", + "enumValues": ["Ev100"], + "defaultValue": "Ev100" + }, + { + "id": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_emissiveColor" + } + }, + { + "id": "intensity", + "displayName": "Intensity", + "description": "The amount of energy emitted.", + "type": "Float", + "defaultValue": 4, + "min": -10, + "max": 20, + "softMin": -6, + "softMax": 16 + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining emissive area.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_emissiveMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Emissive texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_emissiveMapUvIndex" + } + } + ], + "layer2_parallax": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Whether to enable the parallax feature.", + "type": "Bool", + "defaultValue": false + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Depthmap to create parallax effect.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_depthMap" + } + }, + { + "id": "factor", + "displayName": "Heightmap Scale", + "description": "The total height of the heightmap in local model units.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_depthFactor" + } + }, + { + "id": "offset", + "displayName": "Offset", + "description": "Adjusts the overall displacement amount in local model units.", + "type": "Float", + "defaultValue": 0.0, + "softMin": -0.1, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_depthOffset" + } + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert to depthmap if the texture is heightmap", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_depthInverted" + } + } + ], + "layer2_uv": [ + { + "id": "center", + "displayName": "Center", + "description": "Center point for scaling and rotation transformations.", + "type": "vector2", + "vectorLabels": [ "U", "V" ], + "defaultValue": [ 0.0, 0.0 ] + }, + { + "id": "tileU", + "displayName": "Tile U", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "tileV", + "displayName": "Tile V", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "offsetU", + "displayName": "Offset U", + "description": "Offsets texture coordinates in the U direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "offsetV", + "displayName": "Offset V", + "description": "Offsets texture coordinates in the V direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "rotateDegrees", + "displayName": "Rotate", + "description": "Rotates the texture coordinates (degrees).", + "type": "float", + "defaultValue": 0.0, + "min": -180.0, + "max": 180.0, + "step": 1.0 + }, + { + "id": "scale", + "displayName": "Scale", + "description": "Scales texture coordinates in both U and V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + } + ], + //############################################################################################## + // Layer 3 Properties + //############################################################################################## + "layer3_baseColor": [ + { + "id": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_baseColor" + } + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_baseColorFactor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Base color texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_baseColorMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Base color texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_baseColorMapUvIndex" + } + }, + { + "id": "textureBlendMode", + "displayName": "Texture Blend Mode", + "description": "Selects the equation to use when combining Color, Factor, and Texture Map.", + "type": "Enum", + "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], + "defaultValue": "Multiply", + "connection": { + "type": "ShaderOption", + "id": "o_layer3_o_baseColorTextureBlendMode" + } + } + ], + "layer3_metallic": [ + { + "id": "factor", + "displayName": "Factor", + "description": "This value is linear, black is non-metal and white means raw metal.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_metallicFactor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_metallicMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Metallic texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_metallicMapUvIndex" + } + } + ], + "layer3_roughness": [ + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface roughness.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_roughnessMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Roughness texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_roughnessMapUvIndex" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "lowerBound", + "displayName": "Lower Bound", + "description": "The roughness value that corresponds to black in the texture map.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_roughnessLowerBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "upperBound", + "displayName": "Upper Bound", + "description": "The roughness value that corresponds to white in the texture map.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_roughnessUpperBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "factor", + "displayName": "Factor", + "description": "Controls the roughness value", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_roughnessFactor" + } + } + ], + "layer3_specularF0": [ + { + "id": "factor", + "displayName": "Factor", + "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", + "type": "Float", + "defaultValue": 0.5, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularF0Factor" + } + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface reflectance.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularF0Map" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Specular reflection texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularF0MapUvIndex" + } + } + ], + "layer3_normal": [ + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining surface normal direction.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_normalMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just rely on vertex normals.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Normal texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_normalMapUvIndex" + } + }, + { + "id": "flipX", + "displayName": "Flip X Channel", + "description": "Flip tangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_flipNormalX" + } + }, + { + "id": "flipY", + "displayName": "Flip Y Channel", + "description": "Flip bitangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_flipNormalY" + } + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the values", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_normalFactor" + } + } + ], + "layer3_clearCoat": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Enable clear coat", + "type": "Bool", + "defaultValue": false + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the percentage of effect applied", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatFactor" + } + }, + { + "id": "influenceMap", + "displayName": " Influence Map", + "description": "Strength factor texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatInfluenceMap" + } + }, + { + "id": "useInfluenceMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "influenceMapUv", + "displayName": " UV", + "description": "Strength factor texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatInfluenceMapUvIndex" + } + }, + { + "id": "roughness", + "displayName": "Roughness", + "description": "Clear coat layer roughness", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatRoughness" + } + }, + { + "id": "roughnessMap", + "displayName": " Roughness Map", + "description": "Roughness texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatRoughnessMap" + } + }, + { + "id": "useRoughnessMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the roughness value.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "roughnessMapUv", + "displayName": " UV", + "description": "Roughness texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatRoughnessMapUvIndex" + } + }, + { + "id": "normalStrength", + "displayName": "Normal Strength", + "description": "Scales the impact of the clear coat normal map", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatNormalStrength" + } + }, + { + "id": "normalMap", + "displayName": "Normal Map", + "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatNormalMap" + } + }, + { + "id": "useNormalMap", + "displayName": " Use Texture", + "description": "Whether to use the normal map", + "type": "Bool", + "defaultValue": true + }, + { + "id": "normalMapUv", + "displayName": " UV", + "description": "Normal texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_clearCoatNormalMapUvIndex" + } + } + ], + "layer3_occlusion": [ + { + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_diffuseOcclusionMap" + } + }, + { + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_diffuseOcclusionMapUvIndex" + } + }, + { + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularOcclusionFactor" + } + } + ], + "layer3_emissive": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Enable the emissive group", + "type": "Bool", + "defaultValue": false + }, + { + "id": "unit", + "displayName": "Units", + "description": "The photometric units of the Intensity property.", + "type": "Enum", + "enumValues": ["Ev100"], + "defaultValue": "Ev100" + }, + { + "id": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_emissiveColor" + } + }, + { + "id": "intensity", + "displayName": "Intensity", + "description": "The amount of energy emitted.", + "type": "Float", + "defaultValue": 4, + "min": -10, + "max": 20, + "softMin": -6, + "softMax": 16 + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Texture map for defining emissive area.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_emissiveMap" + } + }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Emissive texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_emissiveMapUvIndex" + } + } + ], + "layer3_parallax": [ + { + "id": "enable", + "displayName": "Enable", + "description": "Whether to enable the parallax feature.", + "type": "Bool", + "defaultValue": false + }, + { + "id": "textureMap", + "displayName": "Texture Map", + "description": "Depthmap to create parallax effect.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_depthMap" + } + }, + { + "id": "factor", + "displayName": "Heightmap Scale", + "description": "The total height of the heightmap in local model units.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_depthFactor" + } + }, + { + "id": "offset", + "displayName": "Offset", + "description": "Adjusts the overall displacement amount in local model units.", + "type": "Float", + "defaultValue": 0.0, + "softMin": -0.1, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_depthOffset" + } + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert to depthmap if the texture is heightmap", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_depthInverted" + } + } + ], + "layer3_uv": [ + { + "id": "center", + "displayName": "Center", + "description": "Center point for scaling and rotation transformations.", + "type": "vector2", + "vectorLabels": [ "U", "V" ], + "defaultValue": [ 0.0, 0.0 ] + }, + { + "id": "tileU", + "displayName": "Tile U", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "tileV", + "displayName": "Tile V", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "id": "offsetU", + "displayName": "Offset U", + "description": "Offsets texture coordinates in the U direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "offsetV", + "displayName": "Offset V", + "description": "Offsets texture coordinates in the V direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0, + "step": 0.001 + }, + { + "id": "rotateDegrees", + "displayName": "Rotate", + "description": "Rotates the texture coordinates (degrees).", + "type": "float", + "defaultValue": 0.0, + "min": -180.0, + "max": 180.0, + "step": 1.0 + }, + { + "id": "scale", + "displayName": "Scale", + "description": "Scales texture coordinates in both U and V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + } + ] + } + }, + "shaders": [ + { + "file": "./StandardMultilayerPBR_ForwardPass.shader", + "tag": "ForwardPass" + }, + { + "file": "./StandardMultilayerPBR_ForwardPass_EDS.shader", + "tag": "ForwardPass_EDS" + }, + { + "file": "Shaders/Shadow/Shadowmap.shader", + "tag": "Shadowmap" + }, + { + "file": "./StandardMultilayerPBR_Shadowmap_WithPS.shader", + "tag": "Shadowmap_WithPS" + }, + { + "file": "Shaders/Depth/DepthPass.shader", + "tag": "DepthPass" + }, + { + "file": "./StandardMultilayerPBR_DepthPass_WithPS.shader", + "tag": "DepthPass_WithPS" + }, + // [GFX TODO][ATOM-4726] Use an "isSkinnedMesh" external material property and a functor that enables/disables the appropriate motion-vector shader + { + "file": "Shaders/MotionVector/StaticMeshMotionVector.shader", + "tag": "StaticMeshMotionVector" + }, + { + "file": "Shaders/MotionVector/SkinnedMeshMotionVector.shader", + "tag": "SkinnedMeshMotionVector" + } + ], + "functors": [ + //############################################################################################## + // General Functors + //############################################################################################## + { + // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. + "type": "Transform2D", + "args": { + "transformOrder": [ "Rotate", "Translate", "Scale" ], + "centerProperty": "uv.center", + "scaleProperty": "uv.scale", + "scaleXProperty": "uv.tileU", + "scaleYProperty": "uv.tileV", + "translateXProperty": "uv.offsetU", + "translateYProperty": "uv.offsetV", + "rotateDegreesProperty": "uv.rotateDegrees", + "float3x3ShaderInput": "m_uvMatrix", + "float3x3InverseShaderInput": "m_uvMatrixInverse" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_ShaderEnable.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_LayerEnable.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_ClearCoatEnableFeature.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_Parallax.lua" + } + }, + //############################################################################################## + // Layer 1 Functors + //############################################################################################## + { + "type": "UseTexture", + "args": { + "textureProperty": "layer1_baseColor.textureMap", + "useTextureProperty": "layer1_baseColor.useTexture", + "dependentProperties": ["layer1_baseColor.textureMapUv", "layer1_baseColor.textureBlendMode"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer1_o_baseColor_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer1_metallic.textureMap", + "useTextureProperty": "layer1_metallic.useTexture", + "dependentProperties": ["layer1_metallic.textureMapUv"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer1_o_metallic_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Roughness.lua", + "propertyNamePrefix": "layer1_", + "srgNamePrefix": "m_layer1_", + "optionsNamePrefix": "o_layer1_" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer1_specularF0.textureMap", + "useTextureProperty": "layer1_specularF0.useTexture", + "dependentProperties": ["layer1_specularF0.textureMapUv"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer1_o_specularF0_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer1_normal.textureMap", + "useTextureProperty": "layer1_normal.useTexture", + "dependentProperties": ["layer1_normal.textureMapUv", "layer1_normal.factor", "layer1_normal.flipX", "layer1_normal.flipY"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer1_o_normal_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ClearCoatState.lua", + "propertyNamePrefix": "layer1_", + "srgNamePrefix": "m_layer1_", + "optionsNamePrefix": "o_layer1_" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer1_occlusion.diffuseTextureMap", + "useTextureProperty": "layer1_occlusion.diffuseUseTexture", + "dependentProperties": ["layer1_occlusion.diffuseTextureMapUv", "layer1_occlusion.diffuseFactor"], + "shaderOption": "o_layer1_o_diffuseOcclusion_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer1_occlusion.specularTextureMap", + "useTextureProperty": "layer1_occlusion.specularUseTexture", + "dependentProperties": ["layer1_occlusion.specularTextureMapUv", "layer1_occlusion.specularFactor"], + "shaderOption": "o_layer1_o_specularOcclusion_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_EmissiveState.lua", + "propertyNamePrefix": "layer1_", + "srgNamePrefix": "m_layer1_", + "optionsNamePrefix": "o_layer1_" + } + }, + { + // Convert emissive unit. + "type": "ConvertEmissiveUnit", + "args": { + "intensityProperty": "layer1_emissive.intensity", + "lightUnitProperty": "layer1_emissive.unit", + "shaderInput": "m_layer1_m_emissiveIntensity", + "ev100Index": 0, + "nitIndex" : 1, + "ev100MinMax": [-10, 20], + "nitMinMax": [0.001, 100000.0] + } + }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", + "propertyNamePrefix": "layer1_", + "srgNamePrefix": "m_layer1_", + "optionsNamePrefix": "o_layer1_" + } + }, + { + // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. + "type": "Transform2D", + "args": { + "transformOrder": [ "Rotate", "Translate", "Scale" ], + "centerProperty": "layer1_uv.center", + "scaleProperty": "layer1_uv.scale", + "scaleXProperty": "layer1_uv.tileU", + "scaleYProperty": "layer1_uv.tileV", + "translateXProperty": "layer1_uv.offsetU", + "translateYProperty": "layer1_uv.offsetV", + "rotateDegreesProperty": "layer1_uv.rotateDegrees", + "float3x3ShaderInput": "m_layer1_m_uvMatrix" + } + }, + //############################################################################################## + // Layer 2 Functors + //############################################################################################## + { + "type": "UseTexture", + "args": { + "textureProperty": "layer2_baseColor.textureMap", + "useTextureProperty": "layer2_baseColor.useTexture", + "dependentProperties": ["layer2_baseColor.textureMapUv", "layer2_baseColor.textureBlendMode"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer2_o_baseColor_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer2_metallic.textureMap", + "useTextureProperty": "layer2_metallic.useTexture", + "dependentProperties": ["layer2_metallic.textureMapUv"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer2_o_metallic_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Roughness.lua", + "propertyNamePrefix": "layer2_", + "srgNamePrefix": "m_layer2_", + "optionsNamePrefix": "o_layer2_" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer2_specularF0.textureMap", + "useTextureProperty": "layer2_specularF0.useTexture", + "dependentProperties": ["layer2_specularF0.textureMapUv"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer2_o_specularF0_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer2_normal.textureMap", + "useTextureProperty": "layer2_normal.useTexture", + "dependentProperties": ["layer2_normal.textureMapUv", "layer2_normal.factor", "layer2_normal.flipX", "layer2_normal.flipY"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer2_o_normal_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ClearCoatState.lua", + "propertyNamePrefix": "layer2_", + "srgNamePrefix": "m_layer2_", + "optionsNamePrefix": "o_layer2_" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer2_occlusion.diffuseTextureMap", + "useTextureProperty": "layer2_occlusion.diffuseUseTexture", + "dependentProperties": ["layer2_occlusion.diffuseTextureMapUv", "layer2_occlusion.diffuseFactor"], + "shaderOption": "o_layer2_o_diffuseOcclusion_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer2_occlusion.specularTextureMap", + "useTextureProperty": "layer2_occlusion.specularUseTexture", + "dependentProperties": ["layer2_occlusion.specularTextureMapUv", "layer2_occlusion.specularFactor"], + "shaderOption": "o_layer2_o_specularOcclusion_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_EmissiveState.lua", + "propertyNamePrefix": "layer2_", + "srgNamePrefix": "m_layer2_", + "optionsNamePrefix": "o_layer2_" + } + }, + { + // Convert emissive unit. + "type": "ConvertEmissiveUnit", + "args": { + "intensityProperty": "layer2_emissive.intensity", + "lightUnitProperty": "layer2_emissive.unit", + "shaderInput": "m_layer2_m_emissiveIntensity", + "ev100Index": 0, + "nitIndex" : 1, + "ev100MinMax": [-10, 20], + "nitMinMax": [0.001, 100000.0] + } + }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", + "propertyNamePrefix": "layer2_", + "srgNamePrefix": "m_layer2_", + "optionsNamePrefix": "o_layer2_" + } + }, + { + // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. + "type": "Transform2D", + "args": { + "transformOrder": [ "Rotate", "Translate", "Scale" ], + "centerProperty": "layer2_uv.center", + "scaleProperty": "layer2_uv.scale", + "scaleXProperty": "layer2_uv.tileU", + "scaleYProperty": "layer2_uv.tileV", + "translateXProperty": "layer2_uv.offsetU", + "translateYProperty": "layer2_uv.offsetV", + "rotateDegreesProperty": "layer2_uv.rotateDegrees", + "float3x3ShaderInput": "m_layer2_m_uvMatrix" + } + }, + //############################################################################################## + // Layer 3 Functors + //############################################################################################## + { + "type": "UseTexture", + "args": { + "textureProperty": "layer3_baseColor.textureMap", + "useTextureProperty": "layer3_baseColor.useTexture", + "dependentProperties": ["layer3_baseColor.textureMapUv", "layer3_baseColor.textureBlendMode"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer3_o_baseColor_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer3_metallic.textureMap", + "useTextureProperty": "layer3_metallic.useTexture", + "dependentProperties": ["layer3_metallic.textureMapUv"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer3_o_metallic_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Roughness.lua", + "propertyNamePrefix": "layer3_", + "srgNamePrefix": "m_layer3_", + "optionsNamePrefix": "o_layer3_" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer3_specularF0.textureMap", + "useTextureProperty": "layer3_specularF0.useTexture", + "dependentProperties": ["layer3_specularF0.textureMapUv"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer3_o_specularF0_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer3_normal.textureMap", + "useTextureProperty": "layer3_normal.useTexture", + "dependentProperties": ["layer3_normal.textureMapUv", "layer3_normal.factor", "layer3_normal.flipX", "layer3_normal.flipY"], + "shaderTags": [ + "ForwardPass", + "ForwardPass_EDS" + ], + "shaderOption": "o_layer3_o_normal_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ClearCoatState.lua", + "propertyNamePrefix": "layer3_", + "srgNamePrefix": "m_layer3_", + "optionsNamePrefix": "o_layer3_" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer3_occlusion.diffuseTextureMap", + "useTextureProperty": "layer3_occlusion.diffuseUseTexture", + "dependentProperties": ["layer3_occlusion.diffuseTextureMapUv", "layer3_occlusion.diffuseFactor"], + "shaderOption": "o_layer3_o_diffuseOcclusion_useTexture" + } + }, + { + "type": "UseTexture", + "args": { + "textureProperty": "layer3_occlusion.specularTextureMap", + "useTextureProperty": "layer3_occlusion.specularUseTexture", + "dependentProperties": ["layer3_occlusion.specularTextureMapUv", "layer3_occlusion.specularFactor"], + "shaderOption": "o_layer3_o_specularOcclusion_useTexture" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_EmissiveState.lua", + "propertyNamePrefix": "layer3_", + "srgNamePrefix": "m_layer3_", + "optionsNamePrefix": "o_layer3_" + } + }, + { + // Convert emissive unit. + "type": "ConvertEmissiveUnit", + "args": { + "intensityProperty": "layer3_emissive.intensity", + "lightUnitProperty": "layer3_emissive.unit", + "shaderInput": "m_layer3_m_emissiveIntensity", + "ev100Index": 0, + "nitIndex" : 1, + "ev100MinMax": [-10, 20], + "nitMinMax": [0.001, 100000.0] + } + }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", + "propertyNamePrefix": "layer3_", + "srgNamePrefix": "m_layer3_", + "optionsNamePrefix": "o_layer3_" + } + }, + { + // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. + "type": "Transform2D", + "args": { + "transformOrder": [ "Rotate", "Translate", "Scale" ], + "centerProperty": "layer3_uv.center", + "scaleProperty": "layer3_uv.scale", + "scaleXProperty": "layer3_uv.tileU", + "scaleYProperty": "layer3_uv.tileV", + "translateXProperty": "layer3_uv.offsetU", + "translateYProperty": "layer3_uv.offsetV", + "rotateDegreesProperty": "layer3_uv.rotateDegrees", + "float3x3ShaderInput": "m_layer3_m_uvMatrix" + } + } + ], + "uvNameMap": { + "UV0": "Tiled", + "UV1": "Unwrapped" + } +} + diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index 776999f3ff..dc1b627d29 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -95,10 +95,13 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial // ------ Shader Options ---------------------------------------- -enum class DebugDrawMode { None, BlendSource, DisplacementMaps }; +option bool o_layer2_enabled; +option bool o_layer3_enabled; + +enum class DebugDrawMode { None, BlendMask, Displacement, FinalBlendWeights }; option DebugDrawMode o_debugDrawMode; -enum class LayerBlendSource { BlendMask, VertexColors, Displacement, Fallback }; +enum class LayerBlendSource { TextureMap, VertexColors, Displacement, Fallback }; option LayerBlendSource o_layerBlendSource; // Indicates whether the vertex input struct's "m_optional_blendMask" is bound. If false, it is not safe to read from m_optional_blendMask. @@ -112,12 +115,14 @@ option bool o_blendMask_isBound; // But since we have it, we use it in some other functions as well rather than passing it around. static float3 s_blendMaskFromVertexStream; +// TODO: Consider storing the result of GetFinalLayerBlendSource() in a static similar to s_blendMaskFromVertexStream. That might give better performance when variants aren't used. + //! Returns the LayerBlendSource that will actually be used when rendering (not necessarily the same LayerBlendSource specified by the user) LayerBlendSource GetFinalLayerBlendSource() { - if(o_layerBlendSource == LayerBlendSource::BlendMask) + if(o_layerBlendSource == LayerBlendSource::TextureMap) { - return LayerBlendSource::BlendMask; + return LayerBlendSource::TextureMap; } else if(o_layerBlendSource == LayerBlendSource::VertexColors) { @@ -127,7 +132,7 @@ LayerBlendSource GetFinalLayerBlendSource() } else { - return LayerBlendSource::BlendMask; + return LayerBlendSource::TextureMap; } } else if(o_layerBlendSource == LayerBlendSource::Displacement) @@ -140,24 +145,28 @@ LayerBlendSource GetFinalLayerBlendSource() } } -//! Return the raw blend source values directly from the blend mask or vertex colors, depending on the available data and configuration. +//! Return the applicable blend mask values from the blend mask texture or vertex colors, and filters out any that don't apply. //! layer1 is an implicit base layer -//! layer2 is weighted by r -//! layer3 is weighted by g +//! layer2 mask is in the r channel +//! layer3 mask is in the g channel //! b is reserved for perhaps a dedicated puddle layer -float3 GetBlendSourceValues(float2 uv) +//! @param blendSource indicates where to get the blend mask from +//! @param blendMaskUv for sampling a blend mask texture, if that's the blend source +//! @param blendMaskVertexColors the vertex color values to use for the blend mask, if that's the blend source +//! @return the blend mask values, or 0 if there is no blend mask +float3 GetApplicableBlendMaskValues(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors) { float3 blendSourceValues = float3(0,0,0); if(o_layer2_enabled || o_layer3_enabled) { - switch(GetFinalBlendMaskSource()) + switch(blendSource) { - case BlendMaskSource::TextureMap: - blendSourceValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; + case LayerBlendSource::TextureMap: + blendSourceValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, blendMaskUv).rgb; break; - case BlendMaskSource::VertexColors: - blendSourceValues = s_blendMaskFromVertexStream; + case LayerBlendSource::VertexColors: + blendSourceValues = blendMaskVertexColors; break; } @@ -179,38 +188,57 @@ float3 GetBlendSourceValues(float2 uv) //! @param layerDepthValues - the per-layer depth values as provided by GetLayerDepthValues() float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues) { - float highestPoint = min(layerDepthValues.x, min(layerDepthValues.y, layerDepthValues.z)); + float highestPoint = layerDepthValues.x; + if(o_layer2_enabled) + { + highestPoint = min(highestPoint, layerDepthValues.y); + } + if(o_layer3_enabled) + { + highestPoint = min(highestPoint, layerDepthValues.z); + } + float3 blendWeights = float3(layerDepthValues.x <= highestPoint ? 1.0 : 0.0, - layerDepthValues.y <= highestPoint ? 1.0 : 0.0, - layerDepthValues.z <= highestPoint ? 1.0 : 0.0); + o_layer2_enabled && layerDepthValues.y <= highestPoint ? 1.0 : 0.0, + o_layer3_enabled && layerDepthValues.z <= highestPoint ? 1.0 : 0.0); return blendWeights; } -float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); - -//! Return the final blend mask values to be used for rendering, based on the available data and configuration. +//! Return the final blend weights to be used for rendering, based on the available data and configuration. +//! @param blendSource indicates where to get the blend mask from +//! @param blendMaskUv for sampling a blend mask texture, if that's the blend source +//! @param blendMaskVertexColors the vertex color values to use for the blend mask, if that's the blend source +//! @param layerDepthValues the depth values for each layer, use if the blend source includes displacement //! @return The blend weights for each layer. //! Even though layer1 not explicitly specified in the blend source data, it is explicitly included with the returned values. //! layer1 = r //! layer2 = g //! layer3 = b -float3 GetBlendWeights(float2 uv) +float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors, float3 layerDepthValues) { float3 blendWeights; if(o_layer2_enabled || o_layer3_enabled) { - float3 blendSourceValues = GetBlendSourceValues(uv); + if(LayerBlendSource::Displacement == blendSource) + { + blendWeights = GetBlendWeightsFromLayerDepthValues(layerDepthValues); + } + else + { + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, blendMaskUv, blendMaskVertexColors); - // Calculate blend weights such that multiplying and adding them with layer data is equivalent - // to lerping between each layer. - // final = lerp(final, layer1, blendWeights.r) - // final = lerp(final, layer2, blendWeights.g) - // final = lerp(final, layer3, blendWeights.b) + // Calculate blend weights such that multiplying and adding them with layer data is equivalent + // to lerping between each layer. + // final = lerp(final, layer1, blendWeights.r) + // final = lerp(final, layer2, blendWeights.g) + // final = lerp(final, layer3, blendWeights.b) + + blendWeights.b = blendMaskValues.g; + blendWeights.g = (1.0 - blendMaskValues.g) * blendMaskValues.r; + blendWeights.r = (1.0 - blendMaskValues.g) * (1.0 - blendMaskValues.r); + } - blendWeights.b = blendSourceValues.g; - blendWeights.g = (1.0 - blendSourceValues.g) * blendSourceValues.r; - blendWeights.r = (1.0 - blendSourceValues.g) * (1.0 - blendSourceValues.r); } else { @@ -220,19 +248,21 @@ float3 GetBlendWeights(float2 uv) return blendWeights; } -//! Return the final blend mask values to be used for rendering, based on the available data and configuration. +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); + +//! Return the final blend weights to be used for rendering, based on the available data and configuration. //! Note this will sample the displacement maps in the case of LayerBlendSource::Displacement. If you have already -//! called GetLayerDepthValues(), use the GetBlendWeights() overlad that takes layerDepthValues instead. -float3 GetBlendWeights(float2 uv, float3 vertexBlendWeights) +//! called GetLayerDepthValues(), use the GetBlendWeights() overload that takes layerDepthValues instead. +float3 GetBlendWeights(LayerBlendSource blendSource, float2 uv, float3 blendMaskVertexColors) { float3 layerDepthValues = float3(0,0,0); - if(GetFinalLayerBlendSource() == LayerBlendSource::Displacement) + if(blendSource == LayerBlendSource::Displacement) { layerDepthValues = GetLayerDepthValues(uv, ddx_fine(uv), ddy_fine(uv)); } - return GetBlendWeights(uv, vertexBlendWeights, layerDepthValues); + return GetBlendWeights(blendSource, uv, blendMaskVertexColors, layerDepthValues); } float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeights) @@ -319,7 +349,7 @@ DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) // Note, when the blend source is LayerBlendSource::VertexColors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be so noticeable as long as // you have a small depth factor relative to the size of the blend transition. - float3 blendWeightValues = GetBlendWeights(uv, s_blendWeightsFromVertexStream, layerDepthValues); + float3 blendWeightValues = GetBlendWeights(GetFinalLayerBlendSource(), uv, s_blendMaskFromVertexStream, layerDepthValues); float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); return DepthResultAbsolute(depth); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig new file mode 100644 index 0000000000..471fab991d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig @@ -0,0 +1,401 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include + +#include "MaterialInputs/BaseColorInput.azsli" +#include "MaterialInputs/RoughnessInput.azsli" +#include "MaterialInputs/MetallicInput.azsli" +#include "MaterialInputs/SpecularInput.azsli" +#include "MaterialInputs/NormalInput.azsli" +#include "MaterialInputs/ClearCoatInput.azsli" +#include "MaterialInputs/OcclusionInput.azsli" +#include "MaterialInputs/EmissiveInput.azsli" +#include "MaterialInputs/ParallaxInput.azsli" +#include "MaterialInputs/UvSetCount.azsli" + +// ------ ShaderResourceGroup ---------------------------------------- + +#define DEFINE_LAYER_SRG_INPUTS(prefix) \ +COMMON_SRG_INPUTS_BASE_COLOR(prefix) \ +COMMON_SRG_INPUTS_ROUGHNESS(prefix) \ +COMMON_SRG_INPUTS_METALLIC(prefix) \ +COMMON_SRG_INPUTS_SPECULAR_F0(prefix) \ +COMMON_SRG_INPUTS_NORMAL(prefix) \ +COMMON_SRG_INPUTS_CLEAR_COAT(prefix) \ +COMMON_SRG_INPUTS_OCCLUSION(prefix) \ +COMMON_SRG_INPUTS_EMISSIVE(prefix) \ +COMMON_SRG_INPUTS_PARALLAX(prefix) + +ShaderResourceGroup MaterialSrg : SRG_PerMaterial +{ + Texture2D m_blendMaskTexture; + uint m_blendMaskUvIndex; + + // Auto-generate material SRG fields for common inputs for each layer + DEFINE_LAYER_SRG_INPUTS(m_layer1_) + DEFINE_LAYER_SRG_INPUTS(m_layer2_) + DEFINE_LAYER_SRG_INPUTS(m_layer3_) + + float3x3 m_layer1_m_uvMatrix; + float4 m_pad1; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. + + float3x3 m_layer2_m_uvMatrix; + float4 m_pad2; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. + + float3x3 m_layer3_m_uvMatrix; + float4 m_pad3; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. + + uint m_parallaxUvIndex; + + // These are used to limit the heightmap intersection search range to the narrowest band possible, to give the best quality result. + float m_displacementMin; // The lowest displacement value possible from all layers combined (negative values are below the surface) + float m_displacementMax; // The highest displacement value possible from all layers combined (negative values are below the surface) + + float3x3 m_uvMatrix; + float4 m_pad4; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. + float3x3 m_uvMatrixInverse; + float4 m_pad5; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. + + Sampler m_sampler + { + AddressU = Wrap; + AddressV = Wrap; + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + MaxAnisotropy = 16; + }; + + Texture2D m_brdfMap; + + Sampler m_samplerBrdf + { + AddressU = Clamp; + AddressV = Clamp; + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + }; + +} + +// ------ Shader Options ---------------------------------------- + +<<<<<<< HEAD +option bool o_layer2_enabled; +option bool o_layer3_enabled; + +enum class DebugDrawMode { None, BlendSource, DepthMaps }; +======= +enum class DebugDrawMode { None, BlendWeights, DisplacementMaps }; +>>>>>>> Atom/santorac/MultilayerPbrImprovements +option DebugDrawMode o_debugDrawMode; + +enum class LayerBlendSource { BlendMask, VertexColors, Displacement, Fallback }; +option LayerBlendSource o_layerBlendSource; + +// Indicates whether the vertex input struct's "m_optional_blendMask" is bound. If false, it is not safe to read from m_optional_blendMask. +// This option gets set automatically by the system at runtime; there is a soft naming convention that associates it with m_optional_blendMask. +// (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. +option bool o_blendMask_isBound; + +// ------ Blend Utilities ---------------------------------------- + +<<<<<<< HEAD +// This is mainly used to pass extra data to the GetDepth callback function during the parallax depth search. +// But since we have it, we use it in some other functions as well rather than passing it around. +static float3 s_blendMaskFromVertexStream; + +//! Returns the BlendMaskSource that will actually be used when rendering (not necessarily the same BlendMaskSource specified by the user) +BlendMaskSource GetFinalBlendMaskSource() +======= +//! Returns the LayerBlendSource that will actually be used when rendering (not necessarily the same LayerBlendSource specified by the user) +LayerBlendSource GetFinalLayerBlendSource() +>>>>>>> Atom/santorac/MultilayerPbrImprovements +{ + if(o_layerBlendSource == LayerBlendSource::BlendMask) + { + return LayerBlendSource::BlendMask; + } + else if(o_layerBlendSource == LayerBlendSource::VertexColors) + { + if(o_blendMask_isBound) + { + return LayerBlendSource::VertexColors; + } + else + { + return LayerBlendSource::BlendMask; + } + } + else if(o_layerBlendSource == LayerBlendSource::Displacement) + { + return LayerBlendSource::Displacement; + } + else + { + return LayerBlendSource::Fallback; + } +} + +<<<<<<< HEAD +//! Return the raw blend source values directly from the blend mask or vertex colors, depending on the available data and configuration. +//! layer1 is an implicit base layer +//! layer2 is weighted by r +//! layer3 is weighted by g +//! b is reserved for perhaps a dedicated puddle layer +float3 GetBlendSourceValues(float2 uv) +{ + float3 blendSourceValues = float3(0,0,0); + + if(o_layer2_enabled || o_layer3_enabled) + { + switch(GetFinalBlendMaskSource()) + { + case BlendMaskSource::TextureMap: + blendSourceValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; + break; + case BlendMaskSource::VertexColors: + blendSourceValues = s_blendMaskFromVertexStream; + break; + } + + if(!o_layer2_enabled) + { + blendSourceValues.r = 0.0; + } + + if(!o_layer3_enabled) + { + blendSourceValues.g = 0.0; + } + } + + return blendSourceValues; +} + +//! Return the final blend mask values to be used for rendering, based on the available data and configuration. +//! @return The blend weights for each layer. +//! Even though layer1 not explicitly specified in the blend source data, it is explicitly included with the returned values. +//! layer1 = r +//! layer2 = g +//! layer3 = b +float3 GetBlendWeights(float2 uv) +{ + float3 blendWeights; + + if(o_layer2_enabled || o_layer3_enabled) + { + float3 blendSourceValues = GetBlendSourceValues(uv); + + // Calculate blend weights such that multiplying and adding them with layer data is equivalent + // to lerping between each layer. + // final = lerp(final, layer1, blendWeights.r) + // final = lerp(final, layer2, blendWeights.g) + // final = lerp(final, layer3, blendWeights.b) + + blendWeights.b = blendSourceValues.g; + blendWeights.g = (1.0 - blendSourceValues.g) * blendSourceValues.r; + blendWeights.r = (1.0 - blendSourceValues.g) * (1.0 - blendSourceValues.r); + } + else + { + blendWeights = float3(1,0,0); + } + + return blendWeights; +} + +float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeights) +{ + return dot(float3(layer1, layer2, layer3), blendWeights); +} +float2 BlendLayers(float2 layer1, float2 layer2, float2 layer3, float3 blendWeights) +{ + return layer1 * blendWeights.r + layer2 * blendWeights.g + layer3 * blendWeights.b; +} +float3 BlendLayers(float3 layer1, float3 layer2, float3 layer3, float3 blendWeights) +{ + return layer1 * blendWeights.r + layer2 * blendWeights.g + layer3 * blendWeights.b; +======= +//! Returns blend weights given the depth values for each layer +float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues) +{ + float highestPoint = min(layerDepthValues.x, min(layerDepthValues.y, layerDepthValues.z)); + float3 blendWeights = float3(layerDepthValues.x <= highestPoint ? 1.0 : 0.0, + layerDepthValues.y <= highestPoint ? 1.0 : 0.0, + layerDepthValues.z <= highestPoint ? 1.0 : 0.0); + return blendWeights; +} + +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); + +//! Return the final blend mask values to be used for rendering, based on the available data and configuration. +//! @param vertexBlendWeights - the blend weights that came from the vertex input, relevant for LayerBlendSource::VertexColors +//! @param layerDepthValues - the per-layer depth values as provided by GetLayerDepthValues() +float3 GetBlendWeights(float2 uv, float3 vertexBlendWeights, float3 layerDepthValues) +{ + float3 blendWeightValues; + + switch(GetFinalLayerBlendSource()) + { + case LayerBlendSource::BlendMask: + blendWeightValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; + break; + case LayerBlendSource::VertexColors: + blendWeightValues = vertexBlendWeights; + break; + case LayerBlendSource::Displacement: + blendWeightValues = GetBlendWeightsFromLayerDepthValues(layerDepthValues); + break; + case LayerBlendSource::Fallback: + blendWeightValues = float3(1,1,1); + break; + } + + blendWeightValues = blendWeightValues / (blendWeightValues.r + blendWeightValues.g + blendWeightValues.b); + + return blendWeightValues; +} + +//! Return the final blend mask values to be used for rendering, based on the available data and configuration. +//! Note this will sample the displacement maps in the case of LayerBlendSource::Displacement. If you have already +//! called GetLayerDepthValues(), use the GetBlendWeights() overlad that takes layerDepthValues instead. +float3 GetBlendWeights(float2 uv, float3 vertexBlendWeights) +{ + float3 layerDepthValues = float3(0,0,0); + + if(GetFinalLayerBlendSource() == LayerBlendSource::Displacement) + { + layerDepthValues = GetLayerDepthValues(uv, ddx_fine(uv), ddy_fine(uv)); + } + + return GetBlendWeights(uv, vertexBlendWeights, layerDepthValues); +} + +float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeightValues) +{ + return dot(float3(layer1, layer2, layer3), blendWeightValues); +} +float2 BlendLayers(float2 layer1, float2 layer2, float2 layer3, float3 blendWeightValues) +{ + return layer1 * blendWeightValues.r + layer2 * blendWeightValues.g + layer3 * blendWeightValues.b; +} +float3 BlendLayers(float3 layer1, float3 layer2, float3 layer3, float3 blendWeightValues) +{ + return layer1 * blendWeightValues.r + layer2 * blendWeightValues.g + layer3 * blendWeightValues.b; +>>>>>>> Atom/santorac/MultilayerPbrImprovements +} + +// ------ Parallax Utilities ---------------------------------------- + +bool ShouldHandleParallax() +{ + // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scattering is enabled. + // Also, all the debug draw modes avoid parallax (they early-return before parallax code actually) so you can see exactly where the various maps appear on the surface UV space. + return !o_enableSubsurfaceScattering && o_parallax_feature_enabled && o_debugDrawMode == DebugDrawMode::None; +} + +bool ShouldHandleParallaxInDepthShaders() +{ + // The depth pass shaders need to calculate parallax when the result could affect the depth buffer (or when + // parallax could affect texel clipping but we don't have alpha/clipping support in multilayer PBR). + return ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; +} + +<<<<<<< HEAD +// Callback function for ParallaxMapping.azsli +DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) +======= +// These static values are used to pass extra data to the GetDepth callback function during the parallax depth search. +static float3 s_blendWeightsFromVertexStream; + +//! Setup static variables that are needed by the GetDepth callback function +//! @param vertexBlendWeights - the blend weights from the vertex input stream. +void GetDepth_Setup(float3 vertexBlendWeights) +{ + s_blendWeightsFromVertexStream = vertexBlendWeights; +} + +//! Returns the depth values for each layer +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) +>>>>>>> Atom/santorac/MultilayerPbrImprovements +{ + float3 layerDepthValues = float3(0,0,0); + + if(o_layer1_o_useDepthMap) + { + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer1_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.r = SampleDepthOrHeightMap(MaterialSrg::m_layer1_m_depthInverted, MaterialSrg::m_layer1_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.r *= MaterialSrg::m_layer1_m_depthFactor; + layerDepthValues.r -= MaterialSrg::m_layer1_m_depthOffset; + } + + if(o_layer2_enabled && o_layer2_o_useDepthMap) + { + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer2_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor; + layerDepthValues.g -= MaterialSrg::m_layer2_m_depthOffset; + } + + if(o_layer3_enabled && o_layer3_o_useDepthMap) + { + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer3_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; + layerDepthValues.b -= MaterialSrg::m_layer3_m_depthOffset; + } + + return layerDepthValues; +} + +//! Callback function for ParallaxMapping.azsli +DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) +{ + float3 layerDepthValues = GetLayerDepthValues(uv, uv_ddx, uv_ddy); + + // Note, when the blend source is LayerBlendSource::VertexColors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values + // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be so noticeable as long as + // you have a small depth factor relative to the size of the blend transition. +<<<<<<< HEAD + float3 blendWeights = GetBlendWeights(uv); + + float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeights); +======= + float3 blendWeightValues = GetBlendWeights(uv, s_blendWeightsFromVertexStream, layerDepthValues); + + float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + return DepthResultAbsolute(depth); +} 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 e274945e30..255ba60762 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 @@ -53,7 +53,7 @@ struct VSDepthOutput float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; float3 m_worldPosition : UV0; - float3 m_blendWeights : UV3; + float3 m_blendMask : UV3; }; VSDepthOutput MainVS(VSInput IN) @@ -80,11 +80,11 @@ VSDepthOutput MainVS(VSInput IN) if(o_blendMask_isBound) { - OUT.m_blendWeights = IN.m_optional_blendMask.rgb; + OUT.m_blendMask = IN.m_optional_blendMask.rgb; } else { - OUT.m_blendWeights = float3(1,1,1); + OUT.m_blendMask = float3(0,0,0); } return OUT; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig new file mode 100644 index 0000000000..489bd87037 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig @@ -0,0 +1,132 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include + +#include "MaterialInputs/ParallaxInput.azsli" + + +#include "MaterialInputs/ParallaxInput.azsli" +COMMON_OPTIONS_PARALLAX(o_layer1_) +COMMON_OPTIONS_PARALLAX(o_layer2_) +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 +{ + 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_blendWeights : 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_blendWeights = IN.m_optional_blendMask.rgb; + } + else + { + OUT.m_blendWeights = float3(1,1,1); + } + + return OUT; +} + +struct PSDepthOutput +{ + float m_depth : SV_Depth; +}; + +PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) +{ + PSDepthOutput OUT; + + OUT.m_depth = IN.m_position.z; + + if(ShouldHandleParallaxInDepthShaders()) + { + // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); + +<<<<<<< HEAD + s_blendMaskFromVertexStream = IN.m_blendMask; +======= + GetDepth_Setup(IN.m_blendWeights); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + + 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; +} 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 b6d9e545d7..1fed3acbee 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -94,7 +94,7 @@ struct VSOutput // Extended fields (only referenced in this azsl file)... float2 m_uv[UvSetCount] : UV1; - float3 m_blendWeights : UV7; + float3 m_blendMask : UV7; }; #include @@ -112,11 +112,11 @@ VSOutput ForwardPassVS(VSInput IN) if(o_blendMask_isBound) { - OUT.m_blendWeights = IN.m_optional_blendMask.rgb; + OUT.m_blendMask = IN.m_optional_blendMask.rgb; } else { - OUT.m_blendWeights = float3(1,1,1); + OUT.m_blendMask = float3(0,0,0); } // Shadow coords will be calculated in the pixel shader in this case @@ -310,6 +310,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float s_blendMaskFromVertexStream = IN.m_blendMask; + LayerBlendSource blendSource = GetFinalLayerBlendSource(); + // ------- Tangents & Bitangets ------- // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. @@ -332,17 +334,23 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Debug Modes ------- - if(o_debugDrawMode == DebugDrawMode::BlendMaskValues) + if(o_debugDrawMode == DebugDrawMode::BlendMask) { - float3 blendMaskValues = GetBlendMaskValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); return DebugOutput(blendMaskValues); } - if(o_debugDrawMode == DebugDrawMode::DisplacementMaps) + if(o_debugDrawMode == DebugDrawMode::Displacement) { float depth = GetNormalizedDepth(-MaterialSrg::m_displacementMax, -MaterialSrg::m_displacementMin, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); return DebugOutput(float3(depth,depth,depth)); } + + if(o_debugDrawMode == DebugDrawMode::FinalBlendWeights) + { + float3 blendWeights = GetBlendWeights(blendSource, IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); + return DebugOutput(blendWeights); + } // ------- Parallax ------- @@ -373,7 +381,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Calculate Layer Blend Mask Values ------- // Now that any parallax has been calculated, we calculate the blend factors for any layers that are impacted by the parallax. - float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); + float3 blendWeights = GetBlendWeights(blendSource, IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); // ------- Layer 1 (base layer) ----------- @@ -434,7 +442,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Combine Albedo, roughness, specular, roughness --------- - float3 baseColor = BlendLayers(layer1_baseColor, layer2_baseColor, layer3_baseColor, blendMaskValues); + 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); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig new file mode 100644 index 0000000000..4ddea9b0cf --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig @@ -0,0 +1,710 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +// SRGs +#include +#include +#include + +// Pass Output +#include + +// Utility +#include +#include + +// Custom Surface & Lighting +#include + +// Decals +#include + +// ---------- Material Parameters ---------- + +#include "MaterialInputs/BaseColorInput.azsli" +#include "MaterialInputs/RoughnessInput.azsli" +#include "MaterialInputs/MetallicInput.azsli" +#include "MaterialInputs/SpecularInput.azsli" +#include "MaterialInputs/NormalInput.azsli" +#include "MaterialInputs/ClearCoatInput.azsli" +#include "MaterialInputs/OcclusionInput.azsli" +#include "MaterialInputs/EmissiveInput.azsli" +#include "MaterialInputs/ParallaxInput.azsli" + +#define DEFINE_LAYER_OPTIONS(prefix) \ +COMMON_OPTIONS_BASE_COLOR(prefix) \ +COMMON_OPTIONS_ROUGHNESS(prefix) \ +COMMON_OPTIONS_METALLIC(prefix) \ +COMMON_OPTIONS_SPECULAR_F0(prefix) \ +COMMON_OPTIONS_NORMAL(prefix) \ +COMMON_OPTIONS_CLEAR_COAT(prefix) \ +COMMON_OPTIONS_OCCLUSION(prefix) \ +COMMON_OPTIONS_EMISSIVE(prefix) \ +COMMON_OPTIONS_PARALLAX(prefix) + +DEFINE_LAYER_OPTIONS(o_layer1_) +DEFINE_LAYER_OPTIONS(o_layer2_) +DEFINE_LAYER_OPTIONS(o_layer3_) + +#include "MaterialInputs/TransmissionInput.azsli" +#include "StandardMultilayerPBR_Common.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; + + // 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 VSOutput +{ + // Base fields (required by the template azsli file)... + 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; + + float3 m_blendWeights : UV7; +}; + +#include + +VSOutput 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. + // 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(o_blendMask_isBound) + { + OUT.m_blendWeights = IN.m_optional_blendMask.rgb; + } + else + { + OUT.m_blendWeights = float3(1,1,1); + } + + // 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; +} + +//! Collects all the raw Standard material inputs for a single layer. See ProcessStandardMaterialInputs(). +struct StandardMaterialInputs +{ + COMMON_SRG_INPUTS_BASE_COLOR() + COMMON_SRG_INPUTS_ROUGHNESS() + COMMON_SRG_INPUTS_METALLIC() + COMMON_SRG_INPUTS_SPECULAR_F0() + COMMON_SRG_INPUTS_NORMAL() + COMMON_SRG_INPUTS_CLEAR_COAT() + COMMON_SRG_INPUTS_OCCLUSION() + COMMON_SRG_INPUTS_EMISSIVE() + // Note parallax is omitted here because that requires special handling. + + bool m_normal_useTexture; + bool m_baseColor_useTexture; + bool m_metallic_useTexture; + bool m_specularF0_useTexture; + bool m_roughness_useTexture; + bool m_emissiveEnabled; + bool m_emissive_useTexture; + bool m_diffuseOcclusion_useTexture; + bool m_specularOcclusion_useTexture; + bool m_clearCoatEnabled; + bool m_clearCoat_factor_useTexture; + bool m_clearCoat_roughness_useTexture; + bool m_clearCoat_normal_useTexture; + + TextureBlendMode m_baseColorTextureBlendMode; + + float2 m_vertexUv[UvSetCount]; + float3x3 m_uvMatrix; + float m_normal; + float3 m_tangents[UvSetCount]; + float3 m_bitangents[UvSetCount]; + + sampler m_sampler; + + bool m_isFrontFace; +}; + +//! Holds the final processed material inputs, after all flags have been checked, textures have been sampled, factors have been applied, etc. +//! This data is ready to be copied into a Surface and/or LightingData struct for the lighting system to consume. +class ProcessedMaterialInputs +{ + float3 m_normalTS; //!< Normal in tangent-space + float3 m_baseColor; + float3 m_specularF0Factor; + float m_metallic; + float m_roughness; + float3 m_emissiveLighting; + float m_diffuseAmbientOcclusion; + float m_specularOcclusion; + ClearCoatSurfaceData m_clearCoat; + + void InitializeToZero() + { + m_normalTS = float3(0,0,0); + m_baseColor = float3(0,0,0); + m_specularF0Factor = float3(0,0,0); + m_metallic = 0.0f; + m_roughness = 0.0f; + m_emissiveLighting = float3(0,0,0); + m_diffuseAmbientOcclusion = 0; + m_specularOcclusion = 0; + m_clearCoat.InitializeToZero(); + } +}; + +//! Processes the set of Standard material inputs for a single layer. +//! The FILL_STANDARD_MATERIAL_INPUTS() macro below can be used to fill the StandardMaterialInputs struct. +ProcessedMaterialInputs ProcessStandardMaterialInputs(StandardMaterialInputs inputs) +{ + ProcessedMaterialInputs result; + + float2 transformedUv[UvSetCount]; + transformedUv[0] = mul(inputs.m_uvMatrix, float3(inputs.m_vertexUv[0], 1.0)).xy; + transformedUv[1] = inputs.m_vertexUv[1]; + + float3x3 normalUvMatrix = inputs.m_normalMapUvIndex == 0 ? inputs.m_uvMatrix : CreateIdentity3x3(); + result.m_normalTS = GetNormalInputTS(inputs.m_normalMap, inputs.m_sampler, transformedUv[inputs.m_normalMapUvIndex], inputs.m_flipNormalX, inputs.m_flipNormalY, normalUvMatrix, inputs.m_normal_useTexture, inputs.m_normalFactor); + + float3 sampledBaseColor = GetBaseColorInput(inputs.m_baseColorMap, inputs.m_sampler, transformedUv[inputs.m_baseColorMapUvIndex], inputs.m_baseColor.rgb, inputs.m_baseColor_useTexture); + result.m_baseColor = BlendBaseColor(sampledBaseColor, inputs.m_baseColor.rgb, inputs.m_baseColorFactor, inputs.m_baseColorTextureBlendMode, inputs.m_baseColor_useTexture); + result.m_specularF0Factor = GetSpecularInput(inputs.m_specularF0Map, inputs.m_sampler, transformedUv[inputs.m_specularF0MapUvIndex], inputs.m_specularF0Factor, inputs.m_specularF0_useTexture); + result.m_metallic = GetMetallicInput(inputs.m_metallicMap, inputs.m_sampler, transformedUv[inputs.m_metallicMapUvIndex], inputs.m_metallicFactor, inputs.m_metallic_useTexture); + result.m_roughness = GetRoughnessInput(inputs.m_roughnessMap, MaterialSrg::m_sampler, transformedUv[inputs.m_roughnessMapUvIndex], inputs.m_roughnessFactor, inputs.m_roughnessLowerBound, inputs.m_roughnessUpperBound, inputs.m_roughness_useTexture); + + result.m_emissiveLighting = GetEmissiveInput(inputs.m_emissiveMap, inputs.m_sampler, transformedUv[inputs.m_emissiveMapUvIndex], inputs.m_emissiveIntensity, inputs.m_emissiveColor.rgb, inputs.m_emissiveEnabled, inputs.m_emissive_useTexture); + result.m_diffuseAmbientOcclusion = GetOcclusionInput(inputs.m_diffuseOcclusionMap, inputs.m_sampler, transformedUv[inputs.m_diffuseOcclusionMapUvIndex], inputs.m_diffuseOcclusionFactor, inputs.m_diffuseOcclusion_useTexture); + result.m_specularOcclusion = GetOcclusionInput(inputs.m_specularOcclusionMap, MaterialSrg::m_sampler, transformedUv[inputs.m_specularOcclusionMapUvIndex], inputs.m_specularOcclusionFactor, inputs.m_specularOcclusion_useTexture); + + result.m_clearCoat.InitializeToZero(); + if(inputs.m_clearCoatEnabled) + { + float3x3 clearCoatUvMatrix = inputs.m_clearCoatNormalMapUvIndex == 0 ? inputs.m_uvMatrix : CreateIdentity3x3(); + + GetClearCoatInputs(inputs.m_clearCoatInfluenceMap, transformedUv[inputs.m_clearCoatInfluenceMapUvIndex], inputs.m_clearCoatFactor, inputs.m_clearCoat_factor_useTexture, + inputs.m_clearCoatRoughnessMap, transformedUv[inputs.m_clearCoatRoughnessMapUvIndex], inputs.m_clearCoatRoughness, inputs.m_clearCoat_roughness_useTexture, + inputs.m_clearCoatNormalMap, transformedUv[inputs.m_clearCoatNormalMapUvIndex], inputs.m_normal, inputs.m_clearCoat_normal_useTexture, inputs.m_clearCoatNormalStrength, + clearCoatUvMatrix, inputs.m_tangents[inputs.m_clearCoatNormalMapUvIndex], inputs.m_bitangents[inputs.m_clearCoatNormalMapUvIndex], + inputs.m_sampler, inputs.m_isFrontFace, + result.m_clearCoat.factor, result.m_clearCoat.roughness, result.m_clearCoat.normal); + } + + return result; +} + +//! Fills a StandardMaterialInputs struct with data from the MaterialSrg, shader options, and local vertex data. +#define FILL_STANDARD_MATERIAL_INPUTS(inputs, srgLayerPrefix, optionsLayerPrefix, blendWeight) \ + inputs.m_sampler = MaterialSrg::m_sampler; \ + inputs.m_vertexUv = IN.m_uv; \ + inputs.m_uvMatrix = srgLayerPrefix##m_uvMatrix; \ + inputs.m_normal = IN.m_normal; \ + inputs.m_tangents = tangents; \ + inputs.m_bitangents = bitangents; \ + inputs.m_isFrontFace = isFrontFace; \ + \ + inputs.m_normalMapUvIndex = srgLayerPrefix##m_normalMapUvIndex; \ + inputs.m_normalMap = srgLayerPrefix##m_normalMap; \ + inputs.m_flipNormalX = srgLayerPrefix##m_flipNormalX; \ + inputs.m_flipNormalY = srgLayerPrefix##m_flipNormalY; \ + inputs.m_normal_useTexture = optionsLayerPrefix##o_normal_useTexture; \ + inputs.m_normalFactor = srgLayerPrefix##m_normalFactor * blendWeight; \ + inputs.m_baseColorMap = srgLayerPrefix##m_baseColorMap; \ + inputs.m_baseColorMapUvIndex = srgLayerPrefix##m_baseColorMapUvIndex; \ + inputs.m_baseColor = srgLayerPrefix##m_baseColor; \ + inputs.m_baseColor_useTexture = optionsLayerPrefix##o_baseColor_useTexture; \ + inputs.m_baseColorFactor = srgLayerPrefix##m_baseColorFactor; \ + inputs.m_baseColorTextureBlendMode = optionsLayerPrefix##o_baseColorTextureBlendMode; \ + inputs.m_metallicMap = srgLayerPrefix##m_metallicMap; \ + inputs.m_metallicMapUvIndex = srgLayerPrefix##m_metallicMapUvIndex; \ + inputs.m_metallicFactor = srgLayerPrefix##m_metallicFactor; \ + inputs.m_metallic_useTexture = optionsLayerPrefix##o_metallic_useTexture; \ + inputs.m_specularF0Map = srgLayerPrefix##m_specularF0Map; \ + inputs.m_specularF0MapUvIndex = srgLayerPrefix##m_specularF0MapUvIndex; \ + inputs.m_specularF0Factor = srgLayerPrefix##m_specularF0Factor; \ + inputs.m_specularF0_useTexture = optionsLayerPrefix##o_specularF0_useTexture; \ + inputs.m_roughnessMap = srgLayerPrefix##m_roughnessMap; \ + inputs.m_roughnessMapUvIndex = srgLayerPrefix##m_roughnessMapUvIndex; \ + inputs.m_roughnessFactor = srgLayerPrefix##m_roughnessFactor; \ + inputs.m_roughnessLowerBound = srgLayerPrefix##m_roughnessLowerBound; \ + inputs.m_roughnessUpperBound = srgLayerPrefix##m_roughnessUpperBound; \ + inputs.m_roughness_useTexture = optionsLayerPrefix##o_roughness_useTexture; \ + \ + inputs.m_emissiveMap = srgLayerPrefix##m_emissiveMap; \ + inputs.m_emissiveMapUvIndex = srgLayerPrefix##m_emissiveMapUvIndex; \ + inputs.m_emissiveIntensity = srgLayerPrefix##m_emissiveIntensity; \ + inputs.m_emissiveColor = srgLayerPrefix##m_emissiveColor; \ + inputs.m_emissiveEnabled = optionsLayerPrefix##o_emissiveEnabled; \ + inputs.m_emissive_useTexture = optionsLayerPrefix##o_emissive_useTexture; \ + \ + inputs.m_diffuseOcclusionMap = srgLayerPrefix##m_diffuseOcclusionMap; \ + inputs.m_diffuseOcclusionMapUvIndex = srgLayerPrefix##m_diffuseOcclusionMapUvIndex; \ + inputs.m_diffuseOcclusionFactor = srgLayerPrefix##m_diffuseOcclusionFactor; \ + inputs.m_diffuseOcclusion_useTexture = optionsLayerPrefix##o_diffuseOcclusion_useTexture; \ + \ + inputs.m_specularOcclusionMap = srgLayerPrefix##m_specularOcclusionMap; \ + inputs.m_specularOcclusionMapUvIndex = srgLayerPrefix##m_specularOcclusionMapUvIndex; \ + inputs.m_specularOcclusionFactor = srgLayerPrefix##m_specularOcclusionFactor; \ + inputs.m_specularOcclusion_useTexture = optionsLayerPrefix##o_specularOcclusion_useTexture; \ + \ + inputs.m_clearCoatEnabled = o_clearCoat_feature_enabled && optionsLayerPrefix##o_clearCoat_enabled; \ + inputs.m_clearCoatInfluenceMap = srgLayerPrefix##m_clearCoatInfluenceMap; \ + inputs.m_clearCoatInfluenceMapUvIndex = srgLayerPrefix##m_clearCoatInfluenceMapUvIndex; \ + inputs.m_clearCoatFactor = srgLayerPrefix##m_clearCoatFactor; \ + inputs.m_clearCoat_factor_useTexture = optionsLayerPrefix##o_clearCoat_factor_useTexture; \ + inputs.m_clearCoatRoughnessMap = srgLayerPrefix##m_clearCoatRoughnessMap; \ + inputs.m_clearCoatRoughnessMapUvIndex = srgLayerPrefix##m_clearCoatRoughnessMapUvIndex; \ + inputs.m_clearCoatRoughness = srgLayerPrefix##m_clearCoatRoughness; \ + inputs.m_clearCoat_roughness_useTexture = optionsLayerPrefix##o_clearCoat_roughness_useTexture; \ + inputs.m_clearCoatNormalMap = srgLayerPrefix##m_clearCoatNormalMap; \ + inputs.m_clearCoatNormalMapUvIndex = srgLayerPrefix##m_clearCoatNormalMapUvIndex; \ + inputs.m_clearCoat_normal_useTexture = optionsLayerPrefix##o_clearCoat_normal_useTexture; \ + inputs.m_clearCoatNormalStrength = srgLayerPrefix##m_clearCoatNormalStrength; + + +// ---------- Pixel Shader ---------- + +PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) +{ + depthNDC = IN.m_position.z; + + s_blendMaskFromVertexStream = IN.m_blendMask; + + // ------- Tangents & Bitangets ------- + + // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; + + if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering && MaterialSrg::m_parallaxUvIndex != 0) + || (o_layer1_o_normal_useTexture && MaterialSrg::m_layer1_m_normalMapUvIndex != 0) + || (o_layer2_o_normal_useTexture && MaterialSrg::m_layer2_m_normalMapUvIndex != 0) + || (o_layer3_o_normal_useTexture && MaterialSrg::m_layer3_m_normalMapUvIndex != 0) + || (o_layer1_o_clearCoat_normal_useTexture && MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex != 0) + || (o_layer2_o_clearCoat_normal_useTexture && MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex != 0) + || (o_layer3_o_clearCoat_normal_useTexture && MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex != 0) + ) + { + // Generate the tangent/bitangent for UV[1+] + const int startIndex = 1; + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex); + } + + // ------- Debug Modes ------- + +<<<<<<< HEAD + if(o_debugDrawMode == DebugDrawMode::BlendSource) + { + float3 blendSource = GetBlendSourceValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); + return DebugOutput(blendSource); +======= + if(o_debugDrawMode == DebugDrawMode::BlendWeights) + { + float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendWeights); + return DebugOutput(blendWeights); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + } + + if(o_debugDrawMode == DebugDrawMode::DisplacementMaps) + { +<<<<<<< HEAD +======= + GetDepth_Setup(IN.m_blendWeights); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + float depth = GetNormalizedDepth(-MaterialSrg::m_displacementMax, -MaterialSrg::m_displacementMin, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); + return DebugOutput(float3(depth,depth,depth)); + } + + // ------- Parallax ------- + + bool displacementIsClipped = false; + + if(ShouldHandleParallax()) + { +<<<<<<< HEAD +======= + GetDepth_Setup(IN.m_blendWeights); + +>>>>>>> Atom/santorac/MultilayerPbrImprovements + 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, IN.m_position.w, 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, IN.m_shadowCoords); + } + } + } + + // ------- Calculate Layer Blend Mask Values ------- + + // Now that any parallax has been calculated, we calculate the blend factors for any layers that are impacted by the parallax. +<<<<<<< HEAD + float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); + + // ------- Layer 1 (base layer) ----------- + + ProcessedMaterialInputs lightingInputLayer1; +======= + float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendWeights); + + // ------- Normal ------- + + float3 layer1_normalFactor = MaterialSrg::m_layer1_m_normalFactor * blendWeights.r; + float3 layer2_normalFactor = MaterialSrg::m_layer2_m_normalFactor * blendWeights.g; + float3 layer3_normalFactor = MaterialSrg::m_layer3_m_normalFactor * blendWeights.b; + float3x3 layer1_uvMatrix = MaterialSrg::m_layer1_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer1_m_uvMatrix : CreateIdentity3x3(); + float3x3 layer2_uvMatrix = MaterialSrg::m_layer2_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer2_m_uvMatrix : CreateIdentity3x3(); + float3x3 layer3_uvMatrix = MaterialSrg::m_layer3_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer3_m_uvMatrix : CreateIdentity3x3(); + float3 layer1_normalTS = GetNormalInputTS(MaterialSrg::m_layer1_m_normalMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_normalMapUvIndex], MaterialSrg::m_layer1_m_flipNormalX, MaterialSrg::m_layer1_m_flipNormalY, layer1_uvMatrix, o_layer1_o_normal_useTexture, layer1_normalFactor); + float3 layer2_normalTS = GetNormalInputTS(MaterialSrg::m_layer2_m_normalMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_normalMapUvIndex], MaterialSrg::m_layer2_m_flipNormalX, MaterialSrg::m_layer2_m_flipNormalY, layer2_uvMatrix, o_layer2_o_normal_useTexture, layer2_normalFactor); + float3 layer3_normalTS = GetNormalInputTS(MaterialSrg::m_layer3_m_normalMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_normalMapUvIndex], MaterialSrg::m_layer3_m_flipNormalX, MaterialSrg::m_layer3_m_flipNormalY, layer3_uvMatrix, o_layer3_o_normal_useTexture, layer3_normalFactor); + + float3 normalTS = ReorientTangentSpaceNormal(layer1_normalTS, layer2_normalTS); + normalTS = ReorientTangentSpaceNormal(normalTS, layer3_normalTS); + // [GFX TODO][ATOM-14591]: This will only work if the normal maps all use the same UV stream. We would need to add support for having them in different UV streams. + surface.normal = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex])); + + // ------- Base Color ------- + + float2 layer1_baseColorUv = uvLayer1[MaterialSrg::m_layer1_m_baseColorMapUvIndex]; + float2 layer2_baseColorUv = uvLayer2[MaterialSrg::m_layer2_m_baseColorMapUvIndex]; + float2 layer3_baseColorUv = uvLayer3[MaterialSrg::m_layer3_m_baseColorMapUvIndex]; + + float3 layer1_sampledColor = GetBaseColorInput(MaterialSrg::m_layer1_m_baseColorMap, MaterialSrg::m_sampler, layer1_baseColorUv, MaterialSrg::m_layer1_m_baseColor.rgb, o_layer1_o_baseColor_useTexture); + float3 layer2_sampledColor = GetBaseColorInput(MaterialSrg::m_layer2_m_baseColorMap, MaterialSrg::m_sampler, layer2_baseColorUv, MaterialSrg::m_layer2_m_baseColor.rgb, o_layer2_o_baseColor_useTexture); + float3 layer3_sampledColor = GetBaseColorInput(MaterialSrg::m_layer3_m_baseColorMap, MaterialSrg::m_sampler, layer3_baseColorUv, MaterialSrg::m_layer3_m_baseColor.rgb, o_layer3_o_baseColor_useTexture); + float3 layer1_baseColor = BlendBaseColor(layer1_sampledColor, MaterialSrg::m_layer1_m_baseColor.rgb, MaterialSrg::m_layer1_m_baseColorFactor, o_layer1_o_baseColorTextureBlendMode, o_layer1_o_baseColor_useTexture); + float3 layer2_baseColor = BlendBaseColor(layer2_sampledColor, MaterialSrg::m_layer2_m_baseColor.rgb, MaterialSrg::m_layer2_m_baseColorFactor, o_layer2_o_baseColorTextureBlendMode, o_layer2_o_baseColor_useTexture); + float3 layer3_baseColor = BlendBaseColor(layer3_sampledColor, MaterialSrg::m_layer3_m_baseColor.rgb, MaterialSrg::m_layer3_m_baseColorFactor, o_layer3_o_baseColorTextureBlendMode, o_layer3_o_baseColor_useTexture); + float3 baseColor = BlendLayers(layer1_baseColor, layer2_baseColor, layer3_baseColor, blendWeights); + + if(o_parallax_highlightClipping && displacementIsClipped) +>>>>>>> Atom/santorac/MultilayerPbrImprovements + { + StandardMaterialInputs inputs; + FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer1_, o_layer1_, blendWeights.r) + lightingInputLayer1 = ProcessStandardMaterialInputs(inputs); + } + + // ----------- Layer 2 ----------- + + ProcessedMaterialInputs lightingInputLayer2; + if(o_layer2_enabled) + { +<<<<<<< HEAD + StandardMaterialInputs inputs; + FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer2_, o_layer2_, blendWeights.g) + lightingInputLayer2 = ProcessStandardMaterialInputs(inputs); + } + else + { + lightingInputLayer2.InitializeToZero(); + } + + // ----------- Layer 3 ----------- +======= + float layer1_metallic = GetMetallicInput(MaterialSrg::m_layer1_m_metallicMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_metallicMapUvIndex], MaterialSrg::m_layer1_m_metallicFactor, o_layer1_o_metallic_useTexture); + float layer2_metallic = GetMetallicInput(MaterialSrg::m_layer2_m_metallicMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_metallicMapUvIndex], MaterialSrg::m_layer2_m_metallicFactor, o_layer2_o_metallic_useTexture); + float layer3_metallic = GetMetallicInput(MaterialSrg::m_layer3_m_metallicMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_metallicMapUvIndex], MaterialSrg::m_layer3_m_metallicFactor, o_layer3_o_metallic_useTexture); + metallic = BlendLayers(layer1_metallic, layer2_metallic, layer3_metallic, blendWeights); + } + + // ------- Specular ------- + + float layer1_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer1_m_specularF0Map, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularF0MapUvIndex], MaterialSrg::m_layer1_m_specularF0Factor, o_layer1_o_specularF0_useTexture); + float layer2_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer2_m_specularF0Map, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularF0MapUvIndex], MaterialSrg::m_layer2_m_specularF0Factor, o_layer2_o_specularF0_useTexture); + float layer3_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer3_m_specularF0Map, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularF0MapUvIndex], MaterialSrg::m_layer3_m_specularF0Factor, o_layer3_o_specularF0_useTexture); + float specularF0Factor = BlendLayers(layer1_specularF0Factor, layer2_specularF0Factor, layer3_specularF0Factor, blendWeights); + + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + + ProcessedMaterialInputs lightingInputLayer3; + if(o_layer3_enabled) + { + StandardMaterialInputs inputs; + FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer3_, o_layer3_, blendWeights.b) + lightingInputLayer3 = ProcessStandardMaterialInputs(inputs); + } + else + { + lightingInputLayer3.InitializeToZero(); + } + +<<<<<<< HEAD + // ------- Combine all layers --------- + + Surface surface; + surface.position = IN.m_worldPosition; + surface.transmission.InitializeToZero(); +======= + float layer1_roughness = GetRoughnessInput(MaterialSrg::m_layer1_m_roughnessMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_roughnessMapUvIndex], MaterialSrg::m_layer1_m_roughnessFactor, MaterialSrg::m_layer1_m_roughnessLowerBound, MaterialSrg::m_layer1_m_roughnessUpperBound, o_layer1_o_roughness_useTexture); + float layer2_roughness = GetRoughnessInput(MaterialSrg::m_layer2_m_roughnessMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_roughnessMapUvIndex], MaterialSrg::m_layer2_m_roughnessFactor, MaterialSrg::m_layer2_m_roughnessLowerBound, MaterialSrg::m_layer2_m_roughnessUpperBound, o_layer2_o_roughness_useTexture); + float layer3_roughness = GetRoughnessInput(MaterialSrg::m_layer3_m_roughnessMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_roughnessMapUvIndex], MaterialSrg::m_layer3_m_roughnessFactor, MaterialSrg::m_layer3_m_roughnessLowerBound, MaterialSrg::m_layer3_m_roughnessUpperBound, o_layer3_o_roughness_useTexture); + surface.roughnessLinear = BlendLayers(layer1_roughness, layer2_roughness, layer3_roughness, blendWeights); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + + // ------- Combine Normals --------- + + float3 normalTS = lightingInputLayer1.m_normalTS; + if(o_layer2_enabled) + { + normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer2.m_normalTS); + } + if(o_layer3_enabled) + { + normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer3.m_normalTS); + } + // [GFX TODO][ATOM-14591]: This will only work if the normal maps all use the same UV stream. We would need to add support for having them in different UV streams. + surface.normal = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex])); + + // ------- 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); + + if(o_parallax_highlightClipping && displacementIsClipped) + { + ApplyParallaxClippingHighlight(baseColor); + } + + surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); + + surface.roughnessLinear = BlendLayers(lightingInputLayer1.m_roughness, lightingInputLayer2.m_roughness, lightingInputLayer3.m_roughness, blendWeights); + surface.CalculateRoughnessA(); + + // ------- Init and Combine 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; + +<<<<<<< HEAD + lightingData.emissiveLighting = BlendLayers(lightingInputLayer1.m_emissiveLighting, lightingInputLayer2.m_emissiveLighting, lightingInputLayer3.m_emissiveLighting, blendWeights); + lightingData.specularOcclusion = BlendLayers(lightingInputLayer1.m_specularOcclusion, lightingInputLayer2.m_specularOcclusion, lightingInputLayer3.m_specularOcclusion, blendWeights); + lightingData.diffuseAmbientOcclusion = BlendLayers(lightingInputLayer1.m_diffuseAmbientOcclusion, lightingInputLayer2.m_diffuseAmbientOcclusion, lightingInputLayer3.m_diffuseAmbientOcclusion, blendWeights); + + lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); +======= + float3 layer1_emissive = GetEmissiveInput(MaterialSrg::m_layer1_m_emissiveMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_emissiveMapUvIndex], MaterialSrg::m_layer1_m_emissiveIntensity, MaterialSrg::m_layer1_m_emissiveColor.rgb, o_layer1_o_emissiveEnabled, o_layer1_o_emissive_useTexture); + float3 layer2_emissive = GetEmissiveInput(MaterialSrg::m_layer2_m_emissiveMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_emissiveMapUvIndex], MaterialSrg::m_layer2_m_emissiveIntensity, MaterialSrg::m_layer2_m_emissiveColor.rgb, o_layer2_o_emissiveEnabled, o_layer2_o_emissive_useTexture); + float3 layer3_emissive = GetEmissiveInput(MaterialSrg::m_layer3_m_emissiveMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_emissiveMapUvIndex], MaterialSrg::m_layer3_m_emissiveIntensity, MaterialSrg::m_layer3_m_emissiveColor.rgb, o_layer3_o_emissiveEnabled, o_layer3_o_emissive_useTexture); + lightingData.emissiveLighting = BlendLayers(layer1_emissive, layer2_emissive, layer3_emissive, blendWeights); + + // ------- Occlusion ------- + + float layer1_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer1_m_diffuseOcclusionFactor, o_layer1_o_diffuseOcclusion_useTexture); + float layer2_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer2_m_diffuseOcclusionFactor, o_layer2_o_diffuseOcclusion_useTexture); + float layer3_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer3_m_diffuseOcclusionFactor, o_layer3_o_diffuseOcclusion_useTexture); + lightingData.diffuseAmbientOcclusion = BlendLayers(layer1_diffuseAmbientOcclusion, layer2_diffuseAmbientOcclusion, layer3_diffuseAmbientOcclusion, blendWeights); + + float layer1_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer1_m_specularOcclusionFactor, o_layer1_o_specularOcclusion_useTexture); + float layer2_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer2_m_specularOcclusionFactor, o_layer2_o_specularOcclusion_useTexture); + float layer3_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer3_m_specularOcclusionFactor, o_layer3_o_specularOcclusion_useTexture); + lightingData.specularOcclusion = BlendLayers(layer1_specularOcclusion, layer2_specularOcclusion, layer3_specularOcclusion, blendWeights); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + + // ------- Combine Clearcoat ------- + + if(o_clearCoat_feature_enabled) + { +<<<<<<< HEAD + surface.clearCoat.factor = BlendLayers(lightingInputLayer1.m_clearCoat.factor, lightingInputLayer2.m_clearCoat.factor, lightingInputLayer3.m_clearCoat.factor, blendWeights); + surface.clearCoat.roughness = BlendLayers(lightingInputLayer1.m_clearCoat.roughness, lightingInputLayer2.m_clearCoat.roughness, lightingInputLayer3.m_clearCoat.roughness, blendWeights); + + // [GFX TODO][ATOM-14592] This is not the right way to blend the normals. We need to use ReorientTangentSpaceNormal(), and that requires GetClearCoatInputs() to return the normal in TS instead of WS. + surface.clearCoat.normal = BlendLayers(lightingInputLayer1.m_clearCoat.normal, lightingInputLayer2.m_clearCoat.normal, lightingInputLayer3.m_clearCoat.normal, blendWeights); +======= + // --- Layer 1 --- + + float layer1_clearCoatFactor = 0.0f; + float layer1_clearCoatRoughness = 0.0f; + float3 layer1_clearCoatNormal = float3(0.0, 0.0, 0.0); + if(o_layer1_o_clearCoat_enabled) + { + float3x3 layer1_uvMatrix = MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_layer1_m_uvMatrix : CreateIdentity3x3(); + + GetClearCoatInputs(MaterialSrg::m_layer1_m_clearCoatInfluenceMap, uvLayer1[MaterialSrg::m_layer1_m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_layer1_m_clearCoatFactor, o_layer1_o_clearCoat_factor_useTexture, + MaterialSrg::m_layer1_m_clearCoatRoughnessMap, uvLayer1[MaterialSrg::m_layer1_m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_layer1_m_clearCoatRoughness, o_layer1_o_clearCoat_roughness_useTexture, + MaterialSrg::m_layer1_m_clearCoatNormalMap, uvLayer1[MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex], IN.m_normal, o_layer1_o_clearCoat_normal_useTexture, MaterialSrg::m_layer1_m_clearCoatNormalStrength, + layer1_uvMatrix, tangents[MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex], + MaterialSrg::m_sampler, isFrontFace, + layer1_clearCoatFactor, layer1_clearCoatRoughness, layer1_clearCoatNormal); + } + + // --- Layer 2 --- + + float layer2_clearCoatFactor = 0.0f; + float layer2_clearCoatRoughness = 0.0f; + float3 layer2_clearCoatNormal = float3(0.0, 0.0, 0.0); + if(o_layer2_o_clearCoat_enabled) + { + float3x3 layer2_uvMatrix = MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_layer2_m_uvMatrix : CreateIdentity3x3(); + + GetClearCoatInputs(MaterialSrg::m_layer2_m_clearCoatInfluenceMap, uvLayer2[MaterialSrg::m_layer2_m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_layer2_m_clearCoatFactor, o_layer2_o_clearCoat_factor_useTexture, + MaterialSrg::m_layer2_m_clearCoatRoughnessMap, uvLayer2[MaterialSrg::m_layer2_m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_layer2_m_clearCoatRoughness, o_layer2_o_clearCoat_roughness_useTexture, + MaterialSrg::m_layer2_m_clearCoatNormalMap, uvLayer2[MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex], IN.m_normal, o_layer2_o_clearCoat_normal_useTexture, MaterialSrg::m_layer2_m_clearCoatNormalStrength, + layer2_uvMatrix, tangents[MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex], + MaterialSrg::m_sampler, isFrontFace, + layer2_clearCoatFactor, layer2_clearCoatRoughness, layer2_clearCoatNormal); + } + + // --- Layer 3 --- + + float layer3_clearCoatFactor = 0.0f; + float layer3_clearCoatRoughness = 0.0f; + float3 layer3_clearCoatNormal = float3(0.0, 0.0, 0.0); + if(o_layer3_o_clearCoat_enabled) + { + float3x3 layer3_uvMatrix = MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_layer3_m_uvMatrix : CreateIdentity3x3(); + + GetClearCoatInputs(MaterialSrg::m_layer3_m_clearCoatInfluenceMap, uvLayer3[MaterialSrg::m_layer3_m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_layer3_m_clearCoatFactor, o_layer3_o_clearCoat_factor_useTexture, + MaterialSrg::m_layer3_m_clearCoatRoughnessMap, uvLayer3[MaterialSrg::m_layer3_m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_layer3_m_clearCoatRoughness, o_layer3_o_clearCoat_roughness_useTexture, + MaterialSrg::m_layer3_m_clearCoatNormalMap, uvLayer3[MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex], IN.m_normal, o_layer3_o_clearCoat_normal_useTexture, MaterialSrg::m_layer3_m_clearCoatNormalStrength, + layer3_uvMatrix, tangents[MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex], + MaterialSrg::m_sampler, isFrontFace, + layer3_clearCoatFactor, layer3_clearCoatRoughness, layer3_clearCoatNormal); + } + + // --- Blend Layers --- + + surface.clearCoat.factor = BlendLayers(layer1_clearCoatFactor, layer2_clearCoatFactor, layer3_clearCoatFactor, blendWeights); + surface.clearCoat.roughness = BlendLayers(layer1_clearCoatRoughness, layer2_clearCoatRoughness, layer3_clearCoatRoughness, blendWeights); + + // [GFX TODO][ATOM-14592] This is not the right way to blend the normals. We need to use ReorientTangentSpaceNormal(), and that requires GetClearCoatInputs() to return the normal in TS instead of WS. + surface.clearCoat.normal = BlendLayers(layer1_clearCoatNormal, layer2_clearCoatNormal, layer3_clearCoatNormal, blendWeights); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + surface.clearCoat.normal = normalize(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); + } + + // ------- 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(0); + + + const float alpha = 1.0; + + PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); + + lightingOutput.m_diffuseColor.w = -1; // Disable subsurface scattering + + return lightingOutput; +} + +ForwardPassOutputWithDepth 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_depth = depth; + return OUT; +} + +[earlydepthstencil] +ForwardPassOutput 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; + + return OUT; +} + 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 a4e8bb3c0a..e06fc67be7 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 @@ -53,7 +53,7 @@ struct VertexOutput float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; float3 m_worldPosition : UV0; - float3 m_blendWeights : UV3; + float3 m_blendMask : UV3; }; VertexOutput MainVS(VertexInput IN) @@ -79,11 +79,11 @@ VertexOutput MainVS(VertexInput IN) if(o_blendMask_isBound) { - OUT.m_blendWeights = IN.m_optional_blendMask.rgb; + OUT.m_blendMask = IN.m_optional_blendMask.rgb; } else { - OUT.m_blendWeights = float3(1,1,1); + OUT.m_blendMask = float3(0,0,0); } return OUT; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig new file mode 100644 index 0000000000..a9be92b7a5 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig @@ -0,0 +1,131 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include + +#include "MaterialInputs/ParallaxInput.azsli" + +#include "MaterialInputs/ParallaxInput.azsli" +COMMON_OPTIONS_PARALLAX(o_layer1_) +COMMON_OPTIONS_PARALLAX(o_layer2_) +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_blendWeights : 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_blendWeights = IN.m_optional_blendMask.rgb; + } + else + { + OUT.m_blendWeights = float3(1,1,1); + } + + 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()) + { + // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); + +<<<<<<< HEAD + s_blendMaskFromVertexStream = IN.m_blendMask; +======= + GetDepth_Setup(IN.m_blendWeights); +>>>>>>> Atom/santorac/MultilayerPbrImprovements + + 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); + + OUT.m_depth = depthNDC; + } + + return OUT; +} diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendSource.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material similarity index 86% rename from Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendSource.material rename to Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material index 94a1ec6a30..df81b9b25a 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendSource.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "general": { - "debugDrawMode": "BlendMaskValues" + "debugDrawMode": "BlendMask" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material new file mode 100644 index 0000000000..4cd6546028 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material @@ -0,0 +1,11 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", + "propertyLayoutVersion": 3, + "properties": { + "general": { + "debugDrawMode": "FinalBlendWeights" + } + } +} diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DisplacementMaps.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material similarity index 85% rename from Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DisplacementMaps.material rename to Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material index eb2d01cef2..fb4db87c2c 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DisplacementMaps.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "general": { - "debugDrawMode": "DisplacementMaps" + "debugDrawMode": "Displacement" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material index c29dddc623..477d62737c 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -5,7 +5,9 @@ "propertyLayoutVersion": 3, "properties": { "blend": { - "blendSource": "Displacement" + "blendSource": "Displacement", + "enableLayer2": true, + "enableLayer3": true }, "layer1_baseColor": { "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" From b56667bb64ca9dce548c51a89b9b72da809eefcd Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 14 May 2021 00:02:15 -0700 Subject: [PATCH 03/14] Added new blend source options that allow a blend mask to be used together with depth based blending. --- .../Types/StandardMultilayerPBR.materialtype | 4 +- .../Types/StandardMultilayerPBR_Common.azsli | 115 ++++++++++++++---- .../Types/StandardMultilayerPBR_Parallax.lua | 15 ++- .../004_UseVertexColors.material | 2 +- .../005_UseDisplacement.material | 39 +++--- ...isplacement_With_BlendMaskTexture.material | 11 ++ ...cement_With_BlendMaskVertexColors.material | 14 +++ 7 files changed, 156 insertions(+), 44 deletions(-) create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index f6c0cc3ad3..10f0cecf6d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -322,8 +322,8 @@ "displayName": "Blend Source", "description": "The source to use for defining the blend mask. Note VertexColors mode will still use the texture as a fallback if the mesh does not have a COLOR0 stream.", "type": "Enum", - "enumValues": ["TextureMap", "VertexColors", "Displacement"], - "defaultValue": "TextureMap", + "enumValues": ["BlendMaskTexture", "BlendMaskVertexColors", "Displacement", "Displacement_With_BlendMaskTexture", "Displacement_With_BlendMaskVertexColors"], + "defaultValue": "BlendMaskTexture", "connection": { "type": "ShaderOption", "id": "o_layerBlendSource" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index dc1b627d29..ebeaa988b2 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -42,7 +42,7 @@ COMMON_SRG_INPUTS_PARALLAX(prefix) ShaderResourceGroup MaterialSrg : SRG_PerMaterial { - Texture2D m_blendMaskTexture; + Texture2D m_blendMaskTexture; uint m_blendMaskUvIndex; // Auto-generate material SRG fields for common inputs for each layer @@ -101,7 +101,7 @@ option bool o_layer3_enabled; enum class DebugDrawMode { None, BlendMask, Displacement, FinalBlendWeights }; option DebugDrawMode o_debugDrawMode; -enum class LayerBlendSource { TextureMap, VertexColors, Displacement, Fallback }; +enum class LayerBlendSource { BlendMaskTexture, BlendMaskVertexColors, Displacement, Displacement_With_BlendMaskTexture, Displacement_With_BlendMaskVertexColors, Fallback }; option LayerBlendSource o_layerBlendSource; // Indicates whether the vertex input struct's "m_optional_blendMask" is bound. If false, it is not safe to read from m_optional_blendMask. @@ -120,24 +120,39 @@ static float3 s_blendMaskFromVertexStream; //! Returns the LayerBlendSource that will actually be used when rendering (not necessarily the same LayerBlendSource specified by the user) LayerBlendSource GetFinalLayerBlendSource() { - if(o_layerBlendSource == LayerBlendSource::TextureMap) + if(o_layerBlendSource == LayerBlendSource::BlendMaskTexture) { - return LayerBlendSource::TextureMap; + return o_layerBlendSource; } - else if(o_layerBlendSource == LayerBlendSource::VertexColors) + else if(o_layerBlendSource == LayerBlendSource::BlendMaskVertexColors) { if(o_blendMask_isBound) { - return LayerBlendSource::VertexColors; + return o_layerBlendSource; } else { - return LayerBlendSource::TextureMap; + return LayerBlendSource::Fallback; } } else if(o_layerBlendSource == LayerBlendSource::Displacement) { - return LayerBlendSource::Displacement; + return o_layerBlendSource; + } + else if(o_layerBlendSource == LayerBlendSource::Displacement_With_BlendMaskTexture) + { + return o_layerBlendSource; + } + else if(o_layerBlendSource == LayerBlendSource::Displacement_With_BlendMaskVertexColors) + { + if(o_blendMask_isBound) + { + return o_layerBlendSource; + } + else + { + return LayerBlendSource::Displacement; + } } else { @@ -162,10 +177,16 @@ float3 GetApplicableBlendMaskValues(LayerBlendSource blendSource, float2 blendMa { switch(blendSource) { - case LayerBlendSource::TextureMap: + case LayerBlendSource::Displacement: + // In this case the blend mask has no effect, returning (1,1,1) disables any impact of the mask. + blendSourceValues = float3(1,1,1); + break; + case LayerBlendSource::BlendMaskTexture: + case LayerBlendSource::Displacement_With_BlendMaskTexture: blendSourceValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, blendMaskUv).rgb; break; - case LayerBlendSource::VertexColors: + case LayerBlendSource::BlendMaskVertexColors: + case LayerBlendSource::Displacement_With_BlendMaskVertexColors: blendSourceValues = blendMaskVertexColors; break; } @@ -208,9 +229,9 @@ float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues) //! @param blendSource indicates where to get the blend mask from //! @param blendMaskUv for sampling a blend mask texture, if that's the blend source //! @param blendMaskVertexColors the vertex color values to use for the blend mask, if that's the blend source -//! @param layerDepthValues the depth values for each layer, use if the blend source includes displacement +//! @param layerDepthValues the depth values for each layer, use if the blend source includes displacement. See GetLayerDepthValues() //! @return The blend weights for each layer. -//! Even though layer1 not explicitly specified in the blend source data, it is explicitly included with the returned values. +//! Even though layer1 not explicitly specified in the blend mask data, it is explicitly included with the returned values. //! layer1 = r //! layer2 = g //! layer3 = b @@ -220,8 +241,12 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 if(o_layer2_enabled || o_layer3_enabled) { - if(LayerBlendSource::Displacement == blendSource) + if(LayerBlendSource::Displacement == blendSource || + LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || + LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource) { + // Note that any impact from the blend mask will have already been applied to these layerDepthValues in GetLayerDepthValues(). + // So even though there is no blend mask code here, the blend mask is being applied when enabled. blendWeights = GetBlendWeightsFromLayerDepthValues(layerDepthValues); } else @@ -248,7 +273,7 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 return blendWeights; } -float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); +float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_ddx, float2 uv_ddy, float3 blendMaskVertexColors); //! Return the final blend weights to be used for rendering, based on the available data and configuration. //! Note this will sample the displacement maps in the case of LayerBlendSource::Displacement. If you have already @@ -257,9 +282,11 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 uv, float3 blendMask { float3 layerDepthValues = float3(0,0,0); - if(blendSource == LayerBlendSource::Displacement) + if(blendSource == LayerBlendSource::Displacement || + blendSource == LayerBlendSource::Displacement_With_BlendMaskTexture || + blendSource == LayerBlendSource::Displacement_With_BlendMaskVertexColors) { - layerDepthValues = GetLayerDepthValues(uv, ddx_fine(uv), ddy_fine(uv)); + layerDepthValues = GetLayerDepthValues(blendSource, uv, ddx_fine(uv), ddy_fine(uv), blendMaskVertexColors); } return GetBlendWeights(blendSource, uv, blendMaskVertexColors, layerDepthValues); @@ -294,12 +321,17 @@ bool ShouldHandleParallaxInDepthShaders() return ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; } -//! Returns the depth values for each layer -float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) +//! Returns the depth values for each layer. +//! If the blend source is Displacement_With_BlendMaskTexture or Displacement_With_BlendMaskVertexColors, this will use the blend weights to further offset the depth values. +float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_ddx, float2 uv_ddy, float3 blendMaskVertexColors) { float3 layerDepthValues = float3(0,0,0); + + bool useLayer1 = true; + bool useLayer2 = (o_layer2_enabled && o_layer2_o_useDepthMap); + bool useLayer3 = (o_layer3_enabled && o_layer3_o_useDepthMap); - if(o_layer1_o_useDepthMap) + if(useLayer1) { float2 layerUv = uv; if(MaterialSrg::m_parallaxUvIndex == 0) @@ -312,7 +344,7 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) layerDepthValues.r -= MaterialSrg::m_layer1_m_depthOffset; } - if(o_layer2_enabled && o_layer2_o_useDepthMap) + if(useLayer2) { float2 layerUv = uv; if(MaterialSrg::m_parallaxUvIndex == 0) @@ -323,9 +355,10 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor; layerDepthValues.g -= MaterialSrg::m_layer2_m_depthOffset; + } - if(o_layer3_enabled && o_layer3_o_useDepthMap) + if(useLayer3) { float2 layerUv = uv; if(MaterialSrg::m_parallaxUvIndex == 0) @@ -336,7 +369,37 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; layerDepthValues.b -= MaterialSrg::m_layer3_m_depthOffset; + } + + bool useBlendMask = + LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || + LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource; + + if(useBlendMask && (useLayer2 || useLayer3)) + { + // We use the blend mask to lower each layer's surface so that it disappears under the other surfaces. + // Note the blend mask does not apply to the first layer, it is the implicit base layer. Layers 2 and 3 are masked by the r and g channels. + + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uv, blendMaskVertexColors); + + // We add to the depth value rather than lerp toward m_displacementMin to avoid squashing the topology, but instead lower it out of sight. + + // We might want to consider other approaches to the blend mask factors. They way they work now allows the user to lower + + if(useLayer2) + { + float dropoffRange = MaterialSrg::m_layer2_m_depthOffset - MaterialSrg::m_displacementMin; + layerDepthValues.g += dropoffRange * (1-blendMaskValues.r); + } + + if(useLayer3) + { + float dropoffRange = MaterialSrg::m_layer3_m_depthOffset - MaterialSrg::m_displacementMin; + layerDepthValues.b += dropoffRange * (1-blendMaskValues.g); + } + } + return layerDepthValues; } @@ -344,12 +407,14 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) //! Callback function for ParallaxMapping.azsli DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) { - float3 layerDepthValues = GetLayerDepthValues(uv, uv_ddx, uv_ddy); + LayerBlendSource blendSource = GetFinalLayerBlendSource(); + + float3 layerDepthValues = GetLayerDepthValues(blendSource, uv, uv_ddx, uv_ddy, s_blendMaskFromVertexStream); - // Note, when the blend source is LayerBlendSource::VertexColors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values - // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be so noticeable as long as + // Note, when the blend source uses the blend mask from the vertex colors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values + // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be as noticeable if // you have a small depth factor relative to the size of the blend transition. - float3 blendWeightValues = GetBlendWeights(GetFinalLayerBlendSource(), uv, s_blendMaskFromVertexStream, layerDepthValues); + float3 blendWeightValues = GetBlendWeights(blendSource, uv, s_blendMaskFromVertexStream, layerDepthValues); float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); return DepthResultAbsolute(depth); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua index 24e596d877..669c11b90d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua @@ -16,6 +16,7 @@ function GetMaterialPropertyDependencies() return { + "blend.blendSource", "parallax.enable", "layer1_parallax.enable", "layer2_parallax.enable", @@ -50,6 +51,13 @@ function GetMergedHeightRange(heightMinMax, offset, factor) end end +-- These values must align with LayerBlendSource in StandardMultilayerPBR_Common.azsli. +LayerBlendSource_BlendMaskTexture = 0 +LayerBlendSource_BlendMaskVertexColors = 1 +LayerBlendSource_Displacement = 2 +LayerBlendSource_Displacement_With_BlendMaskTexture = 3 +LayerBlendSource_Displacement_With_BlendMaskVertexColors = 4 + function Process(context) local enableParallax = context:GetMaterialPropertyValue_bool("parallax.enable") local enable1 = context:GetMaterialPropertyValue_bool("layer1_parallax.enable") @@ -58,7 +66,12 @@ function Process(context) enableParallax = enableParallax and (enable1 or enable2 or enable3) context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enableParallax) - if(enableParallax) then + blendSource = context:GetMaterialPropertyValue_enum("blend.blendSource") + blendSourceIncludesDisplacement = (blendSource == LayerBlendSource_Displacement or + blendSource ==LayerBlendSource_Displacement_With_BlendMaskTexture or + blendSource == LayerBlendSource_Displacement_With_BlendMaskVertexColors) + + if(enableParallax or blendSourceIncludesDisplacement) then local factorLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.factor") local factorLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.factor") local factorLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.factor") diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material index ea3ffab467..3201fa3864 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "blend": { - "blendSource": "VertexColors" + "blendSource": "BlendMaskVertexColors" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material index 477d62737c..2db329e11e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -10,39 +10,49 @@ "enableLayer3": true }, "layer1_baseColor": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" + "textureMap": "TestData/Textures/cc0/Ground033_1K_Color.jpg" }, "layer1_normal": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" + "textureMap": "TestData/Textures/cc0/Ground033_1K_Normal.jpg" }, "layer1_occlusion": { - "diffuseTextureMap": "TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg" + "diffuseTextureMap": "TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg" }, "layer1_parallax": { "enable": true, - "factor": 0.10000000149011612, - "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" + "factor": 0.017000000923871995, + "offset": -0.009999999776482582, + "textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg" }, "layer1_roughness": { - "textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg" + "textureMap": "TestData/Textures/cc0/Ground033_1K_Roughness.jpg" }, "layer2_baseColor": { - "textureMap": "TestData/Textures/cc0/Ground033_1K_Color.jpg" + "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" }, "layer2_normal": { - "textureMap": "TestData/Textures/cc0/Ground033_1K_Normal.jpg" + "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" }, "layer2_occlusion": { - "diffuseTextureMap": "TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg" + "diffuseTextureMap": "TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg" }, "layer2_parallax": { "enable": true, - "factor": 0.014999999664723874, - "offset": -0.024000000208616258, - "textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg" + "factor": 0.03099999949336052, + "offset": 0.0020000000949949028, + "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" }, "layer2_roughness": { - "textureMap": "TestData/Textures/cc0/Ground033_1K_Roughness.jpg" + "textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg" + }, + "layer2_uv": { + "center": [ + 0.5, + 0.5 + ], + "offsetU": 0.1599999964237213, + "offsetV": 0.07999999821186066, + "rotateDegrees": 90.0 }, "layer3_baseColor": { "textureMap": "TestData/Textures/cc0/Rocks002_1K_Color.jpg" @@ -53,14 +63,13 @@ "layer3_parallax": { "enable": true, "factor": 0.027000000700354577, - "offset": -0.02199999988079071, "textureMap": "TestData/Textures/cc0/Rocks002_1K_Displacement.jpg" }, "layer3_roughness": { "textureMap": "TestData/Textures/cc0/Rocks002_1K_Roughness.jpg" }, "layer3_uv": { - "scale": 1.600000023841858 + "scale": 3.4999988079071047 }, "parallax": { "algorithm": "Relief", diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material new file mode 100644 index 0000000000..fe30d5caf2 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material @@ -0,0 +1,11 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "blendSource": "Displacement_With_BlendMaskTexture" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material new file mode 100644 index 0000000000..12fb6943d7 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material @@ -0,0 +1,14 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "blendSource": "Displacement_With_BlendMaskVertexColors" + }, + "parallax": { + "enable": false + } + } +} \ No newline at end of file From 8690ce57368ef94c8c384f46b9444ec067a21fde Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 14 May 2021 12:17:15 -0700 Subject: [PATCH 04/14] Added a displacement blend factor for a smooth transition between depth-blended layers. Renamed StandardMultilayerPBR_Parallax.lua to StandardMultilayerPBR_Displacement.lua because it is used for more than just strictly parallax, it generally deals with displcament which can be used for blending even when parallax is disabled. --- .../Types/StandardMultilayerPBR.materialtype | 17 +++- .../Types/StandardMultilayerPBR_Common.azsli | 93 ++++++++++++++----- ...=> StandardMultilayerPBR_Displacement.lua} | 22 +++-- .../005_UseDisplacement.material | 1 + .../005_UseDisplacement_Layer2Off.material | 11 +++ .../005_UseDisplacement_Layer3Off.material | 11 +++ 6 files changed, 126 insertions(+), 29 deletions(-) rename Gems/Atom/Feature/Common/Assets/Materials/Types/{StandardMultilayerPBR_Parallax.lua => StandardMultilayerPBR_Displacement.lua} (83%) create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index 10f0cecf6d..84f7cbe03a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -351,7 +351,22 @@ "type": "ShaderInput", "id": "m_blendMaskUvIndex" } + }, + { + "id": "displacementBlendFactor", + "displayName": "Blend Factor", + "description": "Adjusts how smoothly to transition between layers when displacement blending is enabled.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "step": 0.001, + "connection": { + "type": "ShaderInput", + "id": "m_displacementBlendFactor" + } } + ], "parallax": [ { @@ -2699,7 +2714,7 @@ { "type": "Lua", "args": { - "file": "StandardMultilayerPBR_Parallax.lua" + "file": "StandardMultilayerPBR_Displacement.lua" } }, //############################################################################################## diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index ebeaa988b2..f917ae1f91 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -45,6 +45,13 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial Texture2D m_blendMaskTexture; uint m_blendMaskUvIndex; + // When parallax mapping is used, these limit the heightmap intersection search range to the narrowest band possible, to give the best quality result. + // These are also support other calculations related to displacement-based blending, even when parallax is not used. + float m_displacementMin; // The lowest displacement value possible from all layers combined (negative values are below the surface) + float m_displacementMax; // The highest displacement value possible from all layers combined (negative values are below the surface) + + float m_displacementBlendFactor; + // Auto-generate material SRG fields for common inputs for each layer DEFINE_LAYER_SRG_INPUTS(m_layer1_) DEFINE_LAYER_SRG_INPUTS(m_layer2_) @@ -61,10 +68,6 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial uint m_parallaxUvIndex; - // These are used to limit the heightmap intersection search range to the narrowest band possible, to give the best quality result. - float m_displacementMin; // The lowest displacement value possible from all layers combined (negative values are below the surface) - float m_displacementMax; // The highest displacement value possible from all layers combined (negative values are below the surface) - float3x3 m_uvMatrix; float4 m_pad4; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. float3x3 m_uvMatrixInverse; @@ -207,35 +210,76 @@ float3 GetApplicableBlendMaskValues(LayerBlendSource blendSource, float2 blendMa //! Returns blend weights given the depth values for each layer //! @param layerDepthValues - the per-layer depth values as provided by GetLayerDepthValues() -float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues) +//! @param layerDepthBlendFactor - controls how smoothly to blend layers 2 and 3 with the base layer. +//! when layers are close together their weights will be blended together, otherwise the highest layer will have the full weight. +float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues, float layerDepthBlendFactor) { - float highestPoint = layerDepthValues.x; - if(o_layer2_enabled) + if(!o_layer2_enabled && !o_layer3_enabled) { - highestPoint = min(highestPoint, layerDepthValues.y); + return float3(1,0,0); } - if(o_layer3_enabled) + else { - highestPoint = min(highestPoint, layerDepthValues.z); + // The inputs are depth values, but we change them to height values to make the code a bit more intuitive. + float3 layerHeightValues = -layerDepthValues; + + float highestPoint = layerHeightValues.x; + if(o_layer2_enabled) + { + highestPoint = max(highestPoint, layerHeightValues.y); + } + if(o_layer3_enabled) + { + highestPoint = max(highestPoint, layerHeightValues.z); + } + + float3 blendWeights; + + if(layerDepthBlendFactor > 0.001) + { + float blendDistance = (MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin) * layerDepthBlendFactor; + + // The blend weights are adjusted to give a smooth transition in the surface appearance. + float lowestVisiblePoint = highestPoint - blendDistance; + + blendWeights = saturate(layerHeightValues - lowestVisiblePoint) / blendDistance; + + if(!o_layer2_enabled) + { + blendWeights.y = 0.0; + } + + if(!o_layer3_enabled) + { + blendWeights.z = 0.0; + } + + blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z); + } + else + { + blendWeights = float3(layerHeightValues.x >= highestPoint ? 1.0 : 0.0, + layerHeightValues.y >= highestPoint && o_layer2_enabled ? 1.0 : 0.0, + layerHeightValues.z >= highestPoint && o_layer3_enabled ? 1.0 : 0.0); + } + + return blendWeights; } - float3 blendWeights = float3(layerDepthValues.x <= highestPoint ? 1.0 : 0.0, - o_layer2_enabled && layerDepthValues.y <= highestPoint ? 1.0 : 0.0, - o_layer3_enabled && layerDepthValues.z <= highestPoint ? 1.0 : 0.0); - return blendWeights; } //! Return the final blend weights to be used for rendering, based on the available data and configuration. -//! @param blendSource indicates where to get the blend mask from -//! @param blendMaskUv for sampling a blend mask texture, if that's the blend source -//! @param blendMaskVertexColors the vertex color values to use for the blend mask, if that's the blend source -//! @param layerDepthValues the depth values for each layer, use if the blend source includes displacement. See GetLayerDepthValues() +//! @param blendSource - indicates where to get the blend mask from +//! @param blendMaskUv - for sampling a blend mask texture, if that's the blend source +//! @param blendMaskVertexColors - the vertex color values to use for the blend mask, if that's the blend source +//! @param layerDepthValues - the depth values for each layer, used if the blend source includes displacement. See GetLayerDepthValues(). +//! @param layerDepthBlendFactor - controls how smoothly to blend layers 2 and 3 with the base layer, when the blend source includes displacement. See GetLayerDepthValues(). //! @return The blend weights for each layer. //! Even though layer1 not explicitly specified in the blend mask data, it is explicitly included with the returned values. //! layer1 = r //! layer2 = g //! layer3 = b -float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors, float3 layerDepthValues) +float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors, float3 layerDepthValues, float layerDepthBlendFactors) { float3 blendWeights; @@ -247,7 +291,7 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 { // Note that any impact from the blend mask will have already been applied to these layerDepthValues in GetLayerDepthValues(). // So even though there is no blend mask code here, the blend mask is being applied when enabled. - blendWeights = GetBlendWeightsFromLayerDepthValues(layerDepthValues); + blendWeights = GetBlendWeightsFromLayerDepthValues(layerDepthValues, layerDepthBlendFactors); } else { @@ -289,7 +333,7 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 uv, float3 blendMask layerDepthValues = GetLayerDepthValues(blendSource, uv, ddx_fine(uv), ddy_fine(uv), blendMaskVertexColors); } - return GetBlendWeights(blendSource, uv, blendMaskVertexColors, layerDepthValues); + return GetBlendWeights(blendSource, uv, blendMaskVertexColors, layerDepthValues, MaterialSrg::m_displacementBlendFactor); } float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeights) @@ -411,10 +455,15 @@ DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) float3 layerDepthValues = GetLayerDepthValues(blendSource, uv, uv_ddx, uv_ddy, s_blendMaskFromVertexStream); + // When blending the depth together, we don't use MaterialSrg::m_displacementBlendFactor. The intention is that m_displacementBlendFactor + // is for transitioning the appearance of the surface itself, but we still want a distinct change in the heightmap. If someday we want to + // support smoothly blending the depth as well, there is a bit more work to do to get it to play nice with the blend mask code in GetLayerDepthValues(). + float layerDepthBlendFactor = 0.0f; + // Note, when the blend source uses the blend mask from the vertex colors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be as noticeable if // you have a small depth factor relative to the size of the blend transition. - float3 blendWeightValues = GetBlendWeights(blendSource, uv, s_blendMaskFromVertexStream, layerDepthValues); + float3 blendWeightValues = GetBlendWeights(blendSource, uv, s_blendMaskFromVertexStream, layerDepthValues, layerDepthBlendFactor); float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); return DepthResultAbsolute(depth); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua similarity index 83% rename from Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua rename to Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index 669c11b90d..fda7e20f4d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -58,6 +58,14 @@ LayerBlendSource_Displacement = 2 LayerBlendSource_Displacement_With_BlendMaskTexture = 3 LayerBlendSource_Displacement_With_BlendMaskVertexColors = 4 +function BlendSourceUsesDisplacement(context) + local blendSource = context:GetMaterialPropertyValue_enum("blend.blendSource") + local blendSourceIncludesDisplacement = (blendSource == LayerBlendSource_Displacement or + blendSource ==LayerBlendSource_Displacement_With_BlendMaskTexture or + blendSource == LayerBlendSource_Displacement_With_BlendMaskVertexColors) + return blendSourceIncludesDisplacement +end + function Process(context) local enableParallax = context:GetMaterialPropertyValue_bool("parallax.enable") local enable1 = context:GetMaterialPropertyValue_bool("layer1_parallax.enable") @@ -66,12 +74,7 @@ function Process(context) enableParallax = enableParallax and (enable1 or enable2 or enable3) context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enableParallax) - blendSource = context:GetMaterialPropertyValue_enum("blend.blendSource") - blendSourceIncludesDisplacement = (blendSource == LayerBlendSource_Displacement or - blendSource ==LayerBlendSource_Displacement_With_BlendMaskTexture or - blendSource == LayerBlendSource_Displacement_With_BlendMaskVertexColors) - - if(enableParallax or blendSourceIncludesDisplacement) then + if(enableParallax or BlendSourceUsesDisplacement(context)) then local factorLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.factor") local factorLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.factor") local factorLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.factor") @@ -107,4 +110,11 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("parallax.quality", visibility) context:SetMaterialPropertyVisibility("parallax.pdo", visibility) context:SetMaterialPropertyVisibility("parallax.showClipping", visibility) + + if BlendSourceUsesDisplacement(context) then + context:SetMaterialPropertyVisibility("blend.displacementBlendFactor", MaterialPropertyVisibility_Enabled) + else + context:SetMaterialPropertyVisibility("blend.displacementBlendFactor", MaterialPropertyVisibility_Hidden) + end + end diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material index 2db329e11e..87005ec41c 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -6,6 +6,7 @@ "properties": { "blend": { "blendSource": "Displacement", + "displacementBlendFactor": 0.10000000149011612, "enableLayer2": true, "enableLayer3": true }, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material new file mode 100644 index 0000000000..9413e35128 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material @@ -0,0 +1,11 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "enableLayer2": false + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material new file mode 100644 index 0000000000..93e0b21780 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material @@ -0,0 +1,11 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "enableLayer3": false + } + } +} \ No newline at end of file From ec9cafcef524b3d71354f6a1eb0900a115114ec3 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 14 May 2021 23:05:33 -0700 Subject: [PATCH 05/14] Improved the displacement property handling to be more cohesive and intuitive. Also fixed a bunch of edge cases. I'm not sure which of these edge cases may have existed before updating the property handling, and which were caused by it. - Rearranged the per-layer parallax property groups because these are more general than just parallax. They can be used for displacement-based blending regardless of whether a parallax effect is being used. -- Renamed "Parallax Mapping" to "Displacement" because these properties can be used for other things besides parallax, in particular the new displacement-based blend modes. -- Removed the unnecessary per-layer "enable parallax" flags. This also allowed me to remove the StandardMultilayerPBR_ParallaxPerLayer.lua script and replace this with simply a UseTexture functor for each layer. -- Made the "offset" property always available, so this can be used to adjust displacement for blending purposes even when there is no heightmap or parallax. The "factor" property still only shows up with a heightmap because its only purpose is to scale the heightmap. -- In order to get the offset to work when there is no texture map, I had to fix the logic a bit in GetLayerDepthValues where it was ignoring the offset. -- Had to rearrange the logic in StandardMultilayerPBR_Displacement.lua a bit to get this all working, particularly because the per-layer displacement properties are no longer hidden behind an enable flag. - Change the displacementBlendFactor to displacementBlendDistance because it felt weird when sliding per-layer displacment offset values and seeing this impact the surface property transition. Using an absolute distance value feels more natural. - Made the displacement blend mask push the displacement down *past* the min displacement value to address edge cases where blend mask 0 didn't actually make a layer disappear. (See GetSubMinDisplacement()). - Inlined the GetBlendWeightsFromLayerDepthValues code into GetBlendWeights because I realized it was only being used there, and the code is easier to read this way IMO. - Displacement-based blend weights weren't being normalized in cases where layerDepthBlendDistance is 0, which caused incorrect depth values where two layers meet. --- .../Types/StandardMultilayerPBR.materialtype | 184 ++++++++--------- .../Types/StandardMultilayerPBR_Common.azsli | 190 +++++++++--------- .../StandardMultilayerPBR_Displacement.lua | 62 +++--- ...StandardMultilayerPBR_ParallaxPerLayer.lua | 49 ----- .../001_ManyFeatures.material | 3 - .../002_ParallaxPdo.material | 2 - .../005_UseDisplacement.material | 5 +- ...th_BlendMaskTexture_AllSameHeight.material | 23 +++ ...ith_BlendMaskTexture_NoHeightmaps.material | 23 +++ 9 files changed, 275 insertions(+), 266 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index 84f7cbe03a..88bd87a494 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -74,8 +74,8 @@ }, { "id": "layer1_parallax", - "displayName": "Layer 1: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." + "displayName": "Layer 1: Displacement", + "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { "id": "layer1_uv", @@ -127,8 +127,8 @@ }, { "id": "layer2_parallax", - "displayName": "Layer 2: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." + "displayName": "Layer 2: Displacement", + "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { "id": "layer2_uv", @@ -180,8 +180,8 @@ }, { "id": "layer3_parallax", - "displayName": "Layer 3: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." + "displayName": "Layer 3: Displacement", + "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { "id": "layer3_uv", @@ -353,17 +353,17 @@ } }, { - "id": "displacementBlendFactor", - "displayName": "Blend Factor", + "id": "displacementBlendDistance", + "displayName": "Blend Distance", "description": "Adjusts how smoothly to transition between layers when displacement blending is enabled.", "type": "Float", "defaultValue": 0.0, "min": 0.0, - "max": 1.0, + "softMax": 0.1, "step": 0.001, "connection": { "type": "ShaderInput", - "id": "m_displacementBlendFactor" + "id": "m_displacementBlendDistance" } } @@ -374,7 +374,11 @@ "displayName": "Enable", "description": "Whether to enable the parallax feature for this material.", "type": "Bool", - "defaultValue": false + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_parallax_feature_enabled" + } }, { "id": "parallaxUv", @@ -1105,27 +1109,38 @@ } ], "layer1_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", + "description": "Displacement texture map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", "id": "m_layer1_m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert the displacement map", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_depthInverted" + } + }, { "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", + "displayName": "Scale", + "description": "The total height of the displacement texture map in local model units.", "type": "Float", "defaultValue": 0.0, "min": 0.0, @@ -1147,17 +1162,6 @@ "type": "ShaderInput", "id": "m_layer1_m_depthOffset" } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_depthInverted" - } } ], "layer1_uv": [ @@ -1811,27 +1815,38 @@ } ], "layer2_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", + "description": "Displacement texture map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", "id": "m_layer2_m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert the displacement map", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_depthInverted" + } + }, { "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", + "displayName": "Scale", + "description": "The total height of the displacement texture map in local model units.", "type": "Float", "defaultValue": 0.0, "min": 0.0, @@ -1853,17 +1868,6 @@ "type": "ShaderInput", "id": "m_layer2_m_depthOffset" } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_depthInverted" - } } ], "layer2_uv": [ @@ -2517,27 +2521,38 @@ } ], "layer3_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", + "description": "Displacement texture map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", "id": "m_layer3_m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert the displacement map", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_depthInverted" + } + }, { "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", + "displayName": "Scale", + "description": "The total height of the displacement texture map in local model units.", "type": "Float", "defaultValue": 0.0, "min": 0.0, @@ -2559,17 +2574,6 @@ "type": "ShaderInput", "id": "m_layer3_m_depthOffset" } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_depthInverted" - } } ], "layer3_uv": [ @@ -2831,12 +2835,12 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" + "textureProperty": "layer1_parallax.textureMap", + "useTextureProperty": "layer1_parallax.useTexture", + "dependentProperties": ["layer1_parallax.factor", "layer1_parallax.invert"], + "shaderOption": "o_layer1_o_useDepthMap" } }, { @@ -2968,12 +2972,12 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" + "textureProperty": "layer2_parallax.textureMap", + "useTextureProperty": "layer2_parallax.useTexture", + "dependentProperties": ["layer2_parallax.factor", "layer2_parallax.invert"], + "shaderOption": "o_layer2_o_useDepthMap" } }, { @@ -3105,14 +3109,14 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" + "textureProperty": "layer3_parallax.textureMap", + "useTextureProperty": "layer3_parallax.useTexture", + "dependentProperties": ["layer3_parallax.factor", "layer3_parallax.invert"], + "shaderOption": "o_layer3_o_useDepthMap" } - }, + }, { // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. "type": "Transform2D", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index f917ae1f91..469426666d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -50,7 +50,10 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial float m_displacementMin; // The lowest displacement value possible from all layers combined (negative values are below the surface) float m_displacementMax; // The highest displacement value possible from all layers combined (negative values are below the surface) - float m_displacementBlendFactor; + // When displacement-based blending is used, this is the height range where the surface properties of different layers will be blended together. + // We use an absolute value rather than a relative factor because disconnecting this property from the influence of other properties makes per-layer + // displacement adjustments feel more natural if they don't impact the blend distance. + float m_displacementBlendDistance; // Auto-generate material SRG fields for common inputs for each layer DEFINE_LAYER_SRG_INPUTS(m_layer1_) @@ -208,64 +211,10 @@ float3 GetApplicableBlendMaskValues(LayerBlendSource blendSource, float2 blendMa return blendSourceValues; } -//! Returns blend weights given the depth values for each layer -//! @param layerDepthValues - the per-layer depth values as provided by GetLayerDepthValues() -//! @param layerDepthBlendFactor - controls how smoothly to blend layers 2 and 3 with the base layer. -//! when layers are close together their weights will be blended together, otherwise the highest layer will have the full weight. -float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues, float layerDepthBlendFactor) +//! When dealing with masks for displacement-based blending, we sometimes need to push the value below the min displacement to make it disappear. +float GetSubMinDisplacement() { - if(!o_layer2_enabled && !o_layer3_enabled) - { - return float3(1,0,0); - } - else - { - // The inputs are depth values, but we change them to height values to make the code a bit more intuitive. - float3 layerHeightValues = -layerDepthValues; - - float highestPoint = layerHeightValues.x; - if(o_layer2_enabled) - { - highestPoint = max(highestPoint, layerHeightValues.y); - } - if(o_layer3_enabled) - { - highestPoint = max(highestPoint, layerHeightValues.z); - } - - float3 blendWeights; - - if(layerDepthBlendFactor > 0.001) - { - float blendDistance = (MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin) * layerDepthBlendFactor; - - // The blend weights are adjusted to give a smooth transition in the surface appearance. - float lowestVisiblePoint = highestPoint - blendDistance; - - blendWeights = saturate(layerHeightValues - lowestVisiblePoint) / blendDistance; - - if(!o_layer2_enabled) - { - blendWeights.y = 0.0; - } - - if(!o_layer3_enabled) - { - blendWeights.z = 0.0; - } - - blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z); - } - else - { - blendWeights = float3(layerHeightValues.x >= highestPoint ? 1.0 : 0.0, - layerHeightValues.y >= highestPoint && o_layer2_enabled ? 1.0 : 0.0, - layerHeightValues.z >= highestPoint && o_layer3_enabled ? 1.0 : 0.0); - } - - return blendWeights; - } - + return MaterialSrg::m_displacementMin - 0.001; } //! Return the final blend weights to be used for rendering, based on the available data and configuration. @@ -273,13 +222,14 @@ float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues, float layerD //! @param blendMaskUv - for sampling a blend mask texture, if that's the blend source //! @param blendMaskVertexColors - the vertex color values to use for the blend mask, if that's the blend source //! @param layerDepthValues - the depth values for each layer, used if the blend source includes displacement. See GetLayerDepthValues(). -//! @param layerDepthBlendFactor - controls how smoothly to blend layers 2 and 3 with the base layer, when the blend source includes displacement. See GetLayerDepthValues(). +//! @param layerDepthBlendDistance - controls how smoothly to blend layers 2 and 3 with the base layer, when the blend source includes displacement. +//! When layers are close together their weights will be blended together, otherwise the highest layer will have the full weight. //! @return The blend weights for each layer. //! Even though layer1 not explicitly specified in the blend mask data, it is explicitly included with the returned values. //! layer1 = r //! layer2 = g //! layer3 = b -float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors, float3 layerDepthValues, float layerDepthBlendFactors) +float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors, float3 layerDepthValues, float layerDepthBlendDistance) { float3 blendWeights; @@ -289,9 +239,54 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource) { + // Calculate the blend weights based on displacement values... // Note that any impact from the blend mask will have already been applied to these layerDepthValues in GetLayerDepthValues(). // So even though there is no blend mask code here, the blend mask is being applied when enabled. - blendWeights = GetBlendWeightsFromLayerDepthValues(layerDepthValues, layerDepthBlendFactors); + + // The inputs are depth values, but we change them to height values to make the code a bit more intuitive. + float3 layerHeightValues = -layerDepthValues; + + float highestPoint = layerHeightValues.x; + if(o_layer2_enabled) + { + highestPoint = max(highestPoint, layerHeightValues.y); + } + if(o_layer3_enabled) + { + highestPoint = max(highestPoint, layerHeightValues.z); + } + + if(layerDepthBlendDistance > 0.0001) + { + + // The blend weights are adjusted to give a smooth transition in the surface appearance. + // We clamp to just under m_displacementMin to prevents areas that have been masked to 0 from affecting + // the blend (because these areas get pushed *below* m_displacementMin a bit in GetLayerDepthValues() too). + float lowestVisiblePoint = max(highestPoint - layerDepthBlendDistance, GetSubMinDisplacement()); + blendWeights = saturate(layerHeightValues - lowestVisiblePoint) / layerDepthBlendDistance; + + if(!o_layer2_enabled) + { + blendWeights.y = 0.0; + } + + if(!o_layer3_enabled) + { + blendWeights.z = 0.0; + } + } + else + { + blendWeights = float3(layerHeightValues.x >= highestPoint ? 1.0 : 0.0, + layerHeightValues.y >= highestPoint && o_layer2_enabled ? 1.0 : 0.0, + layerHeightValues.z >= highestPoint && o_layer3_enabled ? 1.0 : 0.0); + } + + float weightSum = blendWeights.x + blendWeights.y + blendWeights.z; + if(weightSum > 0.0) + { + blendWeights = saturate(blendWeights / weightSum); + } } else { @@ -333,7 +328,7 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 uv, float3 blendMask layerDepthValues = GetLayerDepthValues(blendSource, uv, ddx_fine(uv), ddy_fine(uv), blendMaskVertexColors); } - return GetBlendWeights(blendSource, uv, blendMaskVertexColors, layerDepthValues, MaterialSrg::m_displacementBlendFactor); + return GetBlendWeights(blendSource, uv, blendMaskVertexColors, layerDepthValues, MaterialSrg::m_displacementBlendDistance); } float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeights) @@ -371,47 +366,55 @@ float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_dd { float3 layerDepthValues = float3(0,0,0); - bool useLayer1 = true; - bool useLayer2 = (o_layer2_enabled && o_layer2_o_useDepthMap); - bool useLayer3 = (o_layer3_enabled && o_layer3_o_useDepthMap); - - if(useLayer1) + // layer1 { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) + if(o_layer1_o_useDepthMap) { - layerUv = mul(MaterialSrg::m_layer1_m_uvMatrix, float3(uv, 1.0)).xy; + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer1_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.r = SampleDepthOrHeightMap(MaterialSrg::m_layer1_m_depthInverted, MaterialSrg::m_layer1_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.r *= MaterialSrg::m_layer1_m_depthFactor; } - layerDepthValues.r = SampleDepthOrHeightMap(MaterialSrg::m_layer1_m_depthInverted, MaterialSrg::m_layer1_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.r *= MaterialSrg::m_layer1_m_depthFactor; layerDepthValues.r -= MaterialSrg::m_layer1_m_depthOffset; } - if(useLayer2) + if(o_layer2_enabled) { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) + if(o_layer2_o_useDepthMap) { - layerUv = mul(MaterialSrg::m_layer2_m_uvMatrix, float3(uv, 1.0)).xy; + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer2_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor; } - layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor; layerDepthValues.g -= MaterialSrg::m_layer2_m_depthOffset; } - if(useLayer3) + if(o_layer3_enabled) { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) + if(o_layer3_o_useDepthMap) { - layerUv = mul(MaterialSrg::m_layer3_m_uvMatrix, float3(uv, 1.0)).xy; + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer3_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; } - layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; layerDepthValues.b -= MaterialSrg::m_layer3_m_depthOffset; } @@ -420,7 +423,7 @@ float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_dd LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource; - if(useBlendMask && (useLayer2 || useLayer3)) + if(useBlendMask && (o_layer2_enabled || o_layer3_enabled)) { // We use the blend mask to lower each layer's surface so that it disappears under the other surfaces. // Note the blend mask does not apply to the first layer, it is the implicit base layer. Layers 2 and 3 are masked by the r and g channels. @@ -429,17 +432,18 @@ float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_dd // We add to the depth value rather than lerp toward m_displacementMin to avoid squashing the topology, but instead lower it out of sight. - // We might want to consider other approaches to the blend mask factors. They way they work now allows the user to lower + // Regarding GetSubMinDisplacement(), when a mask of 0 pushes the surface all the way to the bottom, we want that + // to go a little below the min so it will disappear if there is something else right at the min. - if(useLayer2) + if(o_layer2_enabled) { - float dropoffRange = MaterialSrg::m_layer2_m_depthOffset - MaterialSrg::m_displacementMin; + float dropoffRange = MaterialSrg::m_layer2_m_depthOffset - GetSubMinDisplacement(); layerDepthValues.g += dropoffRange * (1-blendMaskValues.r); } - if(useLayer3) + if(o_layer3_enabled) { - float dropoffRange = MaterialSrg::m_layer3_m_depthOffset - MaterialSrg::m_displacementMin; + float dropoffRange = MaterialSrg::m_layer3_m_depthOffset - GetSubMinDisplacement(); layerDepthValues.b += dropoffRange * (1-blendMaskValues.g); } } @@ -455,15 +459,15 @@ DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) float3 layerDepthValues = GetLayerDepthValues(blendSource, uv, uv_ddx, uv_ddy, s_blendMaskFromVertexStream); - // When blending the depth together, we don't use MaterialSrg::m_displacementBlendFactor. The intention is that m_displacementBlendFactor + // When blending the depth together, we don't use MaterialSrg::m_displacementBlendDistance. The intention is that m_displacementBlendDistance // is for transitioning the appearance of the surface itself, but we still want a distinct change in the heightmap. If someday we want to // support smoothly blending the depth as well, there is a bit more work to do to get it to play nice with the blend mask code in GetLayerDepthValues(). - float layerDepthBlendFactor = 0.0f; + float layerDepthBlendDistance = 0.0f; // Note, when the blend source uses the blend mask from the vertex colors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be as noticeable if // you have a small depth factor relative to the size of the blend transition. - float3 blendWeightValues = GetBlendWeights(blendSource, uv, s_blendMaskFromVertexStream, layerDepthValues, layerDepthBlendFactor); + float3 blendWeightValues = GetBlendWeights(blendSource, uv, s_blendMaskFromVertexStream, layerDepthValues, layerDepthBlendDistance); float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); return DepthResultAbsolute(depth); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index fda7e20f4d..897bcdc116 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -17,23 +17,24 @@ function GetMaterialPropertyDependencies() return { "blend.blendSource", + "blend.enableLayer2", + "blend.enableLayer3", "parallax.enable", - "layer1_parallax.enable", - "layer2_parallax.enable", - "layer3_parallax.enable", + "layer1_parallax.textureMap", + "layer2_parallax.textureMap", + "layer3_parallax.textureMap", + "layer1_parallax.useTexture", + "layer2_parallax.useTexture", + "layer3_parallax.useTexture", "layer1_parallax.factor", "layer2_parallax.factor", "layer3_parallax.factor", "layer1_parallax.offset", "layer2_parallax.offset", - "layer3_parallax.offset" + "layer3_parallax.offset" } end -function GetShaderOptionDependencies() - return {"o_parallax_feature_enabled"} -end - function GetMergedHeightRange(heightMinMax, offset, factor) top = offset bottom = offset - factor @@ -61,39 +62,50 @@ LayerBlendSource_Displacement_With_BlendMaskVertexColors = 4 function BlendSourceUsesDisplacement(context) local blendSource = context:GetMaterialPropertyValue_enum("blend.blendSource") local blendSourceIncludesDisplacement = (blendSource == LayerBlendSource_Displacement or - blendSource ==LayerBlendSource_Displacement_With_BlendMaskTexture or + blendSource == LayerBlendSource_Displacement_With_BlendMaskTexture or blendSource == LayerBlendSource_Displacement_With_BlendMaskVertexColors) return blendSourceIncludesDisplacement end function Process(context) local enableParallax = context:GetMaterialPropertyValue_bool("parallax.enable") - local enable1 = context:GetMaterialPropertyValue_bool("layer1_parallax.enable") - local enable2 = context:GetMaterialPropertyValue_bool("layer2_parallax.enable") - local enable3 = context:GetMaterialPropertyValue_bool("layer3_parallax.enable") - enableParallax = enableParallax and (enable1 or enable2 or enable3) - context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enableParallax) if(enableParallax or BlendSourceUsesDisplacement(context)) then + local hasTextureLayer1 = nil ~= context:GetMaterialPropertyValue_Image("layer1_parallax.textureMap") + local hasTextureLayer2 = nil ~= context:GetMaterialPropertyValue_Image("layer2_parallax.textureMap") + local hasTextureLayer3 = nil ~= context:GetMaterialPropertyValue_Image("layer3_parallax.textureMap") + + local useTextureLayer1 = context:GetMaterialPropertyValue_bool("layer1_parallax.useTexture") + local useTextureLayer2 = context:GetMaterialPropertyValue_bool("layer2_parallax.useTexture") + local useTextureLayer3 = context:GetMaterialPropertyValue_bool("layer3_parallax.useTexture") + local factorLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.factor") local factorLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.factor") local factorLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.factor") + if not hasTextureLayer1 or not useTextureLayer1 then factorLayer1 = 0 end + if not hasTextureLayer2 or not useTextureLayer2 then factorLayer2 = 0 end + if not hasTextureLayer3 or not useTextureLayer3 then factorLayer3 = 0 end + local offsetLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.offset") local offsetLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.offset") local offsetLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.offset") + + local enableLayer2 = context:GetMaterialPropertyValue_bool("blend.enableLayer2") + local enableLayer3 = context:GetMaterialPropertyValue_bool("blend.enableLayer3") local heightMinMax = {nil, nil} - if(enable1) then GetMergedHeightRange(heightMinMax, offsetLayer1, factorLayer1) end - if(enable2) then GetMergedHeightRange(heightMinMax, offsetLayer2, factorLayer2) end - if(enable3) then GetMergedHeightRange(heightMinMax, offsetLayer3, factorLayer3) end - if(heightMinMax[1] - heightMinMax[0] < 0.0001) then - context:SetShaderOptionValue_bool("o_parallax_feature_enabled", false) - else - context:SetShaderConstant_float("m_displacementMin", heightMinMax[0]) - context:SetShaderConstant_float("m_displacementMax", heightMinMax[1]) - end + GetMergedHeightRange(heightMinMax, offsetLayer1, factorLayer1) + + if(enableLayer2) then GetMergedHeightRange(heightMinMax, offsetLayer2, factorLayer2) end + if(enableLayer3) then GetMergedHeightRange(heightMinMax, offsetLayer3, factorLayer3) end + + context:SetShaderConstant_float("m_displacementMin", heightMinMax[0]) + context:SetShaderConstant_float("m_displacementMax", heightMinMax[1]) + else + context:SetShaderConstant_float("m_displacementMin", 0) + context:SetShaderConstant_float("m_displacementMax", 0) end end @@ -112,9 +124,9 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("parallax.showClipping", visibility) if BlendSourceUsesDisplacement(context) then - context:SetMaterialPropertyVisibility("blend.displacementBlendFactor", MaterialPropertyVisibility_Enabled) + context:SetMaterialPropertyVisibility("blend.displacementBlendDistance", MaterialPropertyVisibility_Enabled) else - context:SetMaterialPropertyVisibility("blend.displacementBlendFactor", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("blend.displacementBlendDistance", MaterialPropertyVisibility_Hidden) end end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua deleted file mode 100644 index bd56292229..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua +++ /dev/null @@ -1,49 +0,0 @@ --------------------------------------------------------------------------------------- --- --- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or --- its licensors. --- --- For complete copyright and license terms please see the LICENSE at the root of this --- distribution (the "License"). All use of this software is governed by the License, --- or, if provided, by the license below or the license accompanying this file. Do not --- remove or modify any license notices. This file is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- --- ----------------------------------------------------------------------------------------------------- - --- This functor handles parallax properties that are specific to a single layer. - -function GetMaterialPropertyDependencies() - return {"parallax.enable", "parallax.textureMap"} -end - -function GetShaderOptionDependencies() - return {"o_useDepthMap"} -end - -function Process(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") - context:SetShaderOptionValue_bool("o_useDepthMap", enable and textureMap ~= nil) -end - -function ProcessEditor(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - - if enable then - context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Enabled) - else - context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Hidden) - end - - local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") - local visibility = MaterialPropertyVisibility_Enabled - if(not enable or textureMap == nil) then - visibility = MaterialPropertyVisibility_Hidden - end - - context:SetMaterialPropertyVisibility("parallax.factor", visibility) - context:SetMaterialPropertyVisibility("parallax.offset", visibility) - context:SetMaterialPropertyVisibility("parallax.invert", visibility) -end diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index d9a4aabe2a..17353a0603 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -36,7 +36,6 @@ "diffuseTextureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, "layer1_parallax": { - "enable": true, "factor": 0.02500000037252903, "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, @@ -80,7 +79,6 @@ "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" }, "layer2_parallax": { - "enable": true, "factor": 0.01600000075995922, "textureMap": "TestData/Textures/cc0/Lava004_1K_Displacement.jpg" }, @@ -118,7 +116,6 @@ "diffuseTextureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" }, "layer3_parallax": { - "enable": true, "factor": 0.004999999888241291, "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" }, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material index 0bf4177db9..8cddab24bc 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material @@ -15,7 +15,6 @@ "textureMap": "TestData/Textures/cc0/bark1_norm.jpg" }, "layer1_parallax": { - "enable": true, "factor": 0.03999999910593033, "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, @@ -32,7 +31,6 @@ "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" }, "layer2_parallax": { - "enable": true, "factor": 0.05299999937415123, "offset": -0.024000000208616258, "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material index 87005ec41c..cf4c6cb531 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -6,7 +6,7 @@ "properties": { "blend": { "blendSource": "Displacement", - "displacementBlendFactor": 0.10000000149011612, + "displacementBlendDistance": 0.003, "enableLayer2": true, "enableLayer3": true }, @@ -20,7 +20,6 @@ "diffuseTextureMap": "TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg" }, "layer1_parallax": { - "enable": true, "factor": 0.017000000923871995, "offset": -0.009999999776482582, "textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg" @@ -38,7 +37,6 @@ "diffuseTextureMap": "TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg" }, "layer2_parallax": { - "enable": true, "factor": 0.03099999949336052, "offset": 0.0020000000949949028, "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" @@ -62,7 +60,6 @@ "textureMap": "TestData/Textures/cc0/Rocks002_1K_Normal.jpg" }, "layer3_parallax": { - "enable": true, "factor": 0.027000000700354577, "textureMap": "TestData/Textures/cc0/Rocks002_1K_Displacement.jpg" }, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material new file mode 100644 index 0000000000..c99b600dbd --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material @@ -0,0 +1,23 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "displacementBlendDistance": 0.0 + }, + "layer1_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + }, + "layer2_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + }, + "layer3_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material new file mode 100644 index 0000000000..6d6d952698 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material @@ -0,0 +1,23 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "displacementBlendDistance": 0.00279999990016222 + }, + "layer1_parallax": { + "offset": -0.03200000151991844, + "textureMap": "" + }, + "layer2_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + }, + "layer3_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + } + } +} \ No newline at end of file From 2983225b4dcc68875ed8d768deb4da0177e63b9b Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 14 May 2021 23:11:36 -0700 Subject: [PATCH 06/14] Removed .orig files that I accidentally added. --- .../StandardMultilayerPBR.materialtype.orig | 3126 ----------------- .../StandardMultilayerPBR_Common.azsli.orig | 401 --- ...rdMultilayerPBR_DepthPass_WithPS.azsl.orig | 132 - .../StandardMultilayerPBR_Displacement.lua | 1 + ...tandardMultilayerPBR_ForwardPass.azsl.orig | 710 ---- ...rdMultilayerPBR_Shadowmap_WithPS.azsl.orig | 131 - 6 files changed, 1 insertion(+), 4500 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig deleted file mode 100644 index d185eecddf..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype.orig +++ /dev/null @@ -1,3126 +0,0 @@ -{ - "description": "Similar to StandardPBR but supports multiple layers blended together.", - "propertyLayout": { - "version": 3, - "groups": [ - { - "id": "general", - "displayName": "General", - "description": "General settings." - }, - { - "id": "blend", - "displayName": "Blend Settings", - "description": "Properties for configuring how layers are blended together." - }, - { - "id": "parallax", - "displayName": "Parallax Settings", - "description": "Properties for configuring the parallax effect, applied to all layers." - }, - { - "id": "uv", - "displayName": "UVs", - "description": "Properties for configuring UV transforms for the entire material, including the blend masks." - }, - { - // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader - "id": "irradiance", - "displayName": "Irradiance", - "description": "Properties for configuring the irradiance used in global illumination." - }, - //############################################################################################## - // Layer 1 Groups - //############################################################################################## - { - "id": "layer1_baseColor", - "displayName": "Layer 1: Base Color", - "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." - }, - { - "id": "layer1_metallic", - "displayName": "Layer 1: Metallic", - "description": "Properties for configuring whether the surface is metallic or not." - }, - { - "id": "layer1_roughness", - "displayName": "Layer 1: Roughness", - "description": "Properties for configuring how rough the surface appears." - }, - { - "id": "layer1_specularF0", - "displayName": "Layer 1: Specular Reflectance f0", - "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." - }, - { - "id": "layer1_normal", - "displayName": "Layer 1: Normal", - "description": "Properties related to configuring surface normal." - }, - { - "id": "layer1_clearCoat", - "displayName": "Layer 1: Clear Coat", - "description": "Properties for configuring gloss clear coat" - }, - { - "id": "layer1_occlusion", - "displayName": "Layer 1: Occlusion", - "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." - }, - { - "id": "layer1_emissive", - "displayName": "Layer 1: Emissive", - "description": "Properties to add light emission, independent of other lights in the scene." - }, - { - "id": "layer1_parallax", - "displayName": "Layer 1: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." - }, - { - "id": "layer1_uv", - "displayName": "Layer 1: UVs", - "description": "Properties for configuring UV transforms." - }, - //############################################################################################## - // Layer 2 Groups - //############################################################################################## - { - "id": "layer2_baseColor", - "displayName": "Layer 2: Base Color", - "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." - }, - { - "id": "layer2_metallic", - "displayName": "Layer 2: Metallic", - "description": "Properties for configuring whether the surface is metallic or not." - }, - { - "id": "layer2_roughness", - "displayName": "Layer 2: Roughness", - "description": "Properties for configuring how rough the surface appears." - }, - { - "id": "layer2_specularF0", - "displayName": "Layer 2: Specular Reflectance f0", - "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." - }, - { - "id": "layer2_normal", - "displayName": "Layer 2: Normal", - "description": "Properties related to configuring surface normal." - }, - { - "id": "layer2_clearCoat", - "displayName": "Layer 2: Clear Coat", - "description": "Properties for configuring gloss clear coat" - }, - { - "id": "layer2_occlusion", - "displayName": "Layer 2: Occlusion", - "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." - }, - { - "id": "layer2_emissive", - "displayName": "Layer 2: Emissive", - "description": "Properties to add light emission, independent of other lights in the scene." - }, - { - "id": "layer2_parallax", - "displayName": "Layer 2: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." - }, - { - "id": "layer2_uv", - "displayName": "Layer 2: UVs", - "description": "Properties for configuring UV transforms." - }, - //############################################################################################## - // Layer 3 Groups - //############################################################################################## - { - "id": "layer3_baseColor", - "displayName": "Layer 3: Base Color", - "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." - }, - { - "id": "layer3_metallic", - "displayName": "Layer 3: Metallic", - "description": "Properties for configuring whether the surface is metallic or not." - }, - { - "id": "layer3_roughness", - "displayName": "Layer 3: Roughness", - "description": "Properties for configuring how rough the surface appears." - }, - { - "id": "layer3_specularF0", - "displayName": "Layer 3: Specular Reflectance f0", - "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." - }, - { - "id": "layer3_normal", - "displayName": "Layer 3: Normal", - "description": "Properties related to configuring surface normal." - }, - { - "id": "layer3_clearCoat", - "displayName": "Layer 3: Clear Coat", - "description": "Properties for configuring gloss clear coat" - }, - { - "id": "layer3_occlusion", - "displayName": "Layer 3: Occlusion", - "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." - }, - { - "id": "layer3_emissive", - "displayName": "Layer 3: Emissive", - "description": "Properties to add light emission, independent of other lights in the scene." - }, - { - "id": "layer3_parallax", - "displayName": "Layer 3: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." - }, - { - "id": "layer3_uv", - "displayName": "Layer 3: UVs", - "description": "Properties for configuring UV transforms." - } - ], - "properties": { - //############################################################################################## - // General Properties - //############################################################################################## - "general": [ - { - "id": "debugDrawMode", - "displayName": "Debug Draw Mode", - "description": "Enables various debug view features.", - "type": "Enum", -<<<<<<< HEAD - "enumValues": [ "None", "BlendSource", "DepthMaps" ], -======= - "enumValues": [ "None", "BlendWeights", "DisplacementMaps" ], ->>>>>>> Atom/santorac/MultilayerPbrImprovements - "defaultValue": "None", - "connection": { - "type": "ShaderOption", - "id": "o_debugDrawMode" - } - }, - { - "id": "applySpecularAA", - "displayName": "Apply Specular AA", - "description": "Whether to apply specular anti-aliasing in the shader.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_applySpecularAA" - } - }, - { - "id": "enableMultiScatterCompensation", - "displayName": "Multiscattering Compensation", - "description": "Whether to enable multiple scattering compensation.", - "type": "Bool", - "connection": { - "type": "ShaderOption", - "id": "o_specularF0_enableMultiScatterCompensation" - } - }, - { - "id": "enableShadows", - "displayName": "Enable Shadows", - "description": "Whether to use the shadow maps.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "id": "o_enableShadows" - } - }, - { - "id": "enableDirectionalLights", - "displayName": "Enable Directional Lights", - "description": "Whether to use directional lights.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "id": "o_enableDirectionalLights" - } - }, - { - "id": "enablePunctualLights", - "displayName": "Enable Punctual Lights", - "description": "Whether to use punctual lights.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "id": "o_enablePunctualLights" - } - }, - { - "id": "enableAreaLights", - "displayName": "Enable Area Lights", - "description": "Whether to use area lights.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "id": "o_enableAreaLights" - } - }, - { - "id": "enableIBL", - "displayName": "Enable IBL", - "description": "Whether to use Image Based Lighting (IBL).", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "id": "o_enableIBL" - } - }, - { - "id": "forwardPassIBLSpecular", - "displayName": "Forward Pass IBL Specular", - "description": "Whether to apply IBL specular in the forward pass.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_materialUseForwardPassIBLSpecular" - } - } - ], - "blend": [ - { - "id": "enableLayer2", - "displayName": "Enable Layer 2", - "description": "Whether to enable layer 2.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_layer2_enabled" - } - }, - { - "id": "enableLayer3", - "displayName": "Enable Layer 3", - "description": "Whether to enable layer 3.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_layer3_enabled" - } - }, - { - "id": "blendSource", - "displayName": "Blend Source", - "description": "The source to use for defining the blend mask. Note VertexColors mode will still use the texture as a fallback if the mesh does not have a COLOR0 stream.", - "type": "Enum", - "enumValues": ["TextureMap", "VertexColors", "Displacement"], - "defaultValue": "TextureMap", - "connection": { - "type": "ShaderOption", - "id": "o_layerBlendSource" - } - }, - { - "id": "textureMap", - "displayName": "Blend Mask", - "description": "RGB image where each channel is the blend mask for one of the three available layers.", - "type": "Image", - "defaultValue": "Textures/DefaultBlendMask_layers.png", - "connection": { - "type": "ShaderInput", - "id": "m_blendMaskTexture" - } - }, - { - "id": "textureMapUv", - "displayName": "Blend Mask UV", - "description": "Blend Mask UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_blendMaskUvIndex" - } - } - ], - "parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature for this material.", - "type": "Bool", - "defaultValue": false - }, - { - "id": "parallaxUv", - "displayName": "UV", - "description": "UV set that supports parallax mapping.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_parallaxUvIndex" - } - }, - { - "id": "algorithm", - "displayName": "Algorithm", - "description": "Select the algorithm to use for parallax mapping.", - "type": "Enum", - "enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ], - "defaultValue": "POM", - "connection": { - "type": "ShaderOption", - "id": "o_parallax_algorithm" - } - }, - { - "id": "quality", - "displayName": "Quality", - "description": "Quality of parallax mapping.", - "type": "Enum", - "enumValues": [ "Low", "Medium", "High", "Ultra" ], - "defaultValue": "Medium", - "connection": { - "type": "ShaderOption", - "id": "o_parallax_quality" - } - }, - { - "id": "pdo", - "displayName": "Pixel Depth Offset", - "description": "Whether to enable the pixel depth offset feature.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_parallax_enablePixelDepthOffset" - } - }, - { - "id": "showClipping", - "displayName": "Show Clipping", - "description": "Highlight areas where the heightmap is clipped by the mesh surface.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_parallax_highlightClipping" - } - } - ], - "uv": [ - { - "id": "center", - "displayName": "Center", - "description": "Center point for scaling and rotation transformations.", - "type": "vector2", - "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] - }, - { - "id": "tileU", - "displayName": "Tile U", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "tileV", - "displayName": "Tile V", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "offsetU", - "displayName": "Offset U", - "description": "Offsets texture coordinates in the U direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "offsetV", - "displayName": "Offset V", - "description": "Offsets texture coordinates in the V direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "rotateDegrees", - "displayName": "Rotate", - "description": "Rotates the texture coordinates (degrees).", - "type": "float", - "defaultValue": 0.0, - "min": -180.0, - "max": 180.0, - "step": 1.0 - }, - { - "id": "scale", - "displayName": "Scale", - "description": "Scales texture coordinates in both U and V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - } - ], - "irradiance": [ - // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader - { - "id": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ] - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0 - } - ], - //############################################################################################## - // Layer 1 Properties - //############################################################################################## - "layer1_baseColor": [ - { - "id": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_baseColor" - } - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_baseColorFactor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Base color texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_baseColorMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Base color texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_baseColorMapUvIndex" - } - }, - { - "id": "textureBlendMode", - "displayName": "Texture Blend Mode", - "description": "Selects the equation to use when combining Color, Factor, and Texture Map.", - "type": "Enum", - "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], - "defaultValue": "Multiply", - "connection": { - "type": "ShaderOption", - "id": "o_layer1_o_baseColorTextureBlendMode" - } - } - ], - "layer1_metallic": [ - { - "id": "factor", - "displayName": "Factor", - "description": "This value is linear, black is non-metal and white means raw metal.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_metallicFactor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_metallicMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Metallic texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_metallicMapUvIndex" - } - } - ], - "layer1_roughness": [ - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface roughness.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_roughnessMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Roughness texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_roughnessMapUvIndex" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", - "displayName": "Lower Bound", - "description": "The roughness value that corresponds to black in the texture map.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_roughnessLowerBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", - "displayName": "Upper Bound", - "description": "The roughness value that corresponds to white in the texture map.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_roughnessUpperBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", - "displayName": "Factor", - "description": "Controls the roughness value", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_roughnessFactor" - } - } - ], - "layer1_specularF0": [ - { - "id": "factor", - "displayName": "Factor", - "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", - "type": "Float", - "defaultValue": 0.5, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_specularF0Factor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface reflectance.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_specularF0Map" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Specular reflection texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_specularF0MapUvIndex" - } - } - ], - "layer1_normal": [ - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface normal direction.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_normalMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just rely on vertex normals.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Normal texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_normalMapUvIndex" - } - }, - { - "id": "flipX", - "displayName": "Flip X Channel", - "description": "Flip tangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_flipNormalX" - } - }, - { - "id": "flipY", - "displayName": "Flip Y Channel", - "description": "Flip bitangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_flipNormalY" - } - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_normalFactor" - } - } - ], - "layer1_clearCoat": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Enable clear coat", - "type": "Bool", - "defaultValue": false - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the percentage of effect applied", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatFactor" - } - }, - { - "id": "influenceMap", - "displayName": " Influence Map", - "description": "Strength factor texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatInfluenceMap" - } - }, - { - "id": "useInfluenceMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "influenceMapUv", - "displayName": " UV", - "description": "Strength factor texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatInfluenceMapUvIndex" - } - }, - { - "id": "roughness", - "displayName": "Roughness", - "description": "Clear coat layer roughness", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatRoughness" - } - }, - { - "id": "roughnessMap", - "displayName": " Roughness Map", - "description": "Roughness texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatRoughnessMap" - } - }, - { - "id": "useRoughnessMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the roughness value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "roughnessMapUv", - "displayName": " UV", - "description": "Roughness texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatRoughnessMapUvIndex" - } - }, - { - "id": "normalStrength", - "displayName": "Normal Strength", - "description": "Scales the impact of the clear coat normal map", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatNormalStrength" - } - }, - { - "id": "normalMap", - "displayName": "Normal Map", - "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatNormalMap" - } - }, - { - "id": "useNormalMap", - "displayName": " Use Texture", - "description": "Whether to use the normal map", - "type": "Bool", - "defaultValue": true - }, - { - "id": "normalMapUv", - "displayName": " UV", - "description": "Normal texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_clearCoatNormalMapUvIndex" - } - } - ], - "layer1_occlusion": [ - { - "id": "diffuseTextureMap", - "displayName": "Diffuse AO", - "description": "Texture map for defining occlusion area for diffuse ambient lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_diffuseOcclusionMap" - } - }, - { - "id": "diffuseUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Diffuse AO texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "diffuseTextureMapUv", - "displayName": " UV", - "description": "Diffuse AO texture map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_diffuseOcclusionMapUvIndex" - } - }, - { - "id": "diffuseFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Diffuse AO", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_diffuseOcclusionFactor" - } - }, - { - "id": "specularTextureMap", - "displayName": "Specular Cavity", - "description": "Texture map for defining occlusion area for specular lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_specularOcclusionMap" - } - }, - { - "id": "specularUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Specular Cavity texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "specularTextureMapUv", - "displayName": " UV", - "description": "Specular Cavity texture map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_specularOcclusionMapUvIndex" - } - }, - { - "id": "specularFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Specular Cavity", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_specularOcclusionFactor" - } - } - ], - "layer1_emissive": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Enable the emissive group", - "type": "Bool", - "defaultValue": false - }, - { - "id": "unit", - "displayName": "Units", - "description": "The photometric units of the Intensity property.", - "type": "Enum", - "enumValues": ["Ev100"], - "defaultValue": "Ev100" - }, - { - "id": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_emissiveColor" - } - }, - { - "id": "intensity", - "displayName": "Intensity", - "description": "The amount of energy emitted.", - "type": "Float", - "defaultValue": 4, - "min": -10, - "max": 20, - "softMin": -6, - "softMax": 16 - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining emissive area.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_emissiveMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Emissive texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_emissiveMapUvIndex" - } - } - ], - "layer1_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_depthMap" - } - }, - { - "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_depthFactor" - } - }, - { - "id": "offset", - "displayName": "Offset", - "description": "Adjusts the overall displacement amount in local model units.", - "type": "Float", - "defaultValue": 0.0, - "softMin": -0.1, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_depthOffset" - } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_depthInverted" - } - } - ], - "layer1_uv": [ - { - "id": "center", - "displayName": "Center", - "description": "Center point for scaling and rotation transformations.", - "type": "vector2", - "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] - }, - { - "id": "tileU", - "displayName": "Tile U", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "tileV", - "displayName": "Tile V", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "offsetU", - "displayName": "Offset U", - "description": "Offsets texture coordinates in the U direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "offsetV", - "displayName": "Offset V", - "description": "Offsets texture coordinates in the V direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "rotateDegrees", - "displayName": "Rotate", - "description": "Rotates the texture coordinates (degrees).", - "type": "float", - "defaultValue": 0.0, - "min": -180.0, - "max": 180.0, - "step": 1.0 - }, - { - "id": "scale", - "displayName": "Scale", - "description": "Scales texture coordinates in both U and V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - } - ], - //############################################################################################## - // Layer 2 Properties - //############################################################################################## - "layer2_baseColor": [ - { - "id": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_baseColor" - } - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_baseColorFactor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Base color texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_baseColorMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Base color texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_baseColorMapUvIndex" - } - }, - { - "id": "textureBlendMode", - "displayName": "Texture Blend Mode", - "description": "Selects the equation to use when combining Color, Factor, and Texture Map.", - "type": "Enum", - "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], - "defaultValue": "Multiply", - "connection": { - "type": "ShaderOption", - "id": "o_layer2_o_baseColorTextureBlendMode" - } - } - ], - "layer2_metallic": [ - { - "id": "factor", - "displayName": "Factor", - "description": "This value is linear, black is non-metal and white means raw metal.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_metallicFactor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_metallicMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Metallic texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_metallicMapUvIndex" - } - } - ], - "layer2_roughness": [ - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface roughness.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_roughnessMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Roughness texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_roughnessMapUvIndex" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", - "displayName": "Lower Bound", - "description": "The roughness value that corresponds to black in the texture map.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_roughnessLowerBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", - "displayName": "Upper Bound", - "description": "The roughness value that corresponds to white in the texture map.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_roughnessUpperBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", - "displayName": "Factor", - "description": "Controls the roughness value", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_roughnessFactor" - } - } - ], - "layer2_specularF0": [ - { - "id": "factor", - "displayName": "Factor", - "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", - "type": "Float", - "defaultValue": 0.5, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_specularF0Factor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface reflectance.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_specularF0Map" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Specular reflection texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_specularF0MapUvIndex" - } - } - ], - "layer2_normal": [ - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface normal direction.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_normalMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just rely on vertex normals.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Normal texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_normalMapUvIndex" - } - }, - { - "id": "flipX", - "displayName": "Flip X Channel", - "description": "Flip tangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_flipNormalX" - } - }, - { - "id": "flipY", - "displayName": "Flip Y Channel", - "description": "Flip bitangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_flipNormalY" - } - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_normalFactor" - } - } - ], - "layer2_clearCoat": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Enable clear coat", - "type": "Bool", - "defaultValue": false - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the percentage of effect applied", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatFactor" - } - }, - { - "id": "influenceMap", - "displayName": " Influence Map", - "description": "Strength factor texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatInfluenceMap" - } - }, - { - "id": "useInfluenceMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "influenceMapUv", - "displayName": " UV", - "description": "Strength factor texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatInfluenceMapUvIndex" - } - }, - { - "id": "roughness", - "displayName": "Roughness", - "description": "Clear coat layer roughness", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatRoughness" - } - }, - { - "id": "roughnessMap", - "displayName": " Roughness Map", - "description": "Roughness texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatRoughnessMap" - } - }, - { - "id": "useRoughnessMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the roughness value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "roughnessMapUv", - "displayName": " UV", - "description": "Roughness texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatRoughnessMapUvIndex" - } - }, - { - "id": "normalStrength", - "displayName": "Normal Strength", - "description": "Scales the impact of the clear coat normal map", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatNormalStrength" - } - }, - { - "id": "normalMap", - "displayName": "Normal Map", - "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatNormalMap" - } - }, - { - "id": "useNormalMap", - "displayName": " Use Texture", - "description": "Whether to use the normal map", - "type": "Bool", - "defaultValue": true - }, - { - "id": "normalMapUv", - "displayName": " UV", - "description": "Normal texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_clearCoatNormalMapUvIndex" - } - } - ], - "layer2_occlusion": [ - { - "id": "diffuseTextureMap", - "displayName": "Diffuse AO", - "description": "Texture map for defining occlusion area for diffuse ambient lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_diffuseOcclusionMap" - } - }, - { - "id": "diffuseUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Diffuse AO texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "diffuseTextureMapUv", - "displayName": " UV", - "description": "Diffuse AO texture map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_diffuseOcclusionMapUvIndex" - } - }, - { - "id": "diffuseFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Diffuse AO", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_diffuseOcclusionFactor" - } - }, - { - "id": "specularTextureMap", - "displayName": "Specular Cavity", - "description": "Texture map for defining occlusion area for specular lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_specularOcclusionMap" - } - }, - { - "id": "specularUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Specular Cavity texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "specularTextureMapUv", - "displayName": " UV", - "description": "Specular Cavity texture map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_specularOcclusionMapUvIndex" - } - }, - { - "id": "specularFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Specular Cavity", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_specularOcclusionFactor" - } - } - ], - "layer2_emissive": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Enable the emissive group", - "type": "Bool", - "defaultValue": false - }, - { - "id": "unit", - "displayName": "Units", - "description": "The photometric units of the Intensity property.", - "type": "Enum", - "enumValues": ["Ev100"], - "defaultValue": "Ev100" - }, - { - "id": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_emissiveColor" - } - }, - { - "id": "intensity", - "displayName": "Intensity", - "description": "The amount of energy emitted.", - "type": "Float", - "defaultValue": 4, - "min": -10, - "max": 20, - "softMin": -6, - "softMax": 16 - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining emissive area.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_emissiveMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Emissive texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_emissiveMapUvIndex" - } - } - ], - "layer2_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_depthMap" - } - }, - { - "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_depthFactor" - } - }, - { - "id": "offset", - "displayName": "Offset", - "description": "Adjusts the overall displacement amount in local model units.", - "type": "Float", - "defaultValue": 0.0, - "softMin": -0.1, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_depthOffset" - } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_depthInverted" - } - } - ], - "layer2_uv": [ - { - "id": "center", - "displayName": "Center", - "description": "Center point for scaling and rotation transformations.", - "type": "vector2", - "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] - }, - { - "id": "tileU", - "displayName": "Tile U", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "tileV", - "displayName": "Tile V", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "offsetU", - "displayName": "Offset U", - "description": "Offsets texture coordinates in the U direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "offsetV", - "displayName": "Offset V", - "description": "Offsets texture coordinates in the V direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "rotateDegrees", - "displayName": "Rotate", - "description": "Rotates the texture coordinates (degrees).", - "type": "float", - "defaultValue": 0.0, - "min": -180.0, - "max": 180.0, - "step": 1.0 - }, - { - "id": "scale", - "displayName": "Scale", - "description": "Scales texture coordinates in both U and V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - } - ], - //############################################################################################## - // Layer 3 Properties - //############################################################################################## - "layer3_baseColor": [ - { - "id": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_baseColor" - } - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_baseColorFactor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Base color texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_baseColorMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Base color texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_baseColorMapUvIndex" - } - }, - { - "id": "textureBlendMode", - "displayName": "Texture Blend Mode", - "description": "Selects the equation to use when combining Color, Factor, and Texture Map.", - "type": "Enum", - "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], - "defaultValue": "Multiply", - "connection": { - "type": "ShaderOption", - "id": "o_layer3_o_baseColorTextureBlendMode" - } - } - ], - "layer3_metallic": [ - { - "id": "factor", - "displayName": "Factor", - "description": "This value is linear, black is non-metal and white means raw metal.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_metallicFactor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_metallicMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Metallic texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_metallicMapUvIndex" - } - } - ], - "layer3_roughness": [ - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface roughness.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_roughnessMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Roughness texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_roughnessMapUvIndex" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", - "displayName": "Lower Bound", - "description": "The roughness value that corresponds to black in the texture map.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_roughnessLowerBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", - "displayName": "Upper Bound", - "description": "The roughness value that corresponds to white in the texture map.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_roughnessUpperBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", - "displayName": "Factor", - "description": "Controls the roughness value", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_roughnessFactor" - } - } - ], - "layer3_specularF0": [ - { - "id": "factor", - "displayName": "Factor", - "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", - "type": "Float", - "defaultValue": 0.5, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_specularF0Factor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface reflectance.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_specularF0Map" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Specular reflection texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_specularF0MapUvIndex" - } - } - ], - "layer3_normal": [ - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining surface normal direction.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_normalMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just rely on vertex normals.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Normal texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_normalMapUvIndex" - } - }, - { - "id": "flipX", - "displayName": "Flip X Channel", - "description": "Flip tangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_flipNormalX" - } - }, - { - "id": "flipY", - "displayName": "Flip Y Channel", - "description": "Flip bitangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_flipNormalY" - } - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_normalFactor" - } - } - ], - "layer3_clearCoat": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Enable clear coat", - "type": "Bool", - "defaultValue": false - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the percentage of effect applied", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatFactor" - } - }, - { - "id": "influenceMap", - "displayName": " Influence Map", - "description": "Strength factor texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatInfluenceMap" - } - }, - { - "id": "useInfluenceMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "influenceMapUv", - "displayName": " UV", - "description": "Strength factor texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatInfluenceMapUvIndex" - } - }, - { - "id": "roughness", - "displayName": "Roughness", - "description": "Clear coat layer roughness", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatRoughness" - } - }, - { - "id": "roughnessMap", - "displayName": " Roughness Map", - "description": "Roughness texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatRoughnessMap" - } - }, - { - "id": "useRoughnessMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the roughness value.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "roughnessMapUv", - "displayName": " UV", - "description": "Roughness texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatRoughnessMapUvIndex" - } - }, - { - "id": "normalStrength", - "displayName": "Normal Strength", - "description": "Scales the impact of the clear coat normal map", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatNormalStrength" - } - }, - { - "id": "normalMap", - "displayName": "Normal Map", - "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatNormalMap" - } - }, - { - "id": "useNormalMap", - "displayName": " Use Texture", - "description": "Whether to use the normal map", - "type": "Bool", - "defaultValue": true - }, - { - "id": "normalMapUv", - "displayName": " UV", - "description": "Normal texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_clearCoatNormalMapUvIndex" - } - } - ], - "layer3_occlusion": [ - { - "id": "diffuseTextureMap", - "displayName": "Diffuse AO", - "description": "Texture map for defining occlusion area for diffuse ambient lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_diffuseOcclusionMap" - } - }, - { - "id": "diffuseUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Diffuse AO texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "diffuseTextureMapUv", - "displayName": " UV", - "description": "Diffuse AO texture map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_diffuseOcclusionMapUvIndex" - } - }, - { - "id": "diffuseFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Diffuse AO", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_diffuseOcclusionFactor" - } - }, - { - "id": "specularTextureMap", - "displayName": "Specular Cavity", - "description": "Texture map for defining occlusion area for specular lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_specularOcclusionMap" - } - }, - { - "id": "specularUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Specular Cavity texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "specularTextureMapUv", - "displayName": " UV", - "description": "Specular Cavity texture map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_specularOcclusionMapUvIndex" - } - }, - { - "id": "specularFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Specular Cavity", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_specularOcclusionFactor" - } - } - ], - "layer3_emissive": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Enable the emissive group", - "type": "Bool", - "defaultValue": false - }, - { - "id": "unit", - "displayName": "Units", - "description": "The photometric units of the Intensity property.", - "type": "Enum", - "enumValues": ["Ev100"], - "defaultValue": "Ev100" - }, - { - "id": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_emissiveColor" - } - }, - { - "id": "intensity", - "displayName": "Intensity", - "description": "The amount of energy emitted.", - "type": "Float", - "defaultValue": 4, - "min": -10, - "max": 20, - "softMin": -6, - "softMax": 16 - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining emissive area.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_emissiveMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Emissive texture map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_emissiveMapUvIndex" - } - } - ], - "layer3_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_depthMap" - } - }, - { - "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_depthFactor" - } - }, - { - "id": "offset", - "displayName": "Offset", - "description": "Adjusts the overall displacement amount in local model units.", - "type": "Float", - "defaultValue": 0.0, - "softMin": -0.1, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_depthOffset" - } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_depthInverted" - } - } - ], - "layer3_uv": [ - { - "id": "center", - "displayName": "Center", - "description": "Center point for scaling and rotation transformations.", - "type": "vector2", - "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] - }, - { - "id": "tileU", - "displayName": "Tile U", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "tileV", - "displayName": "Tile V", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "id": "offsetU", - "displayName": "Offset U", - "description": "Offsets texture coordinates in the U direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "offsetV", - "displayName": "Offset V", - "description": "Offsets texture coordinates in the V direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0, - "step": 0.001 - }, - { - "id": "rotateDegrees", - "displayName": "Rotate", - "description": "Rotates the texture coordinates (degrees).", - "type": "float", - "defaultValue": 0.0, - "min": -180.0, - "max": 180.0, - "step": 1.0 - }, - { - "id": "scale", - "displayName": "Scale", - "description": "Scales texture coordinates in both U and V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - } - ] - } - }, - "shaders": [ - { - "file": "./StandardMultilayerPBR_ForwardPass.shader", - "tag": "ForwardPass" - }, - { - "file": "./StandardMultilayerPBR_ForwardPass_EDS.shader", - "tag": "ForwardPass_EDS" - }, - { - "file": "Shaders/Shadow/Shadowmap.shader", - "tag": "Shadowmap" - }, - { - "file": "./StandardMultilayerPBR_Shadowmap_WithPS.shader", - "tag": "Shadowmap_WithPS" - }, - { - "file": "Shaders/Depth/DepthPass.shader", - "tag": "DepthPass" - }, - { - "file": "./StandardMultilayerPBR_DepthPass_WithPS.shader", - "tag": "DepthPass_WithPS" - }, - // [GFX TODO][ATOM-4726] Use an "isSkinnedMesh" external material property and a functor that enables/disables the appropriate motion-vector shader - { - "file": "Shaders/MotionVector/StaticMeshMotionVector.shader", - "tag": "StaticMeshMotionVector" - }, - { - "file": "Shaders/MotionVector/SkinnedMeshMotionVector.shader", - "tag": "SkinnedMeshMotionVector" - } - ], - "functors": [ - //############################################################################################## - // General Functors - //############################################################################################## - { - // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. - "type": "Transform2D", - "args": { - "transformOrder": [ "Rotate", "Translate", "Scale" ], - "centerProperty": "uv.center", - "scaleProperty": "uv.scale", - "scaleXProperty": "uv.tileU", - "scaleYProperty": "uv.tileV", - "translateXProperty": "uv.offsetU", - "translateYProperty": "uv.offsetV", - "rotateDegreesProperty": "uv.rotateDegrees", - "float3x3ShaderInput": "m_uvMatrix", - "float3x3InverseShaderInput": "m_uvMatrixInverse" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardMultilayerPBR_ShaderEnable.lua" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardMultilayerPBR_LayerEnable.lua" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardMultilayerPBR_ClearCoatEnableFeature.lua" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardMultilayerPBR_Parallax.lua" - } - }, - //############################################################################################## - // Layer 1 Functors - //############################################################################################## - { - "type": "UseTexture", - "args": { - "textureProperty": "layer1_baseColor.textureMap", - "useTextureProperty": "layer1_baseColor.useTexture", - "dependentProperties": ["layer1_baseColor.textureMapUv", "layer1_baseColor.textureBlendMode"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer1_o_baseColor_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer1_metallic.textureMap", - "useTextureProperty": "layer1_metallic.useTexture", - "dependentProperties": ["layer1_metallic.textureMapUv"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer1_o_metallic_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_Roughness.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer1_specularF0.textureMap", - "useTextureProperty": "layer1_specularF0.useTexture", - "dependentProperties": ["layer1_specularF0.textureMapUv"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer1_o_specularF0_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer1_normal.textureMap", - "useTextureProperty": "layer1_normal.useTexture", - "dependentProperties": ["layer1_normal.textureMapUv", "layer1_normal.factor", "layer1_normal.flipX", "layer1_normal.flipY"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer1_o_normal_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_ClearCoatState.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer1_occlusion.diffuseTextureMap", - "useTextureProperty": "layer1_occlusion.diffuseUseTexture", - "dependentProperties": ["layer1_occlusion.diffuseTextureMapUv", "layer1_occlusion.diffuseFactor"], - "shaderOption": "o_layer1_o_diffuseOcclusion_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer1_occlusion.specularTextureMap", - "useTextureProperty": "layer1_occlusion.specularUseTexture", - "dependentProperties": ["layer1_occlusion.specularTextureMapUv", "layer1_occlusion.specularFactor"], - "shaderOption": "o_layer1_o_specularOcclusion_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_EmissiveState.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" - } - }, - { - // Convert emissive unit. - "type": "ConvertEmissiveUnit", - "args": { - "intensityProperty": "layer1_emissive.intensity", - "lightUnitProperty": "layer1_emissive.unit", - "shaderInput": "m_layer1_m_emissiveIntensity", - "ev100Index": 0, - "nitIndex" : 1, - "ev100MinMax": [-10, 20], - "nitMinMax": [0.001, 100000.0] - } - }, - { - "type": "Lua", - "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" - } - }, - { - // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. - "type": "Transform2D", - "args": { - "transformOrder": [ "Rotate", "Translate", "Scale" ], - "centerProperty": "layer1_uv.center", - "scaleProperty": "layer1_uv.scale", - "scaleXProperty": "layer1_uv.tileU", - "scaleYProperty": "layer1_uv.tileV", - "translateXProperty": "layer1_uv.offsetU", - "translateYProperty": "layer1_uv.offsetV", - "rotateDegreesProperty": "layer1_uv.rotateDegrees", - "float3x3ShaderInput": "m_layer1_m_uvMatrix" - } - }, - //############################################################################################## - // Layer 2 Functors - //############################################################################################## - { - "type": "UseTexture", - "args": { - "textureProperty": "layer2_baseColor.textureMap", - "useTextureProperty": "layer2_baseColor.useTexture", - "dependentProperties": ["layer2_baseColor.textureMapUv", "layer2_baseColor.textureBlendMode"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer2_o_baseColor_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer2_metallic.textureMap", - "useTextureProperty": "layer2_metallic.useTexture", - "dependentProperties": ["layer2_metallic.textureMapUv"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer2_o_metallic_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_Roughness.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer2_specularF0.textureMap", - "useTextureProperty": "layer2_specularF0.useTexture", - "dependentProperties": ["layer2_specularF0.textureMapUv"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer2_o_specularF0_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer2_normal.textureMap", - "useTextureProperty": "layer2_normal.useTexture", - "dependentProperties": ["layer2_normal.textureMapUv", "layer2_normal.factor", "layer2_normal.flipX", "layer2_normal.flipY"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer2_o_normal_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_ClearCoatState.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer2_occlusion.diffuseTextureMap", - "useTextureProperty": "layer2_occlusion.diffuseUseTexture", - "dependentProperties": ["layer2_occlusion.diffuseTextureMapUv", "layer2_occlusion.diffuseFactor"], - "shaderOption": "o_layer2_o_diffuseOcclusion_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer2_occlusion.specularTextureMap", - "useTextureProperty": "layer2_occlusion.specularUseTexture", - "dependentProperties": ["layer2_occlusion.specularTextureMapUv", "layer2_occlusion.specularFactor"], - "shaderOption": "o_layer2_o_specularOcclusion_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_EmissiveState.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" - } - }, - { - // Convert emissive unit. - "type": "ConvertEmissiveUnit", - "args": { - "intensityProperty": "layer2_emissive.intensity", - "lightUnitProperty": "layer2_emissive.unit", - "shaderInput": "m_layer2_m_emissiveIntensity", - "ev100Index": 0, - "nitIndex" : 1, - "ev100MinMax": [-10, 20], - "nitMinMax": [0.001, 100000.0] - } - }, - { - "type": "Lua", - "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" - } - }, - { - // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. - "type": "Transform2D", - "args": { - "transformOrder": [ "Rotate", "Translate", "Scale" ], - "centerProperty": "layer2_uv.center", - "scaleProperty": "layer2_uv.scale", - "scaleXProperty": "layer2_uv.tileU", - "scaleYProperty": "layer2_uv.tileV", - "translateXProperty": "layer2_uv.offsetU", - "translateYProperty": "layer2_uv.offsetV", - "rotateDegreesProperty": "layer2_uv.rotateDegrees", - "float3x3ShaderInput": "m_layer2_m_uvMatrix" - } - }, - //############################################################################################## - // Layer 3 Functors - //############################################################################################## - { - "type": "UseTexture", - "args": { - "textureProperty": "layer3_baseColor.textureMap", - "useTextureProperty": "layer3_baseColor.useTexture", - "dependentProperties": ["layer3_baseColor.textureMapUv", "layer3_baseColor.textureBlendMode"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer3_o_baseColor_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer3_metallic.textureMap", - "useTextureProperty": "layer3_metallic.useTexture", - "dependentProperties": ["layer3_metallic.textureMapUv"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer3_o_metallic_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_Roughness.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer3_specularF0.textureMap", - "useTextureProperty": "layer3_specularF0.useTexture", - "dependentProperties": ["layer3_specularF0.textureMapUv"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer3_o_specularF0_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer3_normal.textureMap", - "useTextureProperty": "layer3_normal.useTexture", - "dependentProperties": ["layer3_normal.textureMapUv", "layer3_normal.factor", "layer3_normal.flipX", "layer3_normal.flipY"], - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_layer3_o_normal_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_ClearCoatState.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer3_occlusion.diffuseTextureMap", - "useTextureProperty": "layer3_occlusion.diffuseUseTexture", - "dependentProperties": ["layer3_occlusion.diffuseTextureMapUv", "layer3_occlusion.diffuseFactor"], - "shaderOption": "o_layer3_o_diffuseOcclusion_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "layer3_occlusion.specularTextureMap", - "useTextureProperty": "layer3_occlusion.specularUseTexture", - "dependentProperties": ["layer3_occlusion.specularTextureMapUv", "layer3_occlusion.specularFactor"], - "shaderOption": "o_layer3_o_specularOcclusion_useTexture" - } - }, - { - "type": "Lua", - "args": { - "file": "StandardPBR_EmissiveState.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" - } - }, - { - // Convert emissive unit. - "type": "ConvertEmissiveUnit", - "args": { - "intensityProperty": "layer3_emissive.intensity", - "lightUnitProperty": "layer3_emissive.unit", - "shaderInput": "m_layer3_m_emissiveIntensity", - "ev100Index": 0, - "nitIndex" : 1, - "ev100MinMax": [-10, 20], - "nitMinMax": [0.001, 100000.0] - } - }, - { - "type": "Lua", - "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" - } - }, - { - // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. - "type": "Transform2D", - "args": { - "transformOrder": [ "Rotate", "Translate", "Scale" ], - "centerProperty": "layer3_uv.center", - "scaleProperty": "layer3_uv.scale", - "scaleXProperty": "layer3_uv.tileU", - "scaleYProperty": "layer3_uv.tileV", - "translateXProperty": "layer3_uv.offsetU", - "translateYProperty": "layer3_uv.offsetV", - "rotateDegreesProperty": "layer3_uv.rotateDegrees", - "float3x3ShaderInput": "m_layer3_m_uvMatrix" - } - } - ], - "uvNameMap": { - "UV0": "Tiled", - "UV1": "Unwrapped" - } -} - diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig deleted file mode 100644 index 471fab991d..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli.orig +++ /dev/null @@ -1,401 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -#include "MaterialInputs/BaseColorInput.azsli" -#include "MaterialInputs/RoughnessInput.azsli" -#include "MaterialInputs/MetallicInput.azsli" -#include "MaterialInputs/SpecularInput.azsli" -#include "MaterialInputs/NormalInput.azsli" -#include "MaterialInputs/ClearCoatInput.azsli" -#include "MaterialInputs/OcclusionInput.azsli" -#include "MaterialInputs/EmissiveInput.azsli" -#include "MaterialInputs/ParallaxInput.azsli" -#include "MaterialInputs/UvSetCount.azsli" - -// ------ ShaderResourceGroup ---------------------------------------- - -#define DEFINE_LAYER_SRG_INPUTS(prefix) \ -COMMON_SRG_INPUTS_BASE_COLOR(prefix) \ -COMMON_SRG_INPUTS_ROUGHNESS(prefix) \ -COMMON_SRG_INPUTS_METALLIC(prefix) \ -COMMON_SRG_INPUTS_SPECULAR_F0(prefix) \ -COMMON_SRG_INPUTS_NORMAL(prefix) \ -COMMON_SRG_INPUTS_CLEAR_COAT(prefix) \ -COMMON_SRG_INPUTS_OCCLUSION(prefix) \ -COMMON_SRG_INPUTS_EMISSIVE(prefix) \ -COMMON_SRG_INPUTS_PARALLAX(prefix) - -ShaderResourceGroup MaterialSrg : SRG_PerMaterial -{ - Texture2D m_blendMaskTexture; - uint m_blendMaskUvIndex; - - // Auto-generate material SRG fields for common inputs for each layer - DEFINE_LAYER_SRG_INPUTS(m_layer1_) - DEFINE_LAYER_SRG_INPUTS(m_layer2_) - DEFINE_LAYER_SRG_INPUTS(m_layer3_) - - float3x3 m_layer1_m_uvMatrix; - float4 m_pad1; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. - - float3x3 m_layer2_m_uvMatrix; - float4 m_pad2; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. - - float3x3 m_layer3_m_uvMatrix; - float4 m_pad3; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. - - uint m_parallaxUvIndex; - - // These are used to limit the heightmap intersection search range to the narrowest band possible, to give the best quality result. - float m_displacementMin; // The lowest displacement value possible from all layers combined (negative values are below the surface) - float m_displacementMax; // The highest displacement value possible from all layers combined (negative values are below the surface) - - float3x3 m_uvMatrix; - float4 m_pad4; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. - float3x3 m_uvMatrixInverse; - float4 m_pad5; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. - - Sampler m_sampler - { - AddressU = Wrap; - AddressV = Wrap; - MinFilter = Linear; - MagFilter = Linear; - MipFilter = Linear; - MaxAnisotropy = 16; - }; - - Texture2D m_brdfMap; - - Sampler m_samplerBrdf - { - AddressU = Clamp; - AddressV = Clamp; - MinFilter = Linear; - MagFilter = Linear; - MipFilter = Linear; - }; - -} - -// ------ Shader Options ---------------------------------------- - -<<<<<<< HEAD -option bool o_layer2_enabled; -option bool o_layer3_enabled; - -enum class DebugDrawMode { None, BlendSource, DepthMaps }; -======= -enum class DebugDrawMode { None, BlendWeights, DisplacementMaps }; ->>>>>>> Atom/santorac/MultilayerPbrImprovements -option DebugDrawMode o_debugDrawMode; - -enum class LayerBlendSource { BlendMask, VertexColors, Displacement, Fallback }; -option LayerBlendSource o_layerBlendSource; - -// Indicates whether the vertex input struct's "m_optional_blendMask" is bound. If false, it is not safe to read from m_optional_blendMask. -// This option gets set automatically by the system at runtime; there is a soft naming convention that associates it with m_optional_blendMask. -// (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. -option bool o_blendMask_isBound; - -// ------ Blend Utilities ---------------------------------------- - -<<<<<<< HEAD -// This is mainly used to pass extra data to the GetDepth callback function during the parallax depth search. -// But since we have it, we use it in some other functions as well rather than passing it around. -static float3 s_blendMaskFromVertexStream; - -//! Returns the BlendMaskSource that will actually be used when rendering (not necessarily the same BlendMaskSource specified by the user) -BlendMaskSource GetFinalBlendMaskSource() -======= -//! Returns the LayerBlendSource that will actually be used when rendering (not necessarily the same LayerBlendSource specified by the user) -LayerBlendSource GetFinalLayerBlendSource() ->>>>>>> Atom/santorac/MultilayerPbrImprovements -{ - if(o_layerBlendSource == LayerBlendSource::BlendMask) - { - return LayerBlendSource::BlendMask; - } - else if(o_layerBlendSource == LayerBlendSource::VertexColors) - { - if(o_blendMask_isBound) - { - return LayerBlendSource::VertexColors; - } - else - { - return LayerBlendSource::BlendMask; - } - } - else if(o_layerBlendSource == LayerBlendSource::Displacement) - { - return LayerBlendSource::Displacement; - } - else - { - return LayerBlendSource::Fallback; - } -} - -<<<<<<< HEAD -//! Return the raw blend source values directly from the blend mask or vertex colors, depending on the available data and configuration. -//! layer1 is an implicit base layer -//! layer2 is weighted by r -//! layer3 is weighted by g -//! b is reserved for perhaps a dedicated puddle layer -float3 GetBlendSourceValues(float2 uv) -{ - float3 blendSourceValues = float3(0,0,0); - - if(o_layer2_enabled || o_layer3_enabled) - { - switch(GetFinalBlendMaskSource()) - { - case BlendMaskSource::TextureMap: - blendSourceValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; - break; - case BlendMaskSource::VertexColors: - blendSourceValues = s_blendMaskFromVertexStream; - break; - } - - if(!o_layer2_enabled) - { - blendSourceValues.r = 0.0; - } - - if(!o_layer3_enabled) - { - blendSourceValues.g = 0.0; - } - } - - return blendSourceValues; -} - -//! Return the final blend mask values to be used for rendering, based on the available data and configuration. -//! @return The blend weights for each layer. -//! Even though layer1 not explicitly specified in the blend source data, it is explicitly included with the returned values. -//! layer1 = r -//! layer2 = g -//! layer3 = b -float3 GetBlendWeights(float2 uv) -{ - float3 blendWeights; - - if(o_layer2_enabled || o_layer3_enabled) - { - float3 blendSourceValues = GetBlendSourceValues(uv); - - // Calculate blend weights such that multiplying and adding them with layer data is equivalent - // to lerping between each layer. - // final = lerp(final, layer1, blendWeights.r) - // final = lerp(final, layer2, blendWeights.g) - // final = lerp(final, layer3, blendWeights.b) - - blendWeights.b = blendSourceValues.g; - blendWeights.g = (1.0 - blendSourceValues.g) * blendSourceValues.r; - blendWeights.r = (1.0 - blendSourceValues.g) * (1.0 - blendSourceValues.r); - } - else - { - blendWeights = float3(1,0,0); - } - - return blendWeights; -} - -float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeights) -{ - return dot(float3(layer1, layer2, layer3), blendWeights); -} -float2 BlendLayers(float2 layer1, float2 layer2, float2 layer3, float3 blendWeights) -{ - return layer1 * blendWeights.r + layer2 * blendWeights.g + layer3 * blendWeights.b; -} -float3 BlendLayers(float3 layer1, float3 layer2, float3 layer3, float3 blendWeights) -{ - return layer1 * blendWeights.r + layer2 * blendWeights.g + layer3 * blendWeights.b; -======= -//! Returns blend weights given the depth values for each layer -float3 GetBlendWeightsFromLayerDepthValues(float3 layerDepthValues) -{ - float highestPoint = min(layerDepthValues.x, min(layerDepthValues.y, layerDepthValues.z)); - float3 blendWeights = float3(layerDepthValues.x <= highestPoint ? 1.0 : 0.0, - layerDepthValues.y <= highestPoint ? 1.0 : 0.0, - layerDepthValues.z <= highestPoint ? 1.0 : 0.0); - return blendWeights; -} - -float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); - -//! Return the final blend mask values to be used for rendering, based on the available data and configuration. -//! @param vertexBlendWeights - the blend weights that came from the vertex input, relevant for LayerBlendSource::VertexColors -//! @param layerDepthValues - the per-layer depth values as provided by GetLayerDepthValues() -float3 GetBlendWeights(float2 uv, float3 vertexBlendWeights, float3 layerDepthValues) -{ - float3 blendWeightValues; - - switch(GetFinalLayerBlendSource()) - { - case LayerBlendSource::BlendMask: - blendWeightValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; - break; - case LayerBlendSource::VertexColors: - blendWeightValues = vertexBlendWeights; - break; - case LayerBlendSource::Displacement: - blendWeightValues = GetBlendWeightsFromLayerDepthValues(layerDepthValues); - break; - case LayerBlendSource::Fallback: - blendWeightValues = float3(1,1,1); - break; - } - - blendWeightValues = blendWeightValues / (blendWeightValues.r + blendWeightValues.g + blendWeightValues.b); - - return blendWeightValues; -} - -//! Return the final blend mask values to be used for rendering, based on the available data and configuration. -//! Note this will sample the displacement maps in the case of LayerBlendSource::Displacement. If you have already -//! called GetLayerDepthValues(), use the GetBlendWeights() overlad that takes layerDepthValues instead. -float3 GetBlendWeights(float2 uv, float3 vertexBlendWeights) -{ - float3 layerDepthValues = float3(0,0,0); - - if(GetFinalLayerBlendSource() == LayerBlendSource::Displacement) - { - layerDepthValues = GetLayerDepthValues(uv, ddx_fine(uv), ddy_fine(uv)); - } - - return GetBlendWeights(uv, vertexBlendWeights, layerDepthValues); -} - -float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeightValues) -{ - return dot(float3(layer1, layer2, layer3), blendWeightValues); -} -float2 BlendLayers(float2 layer1, float2 layer2, float2 layer3, float3 blendWeightValues) -{ - return layer1 * blendWeightValues.r + layer2 * blendWeightValues.g + layer3 * blendWeightValues.b; -} -float3 BlendLayers(float3 layer1, float3 layer2, float3 layer3, float3 blendWeightValues) -{ - return layer1 * blendWeightValues.r + layer2 * blendWeightValues.g + layer3 * blendWeightValues.b; ->>>>>>> Atom/santorac/MultilayerPbrImprovements -} - -// ------ Parallax Utilities ---------------------------------------- - -bool ShouldHandleParallax() -{ - // Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scattering is enabled. - // Also, all the debug draw modes avoid parallax (they early-return before parallax code actually) so you can see exactly where the various maps appear on the surface UV space. - return !o_enableSubsurfaceScattering && o_parallax_feature_enabled && o_debugDrawMode == DebugDrawMode::None; -} - -bool ShouldHandleParallaxInDepthShaders() -{ - // The depth pass shaders need to calculate parallax when the result could affect the depth buffer (or when - // parallax could affect texel clipping but we don't have alpha/clipping support in multilayer PBR). - return ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; -} - -<<<<<<< HEAD -// Callback function for ParallaxMapping.azsli -DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) -======= -// These static values are used to pass extra data to the GetDepth callback function during the parallax depth search. -static float3 s_blendWeightsFromVertexStream; - -//! Setup static variables that are needed by the GetDepth callback function -//! @param vertexBlendWeights - the blend weights from the vertex input stream. -void GetDepth_Setup(float3 vertexBlendWeights) -{ - s_blendWeightsFromVertexStream = vertexBlendWeights; -} - -//! Returns the depth values for each layer -float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) ->>>>>>> Atom/santorac/MultilayerPbrImprovements -{ - float3 layerDepthValues = float3(0,0,0); - - if(o_layer1_o_useDepthMap) - { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) - { - layerUv = mul(MaterialSrg::m_layer1_m_uvMatrix, float3(uv, 1.0)).xy; - } - - layerDepthValues.r = SampleDepthOrHeightMap(MaterialSrg::m_layer1_m_depthInverted, MaterialSrg::m_layer1_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.r *= MaterialSrg::m_layer1_m_depthFactor; - layerDepthValues.r -= MaterialSrg::m_layer1_m_depthOffset; - } - - if(o_layer2_enabled && o_layer2_o_useDepthMap) - { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) - { - layerUv = mul(MaterialSrg::m_layer2_m_uvMatrix, float3(uv, 1.0)).xy; - } - - layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor; - layerDepthValues.g -= MaterialSrg::m_layer2_m_depthOffset; - } - - if(o_layer3_enabled && o_layer3_o_useDepthMap) - { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) - { - layerUv = mul(MaterialSrg::m_layer3_m_uvMatrix, float3(uv, 1.0)).xy; - } - - layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; - layerDepthValues.b -= MaterialSrg::m_layer3_m_depthOffset; - } - - return layerDepthValues; -} - -//! Callback function for ParallaxMapping.azsli -DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) -{ - float3 layerDepthValues = GetLayerDepthValues(uv, uv_ddx, uv_ddy); - - // Note, when the blend source is LayerBlendSource::VertexColors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values - // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be so noticeable as long as - // you have a small depth factor relative to the size of the blend transition. -<<<<<<< HEAD - float3 blendWeights = GetBlendWeights(uv); - - float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeights); -======= - float3 blendWeightValues = GetBlendWeights(uv, s_blendWeightsFromVertexStream, layerDepthValues); - - float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - return DepthResultAbsolute(depth); -} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig deleted file mode 100644 index 489bd87037..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl.orig +++ /dev/null @@ -1,132 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include -#include -#include -#include - -#include "MaterialInputs/ParallaxInput.azsli" - - -#include "MaterialInputs/ParallaxInput.azsli" -COMMON_OPTIONS_PARALLAX(o_layer1_) -COMMON_OPTIONS_PARALLAX(o_layer2_) -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 -{ - 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_blendWeights : 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_blendWeights = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendWeights = float3(1,1,1); - } - - return OUT; -} - -struct PSDepthOutput -{ - float m_depth : SV_Depth; -}; - -PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) -{ - PSDepthOutput OUT; - - OUT.m_depth = IN.m_position.z; - - if(ShouldHandleParallaxInDepthShaders()) - { - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); - -<<<<<<< HEAD - s_blendMaskFromVertexStream = IN.m_blendMask; -======= - GetDepth_Setup(IN.m_blendWeights); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - - 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; -} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index 897bcdc116..fb9771fa28 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -130,3 +130,4 @@ function ProcessEditor(context) end end + diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig deleted file mode 100644 index 4ddea9b0cf..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl.orig +++ /dev/null @@ -1,710 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -// SRGs -#include -#include -#include - -// Pass Output -#include - -// Utility -#include -#include - -// Custom Surface & Lighting -#include - -// Decals -#include - -// ---------- Material Parameters ---------- - -#include "MaterialInputs/BaseColorInput.azsli" -#include "MaterialInputs/RoughnessInput.azsli" -#include "MaterialInputs/MetallicInput.azsli" -#include "MaterialInputs/SpecularInput.azsli" -#include "MaterialInputs/NormalInput.azsli" -#include "MaterialInputs/ClearCoatInput.azsli" -#include "MaterialInputs/OcclusionInput.azsli" -#include "MaterialInputs/EmissiveInput.azsli" -#include "MaterialInputs/ParallaxInput.azsli" - -#define DEFINE_LAYER_OPTIONS(prefix) \ -COMMON_OPTIONS_BASE_COLOR(prefix) \ -COMMON_OPTIONS_ROUGHNESS(prefix) \ -COMMON_OPTIONS_METALLIC(prefix) \ -COMMON_OPTIONS_SPECULAR_F0(prefix) \ -COMMON_OPTIONS_NORMAL(prefix) \ -COMMON_OPTIONS_CLEAR_COAT(prefix) \ -COMMON_OPTIONS_OCCLUSION(prefix) \ -COMMON_OPTIONS_EMISSIVE(prefix) \ -COMMON_OPTIONS_PARALLAX(prefix) - -DEFINE_LAYER_OPTIONS(o_layer1_) -DEFINE_LAYER_OPTIONS(o_layer2_) -DEFINE_LAYER_OPTIONS(o_layer3_) - -#include "MaterialInputs/TransmissionInput.azsli" -#include "StandardMultilayerPBR_Common.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; - - // 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 VSOutput -{ - // Base fields (required by the template azsli file)... - 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; - - float3 m_blendWeights : UV7; -}; - -#include - -VSOutput 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. - // 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(o_blendMask_isBound) - { - OUT.m_blendWeights = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendWeights = float3(1,1,1); - } - - // 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; -} - -//! Collects all the raw Standard material inputs for a single layer. See ProcessStandardMaterialInputs(). -struct StandardMaterialInputs -{ - COMMON_SRG_INPUTS_BASE_COLOR() - COMMON_SRG_INPUTS_ROUGHNESS() - COMMON_SRG_INPUTS_METALLIC() - COMMON_SRG_INPUTS_SPECULAR_F0() - COMMON_SRG_INPUTS_NORMAL() - COMMON_SRG_INPUTS_CLEAR_COAT() - COMMON_SRG_INPUTS_OCCLUSION() - COMMON_SRG_INPUTS_EMISSIVE() - // Note parallax is omitted here because that requires special handling. - - bool m_normal_useTexture; - bool m_baseColor_useTexture; - bool m_metallic_useTexture; - bool m_specularF0_useTexture; - bool m_roughness_useTexture; - bool m_emissiveEnabled; - bool m_emissive_useTexture; - bool m_diffuseOcclusion_useTexture; - bool m_specularOcclusion_useTexture; - bool m_clearCoatEnabled; - bool m_clearCoat_factor_useTexture; - bool m_clearCoat_roughness_useTexture; - bool m_clearCoat_normal_useTexture; - - TextureBlendMode m_baseColorTextureBlendMode; - - float2 m_vertexUv[UvSetCount]; - float3x3 m_uvMatrix; - float m_normal; - float3 m_tangents[UvSetCount]; - float3 m_bitangents[UvSetCount]; - - sampler m_sampler; - - bool m_isFrontFace; -}; - -//! Holds the final processed material inputs, after all flags have been checked, textures have been sampled, factors have been applied, etc. -//! This data is ready to be copied into a Surface and/or LightingData struct for the lighting system to consume. -class ProcessedMaterialInputs -{ - float3 m_normalTS; //!< Normal in tangent-space - float3 m_baseColor; - float3 m_specularF0Factor; - float m_metallic; - float m_roughness; - float3 m_emissiveLighting; - float m_diffuseAmbientOcclusion; - float m_specularOcclusion; - ClearCoatSurfaceData m_clearCoat; - - void InitializeToZero() - { - m_normalTS = float3(0,0,0); - m_baseColor = float3(0,0,0); - m_specularF0Factor = float3(0,0,0); - m_metallic = 0.0f; - m_roughness = 0.0f; - m_emissiveLighting = float3(0,0,0); - m_diffuseAmbientOcclusion = 0; - m_specularOcclusion = 0; - m_clearCoat.InitializeToZero(); - } -}; - -//! Processes the set of Standard material inputs for a single layer. -//! The FILL_STANDARD_MATERIAL_INPUTS() macro below can be used to fill the StandardMaterialInputs struct. -ProcessedMaterialInputs ProcessStandardMaterialInputs(StandardMaterialInputs inputs) -{ - ProcessedMaterialInputs result; - - float2 transformedUv[UvSetCount]; - transformedUv[0] = mul(inputs.m_uvMatrix, float3(inputs.m_vertexUv[0], 1.0)).xy; - transformedUv[1] = inputs.m_vertexUv[1]; - - float3x3 normalUvMatrix = inputs.m_normalMapUvIndex == 0 ? inputs.m_uvMatrix : CreateIdentity3x3(); - result.m_normalTS = GetNormalInputTS(inputs.m_normalMap, inputs.m_sampler, transformedUv[inputs.m_normalMapUvIndex], inputs.m_flipNormalX, inputs.m_flipNormalY, normalUvMatrix, inputs.m_normal_useTexture, inputs.m_normalFactor); - - float3 sampledBaseColor = GetBaseColorInput(inputs.m_baseColorMap, inputs.m_sampler, transformedUv[inputs.m_baseColorMapUvIndex], inputs.m_baseColor.rgb, inputs.m_baseColor_useTexture); - result.m_baseColor = BlendBaseColor(sampledBaseColor, inputs.m_baseColor.rgb, inputs.m_baseColorFactor, inputs.m_baseColorTextureBlendMode, inputs.m_baseColor_useTexture); - result.m_specularF0Factor = GetSpecularInput(inputs.m_specularF0Map, inputs.m_sampler, transformedUv[inputs.m_specularF0MapUvIndex], inputs.m_specularF0Factor, inputs.m_specularF0_useTexture); - result.m_metallic = GetMetallicInput(inputs.m_metallicMap, inputs.m_sampler, transformedUv[inputs.m_metallicMapUvIndex], inputs.m_metallicFactor, inputs.m_metallic_useTexture); - result.m_roughness = GetRoughnessInput(inputs.m_roughnessMap, MaterialSrg::m_sampler, transformedUv[inputs.m_roughnessMapUvIndex], inputs.m_roughnessFactor, inputs.m_roughnessLowerBound, inputs.m_roughnessUpperBound, inputs.m_roughness_useTexture); - - result.m_emissiveLighting = GetEmissiveInput(inputs.m_emissiveMap, inputs.m_sampler, transformedUv[inputs.m_emissiveMapUvIndex], inputs.m_emissiveIntensity, inputs.m_emissiveColor.rgb, inputs.m_emissiveEnabled, inputs.m_emissive_useTexture); - result.m_diffuseAmbientOcclusion = GetOcclusionInput(inputs.m_diffuseOcclusionMap, inputs.m_sampler, transformedUv[inputs.m_diffuseOcclusionMapUvIndex], inputs.m_diffuseOcclusionFactor, inputs.m_diffuseOcclusion_useTexture); - result.m_specularOcclusion = GetOcclusionInput(inputs.m_specularOcclusionMap, MaterialSrg::m_sampler, transformedUv[inputs.m_specularOcclusionMapUvIndex], inputs.m_specularOcclusionFactor, inputs.m_specularOcclusion_useTexture); - - result.m_clearCoat.InitializeToZero(); - if(inputs.m_clearCoatEnabled) - { - float3x3 clearCoatUvMatrix = inputs.m_clearCoatNormalMapUvIndex == 0 ? inputs.m_uvMatrix : CreateIdentity3x3(); - - GetClearCoatInputs(inputs.m_clearCoatInfluenceMap, transformedUv[inputs.m_clearCoatInfluenceMapUvIndex], inputs.m_clearCoatFactor, inputs.m_clearCoat_factor_useTexture, - inputs.m_clearCoatRoughnessMap, transformedUv[inputs.m_clearCoatRoughnessMapUvIndex], inputs.m_clearCoatRoughness, inputs.m_clearCoat_roughness_useTexture, - inputs.m_clearCoatNormalMap, transformedUv[inputs.m_clearCoatNormalMapUvIndex], inputs.m_normal, inputs.m_clearCoat_normal_useTexture, inputs.m_clearCoatNormalStrength, - clearCoatUvMatrix, inputs.m_tangents[inputs.m_clearCoatNormalMapUvIndex], inputs.m_bitangents[inputs.m_clearCoatNormalMapUvIndex], - inputs.m_sampler, inputs.m_isFrontFace, - result.m_clearCoat.factor, result.m_clearCoat.roughness, result.m_clearCoat.normal); - } - - return result; -} - -//! Fills a StandardMaterialInputs struct with data from the MaterialSrg, shader options, and local vertex data. -#define FILL_STANDARD_MATERIAL_INPUTS(inputs, srgLayerPrefix, optionsLayerPrefix, blendWeight) \ - inputs.m_sampler = MaterialSrg::m_sampler; \ - inputs.m_vertexUv = IN.m_uv; \ - inputs.m_uvMatrix = srgLayerPrefix##m_uvMatrix; \ - inputs.m_normal = IN.m_normal; \ - inputs.m_tangents = tangents; \ - inputs.m_bitangents = bitangents; \ - inputs.m_isFrontFace = isFrontFace; \ - \ - inputs.m_normalMapUvIndex = srgLayerPrefix##m_normalMapUvIndex; \ - inputs.m_normalMap = srgLayerPrefix##m_normalMap; \ - inputs.m_flipNormalX = srgLayerPrefix##m_flipNormalX; \ - inputs.m_flipNormalY = srgLayerPrefix##m_flipNormalY; \ - inputs.m_normal_useTexture = optionsLayerPrefix##o_normal_useTexture; \ - inputs.m_normalFactor = srgLayerPrefix##m_normalFactor * blendWeight; \ - inputs.m_baseColorMap = srgLayerPrefix##m_baseColorMap; \ - inputs.m_baseColorMapUvIndex = srgLayerPrefix##m_baseColorMapUvIndex; \ - inputs.m_baseColor = srgLayerPrefix##m_baseColor; \ - inputs.m_baseColor_useTexture = optionsLayerPrefix##o_baseColor_useTexture; \ - inputs.m_baseColorFactor = srgLayerPrefix##m_baseColorFactor; \ - inputs.m_baseColorTextureBlendMode = optionsLayerPrefix##o_baseColorTextureBlendMode; \ - inputs.m_metallicMap = srgLayerPrefix##m_metallicMap; \ - inputs.m_metallicMapUvIndex = srgLayerPrefix##m_metallicMapUvIndex; \ - inputs.m_metallicFactor = srgLayerPrefix##m_metallicFactor; \ - inputs.m_metallic_useTexture = optionsLayerPrefix##o_metallic_useTexture; \ - inputs.m_specularF0Map = srgLayerPrefix##m_specularF0Map; \ - inputs.m_specularF0MapUvIndex = srgLayerPrefix##m_specularF0MapUvIndex; \ - inputs.m_specularF0Factor = srgLayerPrefix##m_specularF0Factor; \ - inputs.m_specularF0_useTexture = optionsLayerPrefix##o_specularF0_useTexture; \ - inputs.m_roughnessMap = srgLayerPrefix##m_roughnessMap; \ - inputs.m_roughnessMapUvIndex = srgLayerPrefix##m_roughnessMapUvIndex; \ - inputs.m_roughnessFactor = srgLayerPrefix##m_roughnessFactor; \ - inputs.m_roughnessLowerBound = srgLayerPrefix##m_roughnessLowerBound; \ - inputs.m_roughnessUpperBound = srgLayerPrefix##m_roughnessUpperBound; \ - inputs.m_roughness_useTexture = optionsLayerPrefix##o_roughness_useTexture; \ - \ - inputs.m_emissiveMap = srgLayerPrefix##m_emissiveMap; \ - inputs.m_emissiveMapUvIndex = srgLayerPrefix##m_emissiveMapUvIndex; \ - inputs.m_emissiveIntensity = srgLayerPrefix##m_emissiveIntensity; \ - inputs.m_emissiveColor = srgLayerPrefix##m_emissiveColor; \ - inputs.m_emissiveEnabled = optionsLayerPrefix##o_emissiveEnabled; \ - inputs.m_emissive_useTexture = optionsLayerPrefix##o_emissive_useTexture; \ - \ - inputs.m_diffuseOcclusionMap = srgLayerPrefix##m_diffuseOcclusionMap; \ - inputs.m_diffuseOcclusionMapUvIndex = srgLayerPrefix##m_diffuseOcclusionMapUvIndex; \ - inputs.m_diffuseOcclusionFactor = srgLayerPrefix##m_diffuseOcclusionFactor; \ - inputs.m_diffuseOcclusion_useTexture = optionsLayerPrefix##o_diffuseOcclusion_useTexture; \ - \ - inputs.m_specularOcclusionMap = srgLayerPrefix##m_specularOcclusionMap; \ - inputs.m_specularOcclusionMapUvIndex = srgLayerPrefix##m_specularOcclusionMapUvIndex; \ - inputs.m_specularOcclusionFactor = srgLayerPrefix##m_specularOcclusionFactor; \ - inputs.m_specularOcclusion_useTexture = optionsLayerPrefix##o_specularOcclusion_useTexture; \ - \ - inputs.m_clearCoatEnabled = o_clearCoat_feature_enabled && optionsLayerPrefix##o_clearCoat_enabled; \ - inputs.m_clearCoatInfluenceMap = srgLayerPrefix##m_clearCoatInfluenceMap; \ - inputs.m_clearCoatInfluenceMapUvIndex = srgLayerPrefix##m_clearCoatInfluenceMapUvIndex; \ - inputs.m_clearCoatFactor = srgLayerPrefix##m_clearCoatFactor; \ - inputs.m_clearCoat_factor_useTexture = optionsLayerPrefix##o_clearCoat_factor_useTexture; \ - inputs.m_clearCoatRoughnessMap = srgLayerPrefix##m_clearCoatRoughnessMap; \ - inputs.m_clearCoatRoughnessMapUvIndex = srgLayerPrefix##m_clearCoatRoughnessMapUvIndex; \ - inputs.m_clearCoatRoughness = srgLayerPrefix##m_clearCoatRoughness; \ - inputs.m_clearCoat_roughness_useTexture = optionsLayerPrefix##o_clearCoat_roughness_useTexture; \ - inputs.m_clearCoatNormalMap = srgLayerPrefix##m_clearCoatNormalMap; \ - inputs.m_clearCoatNormalMapUvIndex = srgLayerPrefix##m_clearCoatNormalMapUvIndex; \ - inputs.m_clearCoat_normal_useTexture = optionsLayerPrefix##o_clearCoat_normal_useTexture; \ - inputs.m_clearCoatNormalStrength = srgLayerPrefix##m_clearCoatNormalStrength; - - -// ---------- Pixel Shader ---------- - -PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) -{ - depthNDC = IN.m_position.z; - - s_blendMaskFromVertexStream = IN.m_blendMask; - - // ------- Tangents & Bitangets ------- - - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - - if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering && MaterialSrg::m_parallaxUvIndex != 0) - || (o_layer1_o_normal_useTexture && MaterialSrg::m_layer1_m_normalMapUvIndex != 0) - || (o_layer2_o_normal_useTexture && MaterialSrg::m_layer2_m_normalMapUvIndex != 0) - || (o_layer3_o_normal_useTexture && MaterialSrg::m_layer3_m_normalMapUvIndex != 0) - || (o_layer1_o_clearCoat_normal_useTexture && MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex != 0) - || (o_layer2_o_clearCoat_normal_useTexture && MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex != 0) - || (o_layer3_o_clearCoat_normal_useTexture && MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex != 0) - ) - { - // Generate the tangent/bitangent for UV[1+] - const int startIndex = 1; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex); - } - - // ------- Debug Modes ------- - -<<<<<<< HEAD - if(o_debugDrawMode == DebugDrawMode::BlendSource) - { - float3 blendSource = GetBlendSourceValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); - return DebugOutput(blendSource); -======= - if(o_debugDrawMode == DebugDrawMode::BlendWeights) - { - float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendWeights); - return DebugOutput(blendWeights); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - } - - if(o_debugDrawMode == DebugDrawMode::DisplacementMaps) - { -<<<<<<< HEAD -======= - GetDepth_Setup(IN.m_blendWeights); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - float depth = GetNormalizedDepth(-MaterialSrg::m_displacementMax, -MaterialSrg::m_displacementMin, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); - return DebugOutput(float3(depth,depth,depth)); - } - - // ------- Parallax ------- - - bool displacementIsClipped = false; - - if(ShouldHandleParallax()) - { -<<<<<<< HEAD -======= - GetDepth_Setup(IN.m_blendWeights); - ->>>>>>> Atom/santorac/MultilayerPbrImprovements - 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, IN.m_position.w, 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, IN.m_shadowCoords); - } - } - } - - // ------- Calculate Layer Blend Mask Values ------- - - // Now that any parallax has been calculated, we calculate the blend factors for any layers that are impacted by the parallax. -<<<<<<< HEAD - float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); - - // ------- Layer 1 (base layer) ----------- - - ProcessedMaterialInputs lightingInputLayer1; -======= - float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendWeights); - - // ------- Normal ------- - - float3 layer1_normalFactor = MaterialSrg::m_layer1_m_normalFactor * blendWeights.r; - float3 layer2_normalFactor = MaterialSrg::m_layer2_m_normalFactor * blendWeights.g; - float3 layer3_normalFactor = MaterialSrg::m_layer3_m_normalFactor * blendWeights.b; - float3x3 layer1_uvMatrix = MaterialSrg::m_layer1_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer1_m_uvMatrix : CreateIdentity3x3(); - float3x3 layer2_uvMatrix = MaterialSrg::m_layer2_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer2_m_uvMatrix : CreateIdentity3x3(); - float3x3 layer3_uvMatrix = MaterialSrg::m_layer3_m_normalMapUvIndex == 0 ? MaterialSrg::m_layer3_m_uvMatrix : CreateIdentity3x3(); - float3 layer1_normalTS = GetNormalInputTS(MaterialSrg::m_layer1_m_normalMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_normalMapUvIndex], MaterialSrg::m_layer1_m_flipNormalX, MaterialSrg::m_layer1_m_flipNormalY, layer1_uvMatrix, o_layer1_o_normal_useTexture, layer1_normalFactor); - float3 layer2_normalTS = GetNormalInputTS(MaterialSrg::m_layer2_m_normalMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_normalMapUvIndex], MaterialSrg::m_layer2_m_flipNormalX, MaterialSrg::m_layer2_m_flipNormalY, layer2_uvMatrix, o_layer2_o_normal_useTexture, layer2_normalFactor); - float3 layer3_normalTS = GetNormalInputTS(MaterialSrg::m_layer3_m_normalMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_normalMapUvIndex], MaterialSrg::m_layer3_m_flipNormalX, MaterialSrg::m_layer3_m_flipNormalY, layer3_uvMatrix, o_layer3_o_normal_useTexture, layer3_normalFactor); - - float3 normalTS = ReorientTangentSpaceNormal(layer1_normalTS, layer2_normalTS); - normalTS = ReorientTangentSpaceNormal(normalTS, layer3_normalTS); - // [GFX TODO][ATOM-14591]: This will only work if the normal maps all use the same UV stream. We would need to add support for having them in different UV streams. - surface.normal = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex])); - - // ------- Base Color ------- - - float2 layer1_baseColorUv = uvLayer1[MaterialSrg::m_layer1_m_baseColorMapUvIndex]; - float2 layer2_baseColorUv = uvLayer2[MaterialSrg::m_layer2_m_baseColorMapUvIndex]; - float2 layer3_baseColorUv = uvLayer3[MaterialSrg::m_layer3_m_baseColorMapUvIndex]; - - float3 layer1_sampledColor = GetBaseColorInput(MaterialSrg::m_layer1_m_baseColorMap, MaterialSrg::m_sampler, layer1_baseColorUv, MaterialSrg::m_layer1_m_baseColor.rgb, o_layer1_o_baseColor_useTexture); - float3 layer2_sampledColor = GetBaseColorInput(MaterialSrg::m_layer2_m_baseColorMap, MaterialSrg::m_sampler, layer2_baseColorUv, MaterialSrg::m_layer2_m_baseColor.rgb, o_layer2_o_baseColor_useTexture); - float3 layer3_sampledColor = GetBaseColorInput(MaterialSrg::m_layer3_m_baseColorMap, MaterialSrg::m_sampler, layer3_baseColorUv, MaterialSrg::m_layer3_m_baseColor.rgb, o_layer3_o_baseColor_useTexture); - float3 layer1_baseColor = BlendBaseColor(layer1_sampledColor, MaterialSrg::m_layer1_m_baseColor.rgb, MaterialSrg::m_layer1_m_baseColorFactor, o_layer1_o_baseColorTextureBlendMode, o_layer1_o_baseColor_useTexture); - float3 layer2_baseColor = BlendBaseColor(layer2_sampledColor, MaterialSrg::m_layer2_m_baseColor.rgb, MaterialSrg::m_layer2_m_baseColorFactor, o_layer2_o_baseColorTextureBlendMode, o_layer2_o_baseColor_useTexture); - float3 layer3_baseColor = BlendBaseColor(layer3_sampledColor, MaterialSrg::m_layer3_m_baseColor.rgb, MaterialSrg::m_layer3_m_baseColorFactor, o_layer3_o_baseColorTextureBlendMode, o_layer3_o_baseColor_useTexture); - float3 baseColor = BlendLayers(layer1_baseColor, layer2_baseColor, layer3_baseColor, blendWeights); - - if(o_parallax_highlightClipping && displacementIsClipped) ->>>>>>> Atom/santorac/MultilayerPbrImprovements - { - StandardMaterialInputs inputs; - FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer1_, o_layer1_, blendWeights.r) - lightingInputLayer1 = ProcessStandardMaterialInputs(inputs); - } - - // ----------- Layer 2 ----------- - - ProcessedMaterialInputs lightingInputLayer2; - if(o_layer2_enabled) - { -<<<<<<< HEAD - StandardMaterialInputs inputs; - FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer2_, o_layer2_, blendWeights.g) - lightingInputLayer2 = ProcessStandardMaterialInputs(inputs); - } - else - { - lightingInputLayer2.InitializeToZero(); - } - - // ----------- Layer 3 ----------- -======= - float layer1_metallic = GetMetallicInput(MaterialSrg::m_layer1_m_metallicMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_metallicMapUvIndex], MaterialSrg::m_layer1_m_metallicFactor, o_layer1_o_metallic_useTexture); - float layer2_metallic = GetMetallicInput(MaterialSrg::m_layer2_m_metallicMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_metallicMapUvIndex], MaterialSrg::m_layer2_m_metallicFactor, o_layer2_o_metallic_useTexture); - float layer3_metallic = GetMetallicInput(MaterialSrg::m_layer3_m_metallicMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_metallicMapUvIndex], MaterialSrg::m_layer3_m_metallicFactor, o_layer3_o_metallic_useTexture); - metallic = BlendLayers(layer1_metallic, layer2_metallic, layer3_metallic, blendWeights); - } - - // ------- Specular ------- - - float layer1_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer1_m_specularF0Map, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularF0MapUvIndex], MaterialSrg::m_layer1_m_specularF0Factor, o_layer1_o_specularF0_useTexture); - float layer2_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer2_m_specularF0Map, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularF0MapUvIndex], MaterialSrg::m_layer2_m_specularF0Factor, o_layer2_o_specularF0_useTexture); - float layer3_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer3_m_specularF0Map, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularF0MapUvIndex], MaterialSrg::m_layer3_m_specularF0Factor, o_layer3_o_specularF0_useTexture); - float specularF0Factor = BlendLayers(layer1_specularF0Factor, layer2_specularF0Factor, layer3_specularF0Factor, blendWeights); - - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - - ProcessedMaterialInputs lightingInputLayer3; - if(o_layer3_enabled) - { - StandardMaterialInputs inputs; - FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer3_, o_layer3_, blendWeights.b) - lightingInputLayer3 = ProcessStandardMaterialInputs(inputs); - } - else - { - lightingInputLayer3.InitializeToZero(); - } - -<<<<<<< HEAD - // ------- Combine all layers --------- - - Surface surface; - surface.position = IN.m_worldPosition; - surface.transmission.InitializeToZero(); -======= - float layer1_roughness = GetRoughnessInput(MaterialSrg::m_layer1_m_roughnessMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_roughnessMapUvIndex], MaterialSrg::m_layer1_m_roughnessFactor, MaterialSrg::m_layer1_m_roughnessLowerBound, MaterialSrg::m_layer1_m_roughnessUpperBound, o_layer1_o_roughness_useTexture); - float layer2_roughness = GetRoughnessInput(MaterialSrg::m_layer2_m_roughnessMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_roughnessMapUvIndex], MaterialSrg::m_layer2_m_roughnessFactor, MaterialSrg::m_layer2_m_roughnessLowerBound, MaterialSrg::m_layer2_m_roughnessUpperBound, o_layer2_o_roughness_useTexture); - float layer3_roughness = GetRoughnessInput(MaterialSrg::m_layer3_m_roughnessMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_roughnessMapUvIndex], MaterialSrg::m_layer3_m_roughnessFactor, MaterialSrg::m_layer3_m_roughnessLowerBound, MaterialSrg::m_layer3_m_roughnessUpperBound, o_layer3_o_roughness_useTexture); - surface.roughnessLinear = BlendLayers(layer1_roughness, layer2_roughness, layer3_roughness, blendWeights); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - - // ------- Combine Normals --------- - - float3 normalTS = lightingInputLayer1.m_normalTS; - if(o_layer2_enabled) - { - normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer2.m_normalTS); - } - if(o_layer3_enabled) - { - normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer3.m_normalTS); - } - // [GFX TODO][ATOM-14591]: This will only work if the normal maps all use the same UV stream. We would need to add support for having them in different UV streams. - surface.normal = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex])); - - // ------- 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); - - if(o_parallax_highlightClipping && displacementIsClipped) - { - ApplyParallaxClippingHighlight(baseColor); - } - - surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic); - - surface.roughnessLinear = BlendLayers(lightingInputLayer1.m_roughness, lightingInputLayer2.m_roughness, lightingInputLayer3.m_roughness, blendWeights); - surface.CalculateRoughnessA(); - - // ------- Init and Combine 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; - -<<<<<<< HEAD - lightingData.emissiveLighting = BlendLayers(lightingInputLayer1.m_emissiveLighting, lightingInputLayer2.m_emissiveLighting, lightingInputLayer3.m_emissiveLighting, blendWeights); - lightingData.specularOcclusion = BlendLayers(lightingInputLayer1.m_specularOcclusion, lightingInputLayer2.m_specularOcclusion, lightingInputLayer3.m_specularOcclusion, blendWeights); - lightingData.diffuseAmbientOcclusion = BlendLayers(lightingInputLayer1.m_diffuseAmbientOcclusion, lightingInputLayer2.m_diffuseAmbientOcclusion, lightingInputLayer3.m_diffuseAmbientOcclusion, blendWeights); - - lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation); -======= - float3 layer1_emissive = GetEmissiveInput(MaterialSrg::m_layer1_m_emissiveMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_emissiveMapUvIndex], MaterialSrg::m_layer1_m_emissiveIntensity, MaterialSrg::m_layer1_m_emissiveColor.rgb, o_layer1_o_emissiveEnabled, o_layer1_o_emissive_useTexture); - float3 layer2_emissive = GetEmissiveInput(MaterialSrg::m_layer2_m_emissiveMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_emissiveMapUvIndex], MaterialSrg::m_layer2_m_emissiveIntensity, MaterialSrg::m_layer2_m_emissiveColor.rgb, o_layer2_o_emissiveEnabled, o_layer2_o_emissive_useTexture); - float3 layer3_emissive = GetEmissiveInput(MaterialSrg::m_layer3_m_emissiveMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_emissiveMapUvIndex], MaterialSrg::m_layer3_m_emissiveIntensity, MaterialSrg::m_layer3_m_emissiveColor.rgb, o_layer3_o_emissiveEnabled, o_layer3_o_emissive_useTexture); - lightingData.emissiveLighting = BlendLayers(layer1_emissive, layer2_emissive, layer3_emissive, blendWeights); - - // ------- Occlusion ------- - - float layer1_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer1_m_diffuseOcclusionFactor, o_layer1_o_diffuseOcclusion_useTexture); - float layer2_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer2_m_diffuseOcclusionFactor, o_layer2_o_diffuseOcclusion_useTexture); - float layer3_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer3_m_diffuseOcclusionFactor, o_layer3_o_diffuseOcclusion_useTexture); - lightingData.diffuseAmbientOcclusion = BlendLayers(layer1_diffuseAmbientOcclusion, layer2_diffuseAmbientOcclusion, layer3_diffuseAmbientOcclusion, blendWeights); - - float layer1_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer1_m_specularOcclusionFactor, o_layer1_o_specularOcclusion_useTexture); - float layer2_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer2_m_specularOcclusionFactor, o_layer2_o_specularOcclusion_useTexture); - float layer3_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer3_m_specularOcclusionFactor, o_layer3_o_specularOcclusion_useTexture); - lightingData.specularOcclusion = BlendLayers(layer1_specularOcclusion, layer2_specularOcclusion, layer3_specularOcclusion, blendWeights); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - - // ------- Combine Clearcoat ------- - - if(o_clearCoat_feature_enabled) - { -<<<<<<< HEAD - surface.clearCoat.factor = BlendLayers(lightingInputLayer1.m_clearCoat.factor, lightingInputLayer2.m_clearCoat.factor, lightingInputLayer3.m_clearCoat.factor, blendWeights); - surface.clearCoat.roughness = BlendLayers(lightingInputLayer1.m_clearCoat.roughness, lightingInputLayer2.m_clearCoat.roughness, lightingInputLayer3.m_clearCoat.roughness, blendWeights); - - // [GFX TODO][ATOM-14592] This is not the right way to blend the normals. We need to use ReorientTangentSpaceNormal(), and that requires GetClearCoatInputs() to return the normal in TS instead of WS. - surface.clearCoat.normal = BlendLayers(lightingInputLayer1.m_clearCoat.normal, lightingInputLayer2.m_clearCoat.normal, lightingInputLayer3.m_clearCoat.normal, blendWeights); -======= - // --- Layer 1 --- - - float layer1_clearCoatFactor = 0.0f; - float layer1_clearCoatRoughness = 0.0f; - float3 layer1_clearCoatNormal = float3(0.0, 0.0, 0.0); - if(o_layer1_o_clearCoat_enabled) - { - float3x3 layer1_uvMatrix = MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_layer1_m_uvMatrix : CreateIdentity3x3(); - - GetClearCoatInputs(MaterialSrg::m_layer1_m_clearCoatInfluenceMap, uvLayer1[MaterialSrg::m_layer1_m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_layer1_m_clearCoatFactor, o_layer1_o_clearCoat_factor_useTexture, - MaterialSrg::m_layer1_m_clearCoatRoughnessMap, uvLayer1[MaterialSrg::m_layer1_m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_layer1_m_clearCoatRoughness, o_layer1_o_clearCoat_roughness_useTexture, - MaterialSrg::m_layer1_m_clearCoatNormalMap, uvLayer1[MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex], IN.m_normal, o_layer1_o_clearCoat_normal_useTexture, MaterialSrg::m_layer1_m_clearCoatNormalStrength, - layer1_uvMatrix, tangents[MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex], - MaterialSrg::m_sampler, isFrontFace, - layer1_clearCoatFactor, layer1_clearCoatRoughness, layer1_clearCoatNormal); - } - - // --- Layer 2 --- - - float layer2_clearCoatFactor = 0.0f; - float layer2_clearCoatRoughness = 0.0f; - float3 layer2_clearCoatNormal = float3(0.0, 0.0, 0.0); - if(o_layer2_o_clearCoat_enabled) - { - float3x3 layer2_uvMatrix = MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_layer2_m_uvMatrix : CreateIdentity3x3(); - - GetClearCoatInputs(MaterialSrg::m_layer2_m_clearCoatInfluenceMap, uvLayer2[MaterialSrg::m_layer2_m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_layer2_m_clearCoatFactor, o_layer2_o_clearCoat_factor_useTexture, - MaterialSrg::m_layer2_m_clearCoatRoughnessMap, uvLayer2[MaterialSrg::m_layer2_m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_layer2_m_clearCoatRoughness, o_layer2_o_clearCoat_roughness_useTexture, - MaterialSrg::m_layer2_m_clearCoatNormalMap, uvLayer2[MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex], IN.m_normal, o_layer2_o_clearCoat_normal_useTexture, MaterialSrg::m_layer2_m_clearCoatNormalStrength, - layer2_uvMatrix, tangents[MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex], - MaterialSrg::m_sampler, isFrontFace, - layer2_clearCoatFactor, layer2_clearCoatRoughness, layer2_clearCoatNormal); - } - - // --- Layer 3 --- - - float layer3_clearCoatFactor = 0.0f; - float layer3_clearCoatRoughness = 0.0f; - float3 layer3_clearCoatNormal = float3(0.0, 0.0, 0.0); - if(o_layer3_o_clearCoat_enabled) - { - float3x3 layer3_uvMatrix = MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_layer3_m_uvMatrix : CreateIdentity3x3(); - - GetClearCoatInputs(MaterialSrg::m_layer3_m_clearCoatInfluenceMap, uvLayer3[MaterialSrg::m_layer3_m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_layer3_m_clearCoatFactor, o_layer3_o_clearCoat_factor_useTexture, - MaterialSrg::m_layer3_m_clearCoatRoughnessMap, uvLayer3[MaterialSrg::m_layer3_m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_layer3_m_clearCoatRoughness, o_layer3_o_clearCoat_roughness_useTexture, - MaterialSrg::m_layer3_m_clearCoatNormalMap, uvLayer3[MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex], IN.m_normal, o_layer3_o_clearCoat_normal_useTexture, MaterialSrg::m_layer3_m_clearCoatNormalStrength, - layer3_uvMatrix, tangents[MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex], - MaterialSrg::m_sampler, isFrontFace, - layer3_clearCoatFactor, layer3_clearCoatRoughness, layer3_clearCoatNormal); - } - - // --- Blend Layers --- - - surface.clearCoat.factor = BlendLayers(layer1_clearCoatFactor, layer2_clearCoatFactor, layer3_clearCoatFactor, blendWeights); - surface.clearCoat.roughness = BlendLayers(layer1_clearCoatRoughness, layer2_clearCoatRoughness, layer3_clearCoatRoughness, blendWeights); - - // [GFX TODO][ATOM-14592] This is not the right way to blend the normals. We need to use ReorientTangentSpaceNormal(), and that requires GetClearCoatInputs() to return the normal in TS instead of WS. - surface.clearCoat.normal = BlendLayers(layer1_clearCoatNormal, layer2_clearCoatNormal, layer3_clearCoatNormal, blendWeights); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - surface.clearCoat.normal = normalize(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); - } - - // ------- 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(0); - - - const float alpha = 1.0; - - PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); - - lightingOutput.m_diffuseColor.w = -1; // Disable subsurface scattering - - return lightingOutput; -} - -ForwardPassOutputWithDepth 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_depth = depth; - return OUT; -} - -[earlydepthstencil] -ForwardPassOutput 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; - - return OUT; -} - diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig deleted file mode 100644 index a9be92b7a5..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl.orig +++ /dev/null @@ -1,131 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include -#include -#include -#include -#include - -#include "MaterialInputs/ParallaxInput.azsli" - -#include "MaterialInputs/ParallaxInput.azsli" -COMMON_OPTIONS_PARALLAX(o_layer1_) -COMMON_OPTIONS_PARALLAX(o_layer2_) -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_blendWeights : 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_blendWeights = IN.m_optional_blendMask.rgb; - } - else - { - OUT.m_blendWeights = float3(1,1,1); - } - - 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()) - { - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); - -<<<<<<< HEAD - s_blendMaskFromVertexStream = IN.m_blendMask; -======= - GetDepth_Setup(IN.m_blendWeights); ->>>>>>> Atom/santorac/MultilayerPbrImprovements - - 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); - - OUT.m_depth = depthNDC; - } - - return OUT; -} From be90e62ee798c405dcb1d35da6e38c3a57117c69 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 15 May 2021 14:45:29 -0700 Subject: [PATCH 07/14] Updated the 005_UseDisplacement_With_BlendMaskTexture_AllSameHeight test case to use a displacement blend. After investigation of the artifacts that appear with no displacement blend, I determnined it was not necessayr to address this edge case. --- ...seDisplacement_With_BlendMaskTexture_AllSameHeight.material | 3 --- 1 file changed, 3 deletions(-) diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material index c99b600dbd..512dc79c4d 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material @@ -4,9 +4,6 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", "propertyLayoutVersion": 3, "properties": { - "blend": { - "displacementBlendDistance": 0.0 - }, "layer1_parallax": { "offset": -0.00800000037997961, "textureMap": "" From f7c85141603a5b7cfc99d4c8d493401d4857b422 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 15 May 2021 15:16:40 -0700 Subject: [PATCH 08/14] Made StandardMultilayerPBR automatically set the slider range for displacementBlendDistance to match the total displacement range. --- .../StandardMultilayerPBR_Displacement.lua | 68 +++++++++++-------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index fb9771fa28..3fc7473b3d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -35,23 +35,6 @@ function GetMaterialPropertyDependencies() } end -function GetMergedHeightRange(heightMinMax, offset, factor) - top = offset - bottom = offset - factor - - if(heightMinMax[1] == nil) then - heightMinMax[1] = top - else - heightMinMax[1] = math.max(heightMinMax[1], top) - end - - if(heightMinMax[0] == nil) then - heightMinMax[0] = bottom - else - heightMinMax[0] = math.min(heightMinMax[0], bottom) - end -end - -- These values must align with LayerBlendSource in StandardMultilayerPBR_Common.azsli. LayerBlendSource_BlendMaskTexture = 0 LayerBlendSource_BlendMaskVertexColors = 1 @@ -67,9 +50,31 @@ function BlendSourceUsesDisplacement(context) return blendSourceIncludesDisplacement end -function Process(context) - local enableParallax = context:GetMaterialPropertyValue_bool("parallax.enable") +-- Calculates the min and max displacement height values encompassing all enabled layers. +-- @return a table with two values {min,max}. Negative values are below the surface and positive values are above the surface. +function CalcOverallHeightRange(context) + local heightMinMax = {nil, nil} + + local function GetMergedHeightRange(heightMinMax, offset, factor) + top = offset + bottom = offset - factor + + if(heightMinMax[1] == nil) then + heightMinMax[1] = top + else + heightMinMax[1] = math.max(heightMinMax[1], top) + end + + if(heightMinMax[0] == nil) then + heightMinMax[0] = bottom + else + heightMinMax[0] = math.min(heightMinMax[0], bottom) + end + end + + local enableParallax = context:GetMaterialPropertyValue_bool("parallax.enable") + if(enableParallax or BlendSourceUsesDisplacement(context)) then local hasTextureLayer1 = nil ~= context:GetMaterialPropertyValue_Image("layer1_parallax.textureMap") local hasTextureLayer2 = nil ~= context:GetMaterialPropertyValue_Image("layer2_parallax.textureMap") @@ -94,19 +99,21 @@ function Process(context) local enableLayer2 = context:GetMaterialPropertyValue_bool("blend.enableLayer2") local enableLayer3 = context:GetMaterialPropertyValue_bool("blend.enableLayer3") - local heightMinMax = {nil, nil} - GetMergedHeightRange(heightMinMax, offsetLayer1, factorLayer1) - if(enableLayer2) then GetMergedHeightRange(heightMinMax, offsetLayer2, factorLayer2) end if(enableLayer3) then GetMergedHeightRange(heightMinMax, offsetLayer3, factorLayer3) end - context:SetShaderConstant_float("m_displacementMin", heightMinMax[0]) - context:SetShaderConstant_float("m_displacementMax", heightMinMax[1]) else - context:SetShaderConstant_float("m_displacementMin", 0) - context:SetShaderConstant_float("m_displacementMax", 0) + heightMinMax = {0,0} end + + return heightMinMax +end + +function Process(context) + local heightMinMax = CalcOverallHeightRange(context) + context:SetShaderConstant_float("m_displacementMin", heightMinMax[0]) + context:SetShaderConstant_float("m_displacementMax", heightMinMax[1]) end function ProcessEditor(context) @@ -128,6 +135,13 @@ function ProcessEditor(context) else context:SetMaterialPropertyVisibility("blend.displacementBlendDistance", MaterialPropertyVisibility_Hidden) end - + + -- We set the displacementBlendDistance slider range to match the range of displacement, so the slider will feel good + -- regardless of how big the overall displacement is. Using a soft max allows the user to exceed the limit if desired, + -- but the main reason for the *soft* max is to avoid impacting the value of displacementBlendDistance which could + -- otherwise lead to edge cases. + local heightMinMax = CalcOverallHeightRange(context) + local totalDisplacementRange = heightMinMax[1] - heightMinMax[0] + context:SetMaterialPropertySoftMaxValue_float("blend.displacementBlendDistance", totalDisplacementRange) end From 9683222ce7af9a0cc86fe2335e9b6e9fc68b4e4f Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sun, 16 May 2021 12:52:27 -0700 Subject: [PATCH 09/14] Fixed a pre-existing bug where normals could be length 0. --- Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli index 13e3c652db..6e0209eb3e 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli @@ -52,6 +52,12 @@ float3 GetTangentSpaceNormal_Unnormalized(float2 normalMapSample, float normalSt // The image build pipeline drops the B channel so we have to reconstruct it here. surfaceNormal.z = sqrt(1 - dot(surfaceNormal.xy, surfaceNormal.xy)); + // Don't allow z to be zero just in case normalStrength approaches 0, to avoid a 0-length normal. + // It doesn't make sense anyway to have a surface with a normal map completely tangential. + // This also addresses the possibility of z being NaN, in the case where x^2+y^2 > 1, so we don't need to call saturate in the sqrt operation above. + // (Note this edge case would be particularly evident in multilayer material types, where the normal map is masked out using normalStrength). + surfaceNormal.z = max(surfaceNormal.z, 0.01); + surfaceNormal.xy *= normalStrength; return surfaceNormal; From c84578c37f6846d42ffc39b4bdb2100920be3011 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sun, 16 May 2021 17:54:21 -0700 Subject: [PATCH 10/14] Optimized a bit by skipping layers when the blend weight is 0. This reduced frame time by about 2ms (from 12ms when parallax was off, and from 47ms when parallax was on). --- .../StandardMultilayerPBR_ForwardPass.azsl | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) 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 1fed3acbee..88a3ca29c0 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -386,16 +386,22 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Layer 1 (base layer) ----------- ProcessedMaterialInputs lightingInputLayer1; + if(blendWeights.r > 0) { StandardMaterialInputs inputs; FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer1_, o_layer1_, blendWeights.r) lightingInputLayer1 = ProcessStandardMaterialInputs(inputs); } + else + { + lightingInputLayer1.InitializeToZero(); + blendWeights.r = 0; + } // ----------- Layer 2 ----------- ProcessedMaterialInputs lightingInputLayer2; - if(o_layer2_enabled) + if(o_layer2_enabled && blendWeights.g > 0) { StandardMaterialInputs inputs; FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer2_, o_layer2_, blendWeights.g) @@ -404,12 +410,13 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float else { lightingInputLayer2.InitializeToZero(); + blendWeights.g = 0; } // ----------- Layer 3 ----------- ProcessedMaterialInputs lightingInputLayer3; - if(o_layer3_enabled) + if(o_layer3_enabled && blendWeights.b > 0) { StandardMaterialInputs inputs; FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer3_, o_layer3_, blendWeights.b) @@ -418,6 +425,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float else { lightingInputLayer3.InitializeToZero(); + blendWeights.b = 0; } // ------- Combine all layers --------- @@ -428,12 +436,16 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Combine Normals --------- - float3 normalTS = lightingInputLayer1.m_normalTS; - if(o_layer2_enabled) + float3 normalTS = float3(0,0,1); + if(blendWeights.r > 0) + { + normalTS = lightingInputLayer1.m_normalTS; + } + if(o_layer2_enabled && blendWeights.g > 0) { normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer2.m_normalTS); } - if(o_layer3_enabled) + if(o_layer3_enabled && blendWeights.b > 0) { normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer3.m_normalTS); } From 1d8f5f6f0dc98750121a9a81728fcf10b29dda1b Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Mon, 17 May 2021 15:47:16 -0700 Subject: [PATCH 11/14] Updated to improve the blending of surface properties to have a smoother transition, and remove harsh edges around the blend. It wasn't just a matter of using smoothstep, I had to refactor the code to take a different approach to generating blend weights. We really have to avoid any kind of division for normalization of weights because that causes all the blend functions to become non-linear. So with these changes, the blend weights are calculated based on linear interpretation for displacement-based blending too (before only the non-displacement blending used linear interpolation). With that in place, smoothstep can now be used to give a smooth transition. --- .../Types/StandardMultilayerPBR_Common.azsli | 124 +++++++++++------- .../StandardMultilayerPBR_Displacement.lua | 2 +- .../005_UseDisplacement.material | 4 +- ...isplacement_With_BlendMaskTexture.material | 3 + ...th_BlendMaskTexture_AllSameHeight.material | 3 + ...ith_BlendMaskTexture_NoHeightmaps.material | 3 - ...cement_With_BlendMaskVertexColors.material | 3 +- 7 files changed, 85 insertions(+), 57 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index 469426666d..c20a90c00b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -15,6 +15,7 @@ #include #include #include +#include #include "MaterialInputs/BaseColorInput.azsli" #include "MaterialInputs/RoughnessInput.azsli" @@ -215,13 +216,16 @@ float3 GetApplicableBlendMaskValues(LayerBlendSource blendSource, float2 blendMa float GetSubMinDisplacement() { return MaterialSrg::m_displacementMin - 0.001; + //return MaterialSrg::m_displacementMin - max(MaterialSrg::m_displacementBlendDistance, 0.001); } +float3 ApplyBlendMaskToDepthValues(float3 blendMaskValues, float3 layerDepthValues, float zeroMaskDisplacement); + //! Return the final blend weights to be used for rendering, based on the available data and configuration. //! @param blendSource - indicates where to get the blend mask from -//! @param blendMaskUv - for sampling a blend mask texture, if that's the blend source -//! @param blendMaskVertexColors - the vertex color values to use for the blend mask, if that's the blend source +//! @param blendMaskValues - blend mask values as returned by GetApplicableBlendMaskValues() //! @param layerDepthValues - the depth values for each layer, used if the blend source includes displacement. See GetLayerDepthValues(). +//! Note the blendMaskValues will not be applied here, those should have already been applied to layerDepthValues. //! @param layerDepthBlendDistance - controls how smoothly to blend layers 2 and 3 with the base layer, when the blend source includes displacement. //! When layers are close together their weights will be blended together, otherwise the highest layer will have the full weight. //! @return The blend weights for each layer. @@ -229,7 +233,7 @@ float GetSubMinDisplacement() //! layer1 = r //! layer2 = g //! layer3 = b -float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors, float3 layerDepthValues, float layerDepthBlendDistance) +float3 GetBlendWeights(LayerBlendSource blendSource, float3 blendMaskValues, float3 layerDepthValues, float layerDepthBlendDistance) { float3 blendWeights; @@ -240,8 +244,6 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource) { // Calculate the blend weights based on displacement values... - // Note that any impact from the blend mask will have already been applied to these layerDepthValues in GetLayerDepthValues(). - // So even though there is no blend mask code here, the blend mask is being applied when enabled. // The inputs are depth values, but we change them to height values to make the code a bit more intuitive. float3 layerHeightValues = -layerDepthValues; @@ -258,18 +260,14 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 if(layerDepthBlendDistance > 0.0001) { - - // The blend weights are adjusted to give a smooth transition in the surface appearance. - // We clamp to just under m_displacementMin to prevents areas that have been masked to 0 from affecting - // the blend (because these areas get pushed *below* m_displacementMin a bit in GetLayerDepthValues() too). - float lowestVisiblePoint = max(highestPoint - layerDepthBlendDistance, GetSubMinDisplacement()); - blendWeights = saturate(layerHeightValues - lowestVisiblePoint) / layerDepthBlendDistance; + float lowestVisiblePoint = highestPoint - layerDepthBlendDistance; + blendWeights = smoothstep(lowestVisiblePoint, highestPoint, layerHeightValues); if(!o_layer2_enabled) { blendWeights.y = 0.0; } - + if(!o_layer3_enabled) { blendWeights.z = 0.0; @@ -278,20 +276,21 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 else { blendWeights = float3(layerHeightValues.x >= highestPoint ? 1.0 : 0.0, - layerHeightValues.y >= highestPoint && o_layer2_enabled ? 1.0 : 0.0, - layerHeightValues.z >= highestPoint && o_layer3_enabled ? 1.0 : 0.0); + layerHeightValues.y >= highestPoint && o_layer2_enabled ? 1.0 : 0.0, + layerHeightValues.z >= highestPoint && o_layer3_enabled ? 1.0 : 0.0); } + + // Calculate blend weights such that multiplying and adding them with layer data is equivalent + // to lerping between each layer. + // final = lerp(final, layer1, blendWeights.r) + // final = lerp(final, layer2, blendWeights.g) + // final = lerp(final, layer3, blendWeights.b) - float weightSum = blendWeights.x + blendWeights.y + blendWeights.z; - if(weightSum > 0.0) - { - blendWeights = saturate(blendWeights / weightSum); - } + blendWeights.y = (1 - blendWeights.z) * blendWeights.y; + blendWeights.x = 1 - blendWeights.y - blendWeights.z; } else { - float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, blendMaskUv, blendMaskVertexColors); - // Calculate blend weights such that multiplying and adding them with layer data is equivalent // to lerping between each layer. // final = lerp(final, layer1, blendWeights.r) @@ -312,23 +311,36 @@ float3 GetBlendWeights(LayerBlendSource blendSource, float2 blendMaskUv, float3 return blendWeights; } -float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_ddx, float2 uv_ddy, float3 blendMaskVertexColors); +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); //! Return the final blend weights to be used for rendering, based on the available data and configuration. //! Note this will sample the displacement maps in the case of LayerBlendSource::Displacement. If you have already -//! called GetLayerDepthValues(), use the GetBlendWeights() overload that takes layerDepthValues instead. +//! the layer depth values, use the GetBlendWeights() overload that takes layerDepthValues instead. float3 GetBlendWeights(LayerBlendSource blendSource, float2 uv, float3 blendMaskVertexColors) { float3 layerDepthValues = float3(0,0,0); + + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uv, blendMaskVertexColors); if(blendSource == LayerBlendSource::Displacement || blendSource == LayerBlendSource::Displacement_With_BlendMaskTexture || blendSource == LayerBlendSource::Displacement_With_BlendMaskVertexColors) { - layerDepthValues = GetLayerDepthValues(blendSource, uv, ddx_fine(uv), ddy_fine(uv), blendMaskVertexColors); - } + bool useBlendMask = + LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || + LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource; + + layerDepthValues = GetLayerDepthValues(uv, ddx_fine(uv), ddy_fine(uv)); - return GetBlendWeights(blendSource, uv, blendMaskVertexColors, layerDepthValues, MaterialSrg::m_displacementBlendDistance); + if(useBlendMask) + { + // Unlike the GetDepth() callback used for parallax, we don't just shift the values toward GetSubMinDisplacement(), + // we shift extra to ensure that completely masked-out layers are not blended onto upper layers. + layerDepthValues = ApplyBlendMaskToDepthValues(blendMaskValues, layerDepthValues, GetSubMinDisplacement() - MaterialSrg::m_displacementBlendDistance); + } + } + + return GetBlendWeights(blendSource, blendMaskValues, layerDepthValues, MaterialSrg::m_displacementBlendDistance); } float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeights) @@ -361,8 +373,7 @@ bool ShouldHandleParallaxInDepthShaders() } //! Returns the depth values for each layer. -//! If the blend source is Displacement_With_BlendMaskTexture or Displacement_With_BlendMaskVertexColors, this will use the blend weights to further offset the depth values. -float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_ddx, float2 uv_ddy, float3 blendMaskVertexColors) +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) { float3 layerDepthValues = float3(0,0,0); @@ -419,36 +430,35 @@ float3 GetLayerDepthValues(LayerBlendSource blendSource, float2 uv, float2 uv_dd } - bool useBlendMask = - LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || - LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource; + return layerDepthValues; +} - if(useBlendMask && (o_layer2_enabled || o_layer3_enabled)) - { - // We use the blend mask to lower each layer's surface so that it disappears under the other surfaces. - // Note the blend mask does not apply to the first layer, it is the implicit base layer. Layers 2 and 3 are masked by the r and g channels. - float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uv, blendMaskVertexColors); - +//! Uses a layer blend mask to further displace each layer's surface so that it disappears beyond the other surfaces. +//! Note the blend mask does not apply to the first layer, it is the implicit base layer. Layers 2 and 3 are masked by the r and g channels of the mask. +//! @param blendMaskValues layer mask values as returned by GetApplicableBlendMaskValues() +//! @param layerDepthValues layer depth values as returned by GetLayerDepthValues() +//! @param zeroMaskDisplacement the target displacement value that corresponds to a mask value of 0 +//! @return new layer depth values that have been adjusted according to the layerMaskValues +float3 ApplyBlendMaskToDepthValues(float3 blendMaskValues, float3 layerDepthValues, float zeroMaskDisplacement) +{ + if(o_layer2_enabled || o_layer3_enabled) + { // We add to the depth value rather than lerp toward m_displacementMin to avoid squashing the topology, but instead lower it out of sight. - // Regarding GetSubMinDisplacement(), when a mask of 0 pushes the surface all the way to the bottom, we want that - // to go a little below the min so it will disappear if there is something else right at the min. - if(o_layer2_enabled) { - float dropoffRange = MaterialSrg::m_layer2_m_depthOffset - GetSubMinDisplacement(); + float dropoffRange = MaterialSrg::m_layer2_m_depthOffset - zeroMaskDisplacement; layerDepthValues.g += dropoffRange * (1-blendMaskValues.r); } if(o_layer3_enabled) { - float dropoffRange = MaterialSrg::m_layer3_m_depthOffset - GetSubMinDisplacement(); + float dropoffRange = MaterialSrg::m_layer3_m_depthOffset - zeroMaskDisplacement; layerDepthValues.b += dropoffRange * (1-blendMaskValues.g); } } - return layerDepthValues; } @@ -457,18 +467,32 @@ DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) { LayerBlendSource blendSource = GetFinalLayerBlendSource(); - float3 layerDepthValues = GetLayerDepthValues(blendSource, uv, uv_ddx, uv_ddy, s_blendMaskFromVertexStream); + float3 layerDepthValues = GetLayerDepthValues(uv, uv_ddx, uv_ddy); + + // Note, when the blend source uses the blend mask from the vertex colors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values + // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be as noticeable if + // you have a small depth factor relative to the size of the blend transition. + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uv, s_blendMaskFromVertexStream); + + bool useBlendMask = + LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || + LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource; + + if(useBlendMask) + { + // Regarding GetSubMinDisplacement(), when a mask of 0 pushes the surface all the way to the bottom, we want that + // to go a little below the min so it will disappear if there is something else right at the min. + + layerDepthValues = ApplyBlendMaskToDepthValues(blendMaskValues, layerDepthValues, GetSubMinDisplacement()); + } // When blending the depth together, we don't use MaterialSrg::m_displacementBlendDistance. The intention is that m_displacementBlendDistance // is for transitioning the appearance of the surface itself, but we still want a distinct change in the heightmap. If someday we want to // support smoothly blending the depth as well, there is a bit more work to do to get it to play nice with the blend mask code in GetLayerDepthValues(). float layerDepthBlendDistance = 0.0f; - - // Note, when the blend source uses the blend mask from the vertex colors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values - // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be as noticeable if - // you have a small depth factor relative to the size of the blend transition. - float3 blendWeightValues = GetBlendWeights(blendSource, uv, s_blendMaskFromVertexStream, layerDepthValues, layerDepthBlendDistance); - + float3 blendWeightValues = GetBlendWeights(blendSource, blendMaskValues, layerDepthValues, layerDepthBlendDistance); + float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); + return DepthResultAbsolute(depth); } diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index 3fc7473b3d..34a067577d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -142,6 +142,6 @@ function ProcessEditor(context) -- otherwise lead to edge cases. local heightMinMax = CalcOverallHeightRange(context) local totalDisplacementRange = heightMinMax[1] - heightMinMax[0] - context:SetMaterialPropertySoftMaxValue_float("blend.displacementBlendDistance", totalDisplacementRange) + context:SetMaterialPropertySoftMaxValue_float("blend.displacementBlendDistance", math.max(totalDisplacementRange, 0.001)) end diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material index cf4c6cb531..55a4774d49 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -6,7 +6,7 @@ "properties": { "blend": { "blendSource": "Displacement", - "displacementBlendDistance": 0.003, + "displacementBlendDistance": 0.008999999612569809, "enableLayer2": true, "enableLayer3": true }, @@ -21,7 +21,7 @@ }, "layer1_parallax": { "factor": 0.017000000923871995, - "offset": -0.009999999776482582, + "offset": -0.006000000052154064, "textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg" }, "layer1_roughness": { diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material index fe30d5caf2..6b062f6d1e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material @@ -6,6 +6,9 @@ "properties": { "blend": { "blendSource": "Displacement_With_BlendMaskTexture" + }, + "layer1_parallax": { + "offset": -0.004000000189989805 } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material index 512dc79c4d..0e6519afd4 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material @@ -4,6 +4,9 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", "propertyLayoutVersion": 3, "properties": { + "blend": { + "displacementBlendDistance": 0.0010000000474974514 + }, "layer1_parallax": { "offset": -0.00800000037997961, "textureMap": "" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material index 6d6d952698..b5b5656084 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material @@ -4,9 +4,6 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", "propertyLayoutVersion": 3, "properties": { - "blend": { - "displacementBlendDistance": 0.00279999990016222 - }, "layer1_parallax": { "offset": -0.03200000151991844, "textureMap": "" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material index 12fb6943d7..8461ea429c 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material @@ -5,7 +5,8 @@ "propertyLayoutVersion": 3, "properties": { "blend": { - "blendSource": "Displacement_With_BlendMaskVertexColors" + "blendSource": "Displacement_With_BlendMaskVertexColors", + "displacementBlendDistance": 0.02387000061571598 }, "parallax": { "enable": false From 599877a7e12479f889708efa1f0080f426878c97 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Thu, 20 May 2021 12:13:52 -0700 Subject: [PATCH 12/14] Updated atom_feature_common_asset_files.cmake to reflect recent lua functor file changes. --- .../Common/Assets/atom_feature_common_asset_files.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index f1d8fa81be..841cdf67c8 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 @@ -33,11 +33,11 @@ set(FILES Materials/Types/StandardMultilayerPBR_Common.azsli Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.shader + Materials/Types/StandardMultilayerPBR_Displacement.lua Materials/Types/StandardMultilayerPBR_ForwardPass.azsl Materials/Types/StandardMultilayerPBR_ForwardPass.shader Materials/Types/StandardMultilayerPBR_ForwardPass_EDS.shader - Materials/Types/StandardMultilayerPBR_Parallax.lua - Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua + Materials/Types/StandardMultilayerPBR_LayerEnable.lua Materials/Types/StandardMultilayerPBR_ShaderEnable.lua Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.shader From 4086edc3f7fdf95b8d7b8e2b463d6bc150c3d17f Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Thu, 20 May 2021 12:14:33 -0700 Subject: [PATCH 13/14] Moved the debug view mode setting to the "blend" group because the only modes we have right now are related to layer blending. --- .../Types/StandardMultilayerPBR.materialtype | 35 +++++++++---------- .../003_Debug_BlendMask.material | 2 +- .../003_Debug_BlendWeights.material | 2 +- .../003_Debug_Displacement.material | 2 +- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index 88bd87a494..274cb4dcb5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -3,11 +3,6 @@ "propertyLayout": { "version": 3, "groups": [ - { - "id": "general", - "displayName": "General", - "description": "General settings." - }, { "id": "blend", "displayName": "Blend Settings", @@ -29,6 +24,11 @@ "displayName": "Irradiance", "description": "Properties for configuring the irradiance used in global illumination." }, + { + "id": "general", + "displayName": "General", + "description": "General settings." + }, //############################################################################################## // Layer 1 Groups //############################################################################################## @@ -194,18 +194,6 @@ // General Properties //############################################################################################## "general": [ - { - "id": "debugDrawMode", - "displayName": "Debug Draw Mode", - "description": "Enables various debug view features.", - "type": "Enum", - "enumValues": [ "None", "BlendMask", "Displacement", "FinalBlendWeights" ], - "defaultValue": "None", - "connection": { - "type": "ShaderOption", - "id": "o_debugDrawMode" - } - }, { "id": "applySpecularAA", "displayName": "Apply Specular AA", @@ -365,8 +353,19 @@ "type": "ShaderInput", "id": "m_displacementBlendDistance" } + }, + { + "id": "debugDrawMode", + "displayName": "Debug Draw Mode", + "description": "Enables various debug view features.", + "type": "Enum", + "enumValues": [ "None", "BlendMask", "Displacement", "FinalBlendWeights" ], + "defaultValue": "None", + "connection": { + "type": "ShaderOption", + "id": "o_debugDrawMode" + } } - ], "parallax": [ { diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material index df81b9b25a..ffcbf3ce7e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material @@ -4,7 +4,7 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "propertyLayoutVersion": 3, "properties": { - "general": { + "blend": { "debugDrawMode": "BlendMask" } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material index 4cd6546028..8d13ac781f 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material @@ -4,7 +4,7 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "propertyLayoutVersion": 3, "properties": { - "general": { + "blend": { "debugDrawMode": "FinalBlendWeights" } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material index fb4db87c2c..7aff50cb56 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material @@ -4,7 +4,7 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "propertyLayoutVersion": 3, "properties": { - "general": { + "blend": { "debugDrawMode": "Displacement" } } From f6b9f0e0fb060d5fe5d07613ee41da6ce104ce52 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Thu, 20 May 2021 17:02:26 -0700 Subject: [PATCH 14/14] Reversed the debug view for displacement to show height instead of depth. Also add a LerpInverse utility, though I ended up not using it with these changes, it should be handle elsewhere. --- .../Types/StandardMultilayerPBR_ForwardPass.azsl | 7 +++++-- Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli | 13 +++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) 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 88a3ca29c0..41658b114a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -342,8 +342,11 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float if(o_debugDrawMode == DebugDrawMode::Displacement) { - float depth = GetNormalizedDepth(-MaterialSrg::m_displacementMax, -MaterialSrg::m_displacementMin, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); - return DebugOutput(float3(depth,depth,depth)); + float startDepth = -MaterialSrg::m_displacementMax; + float stopDepth = -MaterialSrg::m_displacementMin; + float depth = GetNormalizedDepth(startDepth, stopDepth, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); + float height = 1 - saturate(depth); + return DebugOutput(float3(height,height,height)); } if(o_debugDrawMode == DebugDrawMode::FinalBlendWeights) diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli index 2381febed0..0bd115d3cc 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli @@ -225,3 +225,16 @@ float NextRandomFloatUniform(inout uint seed) seed = Xorshift(seed); return (float)seed / 4294967295.0f; } + +//! Returns the inverse of lerp, 't', such that value = lerp(a, b, t), or returns 0 when a == b. +float LerpInverse(float a, float b, float value) +{ + if(abs(a - b) <= EPSILON) + { + return 0.0; + } + else + { + return (value - a) / (b - a); + } +} \ No newline at end of file