int diffusionProfile = bsdfData.diffusionProfile;
bsdfData.thickness = _ThicknessRemaps[diffusionProfile].x + _ThicknessRemaps[diffusionProfile].y * thickness;
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * surfaceData. diffusionProfile, 2u);
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * diffusionProfile, 2u);
bsdfData.useThickObjectMode = transmissionMode != TRANSMISSION_MODE_THIN;
#if SHADEROPTIONS_USE_DISNEY_SSS
if (bsdfData.enableSubsurfaceScattering)
{
// Modify fresnel0
FillMaterialSSS(surfaceData.subsurfaceMask);
FillMaterialSSS(surfaceData.subsurfaceMask, bsdfData );
}
if (bsdfData.enableTransmission)
// The priority of feature is handled in the code here and reflect in the UI (see LitUI.cs)
// Process SSS and Transmission together as they encode almost the same data, negligible cost
if (bsdfData.enableSubsurfaceScattering || bsdf Data.enableTransmission)
if (surfaceData.enableSubsurfaceScattering || surface Data.enableTransmission)
{
metallic15 = GBUFFER_LIT_SSS_OR_TRANSMISSION;
// Special case: For SSS we will store the profile id and the subsurface radius at the location of the specular occlusion (in alpha channel of GBuffer0)
outGBuffer2.rgb = float3(surfaceData.specularOcclusion, surfaceData.thickness, bsdfData.enableSubsurfaceScattering ? 1.0 : 0.0); // thickness for Transmission
outGBuffer2.rgb = float3(surfaceData.specularOcclusion, surfaceData.thickness, surfaceData.enableSubsurfaceScattering ? 1.0 : 0.0); // thickness for Transmission
if (bsdfData.enableSpecularColor)
if (surfaceData.enableSpecularColor)
else if (bsdfData.enableAnisotropy)
else if (surfaceData.enableAnisotropy)
else if (bsdfData.enableIridescence)
else if (surfaceData.enableIridescence)
else
{
outGBuffer2.rgb = float3(0.0, 0.0, 0.0);
}
}
// Encode coatMask (4bit) / mettalic (4bit)
// This method allows us to know at compile time what material features should be removed from the code by Tile (Indepenently of the value of material feature flag per pixel).
// This is only useful for classification during lighting, so it's not needed in EncodeIntoGBuffer and ConvertSurfaceDataToBSDFData (where we always know exactly what the material feature is)
bool HasMaterialFeatureFlag(featureFlags, uint featureFlags, uint flag)
bool HasMaterialFeatureFlag(uint featureFlags, uint flag)
{
return ((featureFlags & flag) != 0);
}
// If any of the flags of g_MaterialFeatureFlags (tested with HasMaterialFeatureFlag) is not set, it mean we know statically that
// the material feature is not used, so the compiler can optimize related code. Else we don't know if the material feature will be use, it is a dynamic condition.
bsdfData.enableSpecularColor = (metallic15 == GBUFFER_LIT_SPECULAR_COLOR); // This is always a dynamic test as it is very cheap
bsdfData.enableTransmission = (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && outGb uffer2.g > 0.0) && // Thickness > 0
bsdfData.enableTransmission = (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && inGB uffer2.g > 0.0) && // Thickness > 0
bsdfData.enableSubsurfaceScattering = (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && outGb uffer2.b > 0.0) && // SSS Flags > 0
bsdfData.enableSubsurfaceScattering = (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && inGB uffer2.b > 0.0) && // SSS Flags > 0
bsdfData.enableAnisotropy = (metallic15 <= GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND && outGb uffer2.g > 0.0) && // Anisotropy > 0
bsdfData.enableAnisotropy = (metallic15 <= GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND && inGB uffer2.g > 0.0) && // Anisotropy > 0
HasMaterialFeatureFlag(featureFlags, MATERIALFEATUREFLAGS_LIT_ANISOTROPY);
bsdfData.enableIridescence = (metallic15 == GBUFFER_LIT_IRIDESCENCE) &&
HasMaterialFeatureFlag(featureFlags, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE);
// metallic15 is range [0..12] if mettallic data is needed
float metallic = (metallic15 <= GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND) ? metallic15 / GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND : 0.0;
bsdfData.diffuseColor = ComputeDiffuseColor(surfaceData. baseColor, metallic);
bsdfData.fresnel0 = bsdfData.enableSpecularColor ? outGb uffer2.rgb : ComputeFresnel0(baseColor, metallic, DEFAULT_SPECULAR_VALUE);
bsdfData.diffuseColor = ComputeDiffuseColor(baseColor, metallic);
bsdfData.fresnel0 = bsdfData.enableSpecularColor ? inGB uffer2.rgb : ComputeFresnel0(baseColor, metallic, DEFAULT_SPECULAR_VALUE);
// Always assign even if not used, DIFFUSION_NEUTRAL_PROFILE_ID is 0
// Note: we have ZERO_INITIALIZE the struct, so bsdfData.diffusionProfile == DIFFUSION_NEUTRAL_PROFILE_ID, bsdfData.anisotropy == 0.0, bsdfData.SubsurfaceMask == 0.0 etc...
if (bsdfData.enableSubsurfaceScattering)
{
// Modify fresnel0
FillMaterialSSS(sssData.subsurfaceMask);
FillMaterialSSS(sssData.subsurfaceMask, bsdfData );
}
if (bsdfData.enableTransmission)
if (bsdfData.enableAnisotropy)
{
FillMaterialIridescence(inGb uffer2.g, bsdfData);
FillMaterialIridescence(inGB uffer2.g, bsdfData);
}
if (bsdfData.enableClearCoat)
float3 unused;
// Call the regular function, compiler will optimized out everything not used.
// Note that all material feature flag bellow are in the same GBuffer (outGb uffer2) and thus material classification only sample one Gbuffer
// Note that all material feature flag bellow are in the same GBuffer (inGB uffer2) and thus material classification only sample one Gbuffer
DecodeFromGBuffer(
positionSS,
UINT_MAX,
uint materialFeatures = 0;
uint |= bsdfData.enableTransmission ? MATERIALFEATUREFLAGS_LIT_TRANSMISSION : 0;
uint |= bsdfData.enableSubsurfaceScattering ? MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING : 0;
uint |= bsdfData.enableAnisotropy ? MATERIALFEATUREFLAGS_LIT_ANISOTROPY : 0;
uint |= bsdfData.enableIridescence ? MATERIALFEATUREFLAGS_LIT_IRIDESCENCE : 0;
uint |= bsdfData.enableClearCoat ? MATERIALFEATUREFLAGS_LIT_CLEAR_COAT : 0;
materialFeatures |= bsdfData.enableTransmission ? MATERIALFEATUREFLAGS_LIT_TRANSMISSION : 0;
materialFeatures |= bsdfData.enableSubsurfaceScattering ? MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING : 0;
materialFeatures |= bsdfData.enableAnisotropy ? MATERIALFEATUREFLAGS_LIT_ANISOTROPY : 0;
materialFeatures |= bsdfData.enableIridescence ? MATERIALFEATUREFLAGS_LIT_IRIDESCENCE : 0;
materialFeatures |= bsdfData.enableClearCoat ? MATERIALFEATUREFLAGS_LIT_CLEAR_COAT : 0;
return materialFeatures;
}