Skip to content

Commit ee2edcb

Browse files
authored
Allow passing customized derivatives to texture sampling functions (o3de#17577)
Signed-off-by: Li Hongshan <[email protected]>
1 parent 373f177 commit ee2edcb

22 files changed

+708
-155
lines changed

Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.azsli

Lines changed: 79 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
303303

304304
//! Processes the set of Standard material inputs for a single layer.
305305
//! The FILL_STANDARD_MATERIAL_INPUTS() macro below can be used to fill the StandardMaterialInputs struct.
306-
ProcessedMaterialInputs ProcessStandardMaterialInputs(StandardMaterialInputs inputs)
306+
ProcessedMaterialInputs ProcessStandardMaterialInputs(StandardMaterialInputs inputs, float4 uvDxDy = float4(0.0f, 0.0f, 0.0f, 0.0f), bool customDerivatives = false)
307307
{
308308
ProcessedMaterialInputs result;
309309

@@ -312,17 +312,17 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
312312
transformedUv[1] = inputs.m_vertexUv[1];
313313

314314
real3x3 normalUvMatrix = inputs.m_normalMapUvIndex == 0 ? real3x3(inputs.m_uvMatrix) : real3x3(CreateIdentity3x3());
315-
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, real(inputs.m_normalFactor));
315+
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, real(inputs.m_normalFactor), uvDxDy, customDerivatives);
316316

317-
real3 sampledBaseColor = GetBaseColorInput(inputs.m_baseColorMap, inputs.m_sampler, transformedUv[inputs.m_baseColorMapUvIndex], real3(inputs.m_baseColor.rgb), inputs.m_baseColor_useTexture);
317+
real3 sampledBaseColor = GetBaseColorInput(inputs.m_baseColorMap, inputs.m_sampler, transformedUv[inputs.m_baseColorMapUvIndex], real3(inputs.m_baseColor.rgb), inputs.m_baseColor_useTexture, uvDxDy, customDerivatives);
318318
result.m_baseColor = BlendBaseColor(sampledBaseColor, real3(inputs.m_baseColor.rgb), real(inputs.m_baseColorFactor), inputs.m_baseColorTextureBlendMode, inputs.m_baseColor_useTexture);
319-
result.m_specularF0Factor = GetSpecularInput(inputs.m_specularF0Map, inputs.m_sampler, transformedUv[inputs.m_specularF0MapUvIndex], real(inputs.m_specularF0Factor), inputs.m_specularF0_useTexture);
320-
result.m_metallic = GetMetallicInput(inputs.m_metallicMap, inputs.m_sampler, transformedUv[inputs.m_metallicMapUvIndex], real(inputs.m_metallicFactor), inputs.m_metallic_useTexture);
321-
result.m_roughness = GetRoughnessInput(inputs.m_roughnessMap, MaterialSrg::m_sampler, transformedUv[inputs.m_roughnessMapUvIndex], real(inputs.m_roughnessFactor), real(inputs.m_roughnessLowerBound), real(inputs.m_roughnessUpperBound), inputs.m_roughness_useTexture);
319+
result.m_specularF0Factor = GetSpecularInput(inputs.m_specularF0Map, inputs.m_sampler, transformedUv[inputs.m_specularF0MapUvIndex], real(inputs.m_specularF0Factor), inputs.m_specularF0_useTexture, uvDxDy, customDerivatives);
320+
result.m_metallic = GetMetallicInput(inputs.m_metallicMap, inputs.m_sampler, transformedUv[inputs.m_metallicMapUvIndex], real(inputs.m_metallicFactor), inputs.m_metallic_useTexture, uvDxDy, customDerivatives);
321+
result.m_roughness = GetRoughnessInput(inputs.m_roughnessMap, MaterialSrg::m_sampler, transformedUv[inputs.m_roughnessMapUvIndex], real(inputs.m_roughnessFactor), real(inputs.m_roughnessLowerBound), real(inputs.m_roughnessUpperBound), inputs.m_roughness_useTexture, uvDxDy, customDerivatives);
322322

