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.
This commit is contained in:
+94
-90
@@ -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",
|
||||
|
||||
+97
-93
@@ -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);
|
||||
|
||||
+37
-25
@@ -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
|
||||
|
||||
-49
@@ -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
|
||||
-3
@@ -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"
|
||||
},
|
||||
|
||||
-2
@@ -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"
|
||||
|
||||
+1
-4
@@ -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"
|
||||
},
|
||||
|
||||
+23
@@ -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": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -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": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user