浏览代码

Merge pull request #758 from Unity-Technologies/Rename-Subsurface-Profile-=---Diffusion--profile

Update Subsurface profile
/main
GitHub 7 年前
当前提交
76304378
共有 65 个文件被更改,包括 921 次插入873 次删除
  1. 10
      SampleScenes/HDTest/GraphicTest/SSS/Materials/SSSHead.mat
  2. 10
      SampleScenes/HDTest/GraphicTest/Two Sided/Material/GroundLeaf_DoubleSidedFlipSSS.mat
  3. 1
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonMaterial.hlsl
  4. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDAssetFactory.cs
  5. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDRenderPipelineInspector.Styles.cs
  6. 10
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDRenderPipelineInspector.cs
  7. 54
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDRenderPipelineMenuItems.cs
  8. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/LayeredLit/LayeredLitUI.cs
  9. 48
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Lit/LitUI.cs
  10. 19
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
  11. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipelineAsset.asset
  12. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipelineAsset.cs
  13. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  14. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Deferred.shader
  15. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Deferred.compute
  16. 32
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLit.shader
  17. 44
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl
  18. 32
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitTessellation.shader
  19. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs
  20. 32
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs.hlsl
  21. 73
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl
  22. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.shader
  23. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl
  24. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitDataIndividualLayer.hlsl
  25. 14
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitProperties.hlsl
  26. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitTessellation.shader
  27. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.compute
  28. 46
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.hlsl
  29. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.shader
  30. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringManager.cs
  31. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/RenderPipelineResources.cs
  32. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassForward.hlsl
  33. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.Styles.cs
  34. 36
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs
  35. 18
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Default Diffusion Profile Settings.asset
  36. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawDiffusionProfile.shader
  37. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawTransmittanceGraph.shader
  38. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile.meta
  39. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Default Diffusion Profile Settings.asset.meta
  40. 44
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfile.hlsl
  41. 516
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs
  42. 21
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.hlsl
  43. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/SubsurfaceScattering.meta
  44. 61
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/CommonSubsurfaceScattering.hlsl
  45. 21
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringSettings.cs.hlsl
  46. 513
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringSettings.cs
  47. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/SceneSettings.meta
  48. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfile.hlsl.meta
  49. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.hlsl.meta
  50. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.meta
  51. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile.meta
  52. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.Styles.cs.meta
  53. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs.meta
  54. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.Styles.cs
  55. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs
  56. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Default Diffusion Profile Settings.asset
  57. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawDiffusionProfile.shader.meta
  58. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawTransmittanceGraph.shader.meta
  59. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawDiffusionProfile.shader
  60. 0
      /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawTransmittanceGraph.shader

10
SampleScenes/HDTest/GraphicTest/SSS/Materials/SSSHead.mat


m_PrefabInternal: {fileID: 0}
m_Name: SSSHead
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _BLENDMODE_PRESERVE_SPECULAR_LIGHTING _MATID_SSS _NORMALMAP _NORMALMAP_TANGENT_SPACE
_THICKNESSMAP
m_ShaderKeywords: _MATID_SSS _NORMALMAP _NORMALMAP_TANGENT_SPACE _THICKNESSMAP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SubsurfaceMaskMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SubsurfaceRadiusMap:
m_Texture: {fileID: 2800000, guid: f40319fb453e7e04dbe1e64f7b81efd9, type: 3}
m_Scale: {x: 1, y: 1}

- _BumpScale: 1
- _CoatCoverage: 1
- _CoatIOR: 0.5
- _CoatMask: 1
- _CullMode: 2
- _CullModeForward: 2
- _Cutoff: 0.5

- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DiffusionProfile: 1
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 0

- _StencilWriteMask: 7
- _StencilWriteMaskMV: 128
- _Stiffness: 1
- _SubsurfaceMask: 1
- _SubsurfaceProfile: 1
- _SubsurfaceRadius: 1
- _SurfaceType: 0

10
SampleScenes/HDTest/GraphicTest/Two Sided/Material/GroundLeaf_DoubleSidedFlipSSS.mat


m_PrefabInternal: {fileID: 0}
m_Name: GroundLeaf_DoubleSidedFlipSSS
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _ALPHATEST_ON _BLENDMODE_PRESERVE_SPECULAR_LIGHTING _DOUBLESIDED_ON
_MASKMAP _MATID_SSS _NORMALMAP _NORMALMAP_TANGENT_SPACE
m_ShaderKeywords: _ALPHATEST_ON _DOUBLESIDED_ON _MASKMAP _MATID_SSS _NORMALMAP _NORMALMAP_TANGENT_SPACE
m_LightmapFlags: 1
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 1

m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SubsurfaceMaskMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SubsurfaceRadiusMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}

- _BumpScale: 1
- _CoatCoverage: 1
- _CoatIOR: 0.5
- _CoatMask: 1
- _CullMode: 0
- _CullModeForward: 0
- _Cutoff: 0.5

- _DetailNormalMapScale: 1
- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DiffusionProfile: 2
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 0

- _StencilWriteMask: 7
- _StencilWriteMaskMV: 128
- _Stiffness: 1
- _SubsurfaceMask: 1
- _SubsurfaceProfile: 2
- _SubsurfaceRadius: 1
- _SurfaceType: 0

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


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

5
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDAssetFactory.cs


newAsset.deferredDirectionalShadowComputeShader = Load<ComputeShader>(HDRenderPipelinePath + "Lighting/DeferredDirectionalShadow.compute");
// SubsurfaceScattering
// These shaders don't need to be reference by RenderPipelineResource as they are not use at runtime (only to draw in editor)
// instance.drawSssProfile = UnityEditor.AssetDatabase.LoadAssetAtPath<Shader>(HDRenderPipelinePath + "SceneSettings/DrawSssProfile.shader");
// instance.drawTransmittanceGraphShader = UnityEditor.AssetDatabase.LoadAssetAtPath<Shader>(HDRenderPipelinePath + "SceneSettings/DrawTransmittanceGraph.shader");
newAsset.subsurfaceScatteringCS = Load<ComputeShader>(HDRenderPipelinePath + "Material/SubsurfaceScattering/SubsurfaceScattering.compute");
newAsset.subsurfaceScattering = Load<Shader>(HDRenderPipelinePath + "Material/SubsurfaceScattering/SubsurfaceScattering.shader");
newAsset.combineLighting = Load<Shader>(HDRenderPipelinePath + "Material/SubsurfaceScattering/CombineLighting.shader");

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDRenderPipelineInspector.Styles.cs


// Rendering Settings
public readonly GUIContent renderingSettingsLabel = new GUIContent("Rendering Settings");
public readonly GUIContent sssSettings = new GUIContent("Subsurface Scattering Settings");
public readonly GUIContent diffusionProfileSettings = new GUIContent("Diffusion Profile Settings");
}
static Styles s_Styles;

10
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDRenderPipelineInspector.cs


SerializedProperty m_SkyReflectionSize;
SerializedProperty m_SkyLightingOverrideLayerMask;
// Subsurface Scattering Settings
SerializedProperty m_SubsurfaceScatteringSettings;
// Diffusion profile Settings
SerializedProperty m_DiffusionProfileSettings;
SerializedFrameSettings serializedFrameSettings = null;
FrameSettingsUI m_FrameSettingsUI = new FrameSettingsUI();

m_SkyReflectionSize = properties.Find(x => x.renderPipelineSettings.lightLoopSettings.skyReflectionSize);
m_SkyLightingOverrideLayerMask = properties.Find(x => x.renderPipelineSettings.lightLoopSettings.skyLightingOverrideLayerMask);
// Subsurface Scattering Settings
m_SubsurfaceScatteringSettings = properties.Find(x => x.sssSettings);
// Diffusion profile Settings
m_DiffusionProfileSettings = properties.Find(x => x.diffusionProfileSettings);
serializedFrameSettings = new SerializedFrameSettings(properties.Find(x => x.serializedFrameSettings));

EditorGUILayout.PropertyField(m_RenderPipelineResources, s_Styles.renderPipelineResources);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(m_SubsurfaceScatteringSettings, s_Styles.sssSettings);
EditorGUILayout.PropertyField(m_DiffusionProfileSettings, s_Styles.diffusionProfileSettings);
EditorGUILayout.Space();
SettingsUI(m_Target);

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


var sceneName = Path.GetFileNameWithoutExtension(scenePath);
var description = string.Format("{0} {1}/{2} - ", sceneName, i + 1, scenes.Length);
ResetAllLoadedMaterialKeywords(description, scale, scale * i);
}

if (mat.shader.name == "HDRenderPipeline/LitTessellation" ||
mat.shader.name == "HDRenderPipeline/Lit")
{
float fvalue = mat.GetFloat("_MaterialID");
if (fvalue == 0.0) // SSS
if (mat.HasProperty("_SubsurfaceProfile"))
int ivalue = mat.GetInt("_SubsurfaceProfile");
if (ivalue == 15)
{
mat.SetInt("_SubsurfaceProfile", 0);
}
else
{
mat.SetInt("_SubsurfaceProfile", ivalue + 1);
}
float value = mat.GetInt("_DiffusionProfile");
mat.SetInt("_DiffusionProfile", 0);
EditorUtility.SetDirty(mat);
}

{
float fvalue = mat.GetFloat("_MaterialID");
if (fvalue == 0.0) // SSS
bool hasSubsurfaceProfile = false;
int numLayer = (int)mat.GetFloat("_LayerCount");
for (int x = 0; x < numLayer; ++x)
{
if (mat.HasProperty("_SubsurfaceProfile" + x))
{
hasSubsurfaceProfile = true;
}
}
if (hasSubsurfaceProfile)
int numLayer = (int)mat.GetFloat("_LayerCount");
int ivalue = mat.GetInt("_SubsurfaceProfile" + x);
if (ivalue == 15)
if (mat.HasProperty("_SubsurfaceProfile" + x))
mat.SetInt("_SubsurfaceProfile" + x, 0);
}
else
{
mat.SetInt("_SubsurfaceProfile" + x, ivalue + 1);
CheckOutFile(VSCEnabled, mat);
float value = mat.GetInt("_DiffusionProfile" + x);
mat.SetInt("_DiffusionProfile" + x, 0);
EditorUtility.SetDirty(mat);
EditorUtility.SetDirty(mat);
}
}

}
}
class DoCreateNewAssetSubsurfaceScatteringSettings : DoCreateNewAsset<SubsurfaceScatteringSettings> {}
class DoCreateNewAssetDiffusionProfileSettings : DoCreateNewAsset<DiffusionProfileSettings> {}
[MenuItem("Assets/Create/Render Pipeline/High Definition/Subsurface Scattering Settings", priority = CoreUtils.assetCreateMenuPriority2)]
static void MenuCreateSubsurfaceScatteringProfile()
[MenuItem("Assets/Create/Render Pipeline/High Definition/Diffusion profile Settings", priority = CoreUtils.assetCreateMenuPriority2)]
static void MenuCreateDiffusionProfile()
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAssetSubsurfaceScatteringSettings>(), "New SSS Settings.asset", icon, null);
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAssetDiffusionProfileSettings>(), "New Diffusion Profile Settings.asset", icon, null);
}
static void ResetAllMaterialAssetsKeywords(float progressScale, float progressOffset)

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


CoreUtils.SetKeyword(material, "_HEIGHTMAP" + i, material.GetTexture(kHeightMap + i));
CoreUtils.SetKeyword(material, "_SUBSURFACE_RADIUS_MAP" + i, material.GetTexture(kSubsurfaceRadiusMap + i));
CoreUtils.SetKeyword(material, "_SUBSURFACE_MASK_MAP" + i, material.GetTexture(kSubsurfaceMaskMap + i));
CoreUtils.SetKeyword(material, "_THICKNESSMAP" + i, material.GetTexture(kThicknessMap + i));
}