323-
result.m_emissiveLighting = GetEmissiveInput(inputs.m_emissiveMap, inputs.m_sampler, transformedUv[inputs.m_emissiveMapUvIndex], real(inputs.m_emissiveIntensity), real3(inputs.m_emissiveColor.rgb), 0.0, 1.0, inputs.m_emissiveEnabled, inputs.m_emissive_useTexture);
324-
result.m_diffuseAmbientOcclusion = GetOcclusionInput(inputs.m_diffuseOcclusionMap, inputs.m_sampler, transformedUv[inputs.m_diffuseOcclusionMapUvIndex], real(inputs.m_diffuseOcclusionFactor), inputs.m_diffuseOcclusion_useTexture);
325-
result.m_specularOcclusion = GetOcclusionInput(inputs.m_specularOcclusionMap, MaterialSrg::m_sampler, transformedUv[inputs.m_specularOcclusionMapUvIndex], real(inputs.m_specularOcclusionFactor), inputs.m_specularOcclusion_useTexture);
323+
result.m_emissiveLighting = GetEmissiveInput(inputs.m_emissiveMap, inputs.m_sampler, transformedUv[inputs.m_emissiveMapUvIndex], real(inputs.m_emissiveIntensity), real3(inputs.m_emissiveColor.rgb), 0.0, 1.0, inputs.m_emissiveEnabled, inputs.m_emissive_useTexture, uvDxDy, customDerivatives);
324+
result.m_diffuseAmbientOcclusion = GetOcclusionInput(inputs.m_diffuseOcclusionMap, inputs.m_sampler, transformedUv[inputs.m_diffuseOcclusionMapUvIndex], real(inputs.m_diffuseOcclusionFactor), inputs.m_diffuseOcclusion_useTexture, uvDxDy, customDerivatives);
325+
result.m_specularOcclusion = GetOcclusionInput(inputs.m_specularOcclusionMap, MaterialSrg::m_sampler, transformedUv[inputs.m_specularOcclusionMapUvIndex], real(inputs.m_specularOcclusionFactor), inputs.m_specularOcclusion_useTexture, uvDxDy, customDerivatives);
326326

327327
#if ENABLE_CLEAR_COAT
328328
result.m_clearCoat.InitializeToZero();
@@ -335,7 +335,7 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
335335
inputs.m_clearCoatNormalMap, transformedUv[inputs.m_clearCoatNormalMapUvIndex], inputs.m_normal, inputs.m_clearCoat_normal_useTexture, real(inputs.m_clearCoatNormalStrength),
336336
clearCoatUvMatrix, inputs.m_tangents[inputs.m_clearCoatNormalMapUvIndex], inputs.m_bitangents[inputs.m_clearCoatNormalMapUvIndex],
337337
inputs.m_sampler, inputs.m_isFrontFace,
338-
result.m_clearCoat.factor, result.m_clearCoat.roughness, result.m_clearCoat.normal);
338+
result.m_clearCoat.factor, result.m_clearCoat.roughness, result.m_clearCoat.normal, uvDxDy, customDerivatives);
339339
}
340340
#endif
341341

@@ -427,15 +427,17 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
427427
float2 uvs[UvSetCount],
428428
bool isFrontFace,
429429
bool isDisplacementClipped,
430-
float3 vertexBlendMask)
430+
float3 vertexBlendMask,
431+
float4 uvDxDy,
432+
bool customDerivatives)
431433
{
432434
LayerBlendSource blendSource = GetFinalLayerBlendSource();
433435

434436
// ------- Debug Modes -------
435437

436438
if(o_debugDrawMode == DebugDrawMode::BlendMask)
437439
{
438-
float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask);
440+
float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask, uvDxDy, customDerivatives);
439441
return MakeDebugSurface(positionWS, normalWS, real3(blendMaskValues));
440442
}
441443

@@ -450,14 +452,31 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
450452

451453
if(o_debugDrawMode == DebugDrawMode::FinalBlendWeights)
452454
{
453-
float3 blendWeights = GetBlendWeights(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask);
455+
float3 blendWeights;
456+
if (customDerivatives)
457+
{
458+
blendWeights = GetBlendWeights(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask, uvDxDy, customDerivatives);
459+
}
460+
else
461+
{
462+
blendWeights = GetBlendWeights(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask, float4(0.0f, 0.0f, 0.0f, 0.0f), false);
463+
}
454464
return MakeDebugSurface(positionWS, normalWS, real3(blendWeights));
455465
}
456466

457467
// ------- Calculate Layer Blend Mask Values -------
458468

459469
// Now that any parallax has been calculated, we calculate the blend factors for any layers that are impacted by the parallax.
460-
real3 blendWeights = (GetBlendWeights(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask));
470+
real3 blendWeights;
471+
if (customDerivatives)
472+
{
473+
blendWeights = real3(GetBlendWeights(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask, uvDxDy, customDerivatives));
474+
}
475+
else
476+
{
477+
blendWeights = real3(GetBlendWeights(blendSource, uvs[MaterialSrg::m_blendMaskUvIndex], vertexBlendMask, float4(0.0f, 0.0f, 0.0f, 0.0f), false));
478+
}
479+
461480

462481
// ------- Layer 1 (base layer) -----------
463482

