浏览代码

Merge pull request #764 from Unity-Technologies/Refactor-GBuffer-with-material-feature

Rearrange GBuffer and material classification to switch to material features
/main
GitHub 7 年前
当前提交
19ff5eb4
共有 31 个文件被更改,包括 609 次插入595 次删除
  1. 13
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonMaterial.hlsl
  2. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDRenderPipelineMenuItems.cs
  3. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.Styles.cs
  4. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs
  5. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawTransmittanceGraph.shader
  6. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/LayeredLit/LayeredLitUI.cs
  7. 12
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Lit/BaseLitUI.cs
  8. 39
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Lit/LitUI.cs
  9. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Deferred.shader
  10. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Deferred.compute
  11. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs
  12. 16
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfile.hlsl
  13. 33
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs
  14. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.hlsl
  15. 12
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLit.shader
  16. 18
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl
  17. 12
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitTessellation.shader
  18. 127
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs
  19. 206
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs.hlsl
  20. 590
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl
  21. 12
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.shader
  22. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl
  23. 40
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitDataIndividualLayer.hlsl
  24. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitReference.hlsl
  25. 12
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitTessellation.shader
  26. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.compute
  27. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.hlsl
  28. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.shader
  29. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs
  30. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipeline/FrameSettings.cs
  31. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassForward.hlsl

13
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonMaterial.hlsl


}
// Use with stack BRDF (clear coat / coat)
real roughnessToVariance(real roughness)
real RoughnessToVariance(real roughness)
real varianceToRoughness(real variance)
real VarianceToRoughness(real variance)
{
return sqrt(2.0 / (variance + 2.0));
}

// Assume air interface for top
// Note: Don't handle the case fresnel0 == 1
real Fresnel0ToIor(real fresnel0)
real Fresnel0ToIOR(real fresnel0)
{
real sqrtF0 = sqrt(fresnel0);
return (1.0 + sqrtF0) / (1.0 - sqrtF0);

// This function is equivalent to IORToFresnel0(Fresnel0ToIor(fresnel0), 1.5)
// This function is equivalent to IORToFresnel0(Fresnel0ToIOR(fresnel0), 1.5)
// Optimization: Fit of the function (3 mad) for range 0.04 (should return 0), 1 (should return 1)
// return saturate(-0.0256868 + fresnel0 * (0.326846 + (0.978946 - 0.283835 * fresnel0) * fresnel0));
TEMPLATE_1_REAL(Fresnel0ReajustFor15, fresnel0, return saturate(-0.0256868 + fresnel0 * (0.326846 + (0.978946 - 0.283835 * fresnel0) * fresnel0)) )
// Optimization: Fit of the function (3 mad) for range [0.04 (should return 0), 1 (should return 1)]
TEMPLATE_1_REAL(ConvertF0ForAirInterfaceToF0ForClearCoat15, fresnel0, return saturate(-0.0256868 + fresnel0 * (0.326846 + (0.978946 - 0.283835 * fresnel0) * fresnel0)) )
// same as regular refract except there is not the test for total internal reflection + the vector is flipped for processing
real3 CoatRefract(real3 X, real3 N, real ieta)

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDRenderPipelineMenuItems.cs


if (mat.HasProperty("_SubsurfaceProfile"))
{
CheckOutFile(VSCEnabled, mat);
float value = mat.GetInt("_DiffusionProfile");
mat.SetInt("_DiffusionProfile", 0);
//float value = mat.GetInt("_DiffusionProfile");
//mat.SetInt("_DiffusionProfile", 0);
EditorUtility.SetDirty(mat);
}

if (mat.HasProperty("_SubsurfaceProfile" + x))
{
CheckOutFile(VSCEnabled, mat);
float value = mat.GetInt("_DiffusionProfile" + x);
mat.SetInt("_DiffusionProfile" + x, 0);
//float value = mat.GetInt("_DiffusionProfile" + x);
//mat.SetInt("_DiffusionProfile" + x, 0);
EditorUtility.SetDirty(mat);
}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.Styles.cs


public readonly GUIContent profileMinMaxThickness = new GUIContent("Min-Max Thickness (mm)", "Shows the values of the thickness remap below (in millimeters).");
public readonly GUIContent profileThicknessRemap = new GUIContent("Thickness Remap (mm)", "Remaps the thickness parameter from [0, 1] to the desired range (in millimeters).");
public readonly GUIContent profileWorldScale = new GUIContent("World Scale", "Size of the world unit in meters.");
public readonly GUIContent profileIor = new GUIContent("Index of Refraction", "Index of refraction. 1.4 for skin. 1.5 for most other material.");
public readonly GUIContent profileIor = new GUIContent("Index of Refraction", "Index of refraction. 1.4 for skin. Between 1.3-1.5 for most other material.");
// Jimenez SSS Model
public readonly GUIContent profileScatterDistance1 = new GUIContent("Scattering Distance #1", "The radius (in centimeters) of the 1st Gaussian filter, one per color channel. Alpha is ignored. The blur is energy-preserving, so a wide filter results in a large area with small contributions of individual samples. Smaller values increase the sharpness.");
public readonly GUIContent profileScatterDistance2 = new GUIContent("Scattering Distance #2", "The radius (in centimeters) of the 2nd Gaussian filter, one per color channel. Alpha is ignored. The blur is energy-preserving, so a wide filter results in a large area with small contributions of individual samples. Smaller values increase the sharpness.");

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs


m_ProfileMaterial = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/DrawDiffusionProfile");
m_TransmittanceMaterial = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/DrawTransmittanceGraph");
int count = DiffusionProfileConstants.DIFFUSION_N_PROFILES - 1;
int count = DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT - 1;
m_Profiles = new List<Profile>();
var serializedProfiles = properties.Find(x => x.profiles);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawTransmittanceGraph.shader


float3 T;
#if SHADEROPTIONS_USE_DISNEY_SSS
T = ComputeTransmittanceDisney(_ShapeParam.rgb, float3(0.25, 0.25, 0.25), d, 1);
T = ComputeTransmittanceDisney(_ShapeParam.rgb, float3(0.25, 0.25, 0.25), d);
float3(0.25, 0.25, 0.25), d, 1);
float3(0.25, 0.25, 0.25), d);
#endif
// Apply gamma for visualization only. Do not apply gamma to the color.

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/LayeredLit/LayeredLitUI.cs


}
CoreUtils.SetKeyword(material, "_DENSITY_MODE", useDensityModeEnable);
Lit.MaterialId materialId = (Lit.MaterialId)material.GetFloat(kMaterialID);
BaseLitGUI.MaterialId materialId = (BaseLitGUI.MaterialId)material.GetFloat(kMaterialID);
CoreUtils.SetKeyword(material, "_MATID_SSS", materialId == Lit.MaterialId.LitSSS);
//CoreUtils.SetKeyword(material, "_MATID_STANDARD", materialId == Lit.MaterialId.LitStandard); // See comment in Lit.shader, it is the default, we don't define it
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_SUBSURFACE_SCATTERING", materialId == BaseLitGUI.MaterialId.LitSSS);
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_TRANSMISSION", materialId == BaseLitGUI.MaterialId.LitSSS);
}
private void DoEmissiveGUI(Material material)
{

12
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Lit/BaseLitUI.cs


Tessellation
}
public enum MaterialId
{
LitSSS = 0,
LitStandard = 1,
LitAniso = 2,
LitClearCoat = 3,
LitSpecular = 4,
LitIridescence = 5,
};
protected MaterialProperty doubleSidedNormalMode = null;
protected const string kDoubleSidedNormalMode = "_DoubleSidedNormalMode";
protected MaterialProperty depthOffsetEnable = null;

// Set the reference value for the stencil test.
int stencilRef = (int)StencilLightingUsage.RegularLighting;
if ((int)material.GetFloat(kMaterialID) == (int)Lit.MaterialId.LitSSS)
if ((int)material.GetFloat(kMaterialID) == (int)BaseLitGUI.MaterialId.LitSSS)
{
stencilRef = (int)StencilLightingUsage.SplitLighting;
}

39
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Lit/LitUI.cs


public static GUIContent linkDetailsWithBaseText = new GUIContent("Lock to Base Tiling/Offset", "Lock details Tiling/Offset to Base Tiling/Offset");
// Subsurface
public static GUIContent diffusionProfileText = new GUIContent("Diffusion profile", "A profile determines the shape of the blur/transmission filter.");
public static GUIContent subsurfaceMaskText = new GUIContent("Subsurface radius", "Determines the range of the blur.");
public static GUIContent subsurfaceMaskMapText = new GUIContent("Subsurface radius map (R)", "Determines the range of the blur.");
public static GUIContent diffusionProfileText = new GUIContent("Diffusion profile", "A profile determines the shape of the SSS/transmission filter.");
public static GUIContent subsurfaceMaskText = new GUIContent("Subsurface mask", "Determines the strength of the subsurface scattering effect.");
public static GUIContent subsurfaceMaskMapText = new GUIContent("Subsurface mask map (R)", "Determines the strength of the subsurface scattering effect.");
public static GUIContent coatMaskText = new GUIContent("Coat Mask", "attenuate the coating effect (similar to change to IOR of 1");
public static GUIContent coatMaskText = new GUIContent("Coat Mask", "Attenuate the coating effect (similar to change to IOR of 1");
// Specular color
public static GUIContent specularColorText = new GUIContent("Specular Color", "Specular color (RGB)");

names[0] = new GUIContent("None");
var values = new int[names.Length];
values[0] = DiffusionProfileConstants.DIFFUSION_NEUTRAL_PROFILE_ID;
values[0] = DiffusionProfileConstants.DIFFUSION_PROFILE_NEUTRAL_ID;
for (int i = 0; i < profiles.Length; i++)
{

m_MaterialEditor.TexturePropertySingleLine(Styles.baseColorText, baseColorMap[layerIndex], baseColor[layerIndex]);
if ((Lit.MaterialId)materialID.floatValue == Lit.MaterialId.LitStandard || (Lit.MaterialId)materialID.floatValue == Lit.MaterialId.LitAniso)
if ((BaseLitGUI.MaterialId)materialID.floatValue == BaseLitGUI.MaterialId.LitStandard || (BaseLitGUI.MaterialId)materialID.floatValue == BaseLitGUI.MaterialId.LitAniso)
{
m_MaterialEditor.ShaderProperty(metallic[layerIndex], Styles.metallicText);
}

}
}
m_MaterialEditor.TexturePropertySingleLine(((Lit.MaterialId)materialID.floatValue == Lit.MaterialId.LitSpecular) ? Styles.maskMapSpecularText : Styles.maskMapSText, maskMap[layerIndex]);
m_MaterialEditor.TexturePropertySingleLine(((BaseLitGUI.MaterialId)materialID.floatValue == BaseLitGUI.MaterialId.LitSpecular) ? Styles.maskMapSpecularText : Styles.maskMapSText, maskMap[layerIndex]);
m_MaterialEditor.ShaderProperty(normalMapSpace[layerIndex], Styles.normalMapSpaceText);

heightAmplitude[layerIndex].floatValue = (heightMax[layerIndex].floatValue - heightMin[layerIndex].floatValue) * 0.01f; // Conversion centimeters to meters.
}
switch ((Lit.MaterialId)materialID.floatValue)
switch ((BaseLitGUI.MaterialId)materialID.floatValue)
case Lit.MaterialId.LitSSS:
case BaseLitGUI.MaterialId.LitSSS:
case Lit.MaterialId.LitStandard:
case BaseLitGUI.MaterialId.LitStandard:
case Lit.MaterialId.LitAniso:
case BaseLitGUI.MaterialId.LitAniso:
case Lit.MaterialId.LitSpecular:
case BaseLitGUI.MaterialId.LitSpecular:
case Lit.MaterialId.LitClearCoat:
case BaseLitGUI.MaterialId.LitClearCoat:
ShaderClearCoatInputGUI();
break;
default:

