Merge branch 'Atom/santorac/MultilayerPbrImprovements' into Atom/santorac/DepthBasedLayerBlending
This commit is contained in:
@@ -199,7 +199,7 @@
|
||||
"displayName": "Debug Draw Mode",
|
||||
"description": "Enables various debug view features.",
|
||||
"type": "Enum",
|
||||
"enumValues": [ "None", "BlendSource", "DepthMaps" ],
|
||||
"enumValues": [ "None", "BlendSource", "DisplacementMaps" ],
|
||||
"defaultValue": "None",
|
||||
"connection": {
|
||||
"type": "ShaderOption",
|
||||
@@ -322,11 +322,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"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+58
-22
@@ -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.
|
||||
@@ -95,14 +95,11 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial
|
||||
|
||||
// ------ Shader Options ----------------------------------------
|
||||
|
||||
option bool o_layer2_enabled;
|
||||
option bool o_layer3_enabled;
|
||||
|
||||
enum class DebugDrawMode { None, BlendSource, DepthMaps };
|
||||
enum class DebugDrawMode { None, BlendSource, 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.
|
||||
@@ -111,32 +108,35 @@ option BlendMaskSource o_blendSource;
|
||||
option bool o_blendMask_isBound;
|
||||
|
||||
// ------ Blend Utilities ----------------------------------------
|
||||
|
||||
// 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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +175,19 @@ float3 GetBlendSourceValues(float2 uv)
|
||||
return blendSourceValues;
|
||||
}
|
||||
|
||||
//! 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)
|
||||
{
|
||||
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.
|
||||
//! @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.
|
||||
@@ -207,6 +220,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.
|
||||
//! 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 blendWeights)
|
||||
{
|
||||
return dot(float3(layer1, layer2, layer3), blendWeights);
|
||||
@@ -236,8 +264,8 @@ bool ShouldHandleParallaxInDepthShaders()
|
||||
return ShouldHandleParallax() && o_parallax_enablePixelDepthOffset;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -279,12 +307,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 blendWeights = GetBlendWeights(uv);
|
||||
float3 blendWeightValues = GetBlendWeights(uv, s_blendWeightsFromVertexStream, layerDepthValues);
|
||||
|
||||
float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeights);
|
||||
float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues);
|
||||
return DepthResultAbsolute(depth);
|
||||
}
|
||||
|
||||
+3
-3
@@ -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;
|
||||
|
||||
+8
-8
@@ -94,7 +94,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>
|
||||
@@ -112,11 +112,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
|
||||
@@ -332,13 +332,13 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
|
||||
|
||||
// ------- Debug Modes -------
|
||||
|
||||
if(o_debugDrawMode == DebugDrawMode::BlendSource)
|
||||
if(o_debugDrawMode == DebugDrawMode::BlendMaskValues)
|
||||
{
|
||||
float3 blendSource = GetBlendSourceValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]);
|
||||
return DebugOutput(blendSource);
|
||||
float3 blendMaskValues = GetBlendMaskValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]);
|
||||
return DebugOutput(blendMaskValues);
|
||||
}
|
||||
|
||||
if(o_debugDrawMode == DebugDrawMode::DepthMaps)
|
||||
if(o_debugDrawMode == DebugDrawMode::DisplacementMaps)
|
||||
{
|
||||
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));
|
||||
@@ -434,7 +434,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
|
||||
|
||||
// ------- Combine Albedo, roughness, specular, roughness ---------
|
||||
|
||||
float3 baseColor = BlendLayers(lightingInputLayer1.m_baseColor, lightingInputLayer2.m_baseColor, lightingInputLayer3.m_baseColor, blendWeights);
|
||||
float3 baseColor = BlendLayers(layer1_baseColor, layer2_baseColor, layer3_baseColor, blendMaskValues);
|
||||
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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+3
-3
@@ -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;
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"general": {
|
||||
"debugDrawMode": "BlendSource"
|
||||
"debugDrawMode": "BlendMaskValues"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"general": {
|
||||
"debugDrawMode": "DepthMaps"
|
||||
"debugDrawMode": "DisplacementMaps"
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -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
|
||||
Reference in New Issue
Block a user