@@ -467,7 +486,7 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
467486
StandardMaterialInputs inputs;
468487
FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer1_, o_layer1_, blendWeights.r)
469488
FILL_STANDARD_MATERIAL_INPUTS_CLEAR_COAT(inputs, MaterialSrg::m_layer1_, o_layer1_, blendWeights.r)
470-
lightingInputLayer1 = ProcessStandardMaterialInputs(inputs);
489+
lightingInputLayer1 = ProcessStandardMaterialInputs(inputs, uvDxDy, customDerivatives);
471490
}
472491
else
473492
{
@@ -483,7 +502,7 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
483502
StandardMaterialInputs inputs;
484503
FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer2_, o_layer2_, blendWeights.g)
485504
FILL_STANDARD_MATERIAL_INPUTS_CLEAR_COAT(inputs, MaterialSrg::m_layer2_, o_layer2_, blendWeights.g)
486-
lightingInputLayer2 = ProcessStandardMaterialInputs(inputs);
505+
lightingInputLayer2 = ProcessStandardMaterialInputs(inputs, uvDxDy, customDerivatives);
487506
}
488507
else
489508
{
@@ -499,7 +518,7 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
499518
StandardMaterialInputs inputs;
500519
FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer3_, o_layer3_, blendWeights.b)
501520
FILL_STANDARD_MATERIAL_INPUTS_CLEAR_COAT(inputs, MaterialSrg::m_layer3_, o_layer3_, blendWeights.b)
502-
lightingInputLayer3 = ProcessStandardMaterialInputs(inputs);
521+
lightingInputLayer3 = ProcessStandardMaterialInputs(inputs, uvDxDy, customDerivatives);
503522
}
504523
else
505524
{
@@ -572,6 +591,46 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
572591
return surface;
573592
}
574593

594+
// helper function to keep compatible with the previous version
595+
// because dxc compiler doesn't allow default parameters on functions with overloads
596+
Surface EvaluateSurface_StandardMultilayerPBR(
597+
float3 positionWS,
598+
real3 normalWS,
599+
real3 tangents[UvSetCount],
600+
real3 bitangents[UvSetCount],
601+
float2 uvs[UvSetCount],
602+
bool isFrontFace,
603+
bool isDisplacementClipped,
604+
float3 vertexBlendMask)
605+
{
606+
return EvaluateSurface_StandardMultilayerPBR(
607+
positionWS,
608+
normalWS,
609+
tangents,
610+
bitangents,
611+
uvs,
612+
isFrontFace,
613+
isDisplacementClipped,
614+
vertexBlendMask,
615+
float4(0.0f, 0.0f, 0.0f, 0.0f),
616+
false);
617+
}
618+
619+
Surface EvaluateSurface_StandardMultilayerPBR(VsOutput IN, PixelGeometryData geoData, float4 uvDxDy, bool customDerivatives)
620+
{
621+
return EvaluateSurface_StandardMultilayerPBR(
622+
geoData.positionWS,
623+
geoData.vertexNormal,
624+
geoData.tangents,
625+
geoData.bitangents,
626+
geoData.uvs,
627+
geoData.isFrontFace,
628+
geoData.isDisplacementClipped,
629+
geoData.m_vertexBlendMask,
630+
uvDxDy,
631+
customDerivatives);
632+
}
633+
575634
Surface EvaluateSurface_StandardMultilayerPBR(VsOutput IN, PixelGeometryData geoData)
576635
{
577636
return EvaluateSurface_StandardMultilayerPBR(
@@ -582,7 +641,9 @@ option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opa
582641
geoData.uvs,
583642
geoData.isFrontFace,
584643
geoData.isDisplacementClipped,
585-
geoData.m_vertexBlendMask);
644+
geoData.m_vertexBlendMask,
645+
float4(0.0f, 0.0f, 0.0f, 0.0f),
646+
false);
586647
}
587648

588649
#elif MATERIALPIPELINE_SHADER_HAS_GEOMETRIC_PIXEL_STAGE