material.DisableKeyword("_REQUIRE_UV3");
}
Lit.MaterialId materialId = (Lit.MaterialId)material.GetFloat(kMaterialID);
BaseLitGUI.MaterialId materialId = (BaseLitGUI.MaterialId)material.GetFloat(kMaterialID);
CoreUtils.SetKeyword(material, "_MATID_SSS", materialId == Lit.MaterialId.LitSSS);
//CoreUtils.SetKeyword(material, "_MATID_STANDARD", materialId == Lit.MaterialId.LitStandard); // See comment in Lit.shader, it is the default, we don't define it
CoreUtils.SetKeyword(material, "_MATID_ANISO", materialId == Lit.MaterialId.LitAniso);
CoreUtils.SetKeyword(material, "_MATID_SPECULAR", materialId == Lit.MaterialId.LitSpecular);
CoreUtils.SetKeyword(material, "_MATID_CLEARCOAT", materialId == Lit.MaterialId.LitClearCoat);
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_SUBSURFACE_SCATTERING", materialId == BaseLitGUI.MaterialId.LitSSS);
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_TRANSMISSION", materialId == BaseLitGUI.MaterialId.LitSSS);
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_ANISOTROPY", materialId == BaseLitGUI.MaterialId.LitAniso);
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_CLEAR_COAT", materialId == BaseLitGUI.MaterialId.LitClearCoat);
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_IRIDESCENCE", materialId == BaseLitGUI.MaterialId.LitIridescence);
CoreUtils.SetKeyword(material, "_MATERIAL_FEATURE_SPECULAR_COLOR", materialId == BaseLitGUI.MaterialId.LitSpecular);
var refractionModeValue = (Lit.RefractionMode)material.GetFloat(kRefractionMode);
// We can't have refraction in pre-refraction queue

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Deferred.shader


Outputs outputs;
#ifdef OUTPUT_SPLIT_LIGHTING
if (_EnableSubsurfaceScattering != 0 && HaveSubsurfaceScattering(bsdfData))
if ((_EnableSubsurfaceScattering != 0) && HaveSubsurfaceScattering(bsdfData))
{
outputs.specularLighting = float4(specularLighting, 1.0);
outputs.diffuseLighting = TagLightingForSSS(diffuseLighting);

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Deferred.compute


float3 specularLighting;
LightLoop(V, posInput, preLightData, bsdfData, bakeLightingData, featureFlags, diffuseLighting, specularLighting);
if (_EnableSubsurfaceScattering != 0 && HaveSubsurfaceScattering(bsdfData))
if ((_EnableSubsurfaceScattering != 0) && HaveSubsurfaceScattering(bsdfData))
{
specularLightingUAV[pixelCoord] = float4(specularLighting, 1.0);
diffuseLightingUAV[pixelCoord] = TagLightingForSSS(diffuseLighting);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs


None,
Tile,
Cluster,
FeatureVariants
MaterialFeatureVariants
};
public enum TileClusterCategoryDebug : int

#endif
// Debug tiles
if (lightingDebug.tileClusterDebug == LightLoop.TileClusterDebug.FeatureVariants)
if (lightingDebug.tileClusterDebug == LightLoop.TileClusterDebug.MaterialFeatureVariants)
{
if (GetFeatureVariantsEnabled())
{

16
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfile.hlsl


// Evaluate Int{0, inf}{2 * Pi * r * R(sqrt(r^2 + d^2))}, where R is the diffusion profile.
// Note: 'volumeAlbedo' should be premultiplied by 0.25.
// Ref: Approximate Reflectance Profiles for Efficient Subsurface Scattering by Pixar (BSSRDF only).
float3 ComputeTransmittanceDisney(float3 S, float3 volumeAlbedo, float thickness, float radiusScale)
float3 ComputeTransmittanceDisney(float3 S, float3 volumeAlbedo, float thickness)
// Thickness and SSS radius are decoupled for artists.
// In theory, we should modify the thickness by the inverse of the radius scale of the profile.
// thickness /= radiusScale;
// Thickness and SSS mask are decoupled for artists.
// In theory, we should modify the thickness by the inverse of the mask scale of the profile.
// thickness /= subsurfaceMask;
#if 0
float3 expOneThird = exp(((-1.0 / 3.0) * thickness) * S);

// and 'halfRcpVariance1' should be prescaled by (0.1 * DiffusionProfileConstants.SSS_BASIC_DISTANCE_SCALE)^2.
float3 ComputeTransmittanceJimenez(float3 halfRcpVariance1, float lerpWeight1,
float3 halfRcpVariance2, float lerpWeight2,
float3 volumeAlbedo, float thickness, float radiusScale)
float3 volumeAlbedo, float thickness)
// Thickness and SSS radius are decoupled for artists.
// In theory, we should modify the thickness by the inverse of the radius scale of the profile.
// thickness /= radiusScale;
// Thickness and SSS mask are decoupled for artists.
// In theory, we should modify the thickness by the inverse of the mask scale of the profile.
// thickness /= subsurfaceMask;
float t2 = thickness * thickness;

33
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs


[GenerateHLSL]
public class DiffusionProfileConstants
{
public const int DIFFUSION_N_PROFILES = 16; // Max. number of profiles, including the slot taken by the neutral profile
public const int DIFFUSION_NEUTRAL_PROFILE_ID = 0; // Does not result in blurring
public const int DIFFUSION_PROFILE_COUNT = 16; // Max. number of profiles, including the slot taken by the neutral profile
public const int DIFFUSION_PROFILE_NEUTRAL_ID = 0; // Does not result in blurring
public const int SSS_N_SAMPLES_NEAR_FIELD = 55; // Used for extreme close ups; must be a Fibonacci number
public const int SSS_N_SAMPLES_FAR_FIELD = 21; // Used at a regular distance; must be a Fibonacci number
public const int SSS_LOD_THRESHOLD = 4; // The LoD threshold of the near-field kernel (in pixels)

[NonSerialized] public Vector4[] worldScales; // X = meters per world unit; Y = world units per meter
[NonSerialized] public Vector4[] shapeParams; // RGB = S = 1 / D, A = filter radius
[NonSerialized] public Vector4[] transmissionTintsAndFresnel0; // RGB = color, A = fresnel0
[NonSerialized] public Vector4[] disabledTransmissionTintsAndFresnel0; // RGB = black, A = fresnel0 - For debug to remove the transmission
[NonSerialized] public Vector4[] filterKernels; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
// Old SSS Model >>>

{
get
{
if (index >= DiffusionProfileConstants.DIFFUSION_N_PROFILES - 1)
if (index >= DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT - 1)
throw new IndexOutOfRangeException("index");
return profiles[index];

void OnEnable()
{
// The neutral profile is not a part of the array.
int profileArraySize = DiffusionProfileConstants.DIFFUSION_N_PROFILES - 1;
int profileArraySize = DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT - 1;
if (profiles != null && profiles.Length != profileArraySize)
Array.Resize(ref profiles, profileArraySize);

profiles[i].Validate();
}
ValidateArray(ref thicknessRemaps, DiffusionProfileConstants.DIFFUSION_N_PROFILES);
ValidateArray(ref worldScales, DiffusionProfileConstants.DIFFUSION_N_PROFILES);
ValidateArray(ref shapeParams, DiffusionProfileConstants.DIFFUSION_N_PROFILES);
ValidateArray(ref transmissionTintsAndFresnel0, DiffusionProfileConstants.DIFFUSION_N_PROFILES);
ValidateArray(ref filterKernels, DiffusionProfileConstants.DIFFUSION_N_PROFILES * DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD);
ValidateArray(ref thicknessRemaps, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT);
ValidateArray(ref worldScales, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT);
ValidateArray(ref shapeParams, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT);
ValidateArray(ref transmissionTintsAndFresnel0, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT);
ValidateArray(ref disabledTransmissionTintsAndFresnel0, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT);
ValidateArray(ref filterKernels, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT * DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD);
ValidateArray(ref halfRcpWeightedVariances, DiffusionProfileConstants.DIFFUSION_N_PROFILES);
ValidateArray(ref halfRcpVariancesAndWeights, DiffusionProfileConstants.DIFFUSION_N_PROFILES * 2);
ValidateArray(ref filterKernelsBasic, DiffusionProfileConstants.DIFFUSION_N_PROFILES * DiffusionProfileConstants.SSS_BASIC_N_SAMPLES);
ValidateArray(ref halfRcpWeightedVariances, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT);
ValidateArray(ref halfRcpVariancesAndWeights, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT * 2);
ValidateArray(ref filterKernelsBasic, DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT * DiffusionProfileConstants.SSS_BASIC_N_SAMPLES);
Debug.Assert(DiffusionProfileConstants.DIFFUSION_NEUTRAL_PROFILE_ID < 16, "Transmission flags (32-bit integer) cannot support more than 16 profiles (2 bits per profile).");
Debug.Assert(DiffusionProfileConstants.DIFFUSION_PROFILE_NEUTRAL_ID <= 16, "Transmission flags (32-bit integer) cannot support more than 16 profiles (2 bits per profile).");
UpdateCache();
}

public void UpdateCache()
{
for (int i = 0; i < DiffusionProfileConstants.DIFFUSION_N_PROFILES - 1; i++)
for (int i = 0; i < DiffusionProfileConstants.DIFFUSION_PROFILE_COUNT - 1; i++)
int neutralId = DiffusionProfileConstants.DIFFUSION_NEUTRAL_PROFILE_ID;
int neutralId = DiffusionProfileConstants.DIFFUSION_PROFILE_NEUTRAL_ID;
worldScales[neutralId] = Vector4.one;
shapeParams[neutralId] = Vector4.zero;

float fresnel0 = (profiles[p].ior - 1.0f) / (profiles[p].ior + 1.0f);
fresnel0 *= fresnel0; // square
transmissionTintsAndFresnel0[i] = new Vector4(profiles[p].transmissionTint.r * 0.25f, profiles[p].transmissionTint.g * 0.25f, profiles[p].transmissionTint.b * 0.25f, fresnel0); // Premultiplied
disabledTransmissionTintsAndFresnel0[i] = new Vector4(0.0f, 0.0f, 0.0f, fresnel0);
for (int j = 0, n = DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.hlsl


//
// UnityEngine.Experimental.Rendering.HDPipeline.DiffusionProfileConstants: static fields
//
#define DIFFUSION_N_PROFILES (16)
#define DIFFUSION_NEUTRAL_PROFILE_ID (0)
#define DIFFUSION_PROFILE_COUNT (16)
#define DIFFUSION_PROFILE_NEUTRAL_ID (0)
#define SSS_N_SAMPLES_NEAR_FIELD (55)
#define SSS_N_SAMPLES_FAR_FIELD (21)
#define SSS_LOD_THRESHOLD (4)

12
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLit.shader


[Enum(Flip, 0, Mirror, 1)] _DoubleSidedNormalMode("Double sided normal mode", Float) = 1
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[Enum(Subsurface Scattering, 0, Standard, 1)] _MaterialID("MaterialId", Int) = 1 // MaterialId.RegularLighting
[Enum(Subsurface Scattering, 0, Standard, 1)] _MaterialID("MaterialId", Int) = 1
[Enum(None, 0, Vertex displacement, 1, Pixel displacement, 2)] _DisplacementMode("DisplacementMode", Int) = 0
[ToggleOff] _DisplacementLockObjectScale("displacement lock object scale", Float) = 1.0

#pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
#pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT
// MaterialId are used as shader feature to allow compiler to optimize properly
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
#pragma shader_feature _ _MATID_SSS
// MaterialFeature are used as shader feature to allow compiler to optimize properly
#pragma shader_feature _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
#pragma shader_feature _MATERIAL_FEATURE_TRANSMISSION
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE

#define HAVE_VERTEX_MODIFICATION
// If we use subsurface scattering, enable output split lighting (for forward pass)
#if defined(_MATID_SSS) && !defined(_SURFACE_TYPE_TRANSPARENT)
#if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT)
#define OUTPUT_SPLIT_LIGHTING
#endif

}
}
CustomEditor "Experimental.Rendering.HDPipeline.LayeredLitGUI"
CustomEditor "UnityEditor.Experimental.Rendering.HDPipeline.LayeredLitGUI"
}

18
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl


surfaceData.thickness = SURFACEDATA_BLEND_SCALAR(surfaceData, thickness, weights);
surfaceData.diffusionProfile = SURFACEDATA_BLEND_SSS_PROFILE(surfaceData, diffusionProfile, weights);
// Layered shader support either SSS or standard (can't mix them)
#ifdef _MATID_SSS
surfaceData.materialId = MATERIALID_LIT_SSS;
#else // Default
surfaceData.materialId = MATERIALID_LIT_STANDARD;
// Layered shader support SSS and Transmission features
surfaceData.materialFeatures = 0;
#ifdef _MATERIALFEATURE_SUBSURFACE_SCATTERING
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING;
#endif
#ifdef _MATERIAL_FEATURE_TRANSMISSION
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION;
surfaceData.anisotropy = 0;
surfaceData.anisotropy = 0.0;
surfaceData.coatMask = 0.0f;
surfaceData.coatMask = 0.0;
surfaceData.thicknessIrid = 0.0;
// Transparency parameters
// Use thickness from SSS

12
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitTessellation.shader


[Enum(Flip, 0, Mirror, 1)] _DoubleSidedNormalMode("Double sided normal mode", Float) = 1
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[Enum(Subsurface Scattering, 0, Standard, 1)] _MaterialID("MaterialId", Int) = 1 // MaterialId.RegularLighting
[Enum(Subsurface Scattering, 0, Standard, 1)] _MaterialID("MaterialId", Int) = 1
[Enum(None, 0, Tessellation displacement, 3)] _DisplacementMode("DisplacementMode", Int) = 3
[ToggleOff] _DisplacementLockObjectScale("displacement lock object scale", Float) = 1.0
[ToggleOff] _DisplacementLockTilingScale("displacement lock tiling scale", Float) = 1.0

#pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
#pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT
// MaterialId are used as shader feature to allow compiler to optimize properly
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
#pragma shader_feature _ _MATID_SSS
// MaterialFeature are used as shader feature to allow compiler to optimize properly
#pragma shader_feature _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
#pragma shader_feature _MATERIAL_FEATURE_TRANSMISSION
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE

#define HAVE_TESSELLATION_MODIFICATION
// If we use subsurface scattering, enable output split lighting (for forward pass)
#if defined(_MATID_SSS) && !defined(_SURFACE_TYPE_TRANSPARENT)
#if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT)
#define OUTPUT_SPLIT_LIGHTING
#endif

}
}
CustomEditor "Experimental.Rendering.HDPipeline.LayeredLitGUI"
CustomEditor "UnityEditor.Experimental.Rendering.HDPipeline.LayeredLitGUI"
}