48
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 subsurfaceProfileText = new GUIContent("Subsurface profile", "A profile determines the shape of the blur filter.");
public static GUIContent subsurfaceRadiusText = new GUIContent("Subsurface radius", "Determines the range of the blur.");
public static GUIContent subsurfaceRadiusMapText = 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 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 thicknessText = new GUIContent("Thickness", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
public static GUIContent thicknessMapText = new GUIContent("Thickness map (R)", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
public static GUIContent thicknessRemapText = new GUIContent("Thickness Remap", "Remaps values of the thickness map from [0, 1] to the specified range.");

protected MaterialProperty[] heightMax = new MaterialProperty[kMaxLayerCount];
protected const string kHeightMax = "_HeightMax";
protected MaterialProperty[] subsurfaceProfileID = new MaterialProperty[kMaxLayerCount];
protected const string kSubsurfaceProfileID = "_SubsurfaceProfile";
protected MaterialProperty[] subsurfaceRadius = new MaterialProperty[kMaxLayerCount];
protected const string kSubsurfaceRadius = "_SubsurfaceRadius";
protected MaterialProperty[] subsurfaceRadiusMap = new MaterialProperty[kMaxLayerCount];
protected const string kSubsurfaceRadiusMap = "_SubsurfaceRadiusMap";
protected MaterialProperty[] diffusionProfileID = new MaterialProperty[kMaxLayerCount];
protected const string kDiffusionProfileID = "_DiffusionProfile";
protected MaterialProperty[] subsurfaceMask = new MaterialProperty[kMaxLayerCount];
protected const string kSubsurfaceMask = "_SubsurfaceMask";
protected MaterialProperty[] subsurfaceMaskMap = new MaterialProperty[kMaxLayerCount];
protected const string kSubsurfaceMaskMap = "_SubsurfaceMaskMap";
protected MaterialProperty[] thickness = new MaterialProperty[kMaxLayerCount];
protected const string kThickness = "_Thickness";
protected MaterialProperty[] thicknessMap = new MaterialProperty[kMaxLayerCount];

heightCenter[i] = FindProperty(string.Format("{0}{1}", kHeightCenter, m_PropertySuffixes[i]), props);
// Sub surface
subsurfaceProfileID[i] = FindProperty(string.Format("{0}{1}", kSubsurfaceProfileID, m_PropertySuffixes[i]), props);
subsurfaceRadius[i] = FindProperty(string.Format("{0}{1}", kSubsurfaceRadius, m_PropertySuffixes[i]), props);
subsurfaceRadiusMap[i] = FindProperty(string.Format("{0}{1}", kSubsurfaceRadiusMap, m_PropertySuffixes[i]), props);
diffusionProfileID[i] = FindProperty(string.Format("{0}{1}", kDiffusionProfileID, m_PropertySuffixes[i]), props);
subsurfaceMask[i] = FindProperty(string.Format("{0}{1}", kSubsurfaceMask, m_PropertySuffixes[i]), props);
subsurfaceMaskMap[i] = FindProperty(string.Format("{0}{1}", kSubsurfaceMaskMap, m_PropertySuffixes[i]), props);
thickness[i] = FindProperty(string.Format("{0}{1}", kThickness, m_PropertySuffixes[i]), props);
thicknessMap[i] = FindProperty(string.Format("{0}{1}", kThicknessMap, m_PropertySuffixes[i]), props);
thicknessRemap[i] = FindProperty(string.Format("{0}{1}", kThicknessRemap, m_PropertySuffixes[i]), props);

protected void ShaderSSSInputGUI(Material material, int layerIndex)
{
var hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
var sssSettings = hdPipeline.sssSettings;
var diffusionProfileSettings = hdPipeline.diffusionProfileSettings;
if (sssSettings == null)
if (hdPipeline.IsInternalDiffusionProfile(diffusionProfileSettings))
EditorGUILayout.HelpBox("No Subsurface Scattering Settings have been assigned to the render pipeline asset.", MessageType.Warning);
EditorGUILayout.HelpBox("No diffusion profile Settings have been assigned to the render pipeline asset.", MessageType.Warning);
var profiles = sssSettings.profiles;
var profiles = diffusionProfileSettings.profiles;
values[0] = SssConstants.SSS_NEUTRAL_PROFILE_ID;
values[0] = DiffusionProfileConstants.DIFFUSION_NEUTRAL_PROFILE_ID;
for (int i = 0; i < profiles.Length; i++)
{

using (var scope = new EditorGUI.ChangeCheckScope())
{
int profileID = (int)subsurfaceProfileID[layerIndex].floatValue;
int profileID = (int)diffusionProfileID[layerIndex].floatValue;
EditorGUILayout.PrefixLabel(Styles.subsurfaceProfileText);
EditorGUILayout.PrefixLabel(Styles.diffusionProfileText);
using (new EditorGUILayout.HorizontalScope())
{

Selection.activeObject = sssSettings;
Selection.activeObject = diffusionProfileSettings;
subsurfaceProfileID[layerIndex].floatValue = profileID;
diffusionProfileID[layerIndex].floatValue = profileID;
m_MaterialEditor.ShaderProperty(subsurfaceRadius[layerIndex], Styles.subsurfaceRadiusText);
m_MaterialEditor.TexturePropertySingleLine(Styles.subsurfaceRadiusMapText, subsurfaceRadiusMap[layerIndex]);
m_MaterialEditor.ShaderProperty(subsurfaceMask[layerIndex], Styles.subsurfaceMaskText);
m_MaterialEditor.TexturePropertySingleLine(Styles.subsurfaceMaskMapText, subsurfaceMaskMap[layerIndex]);
m_MaterialEditor.TexturePropertySingleLine(Styles.thicknessMapText, thicknessMap[layerIndex]);
if (thicknessMap[layerIndex].textureValue != null)
{

CoreUtils.SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap));
CoreUtils.SetKeyword(material, "_ANISOTROPYMAP", material.GetTexture(kAnisotropyMap));
CoreUtils.SetKeyword(material, "_DETAIL_MAP", material.GetTexture(kDetailMap));
CoreUtils.SetKeyword(material, "_SUBSURFACE_RADIUS_MAP", material.GetTexture(kSubsurfaceRadiusMap));
CoreUtils.SetKeyword(material, "_SUBSURFACE_MASK_MAP", material.GetTexture(kSubsurfaceMaskMap));
CoreUtils.SetKeyword(material, "_THICKNESSMAP", material.GetTexture(kThicknessMap));
CoreUtils.SetKeyword(material, "_SPECULARCOLORMAP", material.GetTexture(kSpecularColorMap));

19
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs


readonly HDRenderPipelineAsset m_Asset;
SubsurfaceScatteringSettings m_InternalSSSAsset;
public SubsurfaceScatteringSettings sssSettings
DiffusionProfileSettings m_InternalSSSAsset;
public DiffusionProfileSettings diffusionProfileSettings
var asset = m_Asset.sssSettings;
var asset = m_Asset.diffusionProfileSettings;
m_InternalSSSAsset = ScriptableObject.CreateInstance<SubsurfaceScatteringSettings>();
m_InternalSSSAsset = ScriptableObject.CreateInstance<DiffusionProfileSettings>();
asset = m_InternalSSSAsset;
}

}
public bool IsInternalDiffusionProfile(DiffusionProfileSettings profile)
{
return m_InternalSSSAsset == profile;
}
readonly RenderPipelineMaterial m_DeferredMaterial;

m_CurrentHeight = texHeight;
}
public void PushGlobalParams(HDCamera hdCamera, CommandBuffer cmd, SubsurfaceScatteringSettings sssParameters)
public void PushGlobalParams(HDCamera hdCamera, CommandBuffer cmd, DiffusionProfileSettings sssParameters)
{
using (new ProfilingSample(cmd, "Push Global Parameters", GetSampler(CustomSamplerId.PushGlobalParameters)))
{

renderContext.SetupCameraProperties(camera);
PushGlobalParams(hdCamera, cmd, sssSettings);
PushGlobalParams(hdCamera, cmd, diffusionProfileSettings);
// TODO: Find a correct place to bind these material textures
// We have to bind the material specific global parameters in this mode

RenderForwardError(m_CullResults, camera, renderContext, cmd, ForwardPass.Opaque);
// SSS pass here handle both SSS material from deferred and forward
m_SSSBufferManager.SubsurfaceScatteringPass(hdCamera, cmd, sssSettings, m_FrameSettings,
m_SSSBufferManager.SubsurfaceScatteringPass(hdCamera, cmd, diffusionProfileSettings, m_FrameSettings,
m_CameraColorBufferRT, m_CameraSssDiffuseLightingBufferRT, m_CameraDepthStencilBufferRT, GetDepthTexture());
RenderSky(hdCamera, cmd);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipelineAsset.asset


shadowInitParams:
shadowAtlasWidth: 4096
shadowAtlasHeight: 4096
sssSettings: {fileID: 11400000, guid: c4d57f106d34d0046a33b3e66da29a72, type: 2}
diffusionProfileSettings: {fileID: 11400000, guid: 404820c4cf36ad944862fa59c56064f0,
type: 2}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipelineAsset.cs


}
[SerializeField]
public SubsurfaceScatteringSettings sssSettings;
public DiffusionProfileSettings diffusionProfileSettings;
public override Shader GetDefaultShader()
{

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _InputCubemap = Shader.PropertyToID("_InputCubemap");
public static readonly int _Mipmap = Shader.PropertyToID("_Mipmap");
public static readonly int _SubsurfaceProfile = Shader.PropertyToID("_SubsurfaceProfile");
public static readonly int _DiffusionProfile = Shader.PropertyToID("_DiffusionProfile");
public static readonly int _MaxRadius = Shader.PropertyToID("_MaxRadius");
public static readonly int _ShapeParam = Shader.PropertyToID("_ShapeParam");
public static readonly int _StdDev1 = Shader.PropertyToID("_StdDev1");

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


Outputs outputs;
#ifdef OUTPUT_SPLIT_LIGHTING
if (_EnableSSSAndTransmission != 0 && bsdfData.materialId == MATERIALID_LIT_SSS)
if (_EnableSSSAndTransmission != 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 (_EnableSSSAndTransmission != 0 && bsdfData.materialId == MATERIALID_LIT_SSS && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS))
if (_EnableSSSAndTransmission != 0 && HaveSubsurfaceScattering(bsdfData))
{
specularLightingUAV[pixelCoord] = float4(specularLighting, 1.0);
diffuseLightingUAV[pixelCoord] = TagLightingForSSS(diffuseLighting);

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


[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace2("NormalMap space", Float) = 0
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace3("NormalMap space", Float) = 0
_SubsurfaceProfile0("Subsurface Profile0", Int) = 0
_SubsurfaceProfile1("Subsurface Profile1", Int) = 0
_SubsurfaceProfile2("Subsurface Profile2", Int) = 0
_SubsurfaceProfile3("Subsurface Profile3", Int) = 0
_DiffusionProfile0("Diffusion Profile0", Int) = 0
_DiffusionProfile1("Diffusion Profile1", Int) = 0
_DiffusionProfile2("Diffusion Profile2", Int) = 0
_DiffusionProfile3("Diffusion Profile3", Int) = 0
_SubsurfaceRadius0("Subsurface Radius0", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadius1("Subsurface Radius1", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadius2("Subsurface Radius2", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadius3("Subsurface Radius3", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask0("Subsurface Mask0", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask1("Subsurface Mask1", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask2("Subsurface Mask2", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask3("Subsurface Mask3", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadiusMap0("Subsurface Radius Map0", 2D) = "white" {}
_SubsurfaceRadiusMap1("Subsurface Radius Map1", 2D) = "white" {}
_SubsurfaceRadiusMap2("Subsurface Radius Map2", 2D) = "white" {}
_SubsurfaceRadiusMap3("Subsurface Radius Map3", 2D) = "white" {}
_SubsurfaceMaskMap0("Subsurface Mask Map0", 2D) = "white" {}
_SubsurfaceMaskMap1("Subsurface Mask Map1", 2D) = "white" {}
_SubsurfaceMaskMap2("Subsurface Mask Map2", 2D) = "white" {}
_SubsurfaceMaskMap3("Subsurface Mask Map3", 2D) = "white" {}
_Thickness0("Thickness", Range(0.0, 1.0)) = 1.0
_Thickness1("Thickness", Range(0.0, 1.0)) = 1.0

#pragma shader_feature _HEIGHTMAP1
#pragma shader_feature _HEIGHTMAP2
#pragma shader_feature _HEIGHTMAP3
#pragma shader_feature _SUBSURFACE_RADIUS_MAP0
#pragma shader_feature _SUBSURFACE_RADIUS_MAP1
#pragma shader_feature _SUBSURFACE_RADIUS_MAP2
#pragma shader_feature _SUBSURFACE_RADIUS_MAP3
#pragma shader_feature _SUBSURFACE_MASK_MAP0
#pragma shader_feature _SUBSURFACE_MASK_MAP1
#pragma shader_feature _SUBSURFACE_MASK_MAP2
#pragma shader_feature _SUBSURFACE_MASK_MAP3
#pragma shader_feature _THICKNESSMAP0
#pragma shader_feature _THICKNESSMAP1
#pragma shader_feature _THICKNESSMAP2

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


#define SAMPLER_HEIGHTMAP_IDX sampler_HeightMap3
#endif
#if defined(_SUBSURFACE_RADIUS_MAP0)
#define _SUBSURFACE_RADIUS_MAP_IDX sampler_SubsurfaceRadiusMap0
#elif defined(_SUBSURFACE_RADIUS_MAP1)
#define _SUBSURFACE_RADIUS_MAP_IDX sampler_SubsurfaceRadiusMap1
#elif defined(_SUBSURFACE_RADIUS_MAP2)
#define _SUBSURFACE_RADIUS_MAP_IDX sampler_SubsurfaceRadiusMap2
#elif defined(_SUBSURFACE_RADIUS_MAP3)
#define _SUBSURFACE_RADIUS_MAP_IDX sampler_SubsurfaceRadiusMap3
#if defined(_SUBSURFACE_MASK_MAP0)
#define _SUBSURFACE_MASK_MAP_IDX sampler_SubsurfaceMaskMap0
#elif defined(_SUBSURFACE_MASK_MAP1)
#define _SUBSURFACE_MASK_MAP_IDX sampler_SubsurfaceMaskMap1
#elif defined(_SUBSURFACE_MASK_MAP2)
#define _SUBSURFACE_MASK_MAP_IDX sampler_SubsurfaceMaskMap2
#elif defined(_SUBSURFACE_MASK_MAP3)
#define _SUBSURFACE_MASK_MAP_IDX sampler_SubsurfaceMaskMap3
#endif
#if defined(_THICKNESSMAP0)

#ifdef _DETAIL_MAP0
#define _DETAIL_MAP_IDX
#endif
#ifdef _SUBSURFACE_RADIUS_MAP0
#define _SUBSURFACE_RADIUS_MAP_IDX
#ifdef _SUBSURFACE_MASK_MAP0
#define _SUBSURFACE_MASK_MAP_IDX
#endif
#ifdef _THICKNESSMAP0
#define _THICKNESSMAP_IDX

#undef _NORMALMAP_IDX
#undef _NORMALMAP_TANGENT_SPACE_IDX
#undef _DETAIL_MAP_IDX
#undef _SUBSURFACE_RADIUS_MAP_IDX
#undef _SUBSURFACE_MASK_MAP_IDX
#undef _THICKNESSMAP_IDX
#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX

#ifdef _DETAIL_MAP1
#define _DETAIL_MAP_IDX
#endif
#ifdef _SUBSURFACE_RADIUS_MAP1
#define _SUBSURFACE_RADIUS_MAP_IDX
#ifdef _SUBSURFACE_MASK_MAP1
#define _SUBSURFACE_MASK_MAP_IDX
#endif
#ifdef _THICKNESSMAP1
#define _THICKNESSMAP_IDX

#undef _NORMALMAP_IDX
#undef _NORMALMAP_TANGENT_SPACE_IDX
#undef _DETAIL_MAP_IDX
#undef _SUBSURFACE_RADIUS_MAP_IDX
#undef _SUBSURFACE_MASK_MAP_IDX
#undef _THICKNESSMAP_IDX
#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX

#ifdef _DETAIL_MAP2
#define _DETAIL_MAP_IDX
#endif
#ifdef _SUBSURFACE_RADIUS_MAP2
#define _SUBSURFACE_RADIUS_MAP_IDX
#ifdef _SUBSURFACE_MASK_MAP2
#define _SUBSURFACE_MASK_MAP_IDX
#endif
#ifdef _THICKNESSMAP2
#define _THICKNESSMAP_IDX

#undef _NORMALMAP_IDX
#undef _NORMALMAP_TANGENT_SPACE_IDX
#undef _DETAIL_MAP_IDX
#undef _SUBSURFACE_RADIUS_MAP_IDX
#undef _SUBSURFACE_MASK_MAP_IDX
#undef _THICKNESSMAP_IDX
#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX

#ifdef _DETAIL_MAP3
#define _DETAIL_MAP_IDX
#endif
#ifdef _SUBSURFACE_RADIUS_MAP3
#define _SUBSURFACE_RADIUS_MAP_IDX
#ifdef _SUBSURFACE_MASK_MAP3
#define _SUBSURFACE_MASK_MAP_IDX
#endif
#ifdef _THICKNESSMAP3
#define _THICKNESSMAP_IDX

#undef _NORMALMAP_IDX
#undef _NORMALMAP_TANGENT_SPACE_IDX
#undef _DETAIL_MAP_IDX
#undef _SUBSURFACE_RADIUS_MAP_IDX
#undef _SUBSURFACE_MASK_MAP_IDX
#undef _THICKNESSMAP_IDX
#undef _MASKMAP_IDX
#undef _BENTNORMALMAP_IDX

surfaceData.ambientOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, ambientOcclusion, weights);
surfaceData.metallic = SURFACEDATA_BLEND_SCALAR(surfaceData, metallic, weights);
surfaceData.tangentWS = normalize(input.worldToTangent[0].xyz); // The tangent is not normalize in worldToTangent for mikkt. Tag: SURFACE_GRADIENT
surfaceData.subsurfaceRadius = SURFACEDATA_BLEND_SCALAR(surfaceData, subsurfaceRadius, weights);
surfaceData.subsurfaceMask = SURFACEDATA_BLEND_SCALAR(surfaceData, subsurfaceMask, weights);
surfaceData.subsurfaceProfile = SURFACEDATA_BLEND_SSS_PROFILE(surfaceData, subsurfaceProfile, weights);
surfaceData.diffusionProfile = SURFACEDATA_BLEND_SSS_PROFILE(surfaceData, diffusionProfile, weights);
// Layered shader support either SSS or standard (can't mix them)
#ifdef _MATID_SSS

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


[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace2("NormalMap space", Float) = 0
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace3("NormalMap space", Float) = 0
_SubsurfaceProfile0("Subsurface Profile0", Int) = 0
_SubsurfaceProfile1("Subsurface Profile1", Int) = 0
_SubsurfaceProfile2("Subsurface Profile2", Int) = 0
_SubsurfaceProfile3("Subsurface Profile3", Int) = 0
_DiffusionProfile0("Diffusion Profile0", Int) = 0
_DiffusionProfile1("Diffusion Profile1", Int) = 0
_DiffusionProfile2("Diffusion Profile2", Int) = 0
_DiffusionProfile3("Diffusion Profile3", Int) = 0
_SubsurfaceRadius0("Subsurface Radius0", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadius1("Subsurface Radius1", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadius2("Subsurface Radius2", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadius3("Subsurface Radius3", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask0("Subsurface Mask0", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask1("Subsurface Mask1", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask2("Subsurface Mask2", Range(0.0, 1.0)) = 1.0
_SubsurfaceMask3("Subsurface Mask3", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadiusMap0("Subsurface Radius Map0", 2D) = "white" {}
_SubsurfaceRadiusMap1("Subsurface Radius Map1", 2D) = "white" {}
_SubsurfaceRadiusMap2("Subsurface Radius Map2", 2D) = "white" {}
_SubsurfaceRadiusMap3("Subsurface Radius Map3", 2D) = "white" {}
_SubsurfaceMaskMap0("Subsurface Mask Map0", 2D) = "white" {}
_SubsurfaceMaskMap1("Subsurface Mask Map1", 2D) = "white" {}
_SubsurfaceMaskMap2("Subsurface Mask Map2", 2D) = "white" {}
_SubsurfaceMaskMap3("Subsurface Mask Map3", 2D) = "white" {}
_Thickness0("Thickness", Range(0.0, 1.0)) = 1.0
_Thickness1("Thickness", Range(0.0, 1.0)) = 1.0

#pragma shader_feature _HEIGHTMAP1
#pragma shader_feature _HEIGHTMAP2
#pragma shader_feature _HEIGHTMAP3
#pragma shader_feature _SUBSURFACE_RADIUS_MAP0
#pragma shader_feature _SUBSURFACE_RADIUS_MAP1
#pragma shader_feature _SUBSURFACE_RADIUS_MAP2
#pragma shader_feature _SUBSURFACE_RADIUS_MAP3
#pragma shader_feature _SUBSURFACE_MASK_MAP0
#pragma shader_feature _SUBSURFACE_MASK_MAP1
#pragma shader_feature _SUBSURFACE_MASK_MAP2
#pragma shader_feature _SUBSURFACE_MASK_MAP3
#pragma shader_feature _THICKNESSMAP0
#pragma shader_feature _THICKNESSMAP1
#pragma shader_feature _THICKNESSMAP2

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


// SSS
[SurfaceDataAttributes("Subsurface Radius")]
public float subsurfaceRadius;
public float subsurfaceMask;
public int subsurfaceProfile;
public int diffusionProfile;
// SpecColor
[SurfaceDataAttributes("Specular Color", false, true)]

// fold into fresnel0
// SSS
public float subsurfaceRadius;
public float subsurfaceMask;
public int subsurfaceProfile;
public int diffusionProfile;
public bool enableTransmission; // Read from the SSS profile
public bool useThickObjectMode; // Read from the SSS profile
public Vector3 transmittance;

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


#define DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS (1006)
#define DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY (1007)
#define DEBUGVIEW_LIT_SURFACEDATA_METALLIC (1008)
#define DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_RADIUS (1009)
#define DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_MASK (1009)
#define DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_PROFILE (1011)
#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_BSDFDATA_ROUGHNESS_T (1038)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B (1039)
#define DEBUGVIEW_LIT_BSDFDATA_ANISOTROPY (1040)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_RADIUS (1041)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_MASK (1041)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_PROFILE (1043)
#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)

float3 tangentWS;
float anisotropy;
float metallic;
float subsurfaceRadius;
float subsurfaceMask;
int subsurfaceProfile;
int diffusionProfile;
float3 specularColor;
float coatMask;
float ior;

float roughnessT;
float roughnessB;
float anisotropy;
float subsurfaceRadius;
float subsurfaceMask;
int subsurfaceProfile;
int diffusionProfile;
bool enableTransmission;
bool useThickObjectMode;
float3 transmittance;

case DEBUGVIEW_LIT_SURFACEDATA_METALLIC:
result = surfacedata.metallic.xxx;
break;
case DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_RADIUS:
result = surfacedata.subsurfaceRadius.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_MASK:
result = surfacedata.subsurfaceMask.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_PROFILE:
result = GetIndexColor(surfacedata.subsurfaceProfile);
case DEBUGVIEW_LIT_SURFACEDATA_DIFFUSION_PROFILE:
result = GetIndexColor(surfacedata.diffusionProfile);
break;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR:
result = surfacedata.specularColor;

case DEBUGVIEW_LIT_BSDFDATA_ANISOTROPY:
result = bsdfdata.anisotropy.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_RADIUS:
result = bsdfdata.subsurfaceRadius.xxx;
case DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_MASK:
result = bsdfdata.subsurfaceMask.xxx;
case DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_PROFILE:
result = GetIndexColor(bsdfdata.subsurfaceProfile);
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);

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


}
// Fills the data which may be accessed if MATERIALFEATUREFLAGS_LIT_SSS is set.
void FillMaterialIdSssData(int subsurfaceProfile, float radius, float thickness, uint transmissionMode,
void FillMaterialIdSssData(int diffusionProfile, float radius, float thickness, uint transmissionMode,
bsdfData.subsurfaceProfile = subsurfaceProfile;
bsdfData.subsurfaceRadius = radius;
bsdfData.diffusionProfile = diffusionProfile;
bsdfData.subsurfaceMask = radius;
if (bsdfData.enableTransmission && transmissionMode != SSS_TRSM_MODE_NONE)
if (bsdfData.enableTransmission && transmissionMode != TRANSMISSION_MODE_NONE)
bsdfData.thickness = _ThicknessRemaps[subsurfaceProfile].x + _ThicknessRemaps[subsurfaceProfile].y * thickness;
bsdfData.useThickObjectMode = transmissionMode != SSS_TRSM_MODE_THIN;
bsdfData.thickness = _ThicknessRemaps[diffusionProfile].x + _ThicknessRemaps[diffusionProfile].y * thickness;
bsdfData.useThickObjectMode = transmissionMode != TRANSMISSION_MODE_THIN;
bsdfData.transmittance = ComputeTransmittanceDisney(_ShapeParams[subsurfaceProfile].rgb,
_TransmissionTintsAndFresnel0[subsurfaceProfile].rgb,
bsdfData.thickness, bsdfData.subsurfaceRadius);
bsdfData.transmittance = ComputeTransmittanceDisney(_ShapeParams[diffusionProfile].rgb,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness, bsdfData.subsurfaceMask);
bsdfData.transmittance = ComputeTransmittanceJimenez(_HalfRcpVariancesAndWeights[subsurfaceProfile][0].rgb,
_HalfRcpVariancesAndWeights[subsurfaceProfile][0].a,
_HalfRcpVariancesAndWeights[subsurfaceProfile][1].rgb,
_HalfRcpVariancesAndWeights[subsurfaceProfile][1].a,
_TransmissionTintsAndFresnel0[subsurfaceProfile].rgb,
bsdfData.thickness, bsdfData.subsurfaceRadius);
bsdfData.transmittance = ComputeTransmittanceJimenez(_HalfRcpVariancesAndWeights[diffusionProfile][0].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][0].a,
_HalfRcpVariancesAndWeights[diffusionProfile][1].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][1].a,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness, bsdfData.subsurfaceMask);
#endif
}
}

SSSData sssData;
sssData.diffuseColor = surfaceData.baseColor;
sssData.subsurfaceRadius = surfaceData.subsurfaceRadius;
sssData.subsurfaceProfile = surfaceData.subsurfaceProfile;
sssData.subsurfaceMask = surfaceData.subsurfaceMask;
sssData.diffusionProfile = surfaceData.diffusionProfile;
return sssData;
}

else if (bsdfData.materialId == MATERIALID_LIT_SSS)
{
bsdfData.diffuseColor = surfaceData.baseColor;
bsdfData.fresnel0 = _TransmissionTintsAndFresnel0[surfaceData.subsurfaceProfile].a;
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * surfaceData.subsurfaceProfile, 2u);
bsdfData.fresnel0 = _TransmissionTintsAndFresnel0[surfaceData.diffusionProfile].a;
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * surfaceData.diffusionProfile, 2u);
FillMaterialIdSssData(surfaceData.subsurfaceProfile,
surfaceData.subsurfaceRadius,
FillMaterialIdSssData(surfaceData.diffusionProfile,
surfaceData.subsurfaceMask,
surfaceData.thickness,
transmissionMode, bsdfData);
}

if (HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS))
{
int subsurfaceProfile = SSS_NEUTRAL_PROFILE_ID;
uint transmissionMode = SSS_TRSM_MODE_NONE;
int diffusionProfile = DIFFUSION_NEUTRAL_PROFILE_ID;
uint transmissionMode = TRANSMISSION_MODE_NONE;
// Reminder: when using SSS we exchange specular occlusion and subsurfaceRadius/profileID
// Reminder: when using SSS we exchange specular occlusion and subsurfaceMask/profileID
subsurfaceProfile = sssData.subsurfaceProfile;
transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * subsurfaceProfile, 2u);
radius = sssData.subsurfaceRadius;
diffusionProfile = sssData.diffusionProfile;
transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * diffusionProfile, 2u);
radius = sssData.subsurfaceMask;
dielectricF0 = _TransmissionTintsAndFresnel0[subsurfaceProfile].a;
dielectricF0 = _TransmissionTintsAndFresnel0[diffusionProfile].a;
FillMaterialIdSssData(subsurfaceProfile, radius, thickness, transmissionMode, bsdfData);
FillMaterialIdSssData(diffusionProfile, radius, thickness, transmissionMode, bsdfData);
}
float coatMask = 0.0;

{
if (bsdfData.materialId == MATERIALID_LIT_SSS)
{
bsdfData.diffuseColor = ApplyDiffuseTexturingMode(bsdfData.diffuseColor, bsdfData.subsurfaceProfile);
bsdfData.diffuseColor = ApplySubsurfaceScatteringTexturingMode(bsdfData.diffuseColor, bsdfData.diffusionProfile);
}
// Premultiply bake diffuse lighting information with DisneyDiffuse pre-integration

lightTransportData.emissiveColor = builtinData.emissiveColor;
return lightTransportData;
}
//-----------------------------------------------------------------------------
// Subsurface Scattering functions
//-----------------------------------------------------------------------------
bool HaveSubsurfaceScattering(BSDFData bsdfData)
{
return bsdfData.materialId == MATERIALID_LIT_SSS && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS);
}
//-----------------------------------------------------------------------------

{
// Compute the thickness in world units along the normal.
float thicknessInMeters = bsdfData.thickness * METERS_PER_MILLIMETER;
float thicknessInUnits = thicknessInMeters * _WorldScales[bsdfData.subsurfaceProfile].y;
float thicknessInUnits = thicknessInMeters * _WorldScales[bsdfData.diffusionProfile].y;
// Compute the thickness in world units along the light vector.
displacement = thicknessInUnits / -NdotL;

float3 modifiedDiffuseColor;
if (bsdfData.materialId == MATERIALID_LIT_SSS)
modifiedDiffuseColor = ApplyDiffuseTexturingMode(bsdfData.diffuseColor, bsdfData.subsurfaceProfile);
modifiedDiffuseColor = ApplySubsurfaceScatteringTexturingMode(bsdfData.diffuseColor, bsdfData.diffusionProfile);
else
modifiedDiffuseColor = bsdfData.diffuseColor;

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


_Anisotropy("Anisotropy", Range(-1.0, 1.0)) = 0
_AnisotropyMap("AnisotropyMap", 2D) = "white" {}
_SubsurfaceProfile("Subsurface Profile", Int) = 0
_SubsurfaceRadius("Subsurface Radius", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadiusMap("Subsurface Radius Map", 2D) = "white" {}
_DiffusionProfile("Diffusion Profile", Int) = 0
_SubsurfaceMask("Subsurface Radius", Range(0.0, 1.0)) = 1.0
_SubsurfaceMaskMap("Subsurface Radius Map", 2D) = "white" {}
_Thickness("Thickness", Range(0.0, 1.0)) = 1.0
_ThicknessMap("Thickness Map", 2D) = "white" {}
_ThicknessRemap("Thickness Remap", Vector) = (0, 1, 0, 0)

#pragma shader_feature _TANGENTMAP
#pragma shader_feature _ANISOTROPYMAP
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _SUBSURFACE_RADIUS_MAP
#pragma shader_feature _SUBSURFACE_MASK_MAP
#pragma shader_feature _THICKNESSMAP
#pragma shader_feature _SPECULARCOLORMAP
#pragma shader_feature _TRANSMITTANCECOLORMAP

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


#define SAMPLER_MASKMAP_IDX sampler_MaskMap
#define SAMPLER_HEIGHTMAP_IDX sampler_HeightMap
#define SAMPLER_SUBSURFACE_RADIUSMAP_IDX sampler_SubsurfaceRadiusMap
#define SAMPLER_SUBSURFACE_MASKMAP_IDX sampler_SubsurfaceMaskMap
#define SAMPLER_THICKNESSMAP_IDX sampler_ThicknessMap
// include LitDataIndividualLayer to define GetSurfaceData

#ifdef _DETAIL_MAP
#define _DETAIL_MAP_IDX
#endif
#ifdef _SUBSURFACE_RADIUS_MAP
#define _SUBSURFACE_RADIUS_MAP_IDX
#ifdef _SUBSURFACE_MASK_MAP
#define _SUBSURFACE_MASK_MAP_IDX
#endif
#ifdef _THICKNESSMAP
#define _THICKNESSMAP_IDX

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


#endif
surfaceData.metallic *= ADD_IDX(_Metallic);
surfaceData.subsurfaceProfile = ADD_IDX(_SubsurfaceProfile);
surfaceData.subsurfaceRadius = ADD_IDX(_SubsurfaceRadius);
surfaceData.diffusionProfile = ADD_IDX(_DiffusionProfile);
surfaceData.subsurfaceMask = ADD_IDX(_SubsurfaceMask);
#ifdef _SUBSURFACE_RADIUS_MAP_IDX
surfaceData.subsurfaceRadius *= SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_SubsurfaceRadiusMap), SAMPLER_SUBSURFACE_RADIUSMAP_IDX, ADD_IDX(layerTexCoord.base)).r;
#ifdef _SUBSURFACE_MASK_MAP_IDX
surfaceData.subsurfaceMask *= SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_SubsurfaceMaskMap), SAMPLER_SUBSURFACE_MASKMAP_IDX, ADD_IDX(layerTexCoord.base)).r;
#endif
#ifdef _THICKNESSMAP_IDX

14
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitProperties.hlsl


TEXTURE2D(_AnisotropyMap);
SAMPLER(sampler_AnisotropyMap);
TEXTURE2D(_SubsurfaceRadiusMap);
SAMPLER(sampler_SubsurfaceRadiusMap);
TEXTURE2D(_SubsurfaceMaskMap);
SAMPLER(sampler_SubsurfaceMaskMap);
TEXTURE2D(_ThicknessMap);
SAMPLER(sampler_ThicknessMap);

PROP_DECL_TEX2D(_DetailMap);
PROP_DECL_TEX2D(_HeightMap);
PROP_DECL_TEX2D(_SubsurfaceRadiusMap);
PROP_DECL_TEX2D(_SubsurfaceMaskMap);
PROP_DECL_TEX2D(_ThicknessMap);
TEXTURE2D(_LayerMaskMap);

float _Anisotropy;
int _SubsurfaceProfile;
float _SubsurfaceRadius;
int _DiffusionProfile;
float _SubsurfaceMask;
float _Thickness;
float4 _ThicknessRemap;

PROP_DECL(float, _HeightAmplitude);
PROP_DECL(float, _HeightCenter);
PROP_DECL(int, _SubsurfaceProfile);
PROP_DECL(float, _SubsurfaceRadius);
PROP_DECL(int, _DiffusionProfile);
PROP_DECL(float, _SubsurfaceMask);
PROP_DECL(float, _Thickness);
PROP_DECL(float4, _ThicknessRemap);

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


_Anisotropy("Anisotropy", Range(-1.0, 1.0)) = 0
_AnisotropyMap("AnisotropyMap", 2D) = "white" {}
_SubsurfaceProfile("Subsurface Profile", Int) = 0
_SubsurfaceRadius("Subsurface Radius", Range(0.0, 1.0)) = 1.0
_SubsurfaceRadiusMap("Subsurface Radius Map", 2D) = "white" {}
_DiffusionProfile("Diffusion Profile", Int) = 0
_SubsurfaceMask("Subsurface Radius", Range(0.0, 1.0)) = 1.0
_SubsurfaceMaskMap("Subsurface Radius Map", 2D) = "white" {}
_Thickness("Thickness", Range(0.0, 1.0)) = 1.0
_ThicknessMap("Thickness Map", 2D) = "white" {}
_ThicknessRemap("Thickness Remap", Vector) = (0, 1, 0, 0)

#pragma shader_feature _TANGENTMAP
#pragma shader_feature _ANISOTROPYMAP
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _SUBSURFACE_RADIUS_MAP
#pragma shader_feature _SUBSURFACE_MASK_MAP
#pragma shader_feature _THICKNESSMAP
#pragma shader_feature _SPECULARCOLORMAP
#pragma shader_feature _TRANSMITTANCECOLORMAP

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


// Inputs & outputs
//--------------------------------------------------------------------------------------------------
float4 _FilterKernels[SSS_N_PROFILES][SSS_N_SAMPLES_NEAR_FIELD]; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
float4 _FilterKernels[DIFFUSION_N_PROFILES][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

SSSData sssData;
DECODE_FROM_SSSBUFFER(posInput.positionSS, sssData);
int profileID = sssData.subsurfaceProfile;
float distScale = sssData.subsurfaceRadius;
int profileID = sssData.diffusionProfile;
float distScale = sssData.subsurfaceMask;
float3 shapeParam = _ShapeParams[profileID].rgb;
float maxDistance = _ShapeParams[profileID].a;

// divergence of execution across the warp.
float maxDistInPixels = maxDistance * max(pixelsPerMm.x, pixelsPerMm.y);
float3 albedo = ApplyDiffuseTexturingMode(sssData.diffuseColor, profileID);
float3 albedo = ApplySubsurfaceScatteringTexturingMode(sssData.diffuseColor, profileID);
[branch] if (distScale == 0 || maxDistInPixels < 1)
{

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


#include "SubsurfaceScatteringSettings.cs.hlsl"
#include "CommonSubsurfaceScattering.hlsl"
#include "../DiffusionProfile/DiffusionProfileSettings.cs.hlsl"
#include "../DiffusionProfile/DiffusionProfile.hlsl"
CBUFFER_START(UnitySSSParameters)
CBUFFER_START(UnitySSSAndTransmissionParameters)
// 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 _EnableSSSAndTransmission; // Globally toggles subsurface and transmission scattering on/off

float4 _HalfRcpVariancesAndWeights[SSS_N_PROFILES][2]; // 2x Gaussians in RGB, A is interpolation weights
float4 _HalfRcpVariancesAndWeights[DIFFUSION_N_PROFILES][2]; // 2x Gaussians in RGB, A is interpolation weights
float4 _ThicknessRemaps[SSS_N_PROFILES]; // R: start, G = end - start, BA unused
float4 _ShapeParams[SSS_N_PROFILES]; // RGB = S = 1 / D, A = filter radius
float4 _TransmissionTintsAndFresnel0[SSS_N_PROFILES]; // RGB = 1/4 * color, A = fresnel0
float4 _WorldScales[SSS_N_PROFILES]; // X = meters per world unit; Y = world units per meter
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
CBUFFER_END
// ----------------------------------------------------------------------------

// Returns the modified albedo (diffuse color) for materials with subsurface scattering.
// Ref: Advanced Techniques for Realistic Real-Time Skin Rendering.
float3 ApplyDiffuseTexturingMode(float3 color, int subsurfaceProfile)
float3 ApplySubsurfaceScatteringTexturingMode(float3 color, int diffusionProfile)
{
#if defined(SHADERPASS) && (SHADERPASS == SHADERPASS_SUBSURFACE_SCATTERING)
// If the SSS pass is executed, we know we have SSS enabled.

if (enableSssAndTransmission)
{
bool performPostScatterTexturing = IsBitSet(asuint(_TexturingModeFlags), subsurfaceProfile);
bool performPostScatterTexturing = IsBitSet(asuint(_TexturingModeFlags), diffusionProfile);
if (performPostScatterTexturing)
{

struct SSSData
{
float3 diffuseColor;
float subsurfaceRadius;
int subsurfaceProfile;
float subsurfaceMask;
int diffusionProfile;
};
#define SSSBufferType0 float4

// Note: The SSS buffer used here is sRGB
void EncodeIntoSSSBuffer(SSSData sssData, uint2 positionSS, out SSSBufferType0 outSSSBuffer0)
{
outSSSBuffer0 = float4(sssData.diffuseColor, PackFloatInt8bit(sssData.subsurfaceRadius, sssData.subsurfaceProfile, 16.0));
outSSSBuffer0 = float4(sssData.diffuseColor, PackFloatInt8bit(sssData.subsurfaceMask, sssData.diffusionProfile, 16.0));
}
// Note: The SSS buffer used here is sRGB

UnpackFloatInt8bit(sssBuffer.a, 16.0, sssData.subsurfaceRadius, sssData.subsurfaceProfile);
UnpackFloatInt8bit(sssBuffer.a, 16.0, sssData.subsurfaceMask, sssData.diffusionProfile);
}
void DecodeFromSSSBuffer(uint2 positionSS, out SSSData sssData)

#define ENCODE_INTO_SSSBUFFER(SURFACE_DATA, UNPOSITIONSS, NAME) EncodeIntoSSSBuffer(ConvertSurfaceDataToSSSData(SURFACE_DATA), UNPOSITIONSS, MERGE_NAME(NAME, 0))
#define DECODE_FROM_SSSBUFFER(UNPOSITIONSS, SSS_DATA) DecodeFromSSSBuffer(UNPOSITIONSS, SSS_DATA)
// In order to support subsurface scattering, we need to know which pixels have an SSS material.
// It can be accomplished by reading the stencil buffer.
// A faster solution (which avoids an extra texture fetch) is to simply make sure that
// all pixels which belong to an SSS material are not black (those that don't always are).
// We choose the blue color channel since it's perceptually the least noticeable.
float3 TagLightingForSSS(float3 subsurfaceLighting)
{
subsurfaceLighting.b = max(subsurfaceLighting.b, HALF_MIN);
return subsurfaceLighting;
}
// See TagLightingForSSS() for details.
bool TestLightingForSSS(float3 subsurfaceLighting)
{
return subsurfaceLighting.b > 0;
}

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


// Inputs & outputs
//-------------------------------------------------------------------------------------
float4 _FilterKernelsBasic[SSS_N_PROFILES][SSS_BASIC_N_SAMPLES]; // RGB = weights, A = radial distance
float4 _FilterKernelsBasic[DIFFUSION_N_PROFILES][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

SSSData sssData;
DECODE_FROM_SSSBUFFER(posInput.positionSS, sssData);
int profileID = sssData.subsurfaceProfile;
float distScale = sssData.subsurfaceRadius;
int profileID = sssData.diffusionProfile;
float distScale = sssData.subsurfaceMask;
float maxDistance = _FilterKernelsBasic[profileID][SSS_BASIC_N_SAMPLES - 1].a;
// Take the first (central) sample.

float halfRcpVariance = _HalfRcpWeightedVariances[profileID].a;
#endif
float3 albedo = ApplyDiffuseTexturingMode(sssData.diffuseColor, profileID);
float3 albedo = ApplySubsurfaceScatteringTexturingMode(sssData.diffuseColor, profileID);
#ifndef SSS_FILTER_HORIZONTAL_AND_COMBINE
albedo = float3(1, 1, 1);

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


m_HTileRT = new RenderTargetIdentifier(m_HTile);
}
public void PushGlobalParams(CommandBuffer cmd, SubsurfaceScatteringSettings sssParameters, FrameSettings frameSettings)
public void PushGlobalParams(CommandBuffer cmd, DiffusionProfileSettings sssParameters, FrameSettings frameSettings)
{
// Broadcast SSS parameters to all shaders.
cmd.SetGlobalInt(HDShaderIDs._EnableSSSAndTransmission, frameSettings.enableSSSAndTransmission ? 1 : 0);

}
// Combines specular lighting and diffuse lighting with subsurface scattering.
public void SubsurfaceScatteringPass(HDCamera hdCamera, CommandBuffer cmd, SubsurfaceScatteringSettings sssParameters, FrameSettings frameSettings,
public void SubsurfaceScatteringPass(HDCamera hdCamera, CommandBuffer cmd, DiffusionProfileSettings sssParameters, FrameSettings frameSettings,
RenderTargetIdentifier colorBufferRT, RenderTargetIdentifier diffuseBufferRT, RenderTargetIdentifier depthStencilBufferRT, RenderTargetIdentifier depthTextureRT)
{
if (sssParameters == null || !frameSettings.enableSSSAndTransmission)

5
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/RenderPipelineResources.cs


public ComputeShader deferredComputeShader;
public ComputeShader deferredDirectionalShadowComputeShader;
// Subsurface scattering
// These shaders don't need to be reference by RenderPipelineResource as they are not use at runtime (only to draw in editor)
// public Shader drawSssProfile;
// public Shader drawTransmittanceGraphShader;
public ComputeShader subsurfaceScatteringCS; // Disney SSS
public Shader subsurfaceScattering; // Jimenez SSS
public Shader combineLighting;

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


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

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


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public sealed partial class SubsurfaceScatteringSettingsEditor
public sealed partial class DiffusionProfileSettingsEditor
// TODO: missing tooltips
sealed class Styles
{
public readonly GUIContent profilePreview0 = new GUIContent("Profile Preview");

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 profileFresnel0 = new GUIContent("Specular", "Fraction of light reflected at the normal angle of incidence. Typical skin value is 0.028");
public readonly GUIContent profileIor = new GUIContent("Index of Refraction", "Index of refraction. 1.4 for skin. 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.");

public readonly GUIContent SubsurfaceScatteringLabel = new GUIContent("Subsurface Scattering only");
public readonly GUIContent TransmissionLabel = new GUIContent("Transmission only");
public Styles()
{

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


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
[CustomEditor(typeof(SubsurfaceScatteringSettings))]
public sealed partial class SubsurfaceScatteringSettingsEditor : HDBaseEditor<SubsurfaceScatteringSettings>
[CustomEditor(typeof(DiffusionProfileSettings))]
public sealed partial class DiffusionProfileSettingsEditor : HDBaseEditor<DiffusionProfileSettings>
internal SubsurfaceScatteringProfile objReference;
internal DiffusionProfile objReference;
internal SerializedProperty name;

internal SerializedProperty transmissionMode;
internal SerializedProperty thicknessRemap;
internal SerializedProperty worldScale;
internal SerializedProperty fresnel0;
internal SerializedProperty ior;
// Old SSS Model >>>
internal SerializedProperty scatterDistance1;

base.OnEnable();
// These shaders don't need to be reference by RenderPipelineResource as they are not use at runtime
m_ProfileMaterial = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/DrawSssProfile");
m_ProfileMaterial = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/DrawDiffusionProfile");
int count = SssConstants.SSS_N_PROFILES - 1;
int count = DiffusionProfileConstants.DIFFUSION_N_PROFILES - 1;
m_Profiles = new List<Profile>();
var serializedProfiles = properties.Find(x => x.profiles);

var serializedProfile = serializedProfiles.GetArrayElementAtIndex(i);
var rp = new RelativePropertyFetcher<SubsurfaceScatteringProfile>(serializedProfile);
var rp = new RelativePropertyFetcher<DiffusionProfile>(serializedProfile);
var profile = new Profile
{

transmissionMode = rp.Find(x => x.transmissionMode),
thicknessRemap = rp.Find(x => x.thicknessRemap),
worldScale = rp.Find(x => x.worldScale),
fresnel0 = rp.Find(x => x.fresnel0),
ior = rp.Find(x => x.ior),
scatterDistance1 = rp.Find(x => x.scatterDistance1),
scatterDistance2 = rp.Find(x => x.scatterDistance2),

CheckStyles();
// Display a warning if this settings asset is not currently in use
if (m_HDPipeline == null || m_HDPipeline.sssSettings != m_Target)
if (m_HDPipeline == null || m_HDPipeline.diffusionProfileSettings != m_Target)
EditorGUILayout.HelpBox("These profiles aren't currently in use, assign this asset to the HD render pipeline asset to use them.", MessageType.Warning);
serializedObject.Update();

EditorGUILayout.PropertyField(profile.lerpWeight, s_Styles.profileLerpWeight);
}
EditorGUILayout.PropertyField(profile.worldScale, s_Styles.profileWorldScale);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.SubsurfaceScatteringLabel, EditorStyles.boldLabel);
EditorGUILayout.Slider(profile.ior, 1.0f, 2.0f, s_Styles.profileIor);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.TransmissionLabel, EditorStyles.boldLabel);
profile.transmissionMode.intValue = EditorGUILayout.Popup(s_Styles.profileTransmissionMode, profile.transmissionMode.intValue, s_Styles.transmissionModeOptions);
EditorGUILayout.PropertyField(profile.transmissionTint, s_Styles.profileTransmissionTint);

profile.thicknessRemap.vector2Value = thicknessRemap;
EditorGUILayout.PropertyField(profile.worldScale, s_Styles.profileWorldScale);
EditorGUILayout.Slider(profile.fresnel0, 0.0f, 0.1f, s_Styles.profileFresnel0);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.profilePreview0, s_Styles.centeredMiniBoldLabel);

var S = obj.shapeParam;
var T = (Vector4)profile.transmissionTint.colorValue;
var R = profile.thicknessRemap.vector2Value;
bool transmissionEnabled = profile.transmissionMode.intValue != (int)SubsurfaceScatteringProfile.TransmissionMode.None;
bool transmissionEnabled = profile.transmissionMode.intValue != (int)DiffusionProfile.TransmissionMode.None;
m_ProfileMaterial.SetFloat(HDShaderIDs._MaxRadius, r);
m_ProfileMaterial.SetVector(HDShaderIDs._ShapeParam, S);

// Apply the three-sigma rule, and rescale.
float s = (1f / 3f) * SssConstants.SSS_BASIC_DISTANCE_SCALE;
float s = (1f / 3f) * DiffusionProfileConstants.SSS_BASIC_DISTANCE_SCALE;
var scatterDist1 = profile.scatterDistance1.colorValue;
var scatterDist2 = profile.scatterDistance2.colorValue;
float rMax = Mathf.Max(scatterDist1.r, scatterDist1.g, scatterDist1.b,

// Old SSS Model >>>
// Multiply by 0.1 to convert from millimeters to centimeters. Apply the distance scale.
float a = 0.1f * SssConstants.SSS_BASIC_DISTANCE_SCALE;
float a = 0.1f * DiffusionProfileConstants.SSS_BASIC_DISTANCE_SCALE;
var halfRcpVarianceAndWeight1 = new Vector4(a * a * 0.5f / (stdDev1.x * stdDev1.x), a * a * 0.5f / (stdDev1.y * stdDev1.y), a * a * 0.5f / (stdDev1.z * stdDev1.z), 4f * (1f - profile.lerpWeight.floatValue));
var halfRcpVarianceAndWeight2 = new Vector4(a * a * 0.5f / (stdDev2.x * stdDev2.x), a * a * 0.5f / (stdDev2.y * stdDev2.y), a * a * 0.5f / (stdDev2.z * stdDev2.z), 4f * profile.lerpWeight.floatValue);
m_TransmittanceMaterial.SetVector(HDShaderIDs._HalfRcpVarianceAndWeight1, halfRcpVarianceAndWeight1);

18
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Default Diffusion Profile Settings.asset


m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b2686e09ec7aef44bad2843e4416f057, type: 3}
m_Name: SSS Settings
m_Name: Default Diffusion Profile Settings
useDisneySSS: 1
profiles:
- name: Skin
scatteringDistance: {r: 0.7568628, g: 0.32156864, b: 0.20000002, a: 1}

thicknessRemap: {x: 0, y: 8.152544}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3019608, g: 0.20000002, b: 0.20000002, a: 0}
scatterDistance2: {r: 0.6, g: 0.20000002, b: 0.20000002, a: 0}
lerpWeight: 0.5

transmissionMode: 1
thicknessRemap: {x: 0, y: 0.2873168}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 0.5

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
ior: 1.4
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.5, g: 0.5, b: 0.5, a: 0}
lerpWeight: 1

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawDiffusionProfile.shader


Shader "Hidden/HDRenderPipeline/DrawSssProfile"
Shader "Hidden/HDRenderPipeline/DrawDiffusionProfile"
{
SubShader
{

#include "CoreRP/ShaderLibrary/Common.hlsl"
#define USE_LEGACY_UNITY_MATRIX_VARIABLES
#include "../../ShaderVariables.hlsl"
#include "HDRP/ShaderVariables.hlsl"
#include "../../Material/SubsurfaceScattering/SubsurfaceScatteringSettings.cs.hlsl"
#include "HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.hlsl"
#endif
//-------------------------------------------------------------------------------------

#ifdef SSS_MODEL_DISNEY
float4 _ShapeParam; float _MaxRadius; // See 'SubsurfaceScatteringProfile'
float4 _ShapeParam; float _MaxRadius; // See 'DiffusionProfile'
#else
float4 _StdDev1, _StdDev2;
float _LerpWeight, _MaxRadius; // See 'SubsurfaceScatteringParameters'

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


#include "CoreRP/ShaderLibrary/Common.hlsl"
#include "CoreRP/ShaderLibrary/CommonMaterial.hlsl"
#define USE_LEGACY_UNITY_MATRIX_VARIABLES
#include "../../ShaderVariables.hlsl"
#include "../../Material/SubsurfaceScattering/CommonSubsurfaceScattering.hlsl"
#include "HDRP/ShaderVariables.hlsl"
#include "HDRP/Material/DiffusionProfile/DiffusionProfile.hlsl"
//-------------------------------------------------------------------------------------
// Inputs & outputs

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile.meta


fileFormatVersion: 2
guid: 2f0a1a902f8504048ad14c07d71182ff
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Default Diffusion Profile Settings.asset.meta


fileFormatVersion: 2
guid: 404820c4cf36ad944862fa59c56064f0
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

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


// ----------------------------------------------------------------------------
// SSS/Transmittance helper
// ----------------------------------------------------------------------------
// Computes the fraction of light passing through the object.
// 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)
{
// 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;
#if 0
float3 expOneThird = exp(((-1.0 / 3.0) * thickness) * S);
#else
// Help the compiler.
float k = (-1.0 / 3.0) * LOG2_E;
float3 p = (k * thickness) * S;
float3 expOneThird = exp2(p);
#endif
// Premultiply & optimize: T = (1/4 * A) * (e^(-t * S) + 3 * e^(-1/3 * t * S))
return volumeAlbedo * (expOneThird * expOneThird * expOneThird + 3 * expOneThird);
}
// Evaluates transmittance for a linear combination of two normalized 2D Gaussians.
// Ref: Real-Time Realistic Skin Translucency (2010), equation 9 (modified).
// Note: 'volumeAlbedo' should be premultiplied by 0.25, correspondingly 'lerpWeight' by 4,
// 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)
{
// 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;
float t2 = thickness * thickness;
// T = A * lerp(exp(-t2 * halfRcpVariance1), exp(-t2 * halfRcpVariance2), lerpWeight2)
return volumeAlbedo * (exp(-t2 * halfRcpVariance1) * lerpWeight1 + exp(-t2 * halfRcpVariance2) * lerpWeight2);
}

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


using System;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[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 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)
public const int TRANSMISSION_MODE_NONE = 0;
public const int TRANSMISSION_MODE_THIN = 1;
// Old SSS Model >>>
public const int SSS_BASIC_N_SAMPLES = 11; // Must be an odd number
public const int SSS_BASIC_DISTANCE_SCALE = 3; // SSS distance units per centimeter
// <<< Old SSS Model
}
[Serializable]
public sealed class DiffusionProfile
{
public enum TexturingMode : uint
{
PreAndPostScatter = 0,
PostScatter = 1
}
public enum TransmissionMode : uint
{
None = DiffusionProfileConstants.TRANSMISSION_MODE_NONE,
ThinObject = DiffusionProfileConstants.TRANSMISSION_MODE_THIN,
Regular
}
public string name;
[ColorUsage(false, true)]
public Color scatteringDistance; // Per color channel (no meaningful units)
[ColorUsage(false)]
public Color transmissionTint; // Color, 0 to 1
public TexturingMode texturingMode;
public TransmissionMode transmissionMode;
public Vector2 thicknessRemap; // X = min, Y = max (in millimeters)
public float worldScale; // Size of the world unit in meters
public float ior; // 1.4 for skin (mean ~0.028)
// Old SSS Model >>>
[ColorUsage(false, true)]
public Color scatterDistance1;
[ColorUsage(false, true)]
public Color scatterDistance2;
[Range(0f, 1f)]
public float lerpWeight;
// <<< Old SSS Model
public Vector3 shapeParam { get; private set; } // RGB = shape parameter: S = 1 / D
public float maxRadius { get; private set; } // In millimeters
public Vector2[] filterKernelNearField { get; private set; } // X = radius, Y = reciprocal of the PDF
public Vector2[] filterKernelFarField { get; private set; } // X = radius, Y = reciprocal of the PDF
public Vector4 halfRcpWeightedVariances { get; private set; }
public Vector4[] filterKernelBasic { get; private set; }
public DiffusionProfile(string name)
{
this.name = name;
scatteringDistance = Color.grey;
transmissionTint = Color.white;
texturingMode = TexturingMode.PreAndPostScatter;
transmissionMode = TransmissionMode.None;
thicknessRemap = new Vector2(0f, 5f);
worldScale = 1f;
ior = 1.4f; // TYpical value for skin specular reflectance
// Old SSS Model >>>
scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0f);
scatterDistance2 = new Color(0.5f, 0.5f, 0.5f, 0f);
lerpWeight = 1f;
// <<< Old SSS Model
}
public void Validate()
{
thicknessRemap.y = Mathf.Max(thicknessRemap.y, 0f);
thicknessRemap.x = Mathf.Clamp(thicknessRemap.x, 0f, thicknessRemap.y);
worldScale = Mathf.Max(worldScale, 0.001f);
ior = Mathf.Clamp(ior, 1.0f, 2.0f);
// Old SSS Model >>>
scatterDistance1 = new Color
{
r = Mathf.Max(0.05f, scatterDistance1.r),
g = Mathf.Max(0.05f, scatterDistance1.g),
b = Mathf.Max(0.05f, scatterDistance1.b),
a = 0.0f
};
scatterDistance2 = new Color
{
r = Mathf.Max(0.05f, scatterDistance2.r),
g = Mathf.Max(0.05f, scatterDistance2.g),
b = Mathf.Max(0.05f, scatterDistance2.b),
a = 0f
};
// <<< Old SSS Model
UpdateKernel();
}
// Ref: Approximate Reflectance Profiles for Efficient Subsurface Scattering by Pixar.
public void UpdateKernel()
{
if (filterKernelNearField == null || filterKernelNearField.Length != DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD)
filterKernelNearField = new Vector2[DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD];
if (filterKernelFarField == null || filterKernelFarField.Length != DiffusionProfileConstants.SSS_N_SAMPLES_FAR_FIELD)
filterKernelFarField = new Vector2[DiffusionProfileConstants.SSS_N_SAMPLES_FAR_FIELD];
// Clamp to avoid artifacts.
shapeParam = new Vector3(
1f / Mathf.Max(0.001f, scatteringDistance.r),
1f / Mathf.Max(0.001f, scatteringDistance.g),
1f / Mathf.Max(0.001f, scatteringDistance.b)
);
// We importance sample the color channel with the widest scattering distance.
float s = Mathf.Min(shapeParam.x, shapeParam.y, shapeParam.z);
// Importance sample the normalized diffuse reflectance profile for the computed value of 's'.
// ------------------------------------------------------------------------------------
// R[r, phi, s] = s * (Exp[-r * s] + Exp[-r * s / 3]) / (8 * Pi * r)
// PDF[r, phi, s] = r * R[r, phi, s]
// CDF[r, s] = 1 - 1/4 * Exp[-r * s] - 3/4 * Exp[-r * s / 3]
// ------------------------------------------------------------------------------------
// Importance sample the near field kernel.
for (int i = 0, n = DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD; i < n; i++)
{
float p = (i + 0.5f) * (1f / n);
float r = DisneyProfileCdfInverse(p, s);
// N.b.: computation of normalized weights, and multiplication by the surface albedo
// of the actual geometry is performed at runtime (in the shader).
filterKernelNearField[i].x = r;
filterKernelNearField[i].y = 1f / DisneyProfilePdf(r, s);
}
// Importance sample the far field kernel.
for (int i = 0, n = DiffusionProfileConstants.SSS_N_SAMPLES_FAR_FIELD; i < n; i++)
{
float p = (i + 0.5f) * (1f / n);
float r = DisneyProfileCdfInverse(p, s);
// N.b.: computation of normalized weights, and multiplication by the surface albedo
// of the actual geometry is performed at runtime (in the shader).
filterKernelFarField[i].x = r;
filterKernelFarField[i].y = 1f / DisneyProfilePdf(r, s);
}
maxRadius = filterKernelFarField[DiffusionProfileConstants.SSS_N_SAMPLES_FAR_FIELD - 1].x;
// Old SSS Model >>>
UpdateKernelAndVarianceData();
// <<< Old SSS Model
}
// Old SSS Model >>>
public void UpdateKernelAndVarianceData()
{
const int kNumSamples = DiffusionProfileConstants.SSS_BASIC_N_SAMPLES;
const int kDistanceScale = DiffusionProfileConstants.SSS_BASIC_DISTANCE_SCALE;
if (filterKernelBasic == null || filterKernelBasic.Length != kNumSamples)
filterKernelBasic = new Vector4[kNumSamples];
// Apply the three-sigma rule, and rescale.
var stdDev1 = ((1f / 3f) * kDistanceScale) * scatterDistance1;
var stdDev2 = ((1f / 3f) * kDistanceScale) * scatterDistance2;
// Our goal is to blur the image using a filter which is represented
// as a product of a linear combination of two normalized 1D Gaussians
// as suggested by Jimenez et al. in "Separable Subsurface Scattering".
// A normalized (i.e. energy-preserving) 1D Gaussian with the mean of 0
// is defined as follows: G1(x, v) = exp(-x * x / (2 * v)) / sqrt(2 * Pi * v),
// where 'v' is variance and 'x' is the radial distance from the origin.
// Using the weight 'w', our 1D and the resulting 2D filters are given as:
// A1(v1, v2, w, x) = G1(x, v1) * (1 - w) + G1(r, v2) * w,
// A2(v1, v2, w, x, y) = A1(v1, v2, w, x) * A1(v1, v2, w, y).
// The resulting filter function is a non-Gaussian PDF.
// It is separable by design, but generally not radially symmetric.
// N.b.: our scattering distance is rather limited. Therefore, in order to allow
// for a greater range of standard deviation values for flatter profiles,
// we rescale the world using 'distanceScale', effectively reducing the SSS
// distance units from centimeters to (1 / distanceScale).
// Find the widest Gaussian across 3 color channels.
float maxStdDev1 = Mathf.Max(stdDev1.r, stdDev1.g, stdDev1.b);
float maxStdDev2 = Mathf.Max(stdDev2.r, stdDev2.g, stdDev2.b);
var weightSum = Vector3.zero;
float step = 1f / (kNumSamples - 1);
// Importance sample the linear combination of two Gaussians.
for (int i = 0; i < kNumSamples; i++)
{
// Generate 'u' on (0, 0.5] and (0.5, 1).
float u = (i <= kNumSamples / 2) ? 0.5f - i * step // The center and to the left
: i * step; // From the center to the right
u = Mathf.Clamp(u, 0.001f, 0.999f);
float pos = GaussianCombinationCdfInverse(u, maxStdDev1, maxStdDev2, lerpWeight);
float pdf = GaussianCombination(pos, maxStdDev1, maxStdDev2, lerpWeight);
Vector3 val;
val.x = GaussianCombination(pos, stdDev1.r, stdDev2.r, lerpWeight);
val.y = GaussianCombination(pos, stdDev1.g, stdDev2.g, lerpWeight);
val.z = GaussianCombination(pos, stdDev1.b, stdDev2.b, lerpWeight);
// We do not divide by 'numSamples' since we will renormalize, anyway.
filterKernelBasic[i].x = val.x * (1 / pdf);
filterKernelBasic[i].y = val.y * (1 / pdf);
filterKernelBasic[i].z = val.z * (1 / pdf);
filterKernelBasic[i].w = pos;
weightSum.x += filterKernelBasic[i].x;
weightSum.y += filterKernelBasic[i].y;
weightSum.z += filterKernelBasic[i].z;
}
// Renormalize the weights to conserve energy.
for (int i = 0; i < kNumSamples; i++)
{
filterKernelBasic[i].x *= 1 / weightSum.x;
filterKernelBasic[i].y *= 1 / weightSum.y;
filterKernelBasic[i].z *= 1 / weightSum.z;
}
Vector4 weightedStdDev;
weightedStdDev.x = Mathf.Lerp(stdDev1.r, stdDev2.r, lerpWeight);
weightedStdDev.y = Mathf.Lerp(stdDev1.g, stdDev2.g, lerpWeight);
weightedStdDev.z = Mathf.Lerp(stdDev1.b, stdDev2.b, lerpWeight);
weightedStdDev.w = Mathf.Lerp(maxStdDev1, maxStdDev2, lerpWeight);
// Store (1 / (2 * WeightedVariance)) per color channel.
// Warning: do not use halfRcpWeightedVariances.Set(). It will not work.
halfRcpWeightedVariances = new Vector4(0.5f / (weightedStdDev.x * weightedStdDev.x),
0.5f / (weightedStdDev.y * weightedStdDev.y),
0.5f / (weightedStdDev.z * weightedStdDev.z),
0.5f / (weightedStdDev.w * weightedStdDev.w));
}
// <<< Old SSS Model
static float DisneyProfile(float r, float s)
{
return s * (Mathf.Exp(-r * s) + Mathf.Exp(-r * s * (1.0f / 3.0f))) / (8.0f * Mathf.PI * r);
}
static float DisneyProfilePdf(float r, float s)
{
return r * DisneyProfile(r, s);
}
static float DisneyProfileCdf(float r, float s)
{
return 1.0f - 0.25f * Mathf.Exp(-r * s) - 0.75f * Mathf.Exp(-r * s * (1.0f / 3.0f));
}
static float DisneyProfileCdfDerivative1(float r, float s)
{
return 0.25f * s * Mathf.Exp(-r * s) * (1.0f + Mathf.Exp(r * s * (2.0f / 3.0f)));
}
static float DisneyProfileCdfDerivative2(float r, float s)
{
return (-1.0f / 12.0f) * s * s * Mathf.Exp(-r * s) * (3.0f + Mathf.Exp(r * s * (2.0f / 3.0f)));
}
// The CDF is not analytically invertible, so we use Halley's Method of root finding.
// { f(r, s, p) = CDF(r, s) - p = 0 } with the initial guess { r = (10^p - 1) / s }.
static float DisneyProfileCdfInverse(float p, float s)
{
// Supply the initial guess.
float r = (Mathf.Pow(10f, p) - 1f) / s;
float t = float.MaxValue;
while (true)
{
float f0 = DisneyProfileCdf(r, s) - p;
float f1 = DisneyProfileCdfDerivative1(r, s);
float f2 = DisneyProfileCdfDerivative2(r, s);
float dr = f0 / (f1 * (1f - f0 * f2 / (2f * f1 * f1)));
if (Mathf.Abs(dr) < t)
{
r = r - dr;
t = Mathf.Abs(dr);
}
else
{
// Converged to the best result.
break;
}
}
return r;
}
// Old SSS Model >>>
static float Gaussian(float x, float stdDev)
{
float variance = stdDev * stdDev;
return Mathf.Exp(-x * x / (2 * variance)) / Mathf.Sqrt(2 * Mathf.PI * variance);
}
static float GaussianCombination(float x, float stdDev1, float stdDev2, float lerpWeight)
{
return Mathf.Lerp(Gaussian(x, stdDev1), Gaussian(x, stdDev2), lerpWeight);
}
static float RationalApproximation(float t)
{
// Abramowitz and Stegun formula 26.2.23.
// The absolute value of the error should be less than 4.5 e-4.
float[] c = { 2.515517f, 0.802853f, 0.010328f };
float[] d = { 1.432788f, 0.189269f, 0.001308f };
return t - ((c[2] * t + c[1]) * t + c[0]) / (((d[2] * t + d[1]) * t + d[0]) * t + 1.0f);
}
// Ref: https://www.johndcook.com/blog/csharp_phi_inverse/
static float NormalCdfInverse(float p, float stdDev)
{
float x;
if (p < 0.5)
{
// F^-1(p) = - G^-1(p)
x = -RationalApproximation(Mathf.Sqrt(-2f * Mathf.Log(p)));
}
else
{
// F^-1(p) = G^-1(1-p)
x = RationalApproximation(Mathf.Sqrt(-2f * Mathf.Log(1f - p)));
}
return x * stdDev;
}
static float GaussianCombinationCdfInverse(float p, float stdDev1, float stdDev2, float lerpWeight)
{
return Mathf.Lerp(NormalCdfInverse(p, stdDev1), NormalCdfInverse(p, stdDev2), lerpWeight);
}
// <<< Old SSS Model
}
public sealed class DiffusionProfileSettings : ScriptableObject
{
public DiffusionProfile[] profiles;
[NonSerialized] public uint texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
[NonSerialized] public uint transmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
[NonSerialized] public Vector4[] thicknessRemaps; // Remap: 0 = start, 1 = end - start
[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[] filterKernels; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
// Old SSS Model >>>
[NonSerialized] public Vector4[] halfRcpWeightedVariances;
[NonSerialized] public Vector4[] halfRcpVariancesAndWeights;
[NonSerialized] public Vector4[] filterKernelsBasic;
// <<< Old SSS Model
public DiffusionProfile this[int index]
{
get
{
if (index >= DiffusionProfileConstants.DIFFUSION_N_PROFILES - 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;
if (profiles != null && profiles.Length != profileArraySize)
Array.Resize(ref profiles, profileArraySize);
if (profiles == null)
profiles = new DiffusionProfile[profileArraySize];
for (int i = 0; i < profileArraySize; i++)
{
if (profiles[i] == null)
profiles[i] = new DiffusionProfile("Profile " + (i + 1));
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);
// Old SSS Model >>>
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);
Debug.Assert(DiffusionProfileConstants.DIFFUSION_NEUTRAL_PROFILE_ID < 16, "Transmission flags (32-bit integer) cannot support more than 16 profiles (2 bits per profile).");
UpdateCache();
}
static void ValidateArray<T>(ref T[] array, int len)
{
if (array == null || array.Length != len)
array = new T[len];
}
public void UpdateCache()
{
for (int i = 0; i < DiffusionProfileConstants.DIFFUSION_N_PROFILES - 1; i++)
{
UpdateCache(i);
}
// Fill the neutral profile.
int neutralId = DiffusionProfileConstants.DIFFUSION_NEUTRAL_PROFILE_ID;
worldScales[neutralId] = Vector4.one;
shapeParams[neutralId] = Vector4.zero;
for (int j = 0, n = DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * neutralId + j].x = 0f;
filterKernels[n * neutralId + j].y = 1f;
filterKernels[n * neutralId + j].z = 0f;
filterKernels[n * neutralId + j].w = 1f;
}
// Old SSS Model >>>
halfRcpWeightedVariances[neutralId] = Vector4.one;
for (int j = 0, n = DiffusionProfileConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * neutralId + j] = Vector4.one;
filterKernelsBasic[n * neutralId + j].w = 0f;
}
// <<< Old SSS Model
}
public void UpdateCache(int p)
{
// 'p' is the profile array index. 'i' is the index in the shader (accounting for the neutral profile).
int i = p + 1;
// Erase previous value (This need to be done here individually as in the SSS editor we edit individual component)
uint mask = 1u << i;
texturingModeFlags &= ~mask;
mask = 3u << i * 2;
transmissionFlags &= ~mask;
texturingModeFlags |= (uint)profiles[p].texturingMode << i;
transmissionFlags |= (uint)profiles[p].transmissionMode << i * 2;
thicknessRemaps[i] = new Vector4(profiles[p].thicknessRemap.x, profiles[p].thicknessRemap.y - profiles[p].thicknessRemap.x, 0f, 0f);
worldScales[i] = new Vector4(profiles[p].worldScale, 1.0f / profiles[p].worldScale, 0f, 0f);
shapeParams[i] = profiles[p].shapeParam;
shapeParams[i].w = profiles[p].maxRadius;
// Convert ior to fresnel0
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
for (int j = 0, n = DiffusionProfileConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * i + j].x = profiles[p].filterKernelNearField[j].x;
filterKernels[n * i + j].y = profiles[p].filterKernelNearField[j].y;
if (j < DiffusionProfileConstants.SSS_N_SAMPLES_FAR_FIELD)
{
filterKernels[n * i + j].z = profiles[p].filterKernelFarField[j].x;
filterKernels[n * i + j].w = profiles[p].filterKernelFarField[j].y;
}
}
// Old SSS Model >>>
halfRcpWeightedVariances[i] = profiles[p].halfRcpWeightedVariances;
var stdDev1 = ((1f / 3f) * DiffusionProfileConstants.SSS_BASIC_DISTANCE_SCALE) * (Vector4)profiles[p].scatterDistance1;
var stdDev2 = ((1f / 3f) * DiffusionProfileConstants.SSS_BASIC_DISTANCE_SCALE) * (Vector4)profiles[p].scatterDistance2;
// Multiply by 0.1 to convert from millimeters to centimeters. Apply the distance scale.
// Rescale by 4 to counter rescaling of transmission tints.
float a = 0.1f * DiffusionProfileConstants.SSS_BASIC_DISTANCE_SCALE;
halfRcpVariancesAndWeights[2 * i + 0] = new Vector4(a * a * 0.5f / (stdDev1.x * stdDev1.x), a * a * 0.5f / (stdDev1.y * stdDev1.y), a * a * 0.5f / (stdDev1.z * stdDev1.z), 4f * (1f - profiles[p].lerpWeight));
halfRcpVariancesAndWeights[2 * i + 1] = new Vector4(a * a * 0.5f / (stdDev2.x * stdDev2.x), a * a * 0.5f / (stdDev2.y * stdDev2.y), a * a * 0.5f / (stdDev2.z * stdDev2.z), 4f * profiles[p].lerpWeight);
for (int j = 0, n = DiffusionProfileConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * i + j] = profiles[p].filterKernelBasic[j];
}
// <<< Old SSS Model
}
}
}

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


//
// This file was automatically generated. Please don't edit by hand.
//
#ifndef DIFFUSIONPROFILESETTINGS_CS_HLSL
#define DIFFUSIONPROFILESETTINGS_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.DiffusionProfileConstants: static fields
//
#define DIFFUSION_N_PROFILES (16)
#define DIFFUSION_NEUTRAL_PROFILE_ID (0)
#define SSS_N_SAMPLES_NEAR_FIELD (55)
#define SSS_N_SAMPLES_FAR_FIELD (21)
#define SSS_LOD_THRESHOLD (4)
#define TRANSMISSION_MODE_NONE (0)
#define TRANSMISSION_MODE_THIN (1)
#define SSS_BASIC_N_SAMPLES (11)
#define SSS_BASIC_DISTANCE_SCALE (3)
#endif

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/SubsurfaceScattering.meta


fileFormatVersion: 2
guid: fb3f658c087068440b2c5063fc3abaed
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

61
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/CommonSubsurfaceScattering.hlsl


// ----------------------------------------------------------------------------
// SSS/Transmittance helper
// ----------------------------------------------------------------------------
// Computes the fraction of light passing through the object.
// 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)
{
// 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;
#if 0
float3 expOneThird = exp(((-1.0 / 3.0) * thickness) * S);
#else
// Help the compiler.
float k = (-1.0 / 3.0) * LOG2_E;
float3 p = (k * thickness) * S;
float3 expOneThird = exp2(p);
#endif
// Premultiply & optimize: T = (1/4 * A) * (e^(-t * S) + 3 * e^(-1/3 * t * S))
return volumeAlbedo * (expOneThird * expOneThird * expOneThird + 3 * expOneThird);
}
// Evaluates transmittance for a linear combination of two normalized 2D Gaussians.
// Ref: Real-Time Realistic Skin Translucency (2010), equation 9 (modified).
// Note: 'volumeAlbedo' should be premultiplied by 0.25, correspondingly 'lerpWeight' by 4,
// and 'halfRcpVariance1' should be prescaled by (0.1 * SssConstants.SSS_BASIC_DISTANCE_SCALE)^2.
float3 ComputeTransmittanceJimenez(float3 halfRcpVariance1, float lerpWeight1,
float3 halfRcpVariance2, float lerpWeight2,
float3 volumeAlbedo, float thickness, float radiusScale)
{
// 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;
float t2 = thickness * thickness;
// T = A * lerp(exp(-t2 * halfRcpVariance1), exp(-t2 * halfRcpVariance2), lerpWeight2)
return volumeAlbedo * (exp(-t2 * halfRcpVariance1) * lerpWeight1 + exp(-t2 * halfRcpVariance2) * lerpWeight2);
}
// In order to support subsurface scattering, we need to know which pixels have an SSS material.
// It can be accomplished by reading the stencil buffer.
// A faster solution (which avoids an extra texture fetch) is to simply make sure that
// all pixels which belong to an SSS material are not black (those that don't always are).
// We choose the blue color channel since it's perceptually the least noticeable.
float3 TagLightingForSSS(float3 subsurfaceLighting)
{
subsurfaceLighting.b = max(subsurfaceLighting.b, HALF_MIN);
return subsurfaceLighting;
}
// See TagLightingForSSS() for details.
bool TestLightingForSSS(float3 subsurfaceLighting)
{
return subsurfaceLighting.b > 0;
}

21
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringSettings.cs.hlsl


//
// This file was automatically generated. Please don't edit by hand.
//
#ifndef SUBSURFACESCATTERINGSETTINGS_CS_HLSL
#define SUBSURFACESCATTERINGSETTINGS_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.SssConstants: static fields
//
#define SSS_N_PROFILES (16)
#define SSS_NEUTRAL_PROFILE_ID (0)
#define SSS_N_SAMPLES_NEAR_FIELD (55)
#define SSS_N_SAMPLES_FAR_FIELD (21)
#define SSS_LOD_THRESHOLD (4)
#define SSS_TRSM_MODE_NONE (0)
#define SSS_TRSM_MODE_THIN (1)
#define SSS_BASIC_N_SAMPLES (11)
#define SSS_BASIC_DISTANCE_SCALE (3)
#endif

513
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringSettings.cs


using System;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[GenerateHLSL]
public class SssConstants
{
public const int SSS_N_PROFILES = 16; // Max. number of profiles, including the slot taken by the neutral profile
public const int SSS_NEUTRAL_PROFILE_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)
public const int SSS_TRSM_MODE_NONE = 0;
public const int SSS_TRSM_MODE_THIN = 1;
// Old SSS Model >>>
public const int SSS_BASIC_N_SAMPLES = 11; // Must be an odd number
public const int SSS_BASIC_DISTANCE_SCALE = 3; // SSS distance units per centimeter
// <<< Old SSS Model
}
[Serializable]
public sealed class SubsurfaceScatteringProfile
{
public enum TexturingMode : uint
{
PreAndPostScatter = 0,
PostScatter = 1
}
public enum TransmissionMode : uint
{
None = SssConstants.SSS_TRSM_MODE_NONE,
ThinObject = SssConstants.SSS_TRSM_MODE_THIN,
Regular
}
public string name;
[ColorUsage(false, true)]
public Color scatteringDistance; // Per color channel (no meaningful units)
[ColorUsage(false)]
public Color transmissionTint; // Color, 0 to 1
public TexturingMode texturingMode;
public TransmissionMode transmissionMode;
public Vector2 thicknessRemap; // X = min, Y = max (in millimeters)
public float worldScale; // Size of the world unit in meters
public float fresnel0; // Fresnel0, 0.028 for skin
// Old SSS Model >>>
[ColorUsage(false, true)]
public Color scatterDistance1;
[ColorUsage(false, true)]
public Color scatterDistance2;
[Range(0f, 1f)]
public float lerpWeight;
// <<< Old SSS Model
public Vector3 shapeParam { get; private set; } // RGB = shape parameter: S = 1 / D
public float maxRadius { get; private set; } // In millimeters
public Vector2[] filterKernelNearField { get; private set; } // X = radius, Y = reciprocal of the PDF
public Vector2[] filterKernelFarField { get; private set; } // X = radius, Y = reciprocal of the PDF
public Vector4 halfRcpWeightedVariances { get; private set; }
public Vector4[] filterKernelBasic { get; private set; }
public SubsurfaceScatteringProfile(string name)
{
this.name = name;
scatteringDistance = Color.grey;
transmissionTint = Color.white;
texturingMode = TexturingMode.PreAndPostScatter;
transmissionMode = TransmissionMode.None;
thicknessRemap = new Vector2(0f, 5f);
worldScale = 1f;
fresnel0 = 0.028f; // TYpical value for skin specular reflectance
// Old SSS Model >>>
scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0f);
scatterDistance2 = new Color(0.5f, 0.5f, 0.5f, 0f);
lerpWeight = 1f;
// <<< Old SSS Model
}
public void Validate()
{
thicknessRemap.y = Mathf.Max(thicknessRemap.y, 0f);
thicknessRemap.x = Mathf.Clamp(thicknessRemap.x, 0f, thicknessRemap.y);
worldScale = Mathf.Max(worldScale, 0.001f);
fresnel0 = Mathf.Clamp(fresnel0, 0.0f, 0.1f);
// Old SSS Model >>>
scatterDistance1 = new Color
{
r = Mathf.Max(0.05f, scatterDistance1.r),
g = Mathf.Max(0.05f, scatterDistance1.g),
b = Mathf.Max(0.05f, scatterDistance1.b),
a = 0.0f
};
scatterDistance2 = new Color
{
r = Mathf.Max(0.05f, scatterDistance2.r),
g = Mathf.Max(0.05f, scatterDistance2.g),
b = Mathf.Max(0.05f, scatterDistance2.b),
a = 0f
};
// <<< Old SSS Model
UpdateKernel();
}
// Ref: Approximate Reflectance Profiles for Efficient Subsurface Scattering by Pixar.
public void UpdateKernel()
{
if (filterKernelNearField == null || filterKernelNearField.Length != SssConstants.SSS_N_SAMPLES_NEAR_FIELD)
filterKernelNearField = new Vector2[SssConstants.SSS_N_SAMPLES_NEAR_FIELD];
if (filterKernelFarField == null || filterKernelFarField.Length != SssConstants.SSS_N_SAMPLES_FAR_FIELD)
filterKernelFarField = new Vector2[SssConstants.SSS_N_SAMPLES_FAR_FIELD];
// Clamp to avoid artifacts.
shapeParam = new Vector3(
1f / Mathf.Max(0.001f, scatteringDistance.r),
1f / Mathf.Max(0.001f, scatteringDistance.g),
1f / Mathf.Max(0.001f, scatteringDistance.b)
);
// We importance sample the color channel with the widest scattering distance.
float s = Mathf.Min(shapeParam.x, shapeParam.y, shapeParam.z);
// Importance sample the normalized diffuse reflectance profile for the computed value of 's'.
// ------------------------------------------------------------------------------------
// R[r, phi, s] = s * (Exp[-r * s] + Exp[-r * s / 3]) / (8 * Pi * r)
// PDF[r, phi, s] = r * R[r, phi, s]
// CDF[r, s] = 1 - 1/4 * Exp[-r * s] - 3/4 * Exp[-r * s / 3]
// ------------------------------------------------------------------------------------
// Importance sample the near field kernel.
for (int i = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; i < n; i++)
{
float p = (i + 0.5f) * (1f / n);
float r = DisneyProfileCdfInverse(p, s);
// N.b.: computation of normalized weights, and multiplication by the surface albedo
// of the actual geometry is performed at runtime (in the shader).
filterKernelNearField[i].x = r;
filterKernelNearField[i].y = 1f / DisneyProfilePdf(r, s);
}
// Importance sample the far field kernel.
for (int i = 0, n = SssConstants.SSS_N_SAMPLES_FAR_FIELD; i < n; i++)
{
float p = (i + 0.5f) * (1f / n);
float r = DisneyProfileCdfInverse(p, s);
// N.b.: computation of normalized weights, and multiplication by the surface albedo
// of the actual geometry is performed at runtime (in the shader).
filterKernelFarField[i].x = r;
filterKernelFarField[i].y = 1f / DisneyProfilePdf(r, s);
}
maxRadius = filterKernelFarField[SssConstants.SSS_N_SAMPLES_FAR_FIELD - 1].x;
// Old SSS Model >>>
UpdateKernelAndVarianceData();
// <<< Old SSS Model
}
// Old SSS Model >>>
public void UpdateKernelAndVarianceData()
{
const int kNumSamples = SssConstants.SSS_BASIC_N_SAMPLES;
const int kDistanceScale = SssConstants.SSS_BASIC_DISTANCE_SCALE;
if (filterKernelBasic == null || filterKernelBasic.Length != kNumSamples)
filterKernelBasic = new Vector4[kNumSamples];
// Apply the three-sigma rule, and rescale.
var stdDev1 = ((1f / 3f) * kDistanceScale) * scatterDistance1;
var stdDev2 = ((1f / 3f) * kDistanceScale) * scatterDistance2;
// Our goal is to blur the image using a filter which is represented
// as a product of a linear combination of two normalized 1D Gaussians
// as suggested by Jimenez et al. in "Separable Subsurface Scattering".
// A normalized (i.e. energy-preserving) 1D Gaussian with the mean of 0
// is defined as follows: G1(x, v) = exp(-x * x / (2 * v)) / sqrt(2 * Pi * v),
// where 'v' is variance and 'x' is the radial distance from the origin.
// Using the weight 'w', our 1D and the resulting 2D filters are given as:
// A1(v1, v2, w, x) = G1(x, v1) * (1 - w) + G1(r, v2) * w,
// A2(v1, v2, w, x, y) = A1(v1, v2, w, x) * A1(v1, v2, w, y).
// The resulting filter function is a non-Gaussian PDF.
// It is separable by design, but generally not radially symmetric.
// N.b.: our scattering distance is rather limited. Therefore, in order to allow
// for a greater range of standard deviation values for flatter profiles,
// we rescale the world using 'distanceScale', effectively reducing the SSS
// distance units from centimeters to (1 / distanceScale).
// Find the widest Gaussian across 3 color channels.
float maxStdDev1 = Mathf.Max(stdDev1.r, stdDev1.g, stdDev1.b);
float maxStdDev2 = Mathf.Max(stdDev2.r, stdDev2.g, stdDev2.b);
var weightSum = Vector3.zero;
float step = 1f / (kNumSamples - 1);
// Importance sample the linear combination of two Gaussians.
for (int i = 0; i < kNumSamples; i++)
{
// Generate 'u' on (0, 0.5] and (0.5, 1).
float u = (i <= kNumSamples / 2) ? 0.5f - i * step // The center and to the left
: i * step; // From the center to the right
u = Mathf.Clamp(u, 0.001f, 0.999f);
float pos = GaussianCombinationCdfInverse(u, maxStdDev1, maxStdDev2, lerpWeight);
float pdf = GaussianCombination(pos, maxStdDev1, maxStdDev2, lerpWeight);
Vector3 val;
val.x = GaussianCombination(pos, stdDev1.r, stdDev2.r, lerpWeight);
val.y = GaussianCombination(pos, stdDev1.g, stdDev2.g, lerpWeight);
val.z = GaussianCombination(pos, stdDev1.b, stdDev2.b, lerpWeight);
// We do not divide by 'numSamples' since we will renormalize, anyway.
filterKernelBasic[i].x = val.x * (1 / pdf);
filterKernelBasic[i].y = val.y * (1 / pdf);
filterKernelBasic[i].z = val.z * (1 / pdf);
filterKernelBasic[i].w = pos;
weightSum.x += filterKernelBasic[i].x;
weightSum.y += filterKernelBasic[i].y;
weightSum.z += filterKernelBasic[i].z;
}
// Renormalize the weights to conserve energy.
for (int i = 0; i < kNumSamples; i++)
{
filterKernelBasic[i].x *= 1 / weightSum.x;
filterKernelBasic[i].y *= 1 / weightSum.y;
filterKernelBasic[i].z *= 1 / weightSum.z;
}
Vector4 weightedStdDev;
weightedStdDev.x = Mathf.Lerp(stdDev1.r, stdDev2.r, lerpWeight);
weightedStdDev.y = Mathf.Lerp(stdDev1.g, stdDev2.g, lerpWeight);
weightedStdDev.z = Mathf.Lerp(stdDev1.b, stdDev2.b, lerpWeight);
weightedStdDev.w = Mathf.Lerp(maxStdDev1, maxStdDev2, lerpWeight);
// Store (1 / (2 * WeightedVariance)) per color channel.
// Warning: do not use halfRcpWeightedVariances.Set(). It will not work.
halfRcpWeightedVariances = new Vector4(0.5f / (weightedStdDev.x * weightedStdDev.x),
0.5f / (weightedStdDev.y * weightedStdDev.y),
0.5f / (weightedStdDev.z * weightedStdDev.z),
0.5f / (weightedStdDev.w * weightedStdDev.w));
}
// <<< Old SSS Model
static float DisneyProfile(float r, float s)
{
return s * (Mathf.Exp(-r * s) + Mathf.Exp(-r * s * (1.0f / 3.0f))) / (8.0f * Mathf.PI * r);
}
static float DisneyProfilePdf(float r, float s)
{
return r * DisneyProfile(r, s);
}
static float DisneyProfileCdf(float r, float s)
{
return 1.0f - 0.25f * Mathf.Exp(-r * s) - 0.75f * Mathf.Exp(-r * s * (1.0f / 3.0f));
}
static float DisneyProfileCdfDerivative1(float r, float s)
{
return 0.25f * s * Mathf.Exp(-r * s) * (1.0f + Mathf.Exp(r * s * (2.0f / 3.0f)));
}
static float DisneyProfileCdfDerivative2(float r, float s)
{
return (-1.0f / 12.0f) * s * s * Mathf.Exp(-r * s) * (3.0f + Mathf.Exp(r * s * (2.0f / 3.0f)));
}
// The CDF is not analytically invertible, so we use Halley's Method of root finding.
// { f(r, s, p) = CDF(r, s) - p = 0 } with the initial guess { r = (10^p - 1) / s }.
static float DisneyProfileCdfInverse(float p, float s)
{
// Supply the initial guess.
float r = (Mathf.Pow(10f, p) - 1f) / s;
float t = float.MaxValue;
while (true)
{
float f0 = DisneyProfileCdf(r, s) - p;
float f1 = DisneyProfileCdfDerivative1(r, s);
float f2 = DisneyProfileCdfDerivative2(r, s);
float dr = f0 / (f1 * (1f - f0 * f2 / (2f * f1 * f1)));
if (Mathf.Abs(dr) < t)
{
r = r - dr;
t = Mathf.Abs(dr);
}
else
{
// Converged to the best result.
break;
}
}
return r;
}
// Old SSS Model >>>
static float Gaussian(float x, float stdDev)
{
float variance = stdDev * stdDev;
return Mathf.Exp(-x * x / (2 * variance)) / Mathf.Sqrt(2 * Mathf.PI * variance);
}
static float GaussianCombination(float x, float stdDev1, float stdDev2, float lerpWeight)
{
return Mathf.Lerp(Gaussian(x, stdDev1), Gaussian(x, stdDev2), lerpWeight);
}
static float RationalApproximation(float t)
{
// Abramowitz and Stegun formula 26.2.23.
// The absolute value of the error should be less than 4.5 e-4.
float[] c = { 2.515517f, 0.802853f, 0.010328f };
float[] d = { 1.432788f, 0.189269f, 0.001308f };
return t - ((c[2] * t + c[1]) * t + c[0]) / (((d[2] * t + d[1]) * t + d[0]) * t + 1.0f);
}
// Ref: https://www.johndcook.com/blog/csharp_phi_inverse/
static float NormalCdfInverse(float p, float stdDev)
{
float x;
if (p < 0.5)
{
// F^-1(p) = - G^-1(p)
x = -RationalApproximation(Mathf.Sqrt(-2f * Mathf.Log(p)));
}
else
{
// F^-1(p) = G^-1(1-p)
x = RationalApproximation(Mathf.Sqrt(-2f * Mathf.Log(1f - p)));
}
return x * stdDev;
}
static float GaussianCombinationCdfInverse(float p, float stdDev1, float stdDev2, float lerpWeight)
{
return Mathf.Lerp(NormalCdfInverse(p, stdDev1), NormalCdfInverse(p, stdDev2), lerpWeight);
}
// <<< Old SSS Model
}
public sealed class SubsurfaceScatteringSettings : ScriptableObject
{
public SubsurfaceScatteringProfile[] profiles;
[NonSerialized] public uint texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
[NonSerialized] public uint transmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
[NonSerialized] public Vector4[] thicknessRemaps; // Remap: 0 = start, 1 = end - start
[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[] filterKernels; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
// Old SSS Model >>>
[NonSerialized] public Vector4[] halfRcpWeightedVariances;
[NonSerialized] public Vector4[] halfRcpVariancesAndWeights;
[NonSerialized] public Vector4[] filterKernelsBasic;
// <<< Old SSS Model
public SubsurfaceScatteringProfile this[int index]
{
get
{
if (index >= SssConstants.SSS_N_PROFILES - 1)
throw new IndexOutOfRangeException("index");
return profiles[index];
}
}
void OnEnable()
{
// The neutral profile is not a part of the array.
int profileArraySize = SssConstants.SSS_N_PROFILES - 1;
if (profiles != null && profiles.Length != profileArraySize)
Array.Resize(ref profiles, profileArraySize);
if (profiles == null)
profiles = new SubsurfaceScatteringProfile[profileArraySize];
for (int i = 0; i < profileArraySize; i++)
{
if (profiles[i] == null)
profiles[i] = new SubsurfaceScatteringProfile("Profile " + (i + 1));
profiles[i].Validate();
}
ValidateArray(ref thicknessRemaps, SssConstants.SSS_N_PROFILES);
ValidateArray(ref worldScales, SssConstants.SSS_N_PROFILES);
ValidateArray(ref shapeParams, SssConstants.SSS_N_PROFILES);
ValidateArray(ref transmissionTintsAndFresnel0, SssConstants.SSS_N_PROFILES);
ValidateArray(ref filterKernels, SssConstants.SSS_N_PROFILES * SssConstants.SSS_N_SAMPLES_NEAR_FIELD);
// Old SSS Model >>>
ValidateArray(ref halfRcpWeightedVariances, SssConstants.SSS_N_PROFILES);
ValidateArray(ref halfRcpVariancesAndWeights, SssConstants.SSS_N_PROFILES * 2);
ValidateArray(ref filterKernelsBasic, SssConstants.SSS_N_PROFILES * SssConstants.SSS_BASIC_N_SAMPLES);
Debug.Assert(SssConstants.SSS_NEUTRAL_PROFILE_ID < 16, "Transmission flags (32-bit integer) cannot support more than 16 profiles (2 bits per profile).");
UpdateCache();
}
static void ValidateArray<T>(ref T[] array, int len)
{
if (array == null || array.Length != len)
array = new T[len];
}
public void UpdateCache()
{
for (int i = 0; i < SssConstants.SSS_N_PROFILES - 1; i++)
{
UpdateCache(i);
}
// Fill the neutral profile.
int neutralId = SssConstants.SSS_NEUTRAL_PROFILE_ID;
worldScales[neutralId] = Vector4.one;
shapeParams[neutralId] = Vector4.zero;
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * neutralId + j].x = 0f;
filterKernels[n * neutralId + j].y = 1f;
filterKernels[n * neutralId + j].z = 0f;
filterKernels[n * neutralId + j].w = 1f;
}
// Old SSS Model >>>
halfRcpWeightedVariances[neutralId] = Vector4.one;
for (int j = 0, n = SssConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * neutralId + j] = Vector4.one;
filterKernelsBasic[n * neutralId + j].w = 0f;
}
// <<< Old SSS Model
}
public void UpdateCache(int p)
{
// 'p' is the profile array index. 'i' is the index in the shader (accounting for the neutral profile).
int i = p + 1;
// Erase previous value (This need to be done here individually as in the SSS editor we edit individual component)
uint mask = 1u << i;
texturingModeFlags &= ~mask;
mask = 3u << i * 2;
transmissionFlags &= ~mask;
texturingModeFlags |= (uint)profiles[p].texturingMode << i;
transmissionFlags |= (uint)profiles[p].transmissionMode << i * 2;
thicknessRemaps[i] = new Vector4(profiles[p].thicknessRemap.x, profiles[p].thicknessRemap.y - profiles[p].thicknessRemap.x, 0f, 0f);
worldScales[i] = new Vector4(profiles[p].worldScale, 1.0f / profiles[p].worldScale, 0f, 0f);
shapeParams[i] = profiles[p].shapeParam;
shapeParams[i].w = profiles[p].maxRadius;
transmissionTintsAndFresnel0[i] = new Vector4(profiles[p].transmissionTint.r * 0.25f, profiles[p].transmissionTint.g * 0.25f, profiles[p].transmissionTint.b * 0.25f, profiles[p].fresnel0); // Premultiplied
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * i + j].x = profiles[p].filterKernelNearField[j].x;
filterKernels[n * i + j].y = profiles[p].filterKernelNearField[j].y;
if (j < SssConstants.SSS_N_SAMPLES_FAR_FIELD)
{
filterKernels[n * i + j].z = profiles[p].filterKernelFarField[j].x;
filterKernels[n * i + j].w = profiles[p].filterKernelFarField[j].y;
}
}
// Old SSS Model >>>
halfRcpWeightedVariances[i] = profiles[p].halfRcpWeightedVariances;
var stdDev1 = ((1f / 3f) * SssConstants.SSS_BASIC_DISTANCE_SCALE) * (Vector4)profiles[p].scatterDistance1;
var stdDev2 = ((1f / 3f) * SssConstants.SSS_BASIC_DISTANCE_SCALE) * (Vector4)profiles[p].scatterDistance2;
// Multiply by 0.1 to convert from millimeters to centimeters. Apply the distance scale.
// Rescale by 4 to counter rescaling of transmission tints.
float a = 0.1f * SssConstants.SSS_BASIC_DISTANCE_SCALE;
halfRcpVariancesAndWeights[2 * i + 0] = new Vector4(a * a * 0.5f / (stdDev1.x * stdDev1.x), a * a * 0.5f / (stdDev1.y * stdDev1.y), a * a * 0.5f / (stdDev1.z * stdDev1.z), 4f * (1f - profiles[p].lerpWeight));
halfRcpVariancesAndWeights[2 * i + 1] = new Vector4(a * a * 0.5f / (stdDev2.x * stdDev2.x), a * a * 0.5f / (stdDev2.y * stdDev2.y), a * a * 0.5f / (stdDev2.z * stdDev2.z), 4f * profiles[p].lerpWeight);
for (int j = 0, n = SssConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * i + j] = profiles[p].filterKernelBasic[j];
}
// <<< Old SSS Model
}
}
}

9
ScriptableRenderPipeline/HDRenderPipeline/HDRP/SceneSettings.meta


fileFormatVersion: 2
guid: 1b5e87e98ef1994498478f60a6dcdd65
folderAsset: yes
timeCreated: 1481725797
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/CommonSubsurfaceScattering.hlsl.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfile.hlsl.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringSettings.cs.hlsl.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.hlsl.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScatteringSettings.cs.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile/DiffusionProfileSettings.cs.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SSSProfile.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/DiffusionProfile.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/SubsurfaceScattering/SubsurfaceScatteringSettingsEditor.Styles.cs.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.Styles.cs.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/SubsurfaceScattering/SubsurfaceScatteringSettingsEditor.cs.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/SubsurfaceScattering/SubsurfaceScatteringSettingsEditor.Styles.cs → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.Styles.cs

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/SubsurfaceScattering/SubsurfaceScatteringSettingsEditor.cs → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SSSProfile/SSS Settings.asset → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Default Diffusion Profile Settings.asset

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/SceneSettings/Resources/DrawSssProfile.shader.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawDiffusionProfile.shader.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/SceneSettings/Resources/DrawTransmittanceGraph.shader.meta → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawTransmittanceGraph.shader.meta

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/SceneSettings/Resources/DrawSssProfile.shader → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawDiffusionProfile.shader

/ScriptableRenderPipeline/HDRenderPipeline/HDRP/SceneSettings/Resources/DrawTransmittanceGraph.shader → /ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DrawTransmittanceGraph.shader

正在加载...
取消
保存