Gems/Atom/Feature/Common/Assets/Shaders/Materials/BasePBR/BasePBR_SurfaceEval.azsli

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ Surface EvaluateSurface_BasePBR(
2323
real3 tangents[UvSetCount],
2424
real3 bitangents[UvSetCount],
2525
float2 uvs[UvSetCount],
26-
bool isFrontFace)
26+
bool isFrontFace,
27+
float4 uvDxDy,
28+
bool customDerivatives)
2729
{
2830
Surface surface;
2931
surface.position = positionWS;
@@ -33,37 +35,79 @@ Surface EvaluateSurface_BasePBR(
3335
surface.vertexNormal = vertexNormal;
3436
float2 normalUv = uvs[MaterialSrg::m_normalMapUvIndex];
3537
real3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? real3x3(MaterialSrg::m_uvMatrix) : real3x3(CreateIdentity3x3()); // By design, only UV0 is allowed to apply transforms.
36-
surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, vertexNormal,
37-
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, real(MaterialSrg::m_normalFactor));
38+
if (customDerivatives)
39+
{
40+
surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, vertexNormal,
41+
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, real(MaterialSrg::m_normalFactor), uvDxDy, customDerivatives);
42+
}
43+
else
44+
{
45+
surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, vertexNormal,
46+
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, real(MaterialSrg::m_normalFactor), float4(0.0f, 0.0f, 0.0f, 0.0f), false);
47+
}
3848

3949
// ------- Base Color -------
4050

4151
float2 baseColorUv = uvs[MaterialSrg::m_baseColorMapUvIndex];
42-
real3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, real3(MaterialSrg::m_baseColor.rgb), o_baseColor_useTexture);
52+
real3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, real3(MaterialSrg::m_baseColor.rgb), o_baseColor_useTexture, uvDxDy, customDerivatives);
4353
real3 baseColor = BlendBaseColor(sampledColor, real3(MaterialSrg::m_baseColor.rgb), real(MaterialSrg::m_baseColorFactor), o_baseColorTextureBlendMode, o_baseColor_useTexture);
4454

4555
// ------- Metallic -------
4656

4757
float2 metallicUv = uvs[MaterialSrg::m_metallicMapUvIndex];
48-
real metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, real(MaterialSrg::m_metallicFactor), o_metallic_useTexture);
58+
real metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, real(MaterialSrg::m_metallicFactor), o_metallic_useTexture, uvDxDy, customDerivatives);
4959

5060
// ------- Specular -------
5161

5262
float2 specularUv = uvs[MaterialSrg::m_specularF0MapUvIndex];
53-
real specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, real(MaterialSrg::m_specularF0Factor), o_specularF0_useTexture);
63+
real specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, real(MaterialSrg::m_specularF0Factor), o_specularF0_useTexture, uvDxDy, customDerivatives);
5464

5565
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
5666

5767
// ------- Roughness -------
5868

5969
float2 roughnessUv = uvs[MaterialSrg::m_roughnessMapUvIndex];
6070
surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, real(MaterialSrg::m_roughnessFactor),
61-
real(MaterialSrg::m_roughnessLowerBound), real(MaterialSrg::m_roughnessUpperBound), o_roughness_useTexture);
71+
real(MaterialSrg::m_roughnessLowerBound), real(MaterialSrg::m_roughnessUpperBound), o_roughness_useTexture, uvDxDy, customDerivatives);
6272
surface.CalculateRoughnessA();
6373

6474
return surface;
6575
}
6676

77+
// helper function to keep compatible with the previous version
78+
// because dxc compiler doesn't allow default parameters on functions with overloads
79+
Surface EvaluateSurface_BasePBR(
80+
float3 positionWS,
81+
real3 vertexNormal,
82+
real3 tangents[UvSetCount],
83+
real3 bitangents[UvSetCount],
84+
float2 uvs[UvSetCount],
85+
bool isFrontFace)
86+
{
87+
return EvaluateSurface_BasePBR(
88+
positionWS,
89+
vertexNormal,
90+
tangents,
91+
bitangents,
92+
uvs,
93+
isFrontFace,
94+
float4(0.0f, 0.0f, 0.0f, 0.0f),
95+
false);
96+
}
97+
98+
Surface EvaluateSurface_BasePBR(VsOutput IN, PixelGeometryData geoData, float4 uvDxDy, bool customDerivatives)
99+
{
100+
return EvaluateSurface_BasePBR(
101+
geoData.positionWS,
102+
geoData.vertexNormal,
103+
geoData.tangents,
104+
geoData.bitangents,
105+
geoData.uvs,
106+
geoData.isFrontFace,
107+
uvDxDy,
108+
customDerivatives);
109+
}
110+
67111
Surface EvaluateSurface_BasePBR(VsOutput IN, PixelGeometryData geoData)
68112
{
69113
return EvaluateSurface_BasePBR(
@@ -72,5 +116,7 @@ Surface EvaluateSurface_BasePBR(VsOutput IN, PixelGeometryData geoData)
72116
geoData.tangents,
73117
geoData.bitangents,
74118
geoData.uvs,
75-
geoData.isFrontFace);
119+
geoData.isFrontFace,
120+
float4(0.0f, 0.0f, 0.0f, 0.0f),
121+
false);
76122
}

0 commit comments

Comments
 (0)