127
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs


{
public partial class Lit : RenderPipelineMaterial
{
[GenerateHLSL(PackingRules.Exact)]
public enum MaterialId
{
LitSSS = 0,
LitStandard = 1,
LitAniso = 2,
LitClearCoat = 3,
// LitSpecular (DiffuseColor/SpecularColor) is an alternate parametrization for LitStandard (BaseColor/Metal/Specular), but it is the same shading model
// We don't want any specific materialId for it, instead we use LitStandard as materialId. However for UI purpose we still define this value here.
// For material classification we will use LitStandard too
LitSpecular = 4,
};
// Currently we have only one materialId (Standard GGX), so it is not store in the GBuffer and we don't test for it
// Material bit mask must match LightDefinitions.s_MaterialFeatureMaskFlags value
[GenerateHLSL]
// Material bit mask must match the size define LightDefinitions.s_MaterialFeatureMaskFlags value
[GenerateHLSL(PackingRules.Exact)]
LitSSS = 1 << MaterialId.LitSSS,
LitStandard = 1 << MaterialId.LitStandard,
LitAniso = 1 << MaterialId.LitAniso,
LitClearCoat = 1 << MaterialId.LitClearCoat,
LitStandard = 1 << 0, // For material classification we need to identify that we are indeed use as standard material, else we are consider as sky/background element
LitSpecularColor = 1 << 1, // LitSpecularColor is not use statically but only dynamically
LitSubsurfaceScattering = 1 << 2,
LitTransmission = 1 << 3,
LitAnisotropy = 1 << 4,
LitIridescence = 1 << 5,
LitClearCoat = 1 << 6
[GenerateHLSL]
public class StandardDefinitions
{
public static int s_GBufferLitStandardRegularId = 0;
public static int s_GBufferLitStandardSpecularColorId = 1;
public static float s_DefaultSpecularValue = 0.04f;
}
[GenerateHLSL(PackingRules.Exact)]
public enum RefractionMode
{

[GenerateHLSL(PackingRules.Exact, false, true, 1000)]
public struct SurfaceData
{
[SurfaceDataAttributes("MaterialFeatures")]
public uint materialFeatures;
// Standard
[SurfaceDataAttributes("Base Color", false, true)]
public Vector3 baseColor;
[SurfaceDataAttributes("Specular Occlusion")]

public Vector3 normalWS;
[SurfaceDataAttributes("Smoothness")]
public float perceptualSmoothness;
[SurfaceDataAttributes("Material ID")]
public MaterialId materialId; // matId above 3 are store in standard material gbuffer (2bit reserved)
// MaterialId dependent attribute
// standard
[SurfaceDataAttributes("Tangent", true)]
public Vector3 tangentWS;
[SurfaceDataAttributes("Anisotropy")]
public float anisotropy; // anisotropic ratio(0->no isotropic; 1->full anisotropy in tangent direction)
[SurfaceDataAttributes("Coat mask")]
public float coatMask;
// MaterialFeature dependent attribute
// Specular Color
[SurfaceDataAttributes("Specular Color", false, true)]
public Vector3 specularColor;
[SurfaceDataAttributes("Diffusion Profile")]
public int diffusionProfile;
// Transmission
// + Diffusion Profile
[SurfaceDataAttributes("Diffusion Profile")]
public int diffusionProfile;
// SpecColor
[SurfaceDataAttributes("Specular Color", false, true)]
public Vector3 specularColor;
// Anisotropic
[SurfaceDataAttributes("Tangent", true)]
public Vector3 tangentWS;
[SurfaceDataAttributes("Anisotropy")]
public float anisotropy; // anisotropic ratio(0->no isotropic; 1->full anisotropy in tangent direction, -1->full anisotropy in bitangent direction)
// ClearCoat
[SurfaceDataAttributes("Coat mask")]
public float coatMask;
// Iridescence
public float thicknessIrid;
// Only in forward
// Forward property only
// Reuse thickness from SSS
// Reuse thickness from SSS
[SurfaceDataAttributes("Transmittance Color")]
public Vector3 transmittanceColor;
[SurfaceDataAttributes("Transmittance Absorption Distance")]

[GenerateHLSL(PackingRules.Exact, false, true, 1030)]
public struct BSDFData
{
public uint materialFeatures;
public Vector3 fresnel0;
public float specularOcclusion;

public float perceptualRoughness;
public int materialId;
public float coatMask;
// MaterialFeature dependent attribute
// SpecularColor fold into fresnel0
// SSS
public int diffusionProfile;
public float subsurfaceMask;
// MaterialId dependent attribute
// Transmission
// + Diffusion Profile
public float thickness;
public bool useThickObjectMode; // Read from the diffusion profile
public Vector3 transmittance; // Precomputation of transmittance
// standard
// Anisotropic
[SurfaceDataAttributes("", true)]
public Vector3 tangentWS;
[SurfaceDataAttributes("", true)]

public float anisotropy;
// fold into fresnel0
// Iridescence
public float thicknessIrid;
// SSS
public float subsurfaceMask;
public float thickness;
public int diffusionProfile;
public bool enableTransmission; // Read from the SSS profile
public bool useThickObjectMode; // Read from the SSS profile
public Vector3 transmittance;
// ClearCoat
public float coatRoughness; // Automatically fill
// SpecColor
// fold into fresnel0
// Forward property only
// ClearCoat
public float coatMask;
public float coatRoughness;
// Only in forward
// Transparency
public float ior;
// Reuse thickness from SSS

206
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs.hlsl


#ifndef LIT_CS_HLSL
#define LIT_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+MaterialId: static fields
//
#define MATERIALID_LIT_SSS (0)
#define MATERIALID_LIT_STANDARD (1)
#define MATERIALID_LIT_ANISO (2)
#define MATERIALID_LIT_CLEAR_COAT (3)
#define MATERIALID_LIT_SPECULAR (4)
//
#define MATERIALFEATUREFLAGS_LIT_SSS (1)
#define MATERIALFEATUREFLAGS_LIT_STANDARD (2)
#define MATERIALFEATUREFLAGS_LIT_ANISO (4)
#define MATERIALFEATUREFLAGS_LIT_CLEAR_COAT (8)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+StandardDefinitions: static fields
//
#define GBUFFER_LIT_STANDARD_REGULAR_ID (0)
#define GBUFFER_LIT_STANDARD_SPECULAR_COLOR_ID (1)
#define DEFAULT_SPECULAR_VALUE (0.04)
#define MATERIALFEATUREFLAGS_LIT_STANDARD (1)
#define MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR (2)
#define MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING (4)
#define MATERIALFEATUREFLAGS_LIT_TRANSMISSION (8)
#define MATERIALFEATUREFLAGS_LIT_ANISOTROPY (16)
#define MATERIALFEATUREFLAGS_LIT_IRIDESCENCE (32)
#define MATERIALFEATUREFLAGS_LIT_CLEAR_COAT (64)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+RefractionMode: static fields

//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+SurfaceData: static fields
//
#define DEBUGVIEW_LIT_SURFACEDATA_BASE_COLOR (1000)
#define DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_OCCLUSION (1001)
#define DEBUGVIEW_LIT_SURFACEDATA_NORMAL_WS (1002)
#define DEBUGVIEW_LIT_SURFACEDATA_PERCEPTUAL_SMOOTHNESS (1003)
#define DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_ID (1004)
#define DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_FEATURES (1000)
#define DEBUGVIEW_LIT_SURFACEDATA_BASE_COLOR (1001)
#define DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_OCCLUSION (1002)
#define DEBUGVIEW_LIT_SURFACEDATA_NORMAL_WS (1003)
#define DEBUGVIEW_LIT_SURFACEDATA_PERCEPTUAL_SMOOTHNESS (1004)
#define DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS (1006)
#define DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY (1007)
#define DEBUGVIEW_LIT_SURFACEDATA_METALLIC (1008)
#define DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_MASK (1009)
#define DEBUGVIEW_LIT_SURFACEDATA_THICKNESS (1010)
#define DEBUGVIEW_LIT_SURFACEDATA_DIFFUSION_PROFILE (1011)
#define DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR (1012)
#define DEBUGVIEW_LIT_SURFACEDATA_COAT_MASK (1013)
#define DEBUGVIEW_LIT_SURFACEDATA_IOR (1014)
#define DEBUGVIEW_LIT_SURFACEDATA_TRANSMITTANCE_COLOR (1015)
#define DEBUGVIEW_LIT_SURFACEDATA_AT_DISTANCE (1016)
#define DEBUGVIEW_LIT_SURFACEDATA_TRANSMITTANCE_MASK (1017)
#define DEBUGVIEW_LIT_SURFACEDATA_METALLIC (1006)
#define DEBUGVIEW_LIT_SURFACEDATA_COAT_MASK (1007)
#define DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR (1008)
#define DEBUGVIEW_LIT_SURFACEDATA_DIFFUSION_PROFILE (1009)
#define DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_MASK (1010)
#define DEBUGVIEW_LIT_SURFACEDATA_THICKNESS (1011)
#define DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS (1012)
#define DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY (1013)
#define DEBUGVIEW_LIT_SURFACEDATA_THICKNESS_IRID (1014)
#define DEBUGVIEW_LIT_SURFACEDATA_IOR (1015)
#define DEBUGVIEW_LIT_SURFACEDATA_TRANSMITTANCE_COLOR (1016)
#define DEBUGVIEW_LIT_SURFACEDATA_AT_DISTANCE (1017)
#define DEBUGVIEW_LIT_SURFACEDATA_TRANSMITTANCE_MASK (1018)
#define DEBUGVIEW_LIT_BSDFDATA_DIFFUSE_COLOR (1030)
#define DEBUGVIEW_LIT_BSDFDATA_FRESNEL0 (1031)
#define DEBUGVIEW_LIT_BSDFDATA_SPECULAR_OCCLUSION (1032)
#define DEBUGVIEW_LIT_BSDFDATA_NORMAL_WS (1033)
#define DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS (1034)
#define DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID (1035)
#define DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS (1036)
#define DEBUGVIEW_LIT_BSDFDATA_BITANGENT_WS (1037)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_T (1038)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B (1039)
#define DEBUGVIEW_LIT_BSDFDATA_ANISOTROPY (1040)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_MASK (1041)
#define DEBUGVIEW_LIT_BSDFDATA_THICKNESS (1042)
#define DEBUGVIEW_LIT_BSDFDATA_DIFFUSION_PROFILE (1043)
#define DEBUGVIEW_LIT_BSDFDATA_ENABLE_TRANSMISSION (1044)
#define DEBUGVIEW_LIT_BSDFDATA_USE_THICK_OBJECT_MODE (1045)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE (1046)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_MASK (1047)
#define DEBUGVIEW_LIT_BSDFDATA_MATERIAL_FEATURES (1030)
#define DEBUGVIEW_LIT_BSDFDATA_DIFFUSE_COLOR (1031)
#define DEBUGVIEW_LIT_BSDFDATA_FRESNEL0 (1032)
#define DEBUGVIEW_LIT_BSDFDATA_SPECULAR_OCCLUSION (1033)
#define DEBUGVIEW_LIT_BSDFDATA_NORMAL_WS (1034)
#define DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS (1035)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_MASK (1036)
#define DEBUGVIEW_LIT_BSDFDATA_DIFFUSION_PROFILE (1037)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_MASK (1038)
#define DEBUGVIEW_LIT_BSDFDATA_THICKNESS (1039)
#define DEBUGVIEW_LIT_BSDFDATA_USE_THICK_OBJECT_MODE (1040)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE (1041)
#define DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS (1042)
#define DEBUGVIEW_LIT_BSDFDATA_BITANGENT_WS (1043)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_T (1044)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B (1045)
#define DEBUGVIEW_LIT_BSDFDATA_ANISOTROPY (1046)
#define DEBUGVIEW_LIT_BSDFDATA_THICKNESS_IRID (1047)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS (1048)
#define DEBUGVIEW_LIT_BSDFDATA_IOR (1049)
#define DEBUGVIEW_LIT_BSDFDATA_ABSORPTION_COEFFICIENT (1050)

// PackingRules = Exact
struct SurfaceData
{
uint materialFeatures;
int materialId;
float3 tangentWS;
float anisotropy;
float coatMask;
float3 specularColor;
int diffusionProfile;
int diffusionProfile;
float3 specularColor;
float coatMask;
float3 tangentWS;
float anisotropy;
float thicknessIrid;
float ior;
float3 transmittanceColor;
float atDistance;

// PackingRules = Exact
struct BSDFData
{
uint materialFeatures;
int materialId;
float coatMask;
int diffusionProfile;
float subsurfaceMask;
float thickness;
bool useThickObjectMode;
float3 transmittance;
float subsurfaceMask;
float thickness;
int diffusionProfile;
bool enableTransmission;
bool useThickObjectMode;
float3 transmittance;
float coatMask;
float thicknessIrid;
float coatRoughness;
float ior;
float3 absorptionCoefficient;

{
switch (paramId)
{
case DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_FEATURES:
result = GetIndexColor(surfacedata.materialFeatures);
break;
case DEBUGVIEW_LIT_SURFACEDATA_BASE_COLOR:
result = surfacedata.baseColor;
needLinearToSRGB = true;

case DEBUGVIEW_LIT_SURFACEDATA_PERCEPTUAL_SMOOTHNESS:
result = surfacedata.perceptualSmoothness.xxx;
break;
case DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_ID:
result = GetIndexColor(surfacedata.materialId);
break;
case DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS:
result = surfacedata.tangentWS * 0.5 + 0.5;
break;
case DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY:
result = surfacedata.anisotropy.xxx;
break;
case DEBUGVIEW_LIT_SURFACEDATA_COAT_MASK:
result = surfacedata.coatMask.xxx;
break;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR:
result = surfacedata.specularColor;
needLinearToSRGB = true;
break;
case DEBUGVIEW_LIT_SURFACEDATA_DIFFUSION_PROFILE:
result = GetIndexColor(surfacedata.diffusionProfile);
break;
case DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_MASK:
result = surfacedata.subsurfaceMask.xxx;
break;

case DEBUGVIEW_LIT_SURFACEDATA_DIFFUSION_PROFILE:
result = GetIndexColor(surfacedata.diffusionProfile);
case DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS:
result = surfacedata.tangentWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR:
result = surfacedata.specularColor;
needLinearToSRGB = true;
case DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY:
result = surfacedata.anisotropy.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_COAT_MASK:
result = surfacedata.coatMask.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_THICKNESS_IRID:
result = surfacedata.thicknessIrid.xxx;
break;
case DEBUGVIEW_LIT_SURFACEDATA_IOR:
result = surfacedata.ior.xxx;

{
switch (paramId)
{
case DEBUGVIEW_LIT_BSDFDATA_MATERIAL_FEATURES:
result = GetIndexColor(bsdfdata.materialFeatures);
break;
case DEBUGVIEW_LIT_BSDFDATA_DIFFUSE_COLOR:
result = bsdfdata.diffuseColor;
needLinearToSRGB = true;

case DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS:
result = bsdfdata.perceptualRoughness.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID:
result = GetIndexColor(bsdfdata.materialId);
case DEBUGVIEW_LIT_BSDFDATA_COAT_MASK:
result = bsdfdata.coatMask.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_DIFFUSION_PROFILE:
result = GetIndexColor(bsdfdata.diffusionProfile);
break;
case DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_MASK:
result = bsdfdata.subsurfaceMask.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_THICKNESS:
result = bsdfdata.thickness.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_USE_THICK_OBJECT_MODE:
result = (bsdfdata.useThickObjectMode) ? float3(1.0, 1.0, 1.0) : float3(0.0, 0.0, 0.0);
break;
case DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE:
result = bsdfdata.transmittance;
break;
case DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS:
result = bsdfdata.tangentWS * 0.5 + 0.5;

case DEBUGVIEW_LIT_BSDFDATA_ANISOTROPY:
result = bsdfdata.anisotropy.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_MASK:
result = bsdfdata.subsurfaceMask.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_THICKNESS:
result = bsdfdata.thickness.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_DIFFUSION_PROFILE:
result = GetIndexColor(bsdfdata.diffusionProfile);
break;
case DEBUGVIEW_LIT_BSDFDATA_ENABLE_TRANSMISSION:
result = (bsdfdata.enableTransmission) ? float3(1.0, 1.0, 1.0) : float3(0.0, 0.0, 0.0);
break;
case DEBUGVIEW_LIT_BSDFDATA_USE_THICK_OBJECT_MODE:
result = (bsdfdata.useThickObjectMode) ? float3(1.0, 1.0, 1.0) : float3(0.0, 0.0, 0.0);
break;
case DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE:
result = bsdfdata.transmittance;
break;
case DEBUGVIEW_LIT_BSDFDATA_COAT_MASK:
result = bsdfdata.coatMask.xxx;
case DEBUGVIEW_LIT_BSDFDATA_THICKNESS_IRID:
result = bsdfdata.thicknessIrid.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS:
result = bsdfdata.coatRoughness.xxx;

590
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl


#define GBUFFER_LIT_SPECULAR_COLOR 15
#define GBUFFER_LIT_SSS_OR_TRANSMISSION 14
#define GBUFFER_LIT_IRIDESCENCE 13
#define GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND 12
#define CLEAR_COAT_IETA (1.0 / CLEAR_COAT_IOR)
#define CLEAR_COAT_IETA (1.0 / CLEAR_COAT_IOR) // IETA is the inverse eta which is the ratio of IOR of two interface
#define CLEAR_COAT_PERCEPTUAL_ROUGHNESS 0.031622
#define CLEAR_COAT_ROUGHNESS (CLEAR_COAT_PERCEPTUAL_ROUGHNESS * CLEAR_COAT_PERCEPTUAL_ROUGHNESS) // 0.001
#define CLEAR_COAT_ROUGHNESS 0.001
#define CLEAR_COAT_PERCEPTUAL_ROUGHNESS RoughnessToPerceptualRoughness(CLEAR_COAT_ROUGHNESS)
//-----------------------------------------------------------------------------
// Configuration

// If a user do a lighting architecture without material classification, this can be remove
#include "../../Lighting/LightLoop/LightLoop.cs.hlsl"
static uint g_FeatureFlags = UINT_MAX;
// This method allows us to know at compile time what shader features should be removed from the code when the materialID cannot be known on the whole tile (any combination of 2 or more differnet materials in the same tile)
// This is only useful for classification during lighting, so it's not needed in EncodeIntoGBuffer and ConvertSurfaceDataToBSDFData (where we always know exactly what the MaterialID is)
bool HasMaterialFeatureFlag(uint flag)
{
return ((g_FeatureFlags & flag) != 0);
}
// Precomputed illumination (no dynamic lights) for all material types (except for the clear coat)
/* 0 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_ENV | (MATERIAL_FEATURE_MASK_FLAGS & (~MATERIALFEATUREFLAGS_LIT_CLEAR_COAT)),
// Precomputed illumination (no dynamic lights) for all material types
/* 0 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_ENV | MATERIAL_FEATURE_MASK_FLAGS,
// Standard>Specular
/* 1 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 2 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 3 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,

// SSS
/* 6 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_SSS,
/* 7 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_SSS,
/* 8 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SSS,
/* 9 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SSS,
/* 10 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_SSS,
// Standard with SSS and Transmission
/* 6 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 7 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 8 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 9 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 10 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION | MATERIALFEATUREFLAGS_LIT_STANDARD,
// Aniso
/* 11 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 12 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 13 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 14 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 15 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_ANISO,
// Anisotropy
/* 11 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_ANISOTROPY | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 12 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_ANISOTROPY | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 13 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_ANISOTROPY | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 14 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_ANISOTROPY | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 15 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_ANISOTROPY | MATERIALFEATUREFLAGS_LIT_STANDARD,
// With foliage or crowd with SSS and standard can overlap a lot, better to have a dedicated combination
/* 16 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 17 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 18 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 19 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 20 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
// Standard with clear coat
/* 16 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 17 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 18 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 19 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 20 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
// ClearCoat
/* 21 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,
/* 22 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,
/* 23 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,
/* 24 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,
/* 25 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,
// Standard with clear coat and Iridescence
/* 21 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_IRIDESCENCE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 22 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_IRIDESCENCE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 23 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_IRIDESCENCE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 24 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_IRIDESCENCE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 25 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_IRIDESCENCE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 26 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIAL_FEATURE_MASK_FLAGS, // Catch all case with MATERIAL_FEATURE_MASK_FLAGS is needed in case we disable material classification
};

return positionWS + rayWS * hitDistanceFromPosition;
}
float PackMaterialId(int materialId)
// 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(uint featureFlags, uint flag)
return float(materialId) / 3.0;
return ((featureFlags & flag) != 0);
int UnpackMaterialId(float f)
{
return int(round(f * 3.0));
}
float3 ComputeDiffuseColor(float3 baseColor, float metallic)
{

return lerp(dielectricF0.xxx, baseColor, metallic);
}
// Fills the data which may be accessed if MATERIALFEATUREFLAGS_LIT_SSS is set.
void FillMaterialIdSssData(int diffusionProfile, float subsurfaceMask, float thickness, uint transmissionMode, inout BSDFData bsdfData)
// Assume that bsdfData.diffusionProfile is init
void FillMaterialSSS(float subsurfaceMask, inout BSDFData bsdfData)
bsdfData.diffusionProfile = diffusionProfile;
bsdfData.fresnel0 = _TransmissionTintsAndFresnel0[bsdfData.diffusionProfile].a;
bsdfData.enableTransmission = (transmissionMode != TRANSMISSION_MODE_NONE);
// Note: ApplySubsurfaceScatteringTexturingMode also test the diffusionProfile for updating diffuseColor based on SSS
}
// Assume that bsdfData.diffusionProfile is init
void FillMaterialTransmission(float thickness, inout BSDFData bsdfData)
{
int diffusionProfile = bsdfData.diffusionProfile;
if (bsdfData.enableTransmission)
{
bsdfData.thickness = _ThicknessRemaps[diffusionProfile].x + _ThicknessRemaps[diffusionProfile].y * thickness;
bsdfData.useThickObjectMode = transmissionMode != TRANSMISSION_MODE_THIN;
bsdfData.thickness = _ThicknessRemaps[diffusionProfile].x + _ThicknessRemaps[diffusionProfile].y * thickness;
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * diffusionProfile, 2u);
bsdfData.useThickObjectMode = transmissionMode != TRANSMISSION_MODE_THIN;
bsdfData.transmittance = _TransmittanceMultiplier * ComputeTransmittanceDisney( _ShapeParams[diffusionProfile].rgb,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness, 1.0);
bsdfData.transmittance = ComputeTransmittanceDisney( _ShapeParams[diffusionProfile].rgb,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness);
bsdfData.transmittance = _TransmittanceMultiplier * ComputeTransmittanceJimenez( _HalfRcpVariancesAndWeights[diffusionProfile][0].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][0].a,
_HalfRcpVariancesAndWeights[diffusionProfile][1].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][1].a,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness, 1.0);
bsdfData.transmittance = ComputeTransmittanceJimenez( _HalfRcpVariancesAndWeights[diffusionProfile][0].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][0].a,
_HalfRcpVariancesAndWeights[diffusionProfile][1].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][1].a,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness);
}
}
// Assume bsdfData.normalWS is init
void FillMaterialAnisotropy(float anisotropy, float3 tangentWS, inout BSDFData bsdfData)
{
bsdfData.anisotropy = anisotropy;
bsdfData.tangentWS = tangentWS;
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
}
void FillMaterialIridescence(float thicknessIrid, inout BSDFData bsdfData)
{
bsdfData.thicknessIrid = thicknessIrid;
void FillMaterialIdClearCoatData(float coatMask, inout BSDFData bsdfData)
void FillMaterialClearCoatData(float coatMask, inout BSDFData bsdfData)
{
bsdfData.coatMask = coatMask;
float ieta = lerp(1.0, CLEAR_COAT_IETA, bsdfData.coatMask);

float coatRoughnessScale = Sq(ieta);
float sigma = roughnessToVariance(PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness));
bsdfData.perceptualRoughness = RoughnessToPerceptualRoughness(varianceToRoughness(sigma * coatRoughnessScale));
// fresnel0 is deduced from interface between air and material (assume to be 1.5 in Unity, or a metal).
float sigma = RoughnessToVariance(PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness));
bsdfData.perceptualRoughness = RoughnessToPerceptualRoughness(VarianceToRoughness(sigma * coatRoughnessScale));
// Fresnel0 is deduced from interface between air and material (Assume to be 1.5 in Unity, or a metal).
bsdfData.fresnel0 = Fresnel0ReajustFor15(bsdfData.fresnel0);
bsdfData.fresnel0 = ConvertF0ForAirInterfaceToF0ForClearCoat15(bsdfData.fresnel0);
void FillMaterialIdTransparencyData(float3 baseColor, float metallic, float ior, float3 transmittanceColor, float atDistance, float thickness, float transmittanceMask, inout BSDFData bsdfData)
void FillMaterialTransparencyData(float3 baseColor, float metallic, float ior, float3 transmittanceColor, float atDistance, float thickness, float transmittanceMask, inout BSDFData bsdfData)
{
// Uses thickness from SSS's property set
bsdfData.ior = ior;

bsdfData.absorptionCoefficient = TransmittanceColorAtDistanceToAbsorption (transmittanceColor, atDistance);
bsdfData.absorptionCoefficient = TransmittanceColorAtDistanceToAbsorption(transmittanceColor, atDistance);
bsdfData.transmittanceMask = transmittanceMask;
bsdfData.thickness = max(thickness, 0.0001);
}

BSDFData bsdfData;
ZERO_INITIALIZE(BSDFData, bsdfData);
bsdfData.materialId = surfaceData.materialId;
bsdfData.specularOcclusion = surfaceData.specularOcclusion;
bsdfData.normalWS = surfaceData.normalWS;
bsdfData.anisotropy = surfaceData.anisotropy;
bsdfData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness);
// IMPORTANT: In case of foward or gbuffer pass all enable flags are statically know at compile time, so the compiler can do compile time optimization
bsdfData.materialFeatures = surfaceData.materialFeatures | MATERIALFEATUREFLAGS_LIT_STANDARD; // Not really needed but for consistency with deferred path
// Standard material
bsdfData.specularOcclusion = surfaceData.specularOcclusion;
bsdfData.normalWS = surfaceData.normalWS;
bsdfData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness);
// There is no mettalic with SSS and specular color mode
float metallic = HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR | MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION | MATERIALFEATUREFLAGS_LIT_IRIDESCENCE) ?
0.0 : surfaceData.metallic;
bsdfData.diffuseColor = ComputeDiffuseColor(surfaceData.baseColor, metallic);
bsdfData.fresnel0 = HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR) ? surfaceData.specularColor : ComputeFresnel0(surfaceData.baseColor, surfaceData.metallic, DEFAULT_SPECULAR_VALUE);
// Always assign even if not used, DIFFUSION_PROFILE_NEUTRAL_ID is 0
bsdfData.diffusionProfile = surfaceData.diffusionProfile;
// Note: we have ZERO_INITIALIZE the struct so bsdfData.anisotropy == 0.0
// In forward everything is statically know and we could theorically cumulate all the material features. So the code reflect it.
// However in practice we keep parity between deferred and forward, so we should contrain the various features.
// The UI is in charge of setuping the constrain not the code, so if users is forward only and want full power, it is easy to unleash by some UI change
if (surfaceData.materialId != MATERIALID_LIT_ANISO)
if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING))
// Notify the material classification system that we should not use the anisotropic GGX for forward rendering.
// Forward rendering implies automatic material classification, so normally we don't use our material classification
// system, and set 'g_FeatureFlags' to UINT_MAX. However, since our rendering pipeline supports both forward and
// deferred rendering, 'g_FeatureFlags' is always available, so we can use it to control GGX evaluation.
g_FeatureFlags &= ~MATERIALFEATUREFLAGS_LIT_ANISO;
// Modify fresnel0
FillMaterialSSS(surfaceData.subsurfaceMask, bsdfData);
// IMPORTANT: In case of foward or gbuffer pass we must know what we are statically, so compiler can do compile time optimization
if (bsdfData.materialId == MATERIALID_LIT_STANDARD)
if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
bsdfData.diffuseColor = ComputeDiffuseColor(surfaceData.baseColor, surfaceData.metallic);
bsdfData.fresnel0 = ComputeFresnel0(surfaceData.baseColor, surfaceData.metallic, DEFAULT_SPECULAR_VALUE);
FillMaterialTransmission(surfaceData.thickness, bsdfData);
else if (bsdfData.materialId == MATERIALID_LIT_SPECULAR)
if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
// Note: Specular is not a material id but just a way to parameterize the standard materialid, thus we reset materialId to MATERIALID_LIT_STANDARD
bsdfData.materialId = MATERIALID_LIT_STANDARD;
bsdfData.diffuseColor = surfaceData.baseColor;
bsdfData.fresnel0 = surfaceData.specularColor;
FillMaterialAnisotropy(surfaceData.anisotropy, surfaceData.tangentWS, bsdfData);
else if (bsdfData.materialId == MATERIALID_LIT_SSS)
{
bsdfData.diffuseColor = surfaceData.baseColor;
bsdfData.fresnel0 = _TransmissionTintsAndFresnel0[surfaceData.diffusionProfile].a;
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * surfaceData.diffusionProfile, 2u);
FillMaterialIdSssData(surfaceData.diffusionProfile,
surfaceData.subsurfaceMask,
surfaceData.thickness,
transmissionMode, bsdfData);
}
else if (bsdfData.materialId == MATERIALID_LIT_ANISO)
if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE))
bsdfData.diffuseColor = ComputeDiffuseColor(surfaceData.baseColor, surfaceData.metallic);
bsdfData.fresnel0 = ComputeFresnel0(surfaceData.baseColor, surfaceData.metallic, DEFAULT_SPECULAR_VALUE);
bsdfData.tangentWS = surfaceData.tangentWS;
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
FillMaterialIridescence(surfaceData.thicknessIrid, bsdfData);
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT)
if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
// Same as MATERIALID_LIT_STANDARD + coatMask
bsdfData.diffuseColor = ComputeDiffuseColor(surfaceData.baseColor, surfaceData.metallic);
bsdfData.fresnel0 = ComputeFresnel0(surfaceData.baseColor, surfaceData.metallic, DEFAULT_SPECULAR_VALUE);
FillMaterialIdClearCoatData(surfaceData.coatMask, bsdfData);
// Modify fresnel0 and perceptualRoughness
FillMaterialClearCoatData(surfaceData.coatMask, bsdfData);
// perceptualRoughness can be modify by FillMaterialIdClearCoatData, so ConvertAnisotropyToClampRoughness must be call after
// perceptualRoughness can be modify by FillMaterialClearCoatData, so ConvertAnisotropyToClampRoughness must be call after
// Note: Will override thickness of SSS's property set
FillMaterialIdTransparencyData(
surfaceData.baseColor, surfaceData.metallic, surfaceData.ior, surfaceData.transmittanceColor, surfaceData.atDistance, surfaceData.thickness, surfaceData.transmittanceMask,
bsdfData);
// Note: Reuse thickness of transmission's property set
FillMaterialTransparencyData( surfaceData.baseColor, surfaceData.metallic, surfaceData.ior, surfaceData.transmittanceColor, surfaceData.atDistance,
surfaceData.thickness, surfaceData.transmittanceMask, bsdfData);
#endif
return bsdfData;

// To have more precision encode the sign of xy in a separate uint
uint octNormalSign = (octNormalWS.x < 0.0 ? 1 : 0) | (octNormalWS.y < 0.0 ? 2 : 0);
// Store octNormalSign on two bits with perceptualRoughness
outGBuffer1 = float4(abs(octNormalWS), PackFloatInt10bit(PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness), octNormalSign, 4.0), PackMaterialId(surfaceData.materialId));
outGBuffer1 = float4(abs(octNormalWS), PackFloatInt10bit(PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness), octNormalSign, 4.0), 0.0);
if (surfaceData.materialId == MATERIALID_LIT_STANDARD)
{
outGBuffer2 = float4(float3(0.0, 0.0, 0.0), PackFloatInt8bit(surfaceData.metallic, GBUFFER_LIT_STANDARD_REGULAR_ID, 2.0));
}
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
{
outGBuffer1.a = PackMaterialId(MATERIALID_LIT_STANDARD); // Encode MATERIALID_LIT_SPECULAR as MATERIALID_LIT_STANDARD + GBUFFER_LIT_STANDARD_SPECULAR_COLOR_ID value in GBuffer2
outGBuffer2 = float4(surfaceData.specularColor, PackFloatInt8bit(0.0, GBUFFER_LIT_STANDARD_SPECULAR_COLOR_ID, 2.0));
}
else if (surfaceData.materialId == MATERIALID_LIT_SSS)
// mettalic will be store on 4 bit and store special value when not used
int metallic15 = int(surfaceData.metallic * (GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND + 0.5)); // Remap to [0..12] range. 13, 14, 15 are special value
// IMPORTANT: In case of foward or gbuffer pass materialFeatures is statically know at compile time, so the compiler can do compile time optimization
// Currently material features SpecularColor, Iridescence, SubsurfaceScattering/Transmission, Anisotropy are mutually exclusive due to Gbuffer constrain
// 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 (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
metallic15 = GBUFFER_LIT_SSS_OR_TRANSMISSION;
outGBuffer2 = float4(surfaceData.specularOcclusion, surfaceData.thickness, 0.0, 0.0); // Thickness is use for transmission
outGBuffer2.rgb = float3(surfaceData.specularOcclusion, surfaceData.thickness, HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING) ? 1.0 : 0.0); // thickness for Transmission
else if (surfaceData.materialId == MATERIALID_LIT_ANISO)
else
// Encode tangent on 16bit with oct compression
float2 octTangentWS = PackNormalOctEncode(surfaceData.tangentWS);
// To have more precision encode the sign of xy in a separate uint
uint octTangentSign = (octTangentWS.x < 0.0 ? 1 : 0) | (octTangentWS.y < 0.0 ? 2 : 0);
outGBuffer2 = float4(abs(octTangentWS), surfaceData.anisotropy * 0.5 + 0.5, PackFloatInt8bit(surfaceData.metallic, octTangentSign, 4.0));
}
else if (surfaceData.materialId == MATERIALID_LIT_CLEAR_COAT)
{
outGBuffer2 = float4(0.0f, 0.0f, 0.0f, PackFloatInt8bit(surfaceData.coatMask, (int)(surfaceData.metallic * 15.5f), 16.0) );
if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR))
{
metallic15 = GBUFFER_LIT_SPECULAR_COLOR;
outGBuffer2.rgb = LinearToGamma20(surfaceData.specularColor);
}
else if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
{
// Encode tangent on 16bit with oct compression
float2 octTangentWS = PackNormalOctEncode(surfaceData.tangentWS);
outGBuffer2.rgb = float3(octTangentWS * 0.5 + 0.5, surfaceData.anisotropy * 0.5 + 0.5);
}
else if (HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE))
{
metallic15 = GBUFFER_LIT_IRIDESCENCE;
outGBuffer2.rgb = float3(0.0, surfaceData.thicknessIrid, 0.0);
}
else
{
// Caution: Neutral value for anisotropy is 0.5 not 0
outGBuffer2.rgb = float3(0.0, 0.0, 0.5);
}
// Lighting
// Encode coatMask (4bit) / mettalic (4bit)
outGBuffer2.a = PackFloatInt8bit(HasMaterialFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT) ? surfaceData.coatMask : 0.0, metallic15, 16.0);
// Lighting: 11:11:10f
void DecodeFromGBuffer(
uint2 positionSS,
uint featureFlags,
out BSDFData bsdfData,
out float3 bakeDiffuseLighting)
void DecodeFromGBuffer(uint2 positionSS, uint featureFlags, out BSDFData bsdfData, out float3 bakeDiffuseLighting, out uint outMaterialFeatures)
{
GBufferType0 inGBuffer0 = LOAD_TEXTURE2D(_GBufferTexture0, positionSS);
GBufferType1 inGBuffer1 = LOAD_TEXTURE2D(_GBufferTexture1, positionSS);

ZERO_INITIALIZE(BSDFData, bsdfData);
g_FeatureFlags = featureFlags;
// Init all material flags from Gbuffer2
float coatMask;
int metallic15;
UnpackFloatInt8bit(inGBuffer2.a, 16.0, coatMask, metallic15);
// If any of the flags of featureFlags 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.
bool enableSpecularColor = (metallic15 == GBUFFER_LIT_SPECULAR_COLOR); // This is always a dynamic test as it is very cheap
outMaterialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; // It is mandatory to identity ourselve as standard shader, else we are consider as sky/background element
outMaterialFeatures |= (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && inGBuffer2.g > 0.0) ? featureFlags & MATERIALFEATUREFLAGS_LIT_TRANSMISSION : 0; // Thickness > 0
outMaterialFeatures |= (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && inGBuffer2.b > 0.0) ? featureFlags & MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING : 0; // TagSSS > 0
outMaterialFeatures |= (metallic15 <= GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND && abs(inGBuffer2.b - 0.5) > 0.01) ? featureFlags & MATERIALFEATUREFLAGS_LIT_ANISOTROPY : 0; // Anisotropy != 0 (small tolerrance as 0.5 can be correctly encoded)
outMaterialFeatures |= (metallic15 == GBUFFER_LIT_IRIDESCENCE) ? featureFlags & MATERIALFEATUREFLAGS_LIT_IRIDESCENCE : 0;
outMaterialFeatures |= coatMask > 0.0 ? featureFlags & MATERIALFEATUREFLAGS_LIT_CLEAR_COAT : 0;
// Save for material classification
bsdfData.materialFeatures = outMaterialFeatures;
// Start decompressing GBuffer
float3 baseColor = inGBuffer0.rgb;
bsdfData.specularOcclusion = inGBuffer0.a;

bsdfData.normalWS = UnpackNormalOctEncode(float2(inGBuffer1.r, inGBuffer1.g));
// The material features system for material classification must allow compile time optimization (i.e everything should be static)
// Note that as we store materialId for Aniso based on content of RT2 we need to add few extra condition.
// The code is also call from MaterialFeatureFlagsFromGBuffer, so must work fully dynamic if featureFlags is UINT_MAX
int supportsStandard = HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_STANDARD);
int supportsSSS = HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS);
int supportsAniso = HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_ANISO);
int supportClearCoat = HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT);
if (supportsStandard + supportsSSS + supportsAniso + supportClearCoat > 1)
{
// only fetch materialid if it is not statically known from feature flags
bsdfData.materialId = UnpackMaterialId(inGBuffer1.a);
}
else
{
// materialid is statically known. this allows the compiler to eliminate a lot of code.
if (supportsStandard)
bsdfData.materialId = MATERIALID_LIT_STANDARD;
else if (supportsSSS)
bsdfData.materialId = MATERIALID_LIT_SSS;
else if (supportsAniso)
bsdfData.materialId = MATERIALID_LIT_ANISO;
else
bsdfData.materialId = MATERIALID_LIT_CLEAR_COAT;
}
// metallic15 is range [0..12] if mettallic data is needed
float metallic = (metallic15 <= GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND) ? metallic15 * (1.0 / GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND) : 0.0;
bsdfData.diffuseColor = ComputeDiffuseColor(baseColor, metallic);
bsdfData.fresnel0 = enableSpecularColor ? Gamma20ToLinear(inGBuffer2.rgb) : ComputeFresnel0(baseColor, metallic, DEFAULT_SPECULAR_VALUE);
float metallic = 0;
float dielectricF0 = DEFAULT_SPECULAR_VALUE;
bool specularColorMode = false;
// Always assign even if not used, DIFFUSION_PROFILE_NEUTRAL_ID is 0
// Note: we have ZERO_INITIALIZE the struct, so bsdfData.diffusionProfile == DIFFUSION_PROFILE_NEUTRAL_ID, bsdfData.anisotropy == 0.0, bsdfData.SubsurfaceMask == 0.0 etc...
// We avoid divergent evaluation of the GGX, as that nearly doubles the cost.
// If the tile has anisotropy, all the pixels within the tile are evaluated as anisotropic.
if (HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_ANISO))
// Process SSS and Transmission together as they encode almost the same data
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
bsdfData.anisotropy = 0;
bsdfData.tangentWS = GetLocalFrame(bsdfData.normalWS)[0];
// First we must extract the diffusion profile
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
int octTangentSign;
UnpackFloatInt8bit(inGBuffer2.a, 4.0, metallic, octTangentSign);
// Reminder: when using SSS we exchange specular occlusion and subsurfaceMask/profileID
bsdfData.specularOcclusion = inGBuffer2.r;
inGBuffer2.r = (octTangentSign & 1) ? -inGBuffer2.r : inGBuffer2.r;
inGBuffer2.g = (octTangentSign & 2) ? -inGBuffer2.g : inGBuffer2.g;
SSSData sssData;
DecodeFromSSSBuffer(inGBuffer0, positionSS, sssData);
bsdfData.anisotropy = inGBuffer2.b * 2 - 1;
bsdfData.tangentWS = UnpackNormalOctEncode(inGBuffer2.rg);
bsdfData.diffusionProfile = sssData.diffusionProfile;
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING))
{
// Modify fresnel0
FillMaterialSSS(sssData.subsurfaceMask, bsdfData);
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
{
FillMaterialTransmission(inGBuffer2.g, bsdfData);
}
if (HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS))
// Special handling for anisotropy: When anisotropy is present in a tile, the whole tile will use anisotropy to avoid divergent evaluation of GGX that increase the cost
// Note that it mean that when we have the worse case, we always use Anisotropy and shader like deferred.shader are always the worst case (but only used for debugging)
if (HasMaterialFeatureFlag(featureFlags, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
int diffusionProfile = DIFFUSION_NEUTRAL_PROFILE_ID;
uint transmissionMode = TRANSMISSION_MODE_NONE;
float radius = 0;
float thickness = 0;
float anisotropy;
float3 tangentWS;
if (bsdfData.materialId == MATERIALID_LIT_SSS)
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
// Reminder: when using SSS we exchange specular occlusion and subsurfaceMask/profileID
bsdfData.specularOcclusion = inGBuffer2.r;
SSSData sssData;
DecodeFromSSSBuffer(inGBuffer0, positionSS, sssData);
diffusionProfile = sssData.diffusionProfile;
transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * diffusionProfile, 2u);
radius = sssData.subsurfaceMask;
thickness = inGBuffer2.g;
anisotropy = inGBuffer2.b * 2.0 - 1.0;
tangentWS = UnpackNormalOctEncode(inGBuffer2.rg * 2.0 - 1.0);
}
else
{
anisotropy = 0.0;
tangentWS = GetLocalFrame(bsdfData.normalWS)[0];
}
dielectricF0 = _TransmissionTintsAndFresnel0[diffusionProfile].a;
}
FillMaterialAnisotropy(anisotropy, tangentWS, bsdfData);
FillMaterialIdSssData(diffusionProfile, radius, thickness, transmissionMode, bsdfData);
// Force the compiler to use the anisotropy path all the time
bsdfData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY;
float coatMask = 0.0;
if (bsdfData.materialId == MATERIALID_LIT_STANDARD && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_STANDARD))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE))
int materialIdExtent;
UnpackFloatInt8bit(inGBuffer2.a, 2.0, metallic, materialIdExtent);
specularColorMode = (materialIdExtent == GBUFFER_LIT_STANDARD_SPECULAR_COLOR_ID);
}
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
int metallic15;
UnpackFloatInt8bit(inGBuffer2.a, 16.0, coatMask, metallic15);
metallic = metallic15 / 15.0;
FillMaterialIridescence(inGBuffer2.g, bsdfData);
if (specularColorMode)
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
// Note: Specular is not a material id but just a way to parameterize the standard materialid, thus we reset materialId to MATERIALID_LIT_STANDARD
// For material classification it will be consider as Standard as well, thus no need to create special case
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = inGBuffer2.rgb;
}
else
{
bsdfData.diffuseColor = ComputeDiffuseColor(baseColor, metallic);
bsdfData.fresnel0 = ComputeFresnel0(baseColor, metallic, dielectricF0);
// Modify fresnel0 and perceptualRoughness
FillMaterialClearCoatData(coatMask, bsdfData);
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
// fresnel0 must be init before calling FillMaterialIdClearCoatData
FillMaterialIdClearCoatData(coatMask, bsdfData);
}
// Note: the full code below (for both roughness) only execute when we have enableAnisotropy == true, otherwise as we only use roughnessT compiler will optimize out
// Mean that in the worst case we always execute it.
// perceptualRoughness can be modify by FillMaterialIdClearCoatData, so ConvertAnisotropyToClampRoughness must be call after
// perceptualRoughness can be modify by FillMaterialClearCoatData, so ConvertAnisotropyToClampRoughness must be call after
void DecodeFromGBuffer(uint2 positionSS, uint featureFlags, out BSDFData bsdfData, out float3 bakeDiffuseLighting)
{
uint unsused;
DecodeFromGBuffer(positionSS, featureFlags, bsdfData, bakeDiffuseLighting, unsused);
}
// Note that as we store materialId on two buffer (for anisotropy case), the code need to load 2 RGBA8 buffer
// Call the regular function, compiler will optimized out everything not used.
// Note that all material feature flag bellow are in the same GBuffer (inGBuffer2) and thus material classification only sample one Gbuffer
uint materialFeatures;
DecodeFromGBuffer(positionSS, MATERIAL_FEATURE_MASK_FLAGS, bsdfData, unused, materialFeatures);
DecodeFromGBuffer(
positionSS,
UINT_MAX,
bsdfData,
unused
);
return (1 << bsdfData.materialId); // This match all the MATERIALFEATUREFLAGS_LIT_XXX flag
return materialFeatures;
}

float ltcMagnitudeCoatFresnel;
// Refraction
float3 transmissionRefractV; // refracted view vector after exiting the shape
float3 transmissionPositionWS; // start of the refracted ray after exiting the shape
float3 transmissionTransmittance; // transmittance due to absorption
float transmissionSSMipLevel; // mip level of the screen space gaussian pyramid for rough refraction
float3 transparentRefractV; // refracted view vector after exiting the shape
float3 transparentPositionWS; // start of the refracted ray after exiting the shape
float3 transparentTransmittance; // transmittance due to absorption
float transparentSSMipLevel; // mip level of the screen space gaussian pyramid for rough refraction
};
PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfData)

preLightData.clampNdotV = NdotV; // Caution: The handling of edge cases where N is directed away from the screen is handled during Gbuffer/forward pass, so here do nothing
preLightData.iblPerceptualRoughness = bsdfData.perceptualRoughness;
// Clear coat need to modify roughness, V and NdotV for all the other precalculation below
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
preLightData.coatPartLambdaV = GetSmithJointGGXPartLambdaV(NdotV, CLEAR_COAT_ROUGHNESS);
preLightData.coatIblR = reflect(-V, N);

// We avoid divergent evaluation of the GGX, as that nearly doubles the cost.
// If the tile has anisotropy, all the pixels within the tile are evaluated as anisotropic.
if (HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_ANISO))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
{
float TdotV = dot(bsdfData.tangentWS, V);
float BdotV = dot(bsdfData.bitangentWS, V);

// We use a single fetch, and we stretch the normal to use based on various criteria.
// result are far away from the reference but better than nothing
// For positive anisotropy values: tangent = highlight stretch (anisotropy) direction, bitangent = grain (brush) direction.
float3 grainDirWS = (bsdfData.anisotropy >= 0) ? bsdfData.bitangentWS : bsdfData.tangentWS;
float3 grainDirWS = (bsdfData.anisotropy >= 0.0) ? bsdfData.bitangentWS : bsdfData.tangentWS;
// Reduce stretching for (perceptualRoughness < 0.2).
float stretch = abs(bsdfData.anisotropy) * saturate(5 * preLightData.iblPerceptualRoughness);
// NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NdotV) and use 'anisoIblNormalWS'

// to match the reference for rough metals, but further darkens dielectrics.
preLightData.ltcMagnitudeFresnel = bsdfData.fresnel0 * ltcGGXFresnelMagnitudeDiff + (float3)ltcGGXFresnelMagnitude;
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
float2 uv = LTC_LUT_OFFSET + LTC_LUT_SCALE * float2(CLEAR_COAT_PERCEPTUAL_ROUGHNESS, theta * INV_HALF_PI);

preLightData.ltcTransformCoat._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0);
ltcMagnitude = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX, 0).rgb;
ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r; // The difference of magnitudes of GGX and Fresnel
ltcGGXFresnelMagnitude = ltcMagnitude.g;
preLightData.ltcMagnitudeCoatFresnel = (CLEAR_COAT_F0 * ltcGGXFresnelMagnitudeDiff + (float3)ltcGGXFresnelMagnitude) * bsdfData.coatMask;
ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r; // The difference of magnitudes of GGX and Fresnel
ltcGGXFresnelMagnitude = ltcMagnitude.g;
preLightData.ltcMagnitudeCoatFresnel = (CLEAR_COAT_F0 * ltcGGXFresnelMagnitudeDiff + ltcGGXFresnelMagnitude) * bsdfData.coatMask;
preLightData.transmissionRefractV = refraction.rayWS;
preLightData.transmissionPositionWS = refraction.positionWS;
preLightData.transmissionTransmittance = exp(-bsdfData.absorptionCoefficient * refraction.dist);
preLightData.transparentRefractV = refraction.rayWS;
preLightData.transparentPositionWS = refraction.positionWS;
preLightData.transparentTransmittance = exp(-bsdfData.absorptionCoefficient * refraction.dist);
preLightData.transmissionSSMipLevel = sqrt(preLightData.iblPerceptualRoughness) * uint(_GaussianPyramidColorMipSize.z);
preLightData.transparentSSMipLevel = sqrt(preLightData.iblPerceptualRoughness) * uint(_GaussianPyramidColorMipSize.z);
#endif
return preLightData;

// This function require the 3 structure surfaceData, builtinData, bsdfData because it may require both the engine side data, and data that will not be store inside the gbuffer.
float3 GetBakedDiffuseLigthing(SurfaceData surfaceData, BuiltinData builtinData, BSDFData bsdfData, PreLightData preLightData)
{
if (bsdfData.materialId == MATERIALID_LIT_SSS)
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING))
{
bsdfData.diffuseColor = ApplySubsurfaceScatteringTexturingMode(bsdfData.diffuseColor, bsdfData.diffusionProfile);
}

bool HaveSubsurfaceScattering(BSDFData bsdfData)
{
return bsdfData.materialId == MATERIALID_LIT_SSS && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS);
return HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING);
}
//-----------------------------------------------------------------------------

// BSDF share between directional light, punctual light and area light (reference)
//-----------------------------------------------------------------------------
// This function apply BSDF * cos (required to deal with clear coating)
// This function apply BSDF
void BSDF( float3 V, float3 L, float3 positionWS, PreLightData preLightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)

float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
float DV;
// We avoid divergent evaluation of the GGX, as that nearly doubles the cost.
// If the tile has anisotropy, all the pixels within the tile are evaluated as anisotropic.
if (HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_ANISO))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
{
float3 H = (L + V) * invLenLV;
// For anisotropy we must not saturate these values

// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().
diffuseLighting = diffuseTerm;
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
// Apply isotropic GGX for clear coat
// Note: coat F is scalar as it is a dieletric

float DV = DV_SmithJointGGX(NdotH, NdotL, NdotV, bsdfData.coatRoughness, preLightData.coatPartLambdaV);
specularLighting += coatF * DV;
// Note: The modification of the base roughness and fresnel0 by the clear coat is already handled in FillMaterialIdClearCoatData
// Note: The modification of the base roughness and fresnel0 by the clear coat is already handled in FillMaterialClearCoatData
// Scale diffuse for energy conservation (use NdotL as an approximation)
// Very coarse attempt at doing energy conservation for the diffuse layer based on NdotL. No science.
diffuseLighting *= F_Schlick(CLEAR_COAT_F0, NdotL);
}
}

lighting.specular *= intensity * lightData.specularScale;
}
[branch] if (bsdfData.enableTransmission)
[branch] if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
{
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
lighting.diffuse += EvaluateTransmission(bsdfData, NdotL, preLightData.clampNdotV, attenuation * lightData.diffuseScale);

// Simulate a sphere light with this hack
// Note that it is not correct with our pre-computation of PartLambdaV (mean if we disable the optimization we will not have the
// same result) but we don't care as it is a hack anyway
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
bsdfData.coatRoughness = max(bsdfData.coatRoughness, lightData.minRoughness);
}
bsdfData.coatRoughness = max(bsdfData.coatRoughness, lightData.minRoughness);
bsdfData.roughnessT = max(bsdfData.roughnessT, lightData.minRoughness);
bsdfData.roughnessB = max(bsdfData.roughnessB, lightData.minRoughness);

lighting.specular *= intensity * lightData.specularScale;
}
[branch] if (bsdfData.enableTransmission)
[branch] if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
{
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
lighting.diffuse += EvaluateTransmission(bsdfData, NdotL, preLightData.clampNdotV, attenuation * lightData.diffuseScale);

// Evaluate the diffuse part
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformDiffuse);
ltcValue *= lightData.diffuseScale;
[branch] if (bsdfData.enableTransmission)
[branch] if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
{
// Flip the view vector and the normal. The bitangent stays the same.
float3x3 flipMatrix = float3x3(-1, 0, 0,

// The matrix multiplication should not generate any extra ALU on GCN.
// TODO: double evaluation is very inefficient! This is a temporary solution.
ltcValue = LTCEvaluate(P1, P2, B, mul(flipMatrix, k_identity3x3));
ltcValue *= lightData.diffuseScale;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().
lighting.diffuse += bsdfData.transmittance * ltcValue;

ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformSpecular);
ltcValue *= lightData.specularScale;
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
ltcValue *= lightData.specularScale;
lighting.diffuse *= lightData.color * lightData.diffuseScale;
lighting.specular *= lightData.color * lightData.specularScale;;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
#endif // LIT_DISPLAY_REFERENCE_AREA
return lighting;

// Evaluate the diffuse part
// Polygon irradiance in the transformed configuration.
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformDiffuse));
ltcValue *= lightData.diffuseScale;
[branch] if (bsdfData.enableTransmission)
[branch] if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
{
// Flip the view vector and the normal. The bitangent stays the same.
float3x3 flipMatrix = float3x3(-1, 0, 0,

// Polygon irradiance in the transformed configuration.
// TODO: double evaluation is very inefficient! This is a temporary solution.
ltcValue = PolygonIrradiance(mul(lightVerts, ltcTransform));
ltcValue *= lightData.diffuseScale;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().
lighting.diffuse += bsdfData.transmittance * ltcValue;

// Polygon irradiance in the transformed configuration.
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformSpecular));
ltcValue *= lightData.specularScale;
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
ltcValue *= lightData.specularScale;
lighting.diffuse *= lightData.color * lightData.diffuseScale;
lighting.specular *= lightData.color * lightData.specularScale;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
#endif // LIT_DISPLAY_REFERENCE_AREA
return lighting;

// a. Get the corresponding color depending on the roughness from the gaussian pyramid of the color buffer
// b. Multiply by the transmittance for absorption (depends on the optical depth)
float3 refractedBackPointWS = EstimateRaycast(V, posInput, preLightData.transmissionPositionWS, preLightData.transmissionRefractV);
float3 refractedBackPointWS = EstimateRaycast(V, posInput, preLightData.transparentPositionWS, preLightData.transparentRefractV);
// Calculate screen space coordinates of refracted point in back plane
float2 refractedBackPointNDC = ComputeNormalizedDeviceCoordinates(refractedBackPointWS, UNITY_MATRIX_VP);

}
// Map the roughness to the correct mip map level of the color pyramid
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointNDC, preLightData.transmissionSSMipLevel).rgb;
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointNDC, preLightData.transparentSSMipLevel).rgb;
lighting.specularTransmitted *= preLightData.transmissionTransmittance;
lighting.specularTransmitted *= preLightData.transparentTransmittance;
float weight = 1.0;
UpdateLightingHierarchyWeights(hierarchyWeight, weight); // Shouldn't be needed, but safer in case we decide to change hierarchy priority

if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION)
{
positionWS = preLightData.transmissionPositionWS;
R = preLightData.transmissionRefractV;
positionWS = preLightData.transparentPositionWS;
R = preLightData.transparentRefractV;
}
// In Unity the cubemaps are capture with the localToWorld transform of the component.

// We can reuse dist calculate in LS directly in WS as there is no scaling. Also the offset is already include in lightData.positionWS
R = (positionWS + projectionDistance * R) - lightData.positionWS;
// Test again for clear code
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
// Test again for clear coat
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION && HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
dirLS = mul(coatR, worldToLocal);
projectionDistance = IntersectRaySphereSimple(positionLS, dirLS, sphereOuterDistance);

// TODO: add distance based roughness
// Test again for clear code
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
// Test again for clear coat
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION && HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
dirLS = mul(coatR, worldToLocal);
projectionDistance = IntersectRayAABBSimple(positionLS, dirLS, -boxOuterDistance, boxOuterDistance);

envLighting = F * preLD.rgb;
// Evaluate the Clear Coat component if needed
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
// No correction needed for coatR as it is smooth
// Note: coat F is scalar as it is a dieletric

}
else
{
// No clear coat support with refraction
envLighting = (1.0 - F) * preLD.rgb * preLightData.transmissionTransmittance;
// Don't account for clear coat to save ALU
envLighting = (1.0 - F) * preLD.rgb * preLightData.transparentTransmittance;
}
#endif // LIT_DISPLAY_REFERENCE_IBL

if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION)
lighting.specularReflected = envLighting;
else
lighting.specularTransmitted = envLighting * preLightData.transmissionTransmittance;
lighting.specularTransmitted = envLighting * preLightData.transparentTransmittance;
return lighting;
}

#endif
float3 modifiedDiffuseColor;
if (bsdfData.materialId == MATERIALID_LIT_SSS)
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING))
modifiedDiffuseColor = ApplySubsurfaceScatteringTexturingMode(bsdfData.diffuseColor, bsdfData.diffusionProfile);
else
modifiedDiffuseColor = bsdfData.diffuseColor;

12
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.shader


#pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
#pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT
// MaterialId are used as shader feature to allow compiler to optimize properly
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
#pragma shader_feature _ _MATID_SSS _MATID_ANISO _MATID_SPECULAR _MATID_CLEARCOAT
// MaterialFeature are used as shader feature to allow compiler to optimize properly
#pragma shader_feature _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
#pragma shader_feature _MATERIAL_FEATURE_TRANSMISSION
#pragma shader_feature _MATERIAL_FEATURE_ANISOTROPY
#pragma shader_feature _MATERIAL_FEATURE_CLEAR_COAT
#pragma shader_feature _MATERIAL_FEATURE_IRIDESCENCE
#pragma shader_feature _MATERIAL_FEATURE_SPECULAR_COLOR
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE

#define HAVE_VERTEX_MODIFICATION
// If we use subsurface scattering, enable output split lighting (for forward pass)
#if defined(_MATID_SSS) && !defined(_SURFACE_TYPE_TRANSPARENT)
#if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT)
#define OUTPUT_SPLIT_LIGHTING
#endif

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl


// It is safe to call this function here as surfaceData have been filled
// We want to know if we must enable transmission on GI for SSS material, if the material have no SSS, this code will be remove by the compiler.
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
if (bsdfData.enableTransmission)
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
{
// For now simply recall the function with inverted normal, the compiler should be able to optimize the lightmap case to not resample the directional lightmap
// however it will not optimize the lightprobe case due to the proxy volume relying on dynamic if (we rely must get right of this dynamic if), not a problem for SH9, but a problem for proxy volume.

40
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitDataIndividualLayer.hlsl


// This part of the code is not used in case of layered shader but we keep the same macro system for simplicity
#if !defined(LAYERED_LIT_SHADER)
// Having individual shader features for each materialID like this allow the compiler to optimize
#ifdef _MATID_SSS
surfaceData.materialId = MATERIALID_LIT_SSS;
#elif defined(_MATID_ANISO)
surfaceData.materialId = MATERIALID_LIT_ANISO;
#elif defined(_MATID_SPECULAR)
surfaceData.materialId = MATERIALID_LIT_SPECULAR;
#elif defined(_MATID_CLEARCOAT)
surfaceData.materialId = MATERIALID_LIT_CLEAR_COAT;
#else // Default
surfaceData.materialId = MATERIALID_LIT_STANDARD;
// These static material feature allow compile time optimization
surfaceData.materialFeatures = 0;
#ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING;
#endif
#ifdef _MATERIAL_FEATURE_TRANSMISSION
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION;
#endif
#ifdef _MATERIAL_FEATURE_ANISOTROPY
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY;
#endif
#ifdef _MATERIAL_FEATURE_CLEAR_COAT
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT;
#endif
#ifdef _MATERIAL_FEATURE_IRIDESCENCE
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE;
#endif
#ifdef _MATERIAL_FEATURE_SPECULAR_COLOR
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR;
#endif
#ifdef _TANGENTMAP

surfaceData.coatMask = _CoatMask;
surfaceData.thicknessIrid = 0.0;
// Layered shader only supports the standard material
surfaceData.materialId = MATERIALID_LIT_STANDARD;
// Layered shader material feature are define outside of this call
surfaceData.materialFeatures = 0;
// All these parameters are ignore as they are re-setup outside of the layers function
// Note: any parameters set here must also be set in GetSurfaceAndBuiltinData() layer version

surfaceData.coatMask = 0.0f;
surfaceData.thicknessIrid = 0.0;
surfaceData.coatMask = 0.0;
// Transparency
surfaceData.ior = 1.0;

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitReference.hlsl


{
float3x3 localToWorld;
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
{
localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
}

float weightOverPdf;
// GGX BRDF
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
if (HasMaterialFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
{
ImportanceSampleAnisoGGX(u, V, localToWorld, bsdfData.roughnessT, bsdfData.roughnessB, NdotV, L, VdotH, NdotL, weightOverPdf);
}

12
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitTessellation.shader


#pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
#pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT
// MaterialId are used as shader feature to allow compiler to optimize properly
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
#pragma shader_feature _ _MATID_SSS _MATID_ANISO _MATID_SPECULAR _MATID_CLEARCOAT
// MaterialFeature are used as shader feature to allow compiler to optimize properly
#pragma shader_feature _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
#pragma shader_feature _MATERIAL_FEATURE_TRANSMISSION
#pragma shader_feature _MATERIAL_FEATURE_ANISOTROPY
#pragma shader_feature _MATERIAL_FEATURE_CLEAR_COAT
#pragma shader_feature _MATERIAL_FEATURE_IRIDESCENCE
#pragma shader_feature _MATERIAL_FEATURE_SPECULAR_COLOR
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE

#define HAVE_TESSELLATION_MODIFICATION
// If we use subsurface scattering, enable output split lighting (for forward pass)
#if defined(_MATID_SSS) && !defined(_SURFACE_TYPE_TRANSPARENT)
#if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT)
#define OUTPUT_SPLIT_LIGHTING
#endif

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.compute


// Inputs & outputs
//--------------------------------------------------------------------------------------------------
float4 _FilterKernels[DIFFUSION_N_PROFILES][SSS_N_SAMPLES_NEAR_FIELD]; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
float4 _FilterKernels[DIFFUSION_PROFILE_COUNT][SSS_N_SAMPLES_NEAR_FIELD]; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
TEXTURE2D(_DepthTexture); // Z-buffer
TEXTURE2D(_SSSHTile); // DXGI_FORMAT_R8_UINT is not supported by Unity

11
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.hlsl


// Warning: Unity is not able to losslessly transfer integers larger than 2^24 to the shader system.
// Therefore, we bitcast uint to float in C#, and bitcast back to uint in the shader.
uint _EnableSubsurfaceScattering; // Globally toggles subsurface and transmission scattering on/off
float _TransmittanceMultiplier; // Allow to switch on/off the transmittance but doesn't save the cost
float4 _HalfRcpVariancesAndWeights[DIFFUSION_N_PROFILES][2]; // 2x Gaussians in RGB, A is interpolation weights
float4 _HalfRcpVariancesAndWeights[DIFFUSION_PROFILE_COUNT][2]; // 2x Gaussians in RGB, A is interpolation weights
float4 _ThicknessRemaps[DIFFUSION_N_PROFILES]; // R: start, G = end - start, BA unused
float4 _ShapeParams[DIFFUSION_N_PROFILES]; // RGB = S = 1 / D, A = filter radius
float4 _TransmissionTintsAndFresnel0[DIFFUSION_N_PROFILES]; // RGB = 1/4 * color, A = fresnel0
float4 _WorldScales[DIFFUSION_N_PROFILES]; // X = meters per world unit; Y = world units per meter
float4 _ThicknessRemaps[DIFFUSION_PROFILE_COUNT]; // R: start, G = end - start, BA unused
float4 _ShapeParams[DIFFUSION_PROFILE_COUNT]; // RGB = S = 1 / D, A = filter radius
float4 _TransmissionTintsAndFresnel0[DIFFUSION_PROFILE_COUNT]; // RGB = 1/4 * color, A = fresnel0
float4 _WorldScales[DIFFUSION_PROFILE_COUNT]; // X = meters per world unit; Y = world units per meter
CBUFFER_END
// ----------------------------------------------------------------------------

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.shader


// Inputs & outputs
//-------------------------------------------------------------------------------------
float4 _FilterKernelsBasic[DIFFUSION_N_PROFILES][SSS_BASIC_N_SAMPLES]; // RGB = weights, A = radial distance
float4 _FilterKernelsBasic[DIFFUSION_PROFILE_COUNT][SSS_BASIC_N_SAMPLES]; // RGB = weights, A = radial distance
float4 _HalfRcpWeightedVariances[SSS_BASIC_N_SAMPLES]; // RGB for chromatic, A for achromatic
TEXTURE2D(_IrradianceSource); // Includes transmitted light

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs


{
// Broadcast SSS parameters to all shaders.
cmd.SetGlobalInt(HDShaderIDs._EnableSubsurfaceScattering, frameSettings.enableSubsurfaceScattering ? 1 : 0);
cmd.SetGlobalFloat(HDShaderIDs._TransmittanceMultiplier, frameSettings.enableTransmission ? 1.0f : 0.0f);
unsafe
{
// Warning: Unity is not able to losslessly transfer integers larger than 2^24 to the shader system.

cmd.SetGlobalVectorArray(HDShaderIDs._ThicknessRemaps, sssParameters.thicknessRemaps);
cmd.SetGlobalVectorArray(HDShaderIDs._ShapeParams, sssParameters.shapeParams);
cmd.SetGlobalVectorArray(HDShaderIDs._HalfRcpVariancesAndWeights, sssParameters.halfRcpVariancesAndWeights);
cmd.SetGlobalVectorArray(HDShaderIDs._TransmissionTintsAndFresnel0, sssParameters.transmissionTintsAndFresnel0);
// To disable transmission, we simply nullify the transmissionTint
cmd.SetGlobalVectorArray(HDShaderIDs._TransmissionTintsAndFresnel0, frameSettings.enableTransmission ? sssParameters.transmissionTintsAndFresnel0 : sssParameters.disabledTransmissionTintsAndFresnel0);
cmd.SetGlobalVectorArray(HDShaderIDs._WorldScales, sssParameters.worldScales);
}

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipeline/FrameSettings.cs


DebugMenuManager.instance.AddDebugItem<bool>(menuName, kEnableSubsurfaceScattering, () => frameSettings.enableSubsurfaceScattering, (value) => frameSettings.enableSubsurfaceScattering = (bool)value);
DebugMenuManager.instance.AddDebugItem<bool>(menuName, kEnableTransmission, () => frameSettings.enableTransmission, (value) => frameSettings.enableTransmission = (bool)value);
DebugMenuManager.instance.AddDebugItem<bool>(menuName, kForwardOnly, () => frameSettings.enableForwardRenderingOnly, (value) => frameSettings.enableForwardRenderingOnly = (bool)value);
DebugMenuManager.instance.AddDebugItem<bool>(menuName, kDeferredDepthPrepass, () => frameSettings.enableDepthPrepassWithDeferredRendering, (value) => frameSettings.enableDepthPrepassWithDeferredRendering = (bool)value);
DebugMenuManager.instance.AddDebugItem<bool>(menuName, kDeferredDepthPrepassATestOnly, () => frameSettings.enableAlphaTestOnlyInDeferredPrepass, (value) => frameSettings.enableAlphaTestOnlyInDeferredPrepass = (bool)value);

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassForward.hlsl


LightLoop(V, posInput, preLightData, bsdfData, bakeLightingData, featureFlags, diffuseLighting, specularLighting);
#ifdef OUTPUT_SPLIT_LIGHTING
if (_EnableSubsurfaceScattering != 0 && HaveSubsurfaceScattering(bsdfData))
if ((_EnableSubsurfaceScattering != 0) && HaveSubsurfaceScattering(bsdfData))
{
outColor = float4(specularLighting, 1.0);
outDiffuseLighting = float4(TagLightingForSSS(diffuseLighting), 1.0);

正在加载...
取消
保存