You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb none #jira none #preflight shader #fyi sebastien.hillaire [CL 20449809 by Charles deRousiers in ue5-main branch]
688 lines
24 KiB
Plaintext
688 lines
24 KiB
Plaintext
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "../Common.ush"
|
|
|
|
struct FStrataLegacyParameters
|
|
{
|
|
FStrataPixelFootprint PixelFootprint;
|
|
bool UseMetalness;
|
|
float3 DiffuseAlbedo;
|
|
float3 F0;
|
|
float3 F90;
|
|
|
|
float3 BaseColor;
|
|
float Specular;
|
|
float Metallic;
|
|
float Roughness;
|
|
float Anisotropy;
|
|
float SSSProfileID;
|
|
float3 SSSMFP;
|
|
float SSSMFPScale;
|
|
float SSSPhaseAniso;
|
|
bool UseSSSDiffusion;
|
|
float3 Emissive;
|
|
float FuzzAmount;
|
|
float3 FuzzColor;
|
|
float Thickness;
|
|
uint SharedLocalBasisIndex;
|
|
|
|
int LayerDepth;
|
|
int bIsBottom;
|
|
|
|
float Weight;
|
|
};
|
|
|
|
FStrataLegacyParameters InitStrataLegacyParameters(FStrataPixelFootprint InPixelFootprint, uint InSharedLocalBasisIndex, float InWeight)
|
|
{
|
|
const float3 Zeros = float3(0, 0, 0);
|
|
|
|
FStrataLegacyParameters Out;
|
|
|
|
Out.UseMetalness = true;
|
|
Out.DiffuseAlbedo = Zeros;
|
|
Out.F0 = Zeros;
|
|
Out.F90 = Zeros;
|
|
|
|
Out.BaseColor = Zeros;
|
|
Out.Specular = 0.5f;
|
|
Out.Metallic = 0.f;
|
|
Out.Roughness = 0.5f;
|
|
Out.Anisotropy = 0.f;
|
|
Out.SSSProfileID = 0.f;
|
|
Out.SSSMFP = Zeros;
|
|
Out.SSSMFPScale = 1.f;
|
|
Out.SSSPhaseAniso = 0.f;
|
|
Out.UseSSSDiffusion = false;
|
|
Out.Emissive = Zeros;
|
|
Out.FuzzAmount = 0.f;
|
|
Out.FuzzColor = Zeros;
|
|
Out.Thickness = STRATA_LAYER_DEFAULT_THICKNESS_CM;
|
|
Out.SharedLocalBasisIndex = InSharedLocalBasisIndex;
|
|
Out.LayerDepth = 0;
|
|
Out.bIsBottom = 1;
|
|
Out.Weight = InWeight;
|
|
Out.PixelFootprint = InPixelFootprint;
|
|
return Out;
|
|
}
|
|
|
|
FStrataData CreateLegacySlab(
|
|
FStrataLegacyParameters In, inout uint SharedLocalBasisTypes,
|
|
inout FStrataTree StrataTree,
|
|
int OperatorIndex, int BSDFIndex)
|
|
{
|
|
const float3 Zeros = float3(0, 0, 0);
|
|
const float3 Ones = float3(1, 1, 1);
|
|
|
|
// Fixed layer structure for helping compiler to unroll and optimize shader
|
|
return PromoteParameterBlendedBSDFToOperator(
|
|
GetStrataSlabBSDF(
|
|
In.PixelFootprint,
|
|
In.UseMetalness, // UseMetalness
|
|
In.BaseColor, // BaseColor - Metalness workflow
|
|
Ones, // EdgeColor - Metalness workflow
|
|
In.Specular, // Specular - Metalness workflow
|
|
In.Metallic, // Metallic - Metalness workflow
|
|
In.DiffuseAlbedo, // DiffuseAlbedo - !Metalness workflow
|
|
In.F0, // F0 - !Metalness workflow
|
|
In.F90, // F90 - !Metalness workflow
|
|
In.Roughness, // Roughness
|
|
In.Anisotropy, // Anisotropy
|
|
In.SSSProfileID, // SSSProfileID
|
|
In.SSSMFP, // SSSMFP
|
|
In.SSSMFPScale, // SSSMFPScale
|
|
In.SSSPhaseAniso, // SSSPhaseAniso
|
|
In.UseSSSDiffusion, // UseSSSDiffusion
|
|
In.Emissive, // Emissive
|
|
0.f, // Haziness
|
|
In.FuzzAmount, // FuzzAmount
|
|
In.FuzzColor, // FuzzColor
|
|
In.Thickness,
|
|
In.SharedLocalBasisIndex, SharedLocalBasisTypes),
|
|
StrataTree,
|
|
OperatorIndex,
|
|
BSDFIndex,
|
|
In.LayerDepth,
|
|
In.bIsBottom);
|
|
}
|
|
|
|
// Convert legacy shading models - Dynamic
|
|
// This function can handle dynamic shading models (i.e., known only at runtime).
|
|
// For this, the layer topology is 'fixed' and composed of two slabs vertically layered. This is done for
|
|
// helping the compiler to unroll Strata BSDF traversing and packing. In most cases, the bottom slab is
|
|
// weighted by 0 and it will be removed once the data are written-out/packed.
|
|
FStrataData StrataConvertLegacyMaterialDynamic(
|
|
FStrataPixelFootprint PixelFootprint,
|
|
float3 BaseColor, float Specular, float Metallic,
|
|
float Roughness, float Anisotropy,
|
|
float3 SubSurfaceColor, float SubSurfaceProfileId,
|
|
float ClearCoat, float ClearCoatRoughness,
|
|
float3 Emissive,
|
|
float Opacity,
|
|
float3 TransmittanceColor,
|
|
float3 WaterScatteringCoefficients, float3 WaterAbsorptionCoefficients, float WaterPhaseG, float3 ColorScaleBehindWater,
|
|
uint ShadingModel,
|
|
uint SharedLocalBasisIndex,
|
|
uint ClearCoatBottomNormal_SharedLocalBasisIndex,
|
|
inout uint SharedLocalBasisTypes,
|
|
inout FStrataTree StrataTree)
|
|
{
|
|
const float DefaultThickness = STRATA_LAYER_DEFAULT_THICKNESS_CM;
|
|
const float3 Zeros = float3(0, 0, 0);
|
|
const float3 Ones = float3(1, 1, 1);
|
|
|
|
// Can only mix Unlit / DefaultLit / Sub-Surface / Preintegrated-Skin / Subsurface-Profile / ClearCoat / Foliage / Cloth / Eye/ Thin
|
|
|
|
// Note: If hair or single layer water are enabled with other shading model, the code generation won't be ideal, as the compiler will struggle with unrolling the BSDFs
|
|
#if MATERIAL_SHADINGMODEL_SINGLELAYERWATER
|
|
if (ShadingModel == SHADINGMODELID_SINGLELAYERWATER)
|
|
{
|
|
const float3 WaterExtinction = WaterScatteringCoefficients + WaterAbsorptionCoefficients;
|
|
const float3 WaterAlbedo = WaterScatteringCoefficients / WaterExtinction;
|
|
|
|
FStrataData Top_SLW = GetStrataSingleLayerWaterBSDF(
|
|
BaseColor, // BaseColor
|
|
Metallic, // Metallic
|
|
Specular, // Specular
|
|
Roughness, // Roughness
|
|
Emissive, // Emissive
|
|
Opacity, // TopMaterialOpacity
|
|
WaterAlbedo, // WaterAlbedo
|
|
WaterExtinction, // WaterExtinction
|
|
WaterPhaseG, // WaterPhaseG
|
|
ColorScaleBehindWater, // ColorScaleBehindWater
|
|
SharedLocalBasisIndex);
|
|
|
|
FStrataLegacyParameters Bot = InitStrataLegacyParameters(PixelFootprint, SharedLocalBasisIndex, 1.0f);
|
|
|
|
FStrataData Bot_Slab = CreateLegacySlab(Bot, SharedLocalBasisTypes, StrataTree, /*OperatorIndex*/1, /*BSDFIndex*/1);
|
|
FStrataData WTop_Slab = StrataWeight(Top_SLW , 1.0, StrataTree, /*OperatorIndex*/2, /*MaxDistanceFromLeaves*/1);
|
|
FStrataData WBot_Slab = StrataWeight(Bot_Slab, 0.0, StrataTree, /*OperatorIndex*/3, /*MaxDistanceFromLeaves*/1);
|
|
FStrataData Out = StrataVerticalLayering(WTop_Slab, WBot_Slab, StrataTree, /*OperatorIndex*/4, /*MaxDistanceFromLeaves*/2);
|
|
// Out maps to LegacyUpdateBSDFsOperators
|
|
return Out;
|
|
}
|
|
#endif
|
|
#if MATERIAL_SHADINGMODEL_HAIR
|
|
if (ShadingModel == SHADINGMODELID_HAIR)
|
|
{
|
|
return GetStrataHairBSDF(
|
|
BaseColor, // BaseColor
|
|
Metallic, // Scatter
|
|
Specular, // Specular
|
|
Roughness, // Roughness
|
|
ClearCoat, // Backlit
|
|
Emissive, // EmissiveColor
|
|
SharedLocalBasisIndex);
|
|
|
|
// No need to take into account opacity weighting for translucent material, as the coverage is assumed to be 1
|
|
}
|
|
#endif
|
|
|
|
// Top/Bottom
|
|
FStrataLegacyParameters Top = InitStrataLegacyParameters(PixelFootprint, SharedLocalBasisIndex, 1.0f);
|
|
FStrataLegacyParameters Bot = InitStrataLegacyParameters(PixelFootprint, SharedLocalBasisIndex, 1.0f);
|
|
|
|
float FinalWeight = 1.0f;
|
|
|
|
if (ShadingModel == SHADINGMODELID_UNLIT)
|
|
{
|
|
// Unlit is handle with a emissive slab
|
|
Top.BaseColor = Zeros;
|
|
Top.Specular = 0.f;
|
|
Top.Metallic = 0.f;
|
|
Top.Roughness = 0.f;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.Emissive = Emissive;
|
|
|
|
Bot.Weight = 0.f;
|
|
|
|
FinalWeight = 1.0f;
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_DEFAULT_LIT)
|
|
{
|
|
Top.BaseColor = BaseColor;
|
|
Top.Specular = Specular;
|
|
Top.Metallic = Metallic;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.Emissive = Emissive;
|
|
|
|
Bot.Weight = 0.f;
|
|
|
|
FinalWeight = 1.0f;
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_SUBSURFACE)
|
|
{
|
|
const float ThicknessInCm = STRATA_SIMPLEVOLUME_THICKNESS_CM;
|
|
const float3 MFPInCm = TransmittanceToMeanFreePath(SubSurfaceColor, ThicknessInCm * CENTIMETER_TO_METER) * METER_TO_CENTIMETER;
|
|
|
|
Top.BaseColor = BaseColor;
|
|
Top.Specular = Specular;
|
|
Top.Metallic = Metallic;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.SSSMFP = max(1e-05f, MFPInCm); // Ensure the MFP is not null to force the material as have SSS
|
|
Top.SSSMFPScale = 1.0f;
|
|
Top.SSSPhaseAniso = 1.0f - Opacity; // Opaque-Thick: isotropic phase function, Thin: forward phase scattering function
|
|
Top.Emissive = Emissive;
|
|
Top.UseSSSDiffusion = false;
|
|
Top.Thickness = ThicknessInCm;
|
|
|
|
// No need to take into account opacity weighting for translucent material, as the coverage is assumed to be 1
|
|
Bot.Weight = 0.f;
|
|
|
|
FinalWeight = 1.0f;
|
|
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
// STRATA_TODO
|
|
// If we try to reduce the diffusion according to transmittance that will increase mfp and make the material disapear (make it optically thin).
|
|
// Instead for now we use a mfp of 0 and make the material vanish according to opacity.
|
|
// All this will be fixed when this material will be converted to LUT.
|
|
const float Transmittance = saturate(1.f - Opacity);
|
|
Top.SSSMFP = 0;// MFPInCm;
|
|
Top.SSSMFPScale = 1.0f;
|
|
Top.Thickness = ThicknessInCm;
|
|
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_PREINTEGRATED_SKIN)
|
|
{
|
|
// Use default profile MFP (e.g., human skin) as MFP value for converting hardcoded pre-integrated SSS texture for deferred material.
|
|
const float3 MFPInCm = float3(1.0f, 0.088964f, 0.072095f) * 2.6748f * 0.1f;
|
|
|
|
// Legacy material uses Subsurface color as transmission 'tinting', but we can represent that with a single layer. So instead we take
|
|
// the max color of SubSurfaceColro & BaseColor
|
|
Top.BaseColor = max(SubSurfaceColor, BaseColor);
|
|
Top.Specular = Specular;
|
|
Top.Metallic = Metallic;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.SSSMFP = max(1e-05f, MFPInCm); // Ensure the MFP is not null to force the material as have SSS
|
|
Top.SSSMFPScale = 1.0f;
|
|
Top.SSSProfileID = 0.f;
|
|
Top.SSSMFPScale = 1.f - Opacity;
|
|
Top.SSSPhaseAniso = 0.93f;
|
|
Top.UseSSSDiffusion = true;
|
|
Top.Emissive = Emissive;
|
|
|
|
// No need to take into account opacity weighting for translucent material, as the coverage is assumed to be 1
|
|
Bot.Weight = 0.f;
|
|
|
|
FinalWeight = 1.0f;
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_SUBSURFACE_PROFILE)
|
|
{
|
|
Top.BaseColor = BaseColor;
|
|
Top.Specular = Specular;
|
|
Top.Metallic = Metallic;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.SSSProfileID = SubSurfaceProfileId;
|
|
Top.SSSMFPScale = Opacity;
|
|
Top.SSSPhaseAniso = 0.93f;
|
|
Top.UseSSSDiffusion = true;
|
|
Top.Emissive = Emissive;
|
|
|
|
// No need to take into account opacity weighting for translucent material, as the coverage is assumed to be 1
|
|
Bot.Weight = 0.f;
|
|
|
|
FinalWeight = 1.0f;
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_CLEAR_COAT)
|
|
{
|
|
// === BOTTOM layer ===
|
|
Bot.BaseColor = BaseColor;
|
|
Bot.Specular = Specular;
|
|
Bot.Metallic = Metallic;
|
|
Bot.Roughness = Roughness;
|
|
Bot.Anisotropy = Anisotropy;
|
|
Bot.SSSProfileID = 0.f;
|
|
Bot.SSSMFP = Zeros;
|
|
Bot.SSSMFPScale = 0.f;
|
|
Bot.Emissive = Zeros;
|
|
Bot.SharedLocalBasisIndex = ClearCoatBottomNormal_SharedLocalBasisIndex;
|
|
Bot.LayerDepth = 1;
|
|
Bot.bIsBottom = 1;
|
|
Bot.Weight = 1.f;
|
|
// === TOP layer ===
|
|
|
|
// The top layer has a hard coded specular value of 0.5 (F0 = 0.04)
|
|
// BaseColor = 0 to only feature absorption, no scattering
|
|
|
|
// The original clear coat is a complex assemblage of arbitrary functions that do not always make sense.
|
|
// To simplify things, we set the top slab BSDF as having a constant Grey scale transmittance.
|
|
// As for the original, this is achieved with coverage so both transmittance and specular contribution vanishes
|
|
|
|
// Now setup the mean free path with a hard coded transmittance of 0.75 when viewing the surface perpendicularly
|
|
const float Thickness = DefaultThickness;
|
|
const float3 MFP = TransmittanceToMeanFreePath(0.75f, Thickness * CENTIMETER_TO_METER) * METER_TO_CENTIMETER;
|
|
|
|
Top.BaseColor = Zeros;
|
|
Top.Specular = 0.5f;
|
|
Top.Metallic = 0.f;
|
|
Top.Roughness = ClearCoatRoughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.SSSProfileID = 0.f;
|
|
Top.SSSMFP = MFP;
|
|
Top.SSSMFPScale = 1.f;
|
|
Top.Emissive = Emissive;
|
|
Top.Thickness = Thickness;
|
|
Top.SharedLocalBasisIndex = SharedLocalBasisIndex;
|
|
Top.LayerDepth = 0;
|
|
Top.bIsBottom = 0;
|
|
Top.Weight = ClearCoat;
|
|
|
|
FinalWeight = 1.0f;
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_TWOSIDED_FOLIAGE)
|
|
{
|
|
// Set a thickness that will enabled the thin lighting model (corresponding to the legacy two-sided lighting model)
|
|
const float Thickness = STRATA_LAYER_ISTHIN_THICKNESS_THRESHOLD_CM - 1e-5f;
|
|
const float3 MFP = TransmittanceToMeanFreePath(SubSurfaceColor /*TransmittanceColor*/, Thickness * CENTIMETER_TO_METER) * METER_TO_CENTIMETER;
|
|
|
|
Top.BaseColor = BaseColor;
|
|
Top.Specular = Specular;
|
|
Top.Metallic = Metallic;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.SSSProfileID = 0.f;
|
|
Top.SSSMFP = MFP;
|
|
Top.SSSMFPScale = 1.f;
|
|
Top.Emissive = Emissive;
|
|
Top.Thickness = Thickness;
|
|
|
|
// Take in account the legacy opacity weighting for translucent material
|
|
Bot.Weight = 0.f;
|
|
|
|
FinalWeight = 1.0f;
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_CLOTH)
|
|
{
|
|
Top.BaseColor = BaseColor;
|
|
Top.Specular = Specular;
|
|
Top.Metallic = Metallic;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.SSSProfileID = 0.f;
|
|
Top.SSSMFP = 0.f;
|
|
Top.SSSMFPScale = 0.f;
|
|
Top.Emissive = Emissive;
|
|
Top.FuzzAmount = ClearCoat;
|
|
Top.FuzzColor = SubSurfaceColor;
|
|
|
|
Bot.Weight = 0.f;
|
|
|
|
FinalWeight = 1.0f;
|
|
#if STRATA_TRANSLUCENT_MATERIAL
|
|
FinalWeight = Opacity;
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_EYE)
|
|
{
|
|
const float IrisMask = ClearCoat;
|
|
const float IrisDistance = ClearCoatRoughness;
|
|
|
|
// Lerp transmittance rather MFP, as transmittance is perceptually linear unlike MFP
|
|
const float Thickness = DefaultThickness;
|
|
const float3 MFP = TransmittanceToMeanFreePath(IrisMask.xxx, Thickness * CENTIMETER_TO_METER) * METER_TO_CENTIMETER;
|
|
|
|
// Cornea/Sclera
|
|
Top.BaseColor = BaseColor;
|
|
Top.Specular = Specular;
|
|
Top.Metallic = 0.f;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = 0.f;
|
|
Top.SSSProfileID = SubSurfaceProfileId;
|
|
Top.SSSMFP = MFP;
|
|
Top.SSSMFPScale = Opacity;
|
|
Top.Emissive = Emissive;
|
|
Top.SharedLocalBasisIndex = SharedLocalBasisIndex;
|
|
Top.LayerDepth = 0;
|
|
Top.bIsBottom = 0;
|
|
Top.Weight = 1.f;
|
|
|
|
// Iris
|
|
Bot.BaseColor = BaseColor;
|
|
Bot.Specular = Specular;
|
|
Bot.Metallic = .0f;
|
|
Bot.Roughness = Roughness;
|
|
Bot.Anisotropy = 0.f;
|
|
Bot.SSSProfileID = SubSurfaceProfileId;
|
|
Bot.SSSMFP = Zeros;
|
|
Bot.SSSMFPScale = Opacity;
|
|
Bot.Emissive = Emissive;
|
|
Bot.SharedLocalBasisIndex = ClearCoatBottomNormal_SharedLocalBasisIndex;
|
|
Bot.LayerDepth = 1;
|
|
Bot.bIsBottom = 1;
|
|
Bot.Weight = 1.f;
|
|
|
|
// No need to take into account opacity weighting for translucent material, as the coverage is assumed to be 1
|
|
FinalWeight = 1.0f;
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_THIN_TRANSLUCENT)
|
|
{
|
|
const float Thickness = DefaultThickness;
|
|
|
|
// If the material is dieletric, bias the opacity so that the dieletric part extend further. This better matches the two layer approaches.
|
|
Opacity = lerp(1.f - Square(1.f - Opacity), Opacity, Metallic);
|
|
|
|
// Because we are using a single slab for simulating a 'coverage mix' between two BSDFs (a opaque metallic/conductor and a non-scattering translucent medium),
|
|
// we need to do some approximation. In order to reduce avoid hue shift due to difference between 'solid' base-color/diffuse-albedo and 'transparent' transmission
|
|
// color, we lerp BaseColor with transmittance color in LAB space so that the interpolated color minized its 'distance'
|
|
const float3 BaseColor_LAB = LinearRGB_2_LAB(BaseColor, XYZ_WHITE_REF_D65);
|
|
const float3 TransmittanceColor_LAB = LinearRGB_2_LAB(TransmittanceColor, XYZ_WHITE_REF_D65);
|
|
const float3 Color_LAB = lerp(TransmittanceColor_LAB, BaseColor_LAB, Opacity);
|
|
const float3 Color = LAB_2_LinearRGB(Color_LAB, XYZ_WHITE_REF_D65);
|
|
|
|
// Lerp the transmittance color rather than MFP as it is more perceptually linear
|
|
const float3 MFP = TransmittanceToMeanFreePath(lerp(Color, Zeros, Opacity), Thickness * CENTIMETER_TO_METER) * METER_TO_CENTIMETER;
|
|
|
|
const float F0Dieletrict = DielectricSpecularToF0(Specular);
|
|
|
|
const float3 TopF0 = lerp(F0Dieletrict, BaseColor, Metallic);
|
|
const float3 TopAlbedo = Color * (1.f - Metallic);
|
|
const float3 TopMFP = 0;
|
|
|
|
const float3 BotF0 = F0Dieletrict;
|
|
const float3 BotAlbedo = Zeros;
|
|
const float3 BotMFP = MFP;
|
|
|
|
Top.DiffuseAlbedo = lerp(BotAlbedo, TopAlbedo, Opacity);
|
|
Top.SSSMFP = lerp(BotMFP, TopMFP, Opacity);
|
|
Top.F0 = lerp(BotF0, TopF0, Opacity);
|
|
Top.F90 = Ones;
|
|
Top.UseMetalness = false;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = 0.f;
|
|
Top.SSSProfileID = 0.f;
|
|
Top.SSSMFPScale = 1.f;
|
|
Top.Emissive = Emissive;
|
|
Top.Thickness = Thickness;
|
|
Top.SharedLocalBasisIndex = SharedLocalBasisIndex;
|
|
|
|
Top.Weight = 1.0f;
|
|
Bot.Weight = 0.0f;
|
|
|
|
// Reference two layers approach
|
|
#if 0
|
|
// Top slab BSDF as a simple Disney material
|
|
Top.BaseColor = BaseColor;
|
|
Top.Specular = Specular;
|
|
Top.Metallic = Metallic;
|
|
Top.Roughness = Roughness;
|
|
Top.Anisotropy = Anisotropy;
|
|
Top.SSSProfileID = 0.f;
|
|
Top.SSSMFP = Zeros;
|
|
Top.SSSMFPScale = 0.f;
|
|
Top.Emissive = Emissive;
|
|
Top.SharedLocalBasisIndex = SharedLocalBasisIndex;
|
|
|
|
// Bottom slab BSDF will be a simple absorption only layer
|
|
const float Thickness = DefaultThickness;
|
|
const float3 MFP = TransmittanceToMeanFreePath(TransmittanceColor, Thickness * CENTIMETER_TO_METER) * METER_TO_CENTIMETER;
|
|
|
|
// Assign specular properties shared with the top layer.
|
|
Bot.BaseColor = Zeros;
|
|
Bot.Specular = Specular;
|
|
Bot.Metallic = .0f;
|
|
Bot.Roughness = Roughness;
|
|
Bot.Anisotropy = 0.f;
|
|
Bot.SSSProfileID = .0f;
|
|
Bot.SSSMFP = MFP;
|
|
Bot.SSSMFPScale = 1.f;
|
|
Bot.Emissive = Zeros;
|
|
Bot.Thickness = Thickness;
|
|
Bot.SharedLocalBasisIndex = ClearCoatBottomNormal_SharedLocalBasisIndex;
|
|
|
|
// No need to take into account opacity weighting for translucent material, as the coverage is assumed to be 1
|
|
// Now weight the top base material by opacity
|
|
Top.Weight = Opacity;
|
|
#endif
|
|
|
|
// Thin translucency model always have a coverage of 1. It also canont be used in a multiple shading model context.
|
|
FinalWeight = 1.0f;
|
|
}
|
|
|
|
// Fixed layer structure for helping compiler to unroll and optimize shader
|
|
// This must match what is done in PackStrataOut
|
|
FStrataData Top_Slab = CreateLegacySlab(Top, SharedLocalBasisTypes, StrataTree, /*OperatorIndex*/0, /*BSDFIndex*/0);
|
|
FStrataData Bot_Slab = CreateLegacySlab(Bot, SharedLocalBasisTypes, StrataTree, /*OperatorIndex*/1, /*BSDFIndex*/1);
|
|
FStrataData WTop_Slab= StrataWeight(Top_Slab, Top.Weight, StrataTree, /*OperatorIndex*/2, /*MaxDistanceFromLeaves*/1);
|
|
FStrataData WBot_Slab= StrataWeight(Bot_Slab, Bot.Weight, StrataTree, /*OperatorIndex*/3, /*MaxDistanceFromLeaves*/1);
|
|
FStrataData Out = StrataVerticalLayering(WTop_Slab, WBot_Slab, StrataTree, /*OperatorIndex*/4, /*MaxDistanceFromLeaves*/2);
|
|
|
|
// Take in account the legacy opacity weighting for translucent material
|
|
#if STRATA_LEGACY_MATERIAL_APPLIES_FINAL_WEIGHT
|
|
{
|
|
Out = StrataWeight(Out, FinalWeight, StrataTree, /*OperatorIndex*/5, /*MaxDistanceFromLeaves*/3);
|
|
}
|
|
#endif
|
|
|
|
#if STRATA_LEGACY_PREMULT_ALPHA_OVERRIDE
|
|
Out.PreMultipliedAlphaOverrideCoverage = Opacity;
|
|
#endif
|
|
|
|
// We also evaluate the inlined BSDF resulting from parameter blending in case it is used later.
|
|
// For instance, this is used for deferred decals. We only evaluate the top material as this is enough for decals.
|
|
FStrataData ParamBlendVertical = StrataWeightParameterBlending(Top_Slab, Top.Weight);
|
|
// if(Bot.Weight > 0.0)
|
|
// {
|
|
// const float DummyNoV = 1.0f;
|
|
// uint NewNormalIndex = BSDF_GETSHAREDLOCALBASISID(Top_Slab.InlinedBSDF);
|
|
// ParamBlendVertical = StrataVerticalLayeringParameterBlending(ParamBlendVertical, StrataWeightParameterBlending(Bot_Slab, Bot.Weight), NewNormalIndex, DummyNoV);
|
|
// }
|
|
#if STRATA_LEGACY_MATERIAL_APPLIES_FINAL_WEIGHT
|
|
Out.InlinedBSDF = StrataWeightParameterBlending(ParamBlendVertical, FinalWeight).InlinedBSDF;
|
|
#else
|
|
Out.InlinedBSDF = ParamBlendVertical.InlinedBSDF;
|
|
#endif
|
|
|
|
// Out maps to LegacyUpdateBSDFsOperators
|
|
return Out;
|
|
}
|
|
|
|
// Convert legacy shading models - Static
|
|
// This function is for static single shading model (i.e., known at shader compilation time).
|
|
// It reuses the dynamic version for most part, but for special node like Unlit/Hair/Water,
|
|
// we use the dedicated node
|
|
FStrataData StrataConvertLegacyMaterialStatic(
|
|
FStrataPixelFootprint PixelFootprint,
|
|
float3 BaseColor, float Specular, float Metallic,
|
|
float Roughness, float Anisotropy,
|
|
float3 SubSurfaceColor, float SubSurfaceProfileId,
|
|
float ClearCoat, float ClearCoatRoughness,
|
|
float3 Emissive,
|
|
float Opacity,
|
|
float3 TransmittanceColor,
|
|
float3 WaterScatteringCoefficients, float3 WaterAbsorptionCoefficients, float WaterPhaseG, float3 ColorScaleBehindWater,
|
|
uint ShadingModel,
|
|
uint SharedLocalBasisIndex,
|
|
uint ClearCoatBottomNormal_SharedLocalBasisIndex,
|
|
inout uint SharedLocalBasisTypes,
|
|
inout FStrataTree StrataTree)
|
|
{
|
|
FStrataData Out = GetInitialisedStrataData();
|
|
|
|
const float DefaultThickness = STRATA_LAYER_DEFAULT_THICKNESS_CM;
|
|
const float3 Zeros = float3(0, 0, 0);
|
|
const float3 Ones = float3(1, 1, 1);
|
|
|
|
if (ShadingModel == SHADINGMODELID_UNLIT)
|
|
{
|
|
const float GreyTransmittance = saturate(1.0f - Opacity);
|
|
#if MATERIALBLENDING_OPAQUE || MATERIALBLENDING_MASKED
|
|
// Opaque materials only write emissive.
|
|
Out = GetStrataUnlitBSDF(Emissive, 0.0f);
|
|
#elif MATERIALBLENDING_ALPHACOMPOSITE
|
|
// Uses (Luminance, black transmittance) for premultiplied alpha blending. Opacity is controled using coverage
|
|
Out = GetStrataUnlitBSDF(Emissive, 0.0f);
|
|
#if STRATA_INLINE_SHADING
|
|
Out.InlinedBSDF.Coverage = Opacity;
|
|
#endif
|
|
#elif MATERIALBLENDING_TRANSLUCENT
|
|
// Uses (Luminance, black transmittance) for translucency blending. Opacity is controled using coverage
|
|
Out = GetStrataUnlitBSDF(Emissive * Opacity, 0.0f);
|
|
#if STRATA_INLINE_SHADING
|
|
Out.InlinedBSDF.Coverage = Opacity;
|
|
#endif
|
|
#elif MATERIALBLENDING_ALPHAHOLDOUT
|
|
Out = GetStrataUnlitBSDF(0.0f, 1.0f);
|
|
#elif MATERIALBLENDING_ADDITIVE
|
|
// Emissive is weighted by opacity in the legacy material.
|
|
Out = GetStrataUnlitBSDF(Emissive * Opacity, 1.0f);
|
|
#elif MATERIALBLENDING_MODULATE
|
|
// Setting up emissive as the transmittance color. It is not clamped in case brightening is required.
|
|
Out = GetStrataUnlitBSDF(0.0f, Emissive);
|
|
#else
|
|
// Required default for some materials such as Editor UI
|
|
Out = GetStrataUnlitBSDF(Emissive, 0.0f);
|
|
#endif
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_HAIR)
|
|
{
|
|
Out = GetStrataHairBSDF(
|
|
BaseColor, // BaseColor
|
|
Metallic, // Scatter
|
|
Specular, // Specular
|
|
Roughness, // Roughness
|
|
ClearCoat, // Backlit
|
|
Emissive, // EmissiveColor
|
|
SharedLocalBasisIndex);
|
|
|
|
// No need to take into account opacity weighting for translucent material, as the coverage is assumed to be 1
|
|
}
|
|
else if (ShadingModel == SHADINGMODELID_SINGLELAYERWATER)
|
|
{
|
|
const float3 WaterExtinction = WaterScatteringCoefficients + WaterAbsorptionCoefficients;
|
|
const float3 WaterAlbedo = WaterScatteringCoefficients / WaterExtinction;
|
|
|
|
FStrataData Top_SLW = PromoteParameterBlendedBSDFToOperator(
|
|
GetStrataSingleLayerWaterBSDF(
|
|
BaseColor, // BaseColor
|
|
Metallic, // Metallic
|
|
Specular, // Specular
|
|
Roughness, // Roughness
|
|
Emissive, // Emissive
|
|
Opacity, // TopMaterialOpacity
|
|
WaterAlbedo, // WaterAlbedo
|
|
WaterExtinction, // WaterExtinction
|
|
WaterPhaseG, // WaterPhaseG
|
|
ColorScaleBehindWater, // ColorScaleBehindWater
|
|
SharedLocalBasisIndex),
|
|
StrataTree,
|
|
0 /*OperatorIndex*/,
|
|
0 /*BSDFIndex*/,
|
|
0 /*int LayerDepth*/,
|
|
1 /*int bIsBottom*/);
|
|
|
|
FStrataLegacyParameters Bot = InitStrataLegacyParameters(PixelFootprint, SharedLocalBasisIndex, 1.0f);
|
|
FStrataData Bot_Slab = CreateLegacySlab(Bot, SharedLocalBasisTypes, StrataTree, /*OperatorIndex*/1, /*BSDFIndex*/1);
|
|
|
|
FStrataData WTop_Slab = StrataWeight(Top_SLW, 1.0, StrataTree, /*OperatorIndex*/2, /*MaxDistanceFromLeaves*/1);
|
|
FStrataData WBot_Slab = StrataWeight(Bot_Slab, 0.0, StrataTree, /*OperatorIndex*/3, /*MaxDistanceFromLeaves*/1);
|
|
Out = StrataVerticalLayering(WTop_Slab, WBot_Slab, StrataTree, /*OperatorIndex*/4, /*MaxDistanceFromLeaves*/2);
|
|
// Out maps to LegacyUpdateBSDFsOperators
|
|
}
|
|
else
|
|
{
|
|
Out = StrataConvertLegacyMaterialDynamic(
|
|
PixelFootprint,
|
|
BaseColor, Specular, Metallic,
|
|
Roughness, Anisotropy,
|
|
SubSurfaceColor, SubSurfaceProfileId,
|
|
ClearCoat, ClearCoatRoughness,
|
|
Emissive,
|
|
Opacity,
|
|
TransmittanceColor,
|
|
WaterScatteringCoefficients, WaterAbsorptionCoefficients, WaterPhaseG, ColorScaleBehindWater,
|
|
ShadingModel,
|
|
SharedLocalBasisIndex,
|
|
ClearCoatBottomNormal_SharedLocalBasisIndex,
|
|
SharedLocalBasisTypes,
|
|
StrataTree);
|
|
}
|
|
|
|
return Out;
|
|
}
|