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.
This commit is contained in:
Chris Santora
2021-05-07 21:26:50 -07:00
parent 4c453bf4b6
commit 4b2802d8db
19 changed files with 228 additions and 84 deletions
@@ -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"
}
},
{
@@ -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);
}
@@ -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;
@@ -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 <Atom/Features/Vertex/VertexHelper.azsli>
@@ -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
@@ -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)
@@ -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;
@@ -5,7 +5,7 @@
"propertyLayoutVersion": 3,
"properties": {
"general": {
"debugDrawMode": "BlendMaskValues"
"debugDrawMode": "BlendWeights"
}
}
}
@@ -5,7 +5,7 @@
"propertyLayoutVersion": 3,
"properties": {
"general": {
"debugDrawMode": "DepthMaps"
"debugDrawMode": "DisplacementMaps"
}
}
}
@@ -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"
}
}
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f9ec269d03a9552c0ecf24778912fa6190c412b006433db8b7c40e1c0c83e6f7
size 516915
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b53c4aca020d5833618a5b73b6578c8693dd14e603eb32681e2c7ecc90f59047
size 1020622
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:46ea8a9406ce6df21ce3a6045aac5b1421ce119919ff050951277dd76464ee2c
size 258716
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ac1ad9bea240374bfc6aaaacc42e24eadfbf93c7185617fc1c52e610cb45cb69
size 1292910
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8fce266a7445a4d4b5bb3fbf7cb3330e0580b058aeaf2ef7f265a01641dbbdc4
size 637326
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ca54f762bcddc10ab2d609f10864328cb5a567c43efb8c9bcfe9cb2955db9577
size 433887
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5b5f5ff297aef6470045d087cf0c3341f7782e36a750965a052d49d03dd37426
size 1595449
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c8753448320e0916a70036ef77a06bce746bfa45c14e62b2fbda0987a13bfbb3
size 277114
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5ea23ea8d85d1fffa119e481e6ac85ad3a3096470a5e12f252d37e1b293e5e37
size 2119669
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:caa6e94f904135461da4d200fc6c21c86dc99cc7d413ea740e678f7758b2b156
size 555680