浏览代码

Merge pull request #136 from Unity-Technologies/Update-POM-+-Heightmap-behavior

Updating Layered shader
/Branch_Batching2
GitHub 8 年前
当前提交
1b201c94
共有 18 个文件被更改,包括 837 次插入357 次删除
  1. 31
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs
  2. 18
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader
  3. 18
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader
  4. 48
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs
  5. 63
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/LitUI.cs
  6. 24
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.shader
  7. 623
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl
  8. 142
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  9. 6
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl
  10. 20
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitTessellation.hlsl
  11. 3
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitTessellation.shader
  12. 25
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/SampleLayer.hlsl
  13. 20
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/TessellationShare.hlsl
  14. 7
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl
  15. 15
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  16. 17
      Assets/TestScenes/HDTest/GraphicTest/LayeredTessellation/Layer-2-woord-rock.mat
  17. 105
      Assets/ScriptableRenderLoop/ShaderLibrary/PerPixelDisplacement.hlsl
  18. 9
      Assets/ScriptableRenderLoop/ShaderLibrary/PerPixelDisplacement.hlsl.meta

31
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs


MaterialProperty[] heightFactor = new MaterialProperty[kMaxLayerCount];
const string kHeightCenterOffset = "_HeightCenterOffset";
MaterialProperty[] heightCenterOffset = new MaterialProperty[kMaxLayerCount];
const string kLayerHeightAmplitude = "_LayerHeightAmplitude";
MaterialProperty[] layerHeightAmplitude = new MaterialProperty[kMaxLayerCount];
const string kLayerCenterOffset = "_LayerCenterOffset";
MaterialProperty[] layerCenterOffset = new MaterialProperty[kMaxLayerCount];
const string kBlendUsingHeight = "_BlendUsingHeight";
MaterialProperty[] blendUsingHeight = new MaterialProperty[kMaxLayerCount - 1];

opacityAsDensity[i] = FindProperty(string.Format("{0}{1}", kOpacityAsDensity, i), props);
heightFactor[i] = FindProperty(string.Format("{0}{1}", kHeightFactor, i), props);
heightCenterOffset[i] = FindProperty(string.Format("{0}{1}", kHeightCenterOffset, i), props);
layerHeightAmplitude[i] = FindProperty(string.Format("{0}{1}", kLayerHeightAmplitude, i), props);
layerCenterOffset[i] = FindProperty(string.Format("{0}{1}", kLayerCenterOffset, i), props);
if(i != 0)
if (i != 0)
{
blendUsingHeight[i - 1] = FindProperty(string.Format("{0}{1}", kBlendUsingHeight, i), props);
inheritBaseNormal[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseNormal, i), props);

{
warningInputOptions += "Normal Map Space: " + optionValueNames + "\n";
}
if (!CheckInputFloatOptionConsistency(kEnablePerPixelDisplacement, ref optionValueNames))
{
warningInputOptions += "Per pixel displacement: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kDetailMapMode, detailModeShortNames, ref optionValueNames))
{
warningInputOptions += "Detail Map Mode: " + optionValueNames + "\n";

if (!CheckInputMapConsistency(kSpecularOcclusionMap, ref optionValueNames))
{
warningInputMaps += "Specular Occlusion Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kHeightMap, ref optionValueNames))
{
warningInputMaps += "Height Map: " + optionValueNames + "\n";
}
if (warningInputMaps != string.Empty)

{
material.SetFloat(kSmoothnessTextureChannel, firstLayer.GetFloat(kSmoothnessTextureChannel));
material.SetFloat(kNormalMapSpace, firstLayer.GetFloat(kNormalMapSpace));
material.SetFloat(kEnablePerPixelDisplacement, firstLayer.GetFloat(kEnablePerPixelDisplacement));
// Force emissive to be emissive color
material.SetFloat(kEmissiveColorMode, (float)EmissiveColorMode.UseEmissiveColor);
}

EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(heightFactor[layerIndex], styles.heightFactorText);
layerHeightAmplitude[layerIndex].floatValue = material.GetFloat(kHeightAmplitude + layerIndex) * heightFactor[layerIndex].floatValue;
layerCenterOffset[layerIndex].floatValue = material.GetFloat(kHeightCenter + layerIndex) + heightCenterOffset[layerIndex].floatValue;
EditorGUI.indentLevel--;
// influence

SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap + i));
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap + i));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kSpecularOcclusionMap + i));
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap + i));
bool perPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) == 1.0;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", perPixelDisplacement);
SetKeyword(material, "_HEIGHTMAP0", material.GetTexture(kHeightMap + 0));
SetKeyword(material, "_HEIGHTMAP1", material.GetTexture(kHeightMap + 1));
SetKeyword(material, "_HEIGHTMAP2", material.GetTexture(kHeightMap + 2));
SetKeyword(material, "_HEIGHTMAP3", material.GetTexture(kHeightMap + 3));
bool perPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) == 1.0;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", perPixelDisplacement);
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));

18
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader


_HeightFactor2("_HeightFactor2", Float) = 1
_HeightFactor3("_HeightFactor3", Float) = 1
_LayerHeightAmplitude0("_LayerHeightAmplitude0", Float) = 1
_LayerHeightAmplitude1("_LayerHeightAmplitude1", Float) = 1
_LayerHeightAmplitude2("_LayerHeightAmplitude2", Float) = 1
_LayerHeightAmplitude3("_LayerHeightAmplitude3", Float) = 1
_LayerCenterOffset0("_LayerCenterOffset0", Float) = 0.0
_LayerCenterOffset1("_LayerCenterOffset1", Float) = 0.0
_LayerCenterOffset2("_LayerCenterOffset2", Float) = 0.0
_LayerCenterOffset3("_LayerCenterOffset3", Float) = 0.0
_BlendUsingHeight1("_BlendUsingHeight1", Float) = 0.0
_BlendUsingHeight2("_BlendUsingHeight2", Float) = 0.0
_BlendUsingHeight3("_BlendUsingHeight3", Float) = 0.0

[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15
_PPDLodThreshold("Start lod to fade out the POM effect", Range(0.0, 16.0)) = 5
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1

_TexWorldScale2("Tiling", Float) = 1.0
_TexWorldScale3("Tiling", Float) = 1.0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase0("UV Set for base0", Float) = 0
[Enum(UV0, 0, Planar, 4, Triplanar, 5)] _UVBase0("UV Set for base0", Float) = 0 // no UV1/2/3 for main layer (matching Lit.shader and for PPDisplacement restriction)
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase1("UV Set for base1", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase2("UV Set for base2", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase3("UV Set for base3", Float) = 0

#pragma shader_feature _MASKMAP
#pragma shader_feature _SPECULAROCCLUSIONMAP
#pragma shader_feature _EMISSIVE_COLOR_MAP
#pragma shader_feature _HEIGHTMAP
#pragma shader_feature _HEIGHTMAP0
#pragma shader_feature _HEIGHTMAP1
#pragma shader_feature _HEIGHTMAP2
#pragma shader_feature _HEIGHTMAP3
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _ _LAYER_MASK_VERTEX_COLOR_MUL _LAYER_MASK_VERTEX_COLOR_ADD
#pragma shader_feature _MAIN_LAYER_INFLUENCE_MODE

18
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader


_HeightFactor2("_HeightFactor2", Float) = 1
_HeightFactor3("_HeightFactor3", Float) = 1
_LayerHeightAmplitude0("_LayerHeightAmplitude0", Float) = 1
_LayerHeightAmplitude1("_LayerHeightAmplitude1", Float) = 1
_LayerHeightAmplitude2("_LayerHeightAmplitude2", Float) = 1
_LayerHeightAmplitude3("_LayerHeightAmplitude3", Float) = 1
_LayerCenterOffset0("_LayerCenterOffset0", Float) = 0.0
_LayerCenterOffset1("_LayerCenterOffset1", Float) = 0.0
_LayerCenterOffset2("_LayerCenterOffset2", Float) = 0.0
_LayerCenterOffset3("_LayerCenterOffset3", Float) = 0.0
_BlendUsingHeight1("_BlendUsingHeight1", Float) = 0.0
_BlendUsingHeight2("_BlendUsingHeight2", Float) = 0.0
_BlendUsingHeight3("_BlendUsingHeight3", Float) = 0.0

[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15
_PPDLodThreshold("Start lod to fade out the POM effect", Range(0.0, 16.0)) = 5
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1

_TexWorldScale2("Tiling", Float) = 1.0
_TexWorldScale3("Tiling", Float) = 1.0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase0("UV Set for base0", Float) = 0
[Enum(UV0, 0, Planar, 4, Triplanar, 5)] _UVBase0("UV Set for base0", Float) = 0 // no UV1/2/3 for main layer (matching Lit.shader and for PPDisplacement restriction)
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase1("UV Set for base1", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase2("UV Set for base2", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Planar, 4, Triplanar, 5)] _UVBase3("UV Set for base3", Float) = 0

#pragma shader_feature _MASKMAP
#pragma shader_feature _SPECULAROCCLUSIONMAP
#pragma shader_feature _EMISSIVE_COLOR_MAP
#pragma shader_feature _HEIGHTMAP
#pragma shader_feature _HEIGHTMAP0
#pragma shader_feature _HEIGHTMAP1
#pragma shader_feature _HEIGHTMAP2
#pragma shader_feature _HEIGHTMAP3
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _ _LAYER_MASK_VERTEX_COLOR_MUL _LAYER_MASK_VERTEX_COLOR_ADD
#pragma shader_feature _MAIN_LAYER_INFLUENCE_MODE

48
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs


public static GUIContent enablePerPixelDisplacementText = new GUIContent("Enable Per Pixel Displacement", "");
public static GUIContent ppdMinSamplesText = new GUIContent("Minimum samples", "Minimun samples to use with per pixel displacement mapping");
public static GUIContent ppdMaxSamplesText = new GUIContent("Maximum samples", "Maximum samples to use with per pxiel displacement mapping");
public static GUIContent ppdLodThresholdText = new GUIContent("Fading LOD start", "Starting Lod where the parallax occlusion mapping effect start to disappear");
public static GUIContent detailMapModeText = new GUIContent("Detail Map with Normal", "Detail Map with AO / Height");
public static GUIContent UVDetailMappingText = new GUIContent("UV set for Detail", "");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");

public static GUIContent tessellationBackFaceCullEpsilonText = new GUIContent("Triangle culling Epsilon", "If -1.0 back face culling is enabled for tessellation, higher number mean more aggressive culling and better performance");
public static GUIContent tessellationObjectScaleText = new GUIContent("Enable object scale", "Tesselation displacement will take into account the object scale - Only work with uniform positive scale");
public static GUIContent materialIDText = new GUIContent("Material Class", "Subsurface Scattering: enable for translucent materials such as skin, vegetation, fruit, marble, wax and milk.");
public static GUIContent subsurfaceProfileText = new GUIContent("Subsurface scattering profile", "A profile determines the shape of the blur filter.");
public static GUIContent subsurfaceRadiusText = new GUIContent("Subsurface scattering radius", "Determines the range of the blur.");
public static GUIContent subsurfaceRadiusMapText = new GUIContent("Subsurface scattering radius map", "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", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
public static GUIContent perPixelDisplacementText = new GUIContent("Per pixel displacement", "Per pixel displacement options");
public static GUIContent materialIDText = new GUIContent("Material type", "Subsurface Scattering: enable for translucent materials such as skin, vegetation, fruit, marble, wax and milk.");
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", "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", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
}
public enum SurfaceType

m_MaterialEditor.ShaderProperty(tessellationObjectScale, Styles.tessellationObjectScaleText);
EditorGUI.indentLevel--;
}
GUILayout.Label(Styles.perPixelDisplacementText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, Styles.enablePerPixelDisplacementText);
if (enablePerPixelDisplacement.floatValue > 0.0)
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(ppdMinSamples, Styles.ppdMinSamplesText);
m_MaterialEditor.ShaderProperty(ppdMaxSamples, Styles.ppdMaxSamplesText);
ppdMinSamples.floatValue = Mathf.Min(ppdMinSamples.floatValue, ppdMaxSamples.floatValue);
m_MaterialEditor.ShaderProperty(ppdLodThreshold, Styles.ppdLodThresholdText);
EditorGUI.indentLevel--;
}
EditorGUI.indentLevel--;
}
protected void FindCommonOptionProperties(MaterialProperty[] props)

tessellationShapeFactor = FindProperty(kTessellationShapeFactor, props, false);
tessellationBackFaceCullEpsilon = FindProperty(kTessellationBackFaceCullEpsilon, props, false);
tessellationObjectScale = FindProperty(kTessellationObjectScale, props, false);
// Per pixel displacement
enablePerPixelDisplacement = FindProperty(kEnablePerPixelDisplacement, props);
ppdMinSamples = FindProperty(kPpdMinSamples, props);
ppdMaxSamples = FindProperty(kPpdMaxSamples, props);
ppdLodThreshold = FindProperty(kPpdLodThreshold, props);
}
protected void SetupCommonOptionsKeywords(Material material)

const string kTessellationBackFaceCullEpsilon = "_TessellationBackFaceCullEpsilon";
MaterialProperty tessellationObjectScale = null;
const string kTessellationObjectScale = "_TessellationObjectScale";
// Per pixel displacement params
protected MaterialProperty enablePerPixelDisplacement = null;
protected const string kEnablePerPixelDisplacement = "_EnablePerPixelDisplacement";
protected MaterialProperty ppdMinSamples = null;
protected const string kPpdMinSamples = "_PPDMinSamples";
protected MaterialProperty ppdMaxSamples = null;
protected const string kPpdMaxSamples = "_PPDMaxSamples";
protected MaterialProperty ppdLodThreshold = null;
protected const string kPpdLodThreshold = "_PPDLodThreshold";
protected static string[] reservedProperties = new string[] { kSurfaceType, kBlendMode, kAlphaCutoff, kAlphaCutoffEnabled, kDoubleSidedMode };

63
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/LitUI.cs


UseEmissiveMask,
}
public enum MaterialIDType
{
Standard = 0,
SubsurfaceScattering = 1,
ClearCoat = 2,
SpecularColor = 3
}
protected MaterialProperty smoothnessMapChannel = null;
protected const string kSmoothnessTextureChannel = "_SmoothnessTextureChannel";
protected MaterialProperty UVBase = null;

protected const string kUVMappingPlanar = "_UVMappingPlanar";
protected MaterialProperty normalMapSpace = null;
protected const string kNormalMapSpace = "_NormalMapSpace";
protected MaterialProperty enablePerPixelDisplacement = null;
protected const string kEnablePerPixelDisplacement = "_EnablePerPixelDisplacement";
protected MaterialProperty ppdMinSamples = null;
protected const string kPpdMinSamples = "_PPDMinSamples";
protected MaterialProperty ppdMaxSamples = null;
protected const string kPpdMaxSamples = "_PPDMaxSamples";
protected MaterialProperty detailMapMode = null;
protected const string kDetailMapMode = "_DetailMapMode";
protected MaterialProperty UVDetail = null;

protected void FindMaterialOptionProperties(MaterialProperty[] props)
{
smoothnessMapChannel = FindProperty(kSmoothnessTextureChannel, props);
normalMapSpace = FindProperty(kNormalMapSpace, props);
enablePerPixelDisplacement = FindProperty(kEnablePerPixelDisplacement, props);
ppdMinSamples = FindProperty(kPpdMinSamples, props);
ppdMaxSamples = FindProperty(kPpdMaxSamples, props);
normalMapSpace = FindProperty(kNormalMapSpace, props);
detailMapMode = FindProperty(kDetailMapMode, props);
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
}

EditorGUI.indentLevel++;
GUILayout.Label(Styles.InputsOptionsText, EditorStyles.boldLabel);
m_MaterialEditor.ShaderProperty(materialID, Styles.materialIDText);
m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText);
m_MaterialEditor.ShaderProperty(UVBase, enableUVDetail ? Styles.UVBaseDetailMappingText : Styles.UVBaseMappingText);

//m_MaterialEditor.ShaderProperty(detailMapMode, Styles.detailMapModeText);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText);
m_MaterialEditor.ShaderProperty(emissiveColorMode, Styles.emissiveColorModeText);
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, Styles.enablePerPixelDisplacementText);
m_MaterialEditor.ShaderProperty(ppdMinSamples, Styles.ppdMinSamplesText);
m_MaterialEditor.ShaderProperty(ppdMaxSamples, Styles.ppdMaxSamplesText);
ppdMinSamples.floatValue = Mathf.Min(ppdMinSamples.floatValue, ppdMaxSamples.floatValue);
m_MaterialEditor.ShaderProperty(emissiveColorMode, Styles.emissiveColorModeText);
EditorGUI.indentLevel--;
}
m_MaterialEditor.ShaderProperty(materialID, Styles.materialIDText);
m_MaterialEditor.ShaderProperty(subsurfaceProfile, Styles.subsurfaceProfileText);
m_MaterialEditor.ShaderProperty(subsurfaceRadius, Styles.subsurfaceRadiusText);
m_MaterialEditor.ShaderProperty(subsurfaceRadiusMap, Styles.subsurfaceRadiusMapText);
m_MaterialEditor.ShaderProperty(thickness, Styles.thicknessText);
m_MaterialEditor.ShaderProperty(thicknessMap, Styles.thicknessMapText);
protected void ShaderSSSInputGUI()
{
m_MaterialEditor.ShaderProperty(subsurfaceProfile, Styles.subsurfaceProfileText);
m_MaterialEditor.ShaderProperty(subsurfaceRadius, Styles.subsurfaceRadiusText);
m_MaterialEditor.TexturePropertySingleLine(Styles.subsurfaceRadiusMapText, subsurfaceRadiusMap);
m_MaterialEditor.ShaderProperty(thickness, Styles.thicknessText);
m_MaterialEditor.TexturePropertySingleLine(Styles.thicknessMapText, thicknessMap);
}
EditorGUI.indentLevel--;
protected void ShaderStandardInputGUI()
{
m_MaterialEditor.TexturePropertySingleLine(Styles.tangentMapText, tangentMap);
m_MaterialEditor.ShaderProperty(anisotropy, Styles.anisotropyText);
m_MaterialEditor.TexturePropertySingleLine(Styles.anisotropyMapText, anisotropyMap);
}
override protected void ShaderInputGUI()

EditorGUI.indentLevel--;
}
m_MaterialEditor.TexturePropertySingleLine(Styles.tangentMapText, tangentMap);
m_MaterialEditor.ShaderProperty(anisotropy, Styles.anisotropyText);
m_MaterialEditor.TexturePropertySingleLine(Styles.anisotropyMapText, anisotropyMap);
if ((MaterialIDType)materialID.floatValue == MaterialIDType.Standard)
{
ShaderStandardInputGUI();
}
else if ((MaterialIDType)materialID.floatValue == MaterialIDType.SubsurfaceScattering)
{
ShaderSSSInputGUI();
}
EditorGUILayout.Space();
GUILayout.Label(Styles.textureControlText, EditorStyles.label);

24
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.shader


_DetailHeightScale("_DetailHeightScale", Range(-2.0, 2.0)) = 1
_DetailAOScale("_DetailAOScale", Range(-2.0, 2.0)) = 1
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2)] _MaterialID("Material Class", Int) = 0
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2, Specular Color, 3)] _MaterialID("MaterialId", Int) = 0
_SubsurfaceProfile("Subsurface Profile", Int) = 0
_SubsurfaceRadius("Subsurface Radius", Range(0.004, 1.0)) = 0.5
_SubsurfaceRadiusMap("Subsurface Radius Map", 2D) = "white" {}

[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15
_PPDLodThreshold("Start lod to fade out the POM effect", Range(0.0, 16.0)) = 5
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail("UV Set for detail", Float) = 0
[HideInInspector] _UVDetailsMappingMask("_UVDetailsMappingMask", Color) = (1, 0, 0, 0)

#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature _MAPPING_TRIPLANAR
#pragma shader_feature _DETAIL_MAP_WITH_NORMAL
#pragma shader_feature _NORMALMAP_TANGENT_SPACE
#pragma shader_feature _NORMALMAP_TANGENT_SPACE
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
#pragma shader_feature _EMISSIVE_COLOR

#pragma shader_feature _TANGENTMAP
#pragma shader_feature _ANISOTROPYMAP
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _SUBSURFACE_RADIUS_MAP
#pragma shader_feature _SUBSURFACE_RADIUS_MAP
#pragma shader_feature _THICKNESS_MAP
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON

//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON
//-------------------------------------------------------------------------------------
// Define

//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------
#include "common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"

// both direct and indirect lighting) will hand up in the "regular" lightmap->LIGHTMAP_ON.
#define SHADERPASS SHADERPASS_LIGHT_TRANSPORT
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitMetaPass.hlsl"
#include "LitData.hlsl"
#include "../../ShaderPass/ShaderPassLightTransport.hlsl"

Cull[_CullMode]
ZWrite On
ZWrite On
ZTest LEqual
HLSLPROGRAM

Cull[_CullMode]
ZWrite On
ZWrite On
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitDepthPass.hlsl"
#include "LitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"

HLSLPROGRAM
#define SHADERPASS SHADERPASS_VELOCITY
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitVelocityPass.hlsl"
#include "LitData.hlsl"
#include "../../ShaderPass/ShaderPassVelocity.hlsl"

ENDHLSL
}
}
CustomEditor "Experimental.Rendering.HDPipeline.LitGUI"

623
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl


#endif
// triplanar weight
float3 weights;
float3 triplanarWeights;
};
#ifndef LAYERED_LIT_SHADER

{
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
bool isTriplanar = false;
layerTexCoord.weights = ComputeTriplanarWeights(normalWS);
layerTexCoord.triplanarWeights = ComputeTriplanarWeights(normalWS);
isTriplanar = true;
// Be sure that the compiler is aware that we don't touch UV1 to UV3 for base layer in case of non layer shader
// so it can remove code
// Be sure that the compiler is aware that we don't touch UV1 to UV3 for main layer so it can optimize code
bool isTriplanar = false;
#ifdef _MAPPING_TRIPLANAR
isTriplanar = true;
#endif
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
float GetMaxDisplacement()
#if defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT)
float maxDisplacement = 0.0;
#if defined(_HEIGHTMAP)
maxDisplacement = _HeightAmplitude;
#endif
return maxDisplacement;
}
// ref: https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
// Change the number of samples per ray depending on the viewing angle for the surface.
// Oblique angles require smaller step sizes to achieve more accurate precision for computing displacement.
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
// Return the minimun uv size for all layers including triplanar
float2 GetMinUvSize(LayerTexCoord layerTexCoord)
{
float2 minUvSize = float2(FLT_MAX, FLT_MAX);
ParallaxOcclusionMappingLayer(layerTexCoord, numSteps, viewDirTS);
#if defined(_HEIGHTMAP)
if (layerTexCoord.base.isTriplanar)
{
minUvSize = min(layerTexCoord.base.uvYZ * _HeightMap_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base.uvZX * _HeightMap_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base.uvXY * _HeightMap_TexelSize.zw, minUvSize);
}
else
{
minUvSize = min(layerTexCoord.base.uv * _HeightMap_TexelSize.zw, minUvSize);
}
#endif
// TODO: We are supposed to modify lightmaps coordinate (fetch in GetBuiltin), but this isn't the same uv mapping, so can't apply the offset here...
// Let's assume it will be "fine" as indirect diffuse is often low frequency
return minUvSize;
}
struct PerPixelHeightDisplacementParam
{
float2 uv;
};
// Calculate displacement for per vertex displacement mapping
float ComputePerPixelHeightDisplacement(float2 texOffsetCurrent, float lod, PerPixelHeightDisplacementParam param)
{
// Note: No multiply by amplitude here. This is include in the maxHeight provide to POM
// Tiling is automatically handled correctly here.
return SAMPLE_TEXTURE2D_LOD(_HeightMap, sampler_HeightMap, param.uv + texOffsetCurrent, lod).r;
}
#include "PerPixelDisplacement.hlsl"
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
bool ppdEnable = false;
bool isPlanar = false;
bool isTriplanar = false;
#if defined(_PER_PIXEL_DISPLACEMENT) && defined(_HEIGHTMAP)
ppdEnable = true;
isPlanar = layerTexCoord.base.isPlanar;
isTriplanar = layerTexCoord.base.isTriplanar;
if (ppdEnable)
{
// See comment in layered version for details
float maxHeight = GetMaxDisplacement();
float2 minUvSize = GetMinUvSize(layerTexCoord);
float lod = ComputeTextureLOD(minUvSize);
PerPixelHeightDisplacementParam ppdParam;
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
// TODO: implement. Require 3 call to POM + dedicated viewDirTS based on triplanar convention
// apply the 3 offset on all layers
/*
ppdParam.uv = layerTexCoord.base0.uvYZ;
float3 viewDirTS = ;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, abs(viewDirTS.z));
ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
(...)
*/
}
else
{
ppdParam.uv = layerTexCoord.base.uv;
// For planar the view vector is the world view vector (unless we want to support object triplanar ? and in this case used TransformWorldToObject)
// TODO: do we support object triplanar ? See ComputeLayerTexCoord
float3 viewDirTS = isPlanar ? float3(-V.xz, V.y) : TransformWorldToTangent(V, input.tangentToWorld);
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
// Apply offset to all UVSet
layerTexCoord.base.uv += offset;
layerTexCoord.details.uv += offset;
}
}
return SampleHeightmapLod(layerTexCoord, lod);
return (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap, sampler_HeightMap, layerTexCoord.base, lod).r - _HeightCenter) * _HeightAmplitude;
}
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)

#undef LAYER_INDEX
#undef ADD_IDX
void ComputeMaskWeights(float4 inputMasks, out float outWeights[_MAX_LAYER])
{
float masks[_MAX_LAYER];
#if defined(_DENSITY_MODE)
masks[0] = inputMasks.a;
#else
masks[0] = 1.0;
#endif
masks[1] = inputMasks.r;
masks[2] = inputMasks.g;
masks[3] = inputMasks.b;
// calculate weight of each layers
// Algorithm is like this:
// Top layer have priority on others layers
// If a top layer doesn't use the full weight, the remaining can be use by the following layer.
float weightsSum = 0.0;
[unroll]
for (int i = _LAYER_COUNT - 1; i >= 0; --i)
{
outWeights[i] = min(masks[i], (1.0 - weightsSum));
weightsSum = saturate(weightsSum + masks[i]);
}
}
float3 BlendLayeredVector3(float3 x0, float3 x1, float3 x2, float3 x3, float weight[4])
{
float3 result = float3(0.0, 0.0, 0.0);

#if defined(_LAYER_MAPPING_TRIPLANAR_0) || defined(_LAYER_MAPPING_TRIPLANAR_1) || defined(_LAYER_MAPPING_TRIPLANAR_2) || defined(_LAYER_MAPPING_TRIPLANAR_3)
// one weight for each direction XYZ - Use vertex normal for triplanar
layerTexCoord.weights = ComputeTriplanarWeights(normalWS);
layerTexCoord.triplanarWeights = ComputeTriplanarWeights(normalWS);
#endif
bool isTriplanar = false;

// Be sure that the compiler is aware that we don't touch UV1 to UV3 for main layer so it can optimize code
_UVMappingMask0.yzw = float3(0.0, 0.0, 0.0);
ComputeLayerTexCoord0( texCoord0, texCoord1, texCoord2, texCoord3,
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling0);

positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling3);
}
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
#if defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT)
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
ParallaxOcclusionMappingLayer0(layerTexCoord, numSteps, viewDirTS);
ParallaxOcclusionMappingLayer1(layerTexCoord, numSteps, viewDirTS);
ParallaxOcclusionMappingLayer2(layerTexCoord, numSteps, viewDirTS);
ParallaxOcclusionMappingLayer3(layerTexCoord, numSteps, viewDirTS);
// Declare the sampler for the heigthmap - Take the sampler of the first valid Heightmap
#if defined(_HEIGHTMAP0)
#define sampler_ShareHeightMap sampler_HeightMap0
#elif defined(_HEIGHTMAP1)
#define sampler_ShareHeightMap sampler_HeightMap1
#elif defined(_HEIGHTMAP2)
#define sampler_ShareHeightMap sampler_HeightMap2
#elif defined(_HEIGHTMAP3)
#define sampler_ShareHeightMap sampler_HeightMap3
}
float3 ComputeMainNormalInfluence(FragInputs input, float3 normalTS0, float3 normalTS1, float3 normalTS2, float3 normalTS3, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
// This function is just syntaxic sugar to nullify height not used based on heightmap avaibility and layer
void SetEnabledHeightByLayer(inout float height0, inout float height1, inout float height2, inout float height3)
// Get our regular normal from regular layering
float3 normalTS = BlendLayeredVector3(normalTS0, normalTS1, normalTS2, normalTS3, weights);
#ifndef _HEIGHTMAP0
height0 = 0.0;
#endif
#ifndef _HEIGHTMAP1
height1 = 0.0;
#endif
#ifndef _HEIGHTMAP2
height2 = 0.0;
#endif
#ifndef _HEIGHTMAP3
height3 = 0.0;
#endif
// THen get Main Layer Normal influence factor. Main layer is 0 because it can't be influence. In this case the final lerp return normalTS.
float influenceFactor = BlendLayeredScalar(0.0, _InheritBaseNormal1, _InheritBaseNormal2, _InheritBaseNormal3, weights);
// We will add smoothly the contribution of the normal map by using lower mips with help of bias sampling. InfluenceFactor must be [0..numMips] // Caution it cause banding...
// Note: that we don't take details map into account here.
float maxMipBias = log2(max(_NormalMap0_TexelSize.z, _NormalMap0_TexelSize.w)); // don't do + 1 as it is for bias, not lod
float3 mainNormalTS = GetNormalTS0(input, layerTexCoord, float3(0.0, 0.0, 1.0), 0.0, true, maxMipBias * (1.0 - influenceFactor));
// Add on our regular normal a bit of Main Layer normal base on influence factor. Note that this affect only the "visible" normal.
return lerp(normalTS, BlendNormalRNM(normalTS, mainNormalTS), influenceFactor);
#if _LAYER_COUNT < 4
height3 = 0.0;
#endif
#if _LAYER_COUNT < 3
height2 = 0.0;
#endif
float3 ComputeMainBaseColorInfluence(float3 baseColor0, float3 baseColor1, float3 baseColor2, float3 baseColor3, float compoMask, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
void ComputeMaskWeights(float4 inputMasks, out float outWeights[_MAX_LAYER])
float3 baseColor = BlendLayeredVector3(baseColor0, baseColor1, baseColor2, baseColor3, weights);
float influenceFactor = BlendLayeredScalar(0.0, _InheritBaseColor1, _InheritBaseColor2, _InheritBaseColor3, weights);
float influenceThreshold = BlendLayeredScalar(1.0, _InheritBaseColorThreshold1, _InheritBaseColorThreshold2, _InheritBaseColorThreshold3, weights);
float masks[_MAX_LAYER];
#if defined(_DENSITY_MODE)
masks[0] = inputMasks.a;
#else
masks[0] = 1.0;
#endif
masks[1] = inputMasks.r;
#if _LAYER_COUNT > 2
masks[2] = inputMasks.g;
#else
masks[2] = 0.0;
#endif
#if _LAYER_COUNT > 3
masks[3] = inputMasks.b;
#else
masks[3] = 0.0;
#endif
influenceFactor = influenceFactor * (1.0 - saturate(compoMask / influenceThreshold));
// We want to calculate the mean color of the texture. For this we will sample a low mipmap
float textureBias = 15.0; // Use maximum bias
float3 baseMeanColor0 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap0, sampler_BaseColorMap0, layerTexCoord.base0, textureBias).rgb *_BaseColor0.rgb;
float3 baseMeanColor1 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap1, sampler_BaseColorMap0, layerTexCoord.base1, textureBias).rgb *_BaseColor1.rgb;
float3 baseMeanColor2 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap2, sampler_BaseColorMap0, layerTexCoord.base2, textureBias).rgb *_BaseColor2.rgb;
float3 baseMeanColor3 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap3, sampler_BaseColorMap0, layerTexCoord.base3, textureBias).rgb *_BaseColor3.rgb;
float3 meanColor = BlendLayeredVector3(baseMeanColor0, baseMeanColor1, baseMeanColor2, baseMeanColor3, weights);
// calculate weight of each layers
// Algorithm is like this:
// Top layer have priority on others layers
// If a top layer doesn't use the full weight, the remaining can be use by the following layer.
float weightsSum = 0.0;
// If we inherit from base layer, we will add a bit of it
// We add variance of current visible level and the base color 0 or mean (to retrieve initial color) depends on influence
// (baseColor - meanColor) + lerp(meanColor, baseColor0, inheritBaseColor) simplify to
return saturate(influenceFactor * (baseColor0 - meanColor) + baseColor);
[unroll]
for (int i = _LAYER_COUNT - 1; i >= 0; --i)
{
outWeights[i] = min(masks[i], (1.0 - weightsSum));
weightsSum = saturate(weightsSum + masks[i]);
}
}
// Caution: Blend mask are Layer 1 R - Layer 2 G - Layer 3 B - Main Layer A

// Blend mask are Main Layer A - Layer 1 R - Layer 2 G - Layer 3 B
// Value for Mani layer is not use for blending itself but for alternate weighting like density.
// Value for main layer is not use for blending itself but for alternate weighting like density.
// Settings this specific Main layer blend mask in alpha allow to be transparent in case we don't use it and 1 is provide by default.
float4 blendMasks = useLodSampling ? SAMPLE_LAYER_TEXTURE2D_LOD(_LayerMaskMap, sampler_LayerMaskMap, layerTexCoord.base0, lod) : SAMPLE_LAYER_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, layerTexCoord.base0);

return blendMasks;
}
// Return the maximun amplitude use by all enabled heightmap
// use for tessellation culling and per pixel displacement
float GetMaxDisplacement()
{
float maxDisplacement = 0.0;
#if defined(_HEIGHTMAP0)
maxDisplacement = max( _LayerHeightAmplitude0, maxDisplacement);
#endif
#if defined(_HEIGHTMAP1)
maxDisplacement = max( _LayerHeightAmplitude1
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
+_LayerHeightAmplitude0 * _InheritBaseHeight1
#endif
, maxDisplacement);
#endif
#if _LAYER_COUNT >= 3
#if defined(_HEIGHTMAP2)
maxDisplacement = max( _LayerHeightAmplitude2
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
+_LayerHeightAmplitude0 * _InheritBaseHeight2
#endif
, maxDisplacement);
#endif
#endif
#if _LAYER_COUNT >= 4
#if defined(_HEIGHTMAP3)
maxDisplacement = max( _LayerHeightAmplitude3
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
+_LayerHeightAmplitude0 * _InheritBaseHeight3
#endif
, maxDisplacement);
#endif
#endif
return maxDisplacement;
}
// Return the minimun uv size for all layers including triplanar
float2 GetMinUvSize(LayerTexCoord layerTexCoord)
{
float2 minUvSize = float2(FLT_MAX, FLT_MAX);
#if defined(_HEIGHTMAP0)
if (layerTexCoord.base0.isTriplanar)
{
minUvSize = min(layerTexCoord.base0.uvYZ * _HeightMap0_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base0.uvZX * _HeightMap0_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base0.uvXY * _HeightMap0_TexelSize.zw, minUvSize);
}
else
{
minUvSize = min(layerTexCoord.base0.uv * _HeightMap0_TexelSize.zw, minUvSize);
}
#endif
#if defined(_HEIGHTMAP1)
if (layerTexCoord.base1.isTriplanar)
{
minUvSize = min(layerTexCoord.base1.uvYZ * _HeightMap1_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base1.uvZX * _HeightMap1_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base1.uvXY * _HeightMap1_TexelSize.zw, minUvSize);
}
else
{
minUvSize = min(layerTexCoord.base1.uv * _HeightMap1_TexelSize.zw, minUvSize);
}
#endif
#if _LAYER_COUNT >= 3
#if defined(_HEIGHTMAP2)
if (layerTexCoord.base2.isTriplanar)
{
minUvSize = min(layerTexCoord.base2.uvYZ * _HeightMap2_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base2.uvZX * _HeightMap2_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base2.uvXY * _HeightMap2_TexelSize.zw, minUvSize);
}
else
{
minUvSize = min(layerTexCoord.base2.uv * _HeightMap2_TexelSize.zw, minUvSize);
}
#endif
#endif
#if _LAYER_COUNT >= 4
#if defined(_HEIGHTMAP3)
if (layerTexCoord.base3.isTriplanar)
{
minUvSize = min(layerTexCoord.base3.uvYZ * _HeightMap3_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base3.uvZX * _HeightMap3_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base3.uvXY * _HeightMap3_TexelSize.zw, minUvSize);
}
else
{
minUvSize = min(layerTexCoord.base3.uv * _HeightMap3_TexelSize.zw, minUvSize);
}
#endif
#endif
return minUvSize;
}
struct PerPixelHeightDisplacementParam
{
float weights[_MAX_LAYER];
float2 uv[_MAX_LAYER];
float mainHeightInfluence;
};
// Calculate displacement for per vertex displacement mapping
float ComputePerPixelHeightDisplacement(float2 texOffsetCurrent, float lod, PerPixelHeightDisplacementParam param)
{
#if defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || defined(_HEIGHTMAP2) || defined(_HEIGHTMAP3)
// Note: No multiply by amplitude here, this is bake into the weights and apply in BlendLayeredScalar
// The amplitude is normalize to be able to work with POM algorithm
// Tiling is automatically handled correctly here as we use 4 differents uv even if they come from the same UVSet (they include the tiling)
float height0 = SAMPLE_TEXTURE2D_LOD(_HeightMap0, sampler_ShareHeightMap, param.uv[0] + texOffsetCurrent, lod).r;
float height1 = SAMPLE_TEXTURE2D_LOD(_HeightMap1, sampler_ShareHeightMap, param.uv[1] + texOffsetCurrent, lod).r;
float height2 = SAMPLE_TEXTURE2D_LOD(_HeightMap2, sampler_ShareHeightMap, param.uv[2] + texOffsetCurrent, lod).r;
float height3 = SAMPLE_TEXTURE2D_LOD(_HeightMap3, sampler_ShareHeightMap, param.uv[3] + texOffsetCurrent, lod).r;
SetEnabledHeightByLayer(height0, height1, height2, height3); // Not needed as already put in weights but paranoid mode
return BlendLayeredScalar(height0, height1, height2, height3, param.weights) + height0 * param.mainHeightInfluence;
#else
return 0.0;
#endif
}
#include "PerPixelDisplacement.hlsl"
// PPD is affecting only one mapping at the same time, mean we need to execute it for each mapping (UV0, UV1, 3 times for triplanar etc..)
// We chose to not support all this case that are extremely hard to manage (for example mixing different mapping, mean it also require different tangent space that is not supported in Unity)
// For these reasons we put the following rules
// Rules:
// - Mapping is the same for all layers that use an Heightmap (i.e all are UV, planar or triplanar)
// - Mapping UV is UV0 only because we need to convert view vector in texture space and this is only available for UV0
// - Heightmap can be enabled per layer
// - Blend Mask use same mapping as main layer (UVO, Planar, Triplanar)
// From these rules it mean that PPD is enable only if the user 1) ask for it, 2) if there is one heightmap enabled on active layer, 3) if mapping is the same for all layer respecting 2), 4) if mapping is UV0, planar or triplanar mapping
// Most contraint are handled by the inspector (i.e the UI) like the mapping constraint and is assumed in the shader.
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
bool ppdEnable = false;
bool isPlanar = false;
bool isTriplanar = false;
#ifdef _PER_PIXEL_DISPLACEMENT
// To know if we are planar or triplanar just need to check if any of the active heightmap layer is true as they are enforce to be the same mapping
#if defined(_HEIGHTMAP0)
ppdEnable = true;
isPlanar = layerTexCoord.base0.isPlanar;
isTriplanar = layerTexCoord.base0.isTriplanar;
#endif
#if defined(_HEIGHTMAP1)
ppdEnable = true;
isPlanar = layerTexCoord.base1.isPlanar;
isTriplanar = layerTexCoord.base1.isTriplanar;
#endif
#if _LAYER_COUNT >= 3
#if defined(_HEIGHTMAP2)
ppdEnable = true;
isPlanar = layerTexCoord.base2.isPlanar;
isTriplanar = layerTexCoord.base2.isTriplanar;
#endif
#endif
#if _LAYER_COUNT >= 4
#if defined(_HEIGHTMAP3)
ppdEnable = true;
isPlanar = layerTexCoord.base3.isPlanar;
isTriplanar = layerTexCoord.base3.isTriplanar;
#endif
#endif
#endif // _PER_PIXEL_DISPLACEMENT
if (ppdEnable)
{
// Even if we use same mapping we can have different tiling. For per pixel displacement we will perform the ray marching with already tiled uv
float maxHeight = GetMaxDisplacement();
// Compute lod as we will sample inside a loop(so can't use regular sampling)
// Note: It appear that CALCULATE_TEXTURE2D_LOD only return interger lod. We want to use float lod to have smoother transition and fading, so do our own calculation.
// Approximation of lod to used. Be conservative here, we will take the highest mip of all layers.
// Remember, we assume that we used the same mapping for all layer, so only size matter.
float2 minUvSize = GetMinUvSize(layerTexCoord);
float lod = ComputeTextureLOD(minUvSize);
// Calculate blend weights
float4 blendMasks = GetBlendMask(layerTexCoord, input.color);
float weights[_MAX_LAYER];
ComputeMaskWeights(blendMasks, weights);
// Be sure we are not considering weight here were there is no heightmap
SetEnabledHeightByLayer(weights[0], weights[1], weights[2], weights[3]);
PerPixelHeightDisplacementParam ppdParam;
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
// For per pixel displacement we need to have normalized height scale to calculate the interesection (required by the algorithm we use)
// mean that we will normalize by the highest amplitude.
// We store this normalization factor with the weights as it will be multiply by the readed height.
ppdParam.weights[0] = weights[0] * (_LayerHeightAmplitude0) / maxHeight;
ppdParam.weights[1] = weights[1] * (_LayerHeightAmplitude1 + _LayerHeightAmplitude0 * _InheritBaseHeight1) / maxHeight;
ppdParam.weights[2] = weights[2] * (_LayerHeightAmplitude2 + _LayerHeightAmplitude0 * _InheritBaseHeight2) / maxHeight;
ppdParam.weights[3] = weights[3] * (_LayerHeightAmplitude3 + _LayerHeightAmplitude0 * _InheritBaseHeight3) / maxHeight;
// Think that inheritbasedheight will be 0 if height0 is fully visible in weights. So there is no double contribution of height0
float mainHeightInfluence = BlendLayeredScalar(0.0, _InheritBaseHeight1, _InheritBaseHeight2, _InheritBaseHeight3, weights);
ppdParam.mainHeightInfluence = mainHeightInfluence;
#else
[unroll]
for (int i = 0; i < _MAX_LAYER; ++i)
{
ppdParam.weights[i] = weights[i];
}
ppdParam.mainHeightInfluence = 0.0;
#endif
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
// TODO: implement. Require 3 call to POM + dedicated viewDirTS based on triplanar convention
// apply the 3 offset on all layers
/*
ppdParam.uv[0] = layerTexCoord.base0.uvYZ;
ppdParam.uv[1] = layerTexCoord.base1.uvYZ;
ppdParam.uv[2] = layerTexCoord.base2.uvYZ;
ppdParam.uv[3] = layerTexCoord.base3.uvYZ;
float3 viewDirTS = ;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, abs(viewDirTS.z));
ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
// Apply to all uvYZ
// Repeat for uvZX
// Repeat for uvXY
// Apply to all layer that used triplanar
*/
}
else
{
ppdParam.uv[0] = layerTexCoord.base0.uv;
ppdParam.uv[1] = layerTexCoord.base1.uv;
ppdParam.uv[2] = layerTexCoord.base2.uv;
ppdParam.uv[3] = layerTexCoord.base3.uv;
// For planar the view vector is the world view vector (unless we want to support object triplanar ? and in this case used TransformWorldToObject)
// TODO: do we support object triplanar ? See ComputeLayerTexCoord
float3 viewDirTS = isPlanar ? float3(-V.xz, V.y) : TransformWorldToTangent(V, input.tangentToWorld);
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
// Apply offset to all planar uvset
// _UVMappingPlanar0 will be 1.0 is planar is used - _UVMappingMask0.x will be 1.0 is UVSet0 is used;
float4 offsetWeights = isPlanar ? float4(_UVMappingPlanar0, _UVMappingPlanar1, _UVMappingPlanar2, _UVMappingPlanar3) : float4(_UVMappingMask0.x, _UVMappingMask1.x, _UVMappingMask2.x, _UVMappingMask3.x);
layerTexCoord.base0.uv += offsetWeights.x * offset;
layerTexCoord.base1.uv += offsetWeights.y * offset;
layerTexCoord.base2.uv += offsetWeights.z * offset;
layerTexCoord.base3.uv += offsetWeights.w * offset;
offsetWeights = isPlanar ? float4(_UVMappingPlanar0, _UVMappingPlanar1, _UVMappingPlanar2, _UVMappingPlanar3) : float4(_UVDetailsMappingMask0.x, _UVDetailsMappingMask1.x, _UVDetailsMappingMask2.x, _UVDetailsMappingMask3.x);
layerTexCoord.details0.uv += offsetWeights.x * offset;
layerTexCoord.details1.uv += offsetWeights.y * offset;
layerTexCoord.details2.uv += offsetWeights.z * offset;
layerTexCoord.details3.uv += offsetWeights.w * offset;
}
}
}
// Calculate displacement for per vertex displacement mapping
float ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
{

ComputeMaskWeights(blendMasks, weights);
float height0 = SampleHeightmapLod0(layerTexCoord, lod, _HeightCenterOffset0, _HeightFactor0);
float height1 = SampleHeightmapLod1(layerTexCoord, lod, _HeightCenterOffset1, _HeightFactor1);
float height2 = SampleHeightmapLod2(layerTexCoord, lod, _HeightCenterOffset2, _HeightFactor2);
float height3 = SampleHeightmapLod3(layerTexCoord, lod, _HeightCenterOffset3, _HeightFactor3);
#if defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || defined(_HEIGHTMAP2) || defined(_HEIGHTMAP3)
float height0 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap0, sampler_ShareHeightMap, layerTexCoord.base0, lod).r - _LayerCenterOffset0) * _LayerHeightAmplitude0;
float height1 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap1, sampler_ShareHeightMap, layerTexCoord.base1, lod).r - _LayerCenterOffset1) * _LayerHeightAmplitude1;
float height2 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap2, sampler_ShareHeightMap, layerTexCoord.base2, lod).r - _LayerCenterOffset2) * _LayerHeightAmplitude2;
float height3 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap3, sampler_ShareHeightMap, layerTexCoord.base3, lod).r - _LayerCenterOffset3) * _LayerHeightAmplitude3;
SetEnabledHeightByLayer(height0, height1, height2, height3);
float heightResult = BlendLayeredScalar(height0, height1, height2, height3, weights);
#if defined(_MAIN_LAYER_INFLUENCE_MODE)

#endif
#else
float heightResult = 0.0;
#endif
return heightResult;
}

}
// Calculate weights to apply to each layer
// Caution: This function must not be use for per vertex of per pixel displacement, there is a dedicated function for them.
// this function handle triplanar
// Caution: This function must not be use for per vertex/pixel displacement, there is a dedicated function for them.
// This function handle triplanar
void ComputeLayerWeights(FragInputs input, LayerTexCoord layerTexCoord, float4 inputAlphaMask, out float outWeights[_MAX_LAYER])
{
float4 blendMasks = GetBlendMask(layerTexCoord, input.color);

#endif
#if defined(_HEIGHT_BASED_BLEND)
float height0 = SampleHeightmap0(layerTexCoord, _HeightCenterOffset0, _HeightFactor0);
float height1 = SampleHeightmap1(layerTexCoord, _HeightCenterOffset1, _HeightFactor1);
float height2 = SampleHeightmap2(layerTexCoord, _HeightCenterOffset2, _HeightFactor2);
float height3 = SampleHeightmap3(layerTexCoord, _HeightCenterOffset3, _HeightFactor3);
float4 heights = float4(height0, height1, height2, height3);
// HACK, use height0 to avoid compiler error for unused sampler
// To remove once we have POM
heights.y += (heights.x * 0.0001);
#if defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || defined(_HEIGHTMAP2) || defined(_HEIGHTMAP3)
float height0 = SAMPLE_LAYER_TEXTURE2D(_HeightMap0, sampler_ShareHeightMap, layerTexCoord.base0).r - _LayerCenterOffset0) * _LayerHeightAmplitude0;
float height1 = SAMPLE_LAYER_TEXTURE2D(_HeightMap1, sampler_ShareHeightMap, layerTexCoord.base1).r - _LayerCenterOffset1) * _LayerHeightAmplitude1;
float height2 = SAMPLE_LAYER_TEXTURE2D(_HeightMap2, sampler_ShareHeightMap, layerTexCoord.base2).r - _LayerCenterOffset2) * _LayerHeightAmplitude2;
float height3 = SAMPLE_LAYER_TEXTURE2D(_HeightMap3, sampler_ShareHeightMap, layerTexCoord.base3).r - _LayerCenterOffset3) * _LayerHeightAmplitude3;
SetEnabledHeightByLayer(height0, height1, height2, height3);
float4 heights = float4(height0, height1, height2, height3);
#else
float4 heights = float4(0.0, 0.0, 0.0, 0.0);
#endif
// don't apply on main layer
blendMasks.rgb = ApplyHeightBasedBlend(blendMasks.rgb, heights.yzw, float3(_BlendUsingHeight1, _BlendUsingHeight2, _BlendUsingHeight3));

}
float3 ComputeMainNormalInfluence(FragInputs input, float3 normalTS0, float3 normalTS1, float3 normalTS2, float3 normalTS3, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
{
// Get our regular normal from regular layering
float3 normalTS = BlendLayeredVector3(normalTS0, normalTS1, normalTS2, normalTS3, weights);
// THen get Main Layer Normal influence factor. Main layer is 0 because it can't be influence. In this case the final lerp return normalTS.
float influenceFactor = BlendLayeredScalar(0.0, _InheritBaseNormal1, _InheritBaseNormal2, _InheritBaseNormal3, weights);
// We will add smoothly the contribution of the normal map by using lower mips with help of bias sampling. InfluenceFactor must be [0..numMips] // Caution it cause banding...
// Note: that we don't take details map into account here.
float maxMipBias = log2(max(_NormalMap0_TexelSize.z, _NormalMap0_TexelSize.w)); // don't do + 1 as it is for bias, not lod
float3 mainNormalTS = GetNormalTS0(input, layerTexCoord, float3(0.0, 0.0, 1.0), 0.0, true, maxMipBias * (1.0 - influenceFactor));
// Add on our regular normal a bit of Main Layer normal base on influence factor. Note that this affect only the "visible" normal.
return lerp(normalTS, BlendNormalRNM(normalTS, mainNormalTS), influenceFactor);
}
float3 ComputeMainBaseColorInfluence(float3 baseColor0, float3 baseColor1, float3 baseColor2, float3 baseColor3, float compoMask, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
{
float3 baseColor = BlendLayeredVector3(baseColor0, baseColor1, baseColor2, baseColor3, weights);
float influenceFactor = BlendLayeredScalar(0.0, _InheritBaseColor1, _InheritBaseColor2, _InheritBaseColor3, weights);
float influenceThreshold = BlendLayeredScalar(1.0, _InheritBaseColorThreshold1, _InheritBaseColorThreshold2, _InheritBaseColorThreshold3, weights);
influenceFactor = influenceFactor * (1.0 - saturate(compoMask / influenceThreshold));
// We want to calculate the mean color of the texture. For this we will sample a low mipmap
float textureBias = 15.0; // Use maximum bias
float3 baseMeanColor0 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap0, sampler_BaseColorMap0, layerTexCoord.base0, textureBias).rgb *_BaseColor0.rgb;
float3 baseMeanColor1 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap1, sampler_BaseColorMap0, layerTexCoord.base1, textureBias).rgb *_BaseColor1.rgb;
float3 baseMeanColor2 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap2, sampler_BaseColorMap0, layerTexCoord.base2, textureBias).rgb *_BaseColor2.rgb;
float3 baseMeanColor3 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap3, sampler_BaseColorMap0, layerTexCoord.base3, textureBias).rgb *_BaseColor3.rgb;
float3 meanColor = BlendLayeredVector3(baseMeanColor0, baseMeanColor1, baseMeanColor2, baseMeanColor3, weights);
// If we inherit from base layer, we will add a bit of it
// We add variance of current visible level and the base color 0 or mean (to retrieve initial color) depends on influence
// (baseColor - meanColor) + lerp(meanColor, baseColor0, inheritBaseColor) simplify to
return saturate(influenceFactor * (baseColor0 - meanColor) + baseColor);
}
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
{
LayerTexCoord layerTexCoord;

float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2, normalTS2);
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3, normalTS3);
// For layering we kill pixel based on maximun alpha
#ifdef _ALPHATEST_ON
#if _LAYER_COUNT == 2
clip(max(alpha0, alpha1) - _AlphaCutoff);
#endif
#if _LAYER_COUNT == 3
clip(max3(alpha0, alpha1, alpha2) - _AlphaCutoff);
#endif
#if _LAYER_COUNT == 4
clip(max(alpha3, max3(alpha0, alpha1, alpha2)) - _AlphaCutoff);
#endif
#endif
// Note: If per pixel displacement is enabled it mean we will fetch again the various heightmaps at the intersection location. Not sure the compiler can optimize.
#ifdef _ALPHATEST_ON
clip(alpha - _AlphaCutoff);
#endif
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
surfaceData.baseColor = ComputeMainBaseColorInfluence(surfaceData0.baseColor, surfaceData1.baseColor, surfaceData2.baseColor, surfaceData3.baseColor, alpha, layerTexCoord, weights);

142
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


void ADD_IDX(ComputeLayerTexCoord)( float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3,
float3 positionWS, float3 normalWS, bool isTriplanar, inout LayerTexCoord layerTexCoord, float additionalTiling = 1.0)
float3 positionWS, float3 vertexNormalWS, bool isTriplanar, inout LayerTexCoord layerTexCoord, float additionalTiling = 1.0)
{
// Handle uv0, uv1, uv2, uv3 based on _UVMappingMask weight (exclusif 0..1)
float2 uvBase = ADD_IDX(_UVMappingMask).x * texCoord0 +

// Note that if base is planar/triplanar, detail map is too
// planar
// TODO: Do we want to manage local or world triplanar/planar
// TODO: Do we want to manage local or world triplanar/planar ? In this case update ApplyPerPixelDisplacement() too
//float3 position = localTriplanar ? TransformWorldToObject(positionWS) : positionWS;
float3 position = positionWS;
position *= ADD_IDX(_TexWorldScale);

uvBase = -position.xz;
uvDetails = -position.xz;
ADD_IDX(layerTexCoord.base).isPlanar = true;
ADD_IDX(layerTexCoord.details).isPlanar = true;
}
else
{
ADD_IDX(layerTexCoord.base).isPlanar = false;
ADD_IDX(layerTexCoord.details).isPlanar = false;
}
ADD_IDX(layerTexCoord.base).uv = TRANSFORM_TEX(uvBase, ADD_IDX(_BaseColorMap));

ADD_IDX(layerTexCoord.base).isTriplanar = isTriplanar;
float3 direction = sign(normalWS);
float3 direction = sign(vertexNormalWS);
// In triplanar, if we are facing away from the world axis, a different axis will be flipped for each direction.
// This is particularly problematic for tangent space normal maps which need to be in the right direction.

ADD_IDX(layerTexCoord.details).uvYZ = TRANSFORM_TEX(uvYZ, ADD_IDX(_DetailMap));
ADD_IDX(layerTexCoord.details).uvZX = TRANSFORM_TEX(uvZX, ADD_IDX(_DetailMap));
ADD_IDX(layerTexCoord.details).uvXY = TRANSFORM_TEX(uvXY, ADD_IDX(_DetailMap));
}
float ADD_IDX(SampleHeightmap)(LayerTexCoord layerTexCoord, float centerOffset = 0.0, float multiplier = 1.0)
{
#ifdef _HEIGHTMAP
return (SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), ADD_IDX(layerTexCoord.base)).r - ADD_IDX(_HeightCenter) - centerOffset) * ADD_IDX(_HeightAmplitude) * multiplier;
#else
return 0.0;
#endif
}
float ADD_IDX(SampleHeightmapLod)(LayerTexCoord layerTexCoord, float lod, float centerOffset = 0.0, float multiplier = 1.0)
{
#ifdef _HEIGHTMAP
return (SAMPLE_LAYER_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), ADD_IDX(layerTexCoord.base), lod).r - ADD_IDX(_HeightCenter) - centerOffset) * ADD_IDX(_HeightAmplitude) * multiplier;
#else
return 0.0;
#endif
}
// Note: The sampling of heightmap inside POM don't use sampling abstraction (with triplanar) as
// POM must be apply separately for each uv set (so 3 time for triplanar)
void ADD_IDX(ParallaxOcclusionMappingLayer)(inout LayerTexCoord layerTexCoord, int numSteps, float3 viewDirTS)
{
// Convention: 1.0 is top, 0.0 is bottom - POM is always inward, no extrusion
float stepSize = 1.0 / (float)numSteps;
// View vector is from the point to the camera, but we want to raymarch from camera to point, so reverse the sign
// The length of viewDirTS vector determines the furthest amount of displacement:
// float parallaxLimit = -length(viewDirTS.xy) / viewDirTS.z;
// float2 parallaxDir = normalize(Out.viewDirTS.xy);
// float2 parallaxMaxOffsetTS = parallaxDir * parallaxLimit;
// Above code simplify to
float2 parallaxMaxOffsetTS = (viewDirTS.xy / -viewDirTS.z) * ADD_IDX(_HeightAmplitude);
float2 texOffsetPerStep = stepSize * parallaxMaxOffsetTS;
float2 uv = ADD_IDX(layerTexCoord.base).uv;
// Compute lod as we will sample inside a loop (so can't use regular sampling)
// It appear that CALCULATE_TEXTURE2D_LOD only return interger lod. We want to use float lod to have smoother transition and fading
// float lod = CALCULATE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv);
float lod = ComputeTextureLOD(uv, GET_TEXELSIZE_NAME(ADD_IDX(_HeightMap)));
// Do a first step before the loop to init all value correctly
float2 texOffsetCurrent = 0;
float prevHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + texOffsetCurrent, lod).r;
texOffsetCurrent += texOffsetPerStep;
float currHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + texOffsetCurrent, lod).r;
float rayHeight = 1.0 - stepSize; // Start at top less one sample
// Linear search
for (int stepIndex = 0; stepIndex < numSteps; ++stepIndex)
{
// Have we found a height below our ray height ? then we have an intersection
if (currHeight > rayHeight)
break; // end the loop
prevHeight = currHeight;
rayHeight -= stepSize;
texOffsetCurrent += texOffsetPerStep;
// Sample height map which in this case is stored in the alpha channel of the normal map:
currHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + texOffsetCurrent, lod).r;
}
// Found below and above points, now perform line interesection (ray) with piecewise linear heightfield approximation
// Refine the search by adding few extra intersection
#define POM_REFINE 1
#if POM_REFINE
float pt0 = rayHeight + stepSize;
float pt1 = rayHeight;
float delta0 = pt0 - prevHeight;
float delta1 = pt1 - currHeight;
float2 offset = float2(0.0, 0.0);
float threshold = 1.0;
for (int i = 0; i < 5; ++i)
{
float t = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
offset = (1 - t) * texOffsetPerStep * numSteps;
currHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + offset, lod).r;
threshold = t - currHeight;
if (abs(threshold) <= 0.01)
break;
if (threshold < 0.0)
{
delta1 = threshold;
pt1 = t;
}
else
{
delta0 = threshold;
pt0 = t;
}
}
#else
//float pt0 = rayHeight + stepSize;
//float pt1 = rayHeight;
//float delta0 = pt0 - prevHeight;
//float delta1 = pt1 - currHeight;
//float t = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
//float2 offset = (1 - t) * texOffsetPerStep * numSteps;
// A bit more optimize
float delta0 = currHeight - rayHeight;
float delta1 = (rayHeight + stepSize) - prevHeight;
float ratio = delta0 / (delta0 + delta1);
float2 offset = texOffsetCurrent - ratio * texOffsetPerStep;
#endif
// TODO: expose LOD fading
//float lodThreshold = 0.0;
//offset *= (1.0 - saturate(lod - lodThreshold));
// Apply offset only on base. Details could use another mapping and will not be consistant...
// Don't know if this will still ok.
// TODO: check with artists
ADD_IDX(layerTexCoord.base).uv += offset;
}
float3 ADD_IDX(GetNormalTS)(FragInputs input, LayerTexCoord layerTexCoord, float3 detailNormalTS, float detailMask, bool useBias, float bias)

6
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl


float _PPDMaxSamples;
float _PPDMinSamples;
float _PPDLodThreshold;
#else // LAYERED_LIT_SHADER

float _BlendUsingHeight1;
float _BlendUsingHeight2;
float _BlendUsingHeight3;
PROP_DECL(float, _HeightFactor);
PROP_DECL(float, _HeightCenterOffset);
PROP_DECL(float, _LayerHeightAmplitude);
PROP_DECL(float, _LayerCenterOffset);
PROP_DECL(float, _MinimumOpacity);
PROP_DECL(float, _OpacityAsDensity);
float _InheritBaseNormal1;

float _PPDMaxSamples;
float _PPDMinSamples;
float _PPDLodThreshold;
#endif // LAYERED_LIT_SHADER

20
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitTessellation.hlsl


float4 GetTessellationFactors(float3 p0, float3 p1, float3 p2, float3 n0, float3 n1, float3 n2)
{
float maxDisplacement = ADD_ZERO_IDX(_HeightAmplitude);
#ifdef _LAYER_COUNT
maxDisplacement = max(maxDisplacement, _HeightAmplitude1);
#if _LAYER_COUNT >= 3
maxDisplacement = max(maxDisplacement, _HeightAmplitude2);
#endif
#if _LAYER_COUNT >= 4
maxDisplacement = max(maxDisplacement, _HeightAmplitude3);
#endif
#endif
float maxDisplacement = GetMaxDisplacement();
bool frustumCulled = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])unity_CameraWorldClipPlanes);

return CalcTriEdgeTessFactors(tessFactor);
}
float3 GetDisplacement(VaryingsMeshToDS input)
// tessellationFactors
// x - 1->2 edge
// y - 2->0 edge
// z - 0->1 edge
// w - inside tessellation factor
float3 GetTessellationDisplacement(VaryingsMeshToDS input)
{
// This call will work for both LayeredLit and Lit shader
LayerTexCoord layerTexCoord;

input.normalWS,
layerTexCoord);
// TODO: Move to camera relative and change distance to length
// http://www.sebastiansylvan.com/post/the-problem-with-tessellation-in-directx-11/
float lod = 0.0;
float4 vertexColor = float4(0.0, 0.0, 0.0, 0.0);
#ifdef VARYINGS_DS_NEED_COLOR

3
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitTessellation.shader


_DetailHeightScale("_DetailHeightScale", Range(-2.0, 2.0)) = 1
_DetailAOScale("_DetailAOScale", Range(-2.0, 2.0)) = 1
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2)] _MaterialID("Material Class", Int) = 0
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2, Specular Color, 3)] _MaterialID("MaterialId", Int) = 0
_SubsurfaceProfile("Subsurface Profile", Int) = 0
_SubsurfaceRadius("Subsurface Radius", Range(0.004, 1.0)) = 0.5
_SubsurfaceRadiusMap("Subsurface Radius Map", 2D) = "white" {}

[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15
_PPDLodThreshold("Start lod to fade out the POM effect", Range(0.0, 16.0)) = 5
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail("UV Set for detail", Float) = 0
[HideInInspector] _UVDetailsMappingMask("_UVDetailsMappingMask", Color) = (1, 0, 0, 0)

25
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/SampleLayer.hlsl


struct LayerUV
{
float2 uv;
bool isPlanar; // mutually exclusive with isTriplanar
// triplanar
bool isTriplanar;
float2 uvYZ;

#undef SAMPLE_TEXTURE_FUNC
// Macro to improve readibility of surface data
#define SAMPLE_LAYER_TEXTURE2D(textureName, samplerName, coord) SampleLayer(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, 0.0) // Last 0.0 is unused
#define SAMPLE_LAYER_TEXTURE2D_LOD(textureName, samplerName, coord, lod) SampleLayerLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, lod)
#define SAMPLE_LAYER_TEXTURE2D_BIAS(textureName, samplerName, coord, bias) SampleLayerBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, bias)
#define SAMPLE_LAYER_TEXTURE2D(textureName, samplerName, coord) SampleLayer(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, 0.0) // Last 0.0 is unused
#define SAMPLE_LAYER_TEXTURE2D_LOD(textureName, samplerName, coord, lod) SampleLayerLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, lod)
#define SAMPLE_LAYER_TEXTURE2D_BIAS(textureName, samplerName, coord, bias) SampleLayerBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, bias)
#define SAMPLE_LAYER_NORMALMAP(textureName, samplerName, coord, scale) SampleLayerNormal(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, 0.0)
#define SAMPLE_LAYER_NORMALMAP_LOD(textureName, samplerName, coord, scale, lod) SampleLayerNormalLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, lod)
#define SAMPLE_LAYER_NORMALMAP_BIAS(textureName, samplerName, coord, scale, bias) SampleLayerNormalBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, bias)
#define SAMPLE_LAYER_NORMALMAP(textureName, samplerName, coord, scale) SampleLayerNormal(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, 0.0)
#define SAMPLE_LAYER_NORMALMAP_LOD(textureName, samplerName, coord, scale, lod) SampleLayerNormalLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, lod)
#define SAMPLE_LAYER_NORMALMAP_BIAS(textureName, samplerName, coord, scale, bias) SampleLayerNormalBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, bias)
#define SAMPLE_LAYER_NORMALMAP_AG(textureName, samplerName, coord, scale) SampleLayerNormalAG(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, 0.0)
#define SAMPLE_LAYER_NORMALMAP_AG_LOD(textureName, samplerName, coord, scale, lod) SampleLayerNormalAGLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, lod)
#define SAMPLE_LAYER_NORMALMAP_AG_BIAS(textureName, samplerName, coord, scale, bias) SampleLayerNormalAGBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, bias)
#define SAMPLE_LAYER_NORMALMAP_AG(textureName, samplerName, coord, scale) SampleLayerNormalAG(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, 0.0)
#define SAMPLE_LAYER_NORMALMAP_AG_LOD(textureName, samplerName, coord, scale, lod) SampleLayerNormalAGLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, lod)
#define SAMPLE_LAYER_NORMALMAP_AG_BIAS(textureName, samplerName, coord, scale, bias) SampleLayerNormalAGBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, bias)
#define SAMPLE_LAYER_NORMALMAP_RGB(textureName, samplerName, coord, scale) SampleLayerNormalRGB(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, 0.0)
#define SAMPLE_LAYER_NORMALMAP_RGB_LOD(textureName, samplerName, coord, scale, lod) SampleLayerNormalRGBLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, lod)
#define SAMPLE_LAYER_NORMALMAP_RGB_BIAS(textureName, samplerName, coord, scale, bias) SampleLayerNormalRGBBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale, bias)
#define SAMPLE_LAYER_NORMALMAP_RGB(textureName, samplerName, coord, scale) SampleLayerNormalRGB(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, 0.0)
#define SAMPLE_LAYER_NORMALMAP_RGB_LOD(textureName, samplerName, coord, scale, lod) SampleLayerNormalRGBLod(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, lod)
#define SAMPLE_LAYER_NORMALMAP_RGB_BIAS(textureName, samplerName, coord, scale, bias) SampleLayerNormalRGBBias(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.triplanarWeights, scale, bias)

20
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/TessellationShare.hlsl


// AMD recommand this value for GCN http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/05/GCNPerformanceTweets.pdf
#define MAX_TESSELLATION_FACTORS 15.0
struct TessellationFactors
{
float edge[3] : SV_TessFactor;

float3 n1 = varying1.vmesh.normalWS;
float3 n2 = varying2.vmesh.normalWS;
// ref: http://reedbeta.com/blog/tess-quick-ref/
// x - 1->2 edge
// y - 2->0 edge
// z - 0->1 edge
// w - inside tessellation factor
output.edge[0] = tf.x;
output.edge[1] = tf.y;
output.edge[2] = tf.z;
output.inside = tf.w;
output.edge[0] = min(tf.x, MAX_TESSELLATION_FACTORS);
output.edge[1] = min(tf.y, MAX_TESSELLATION_FACTORS);
output.edge[2] = min(tf.z, MAX_TESSELLATION_FACTORS);
output.inside = min(tf.w, MAX_TESSELLATION_FACTORS);
[maxtessfactor(15.0)] // AMD recommand this value for GCN http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/05/GCNPerformanceTweets.pdf
[maxtessfactor(MAX_TESSELLATION_FACTORS)]
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]

#endif
#if defined(_TESSELLATION_DISPLACEMENT) || defined(_TESSELLATION_DISPLACEMENT_PHONG)
varying.vmesh.positionWS += GetDisplacement(varying.vmesh);
varying.vmesh.positionWS += GetTessellationDisplacement(varying.vmesh);
#endif
return VertTesselation(varying);

7
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl


// As I haven't change the variables name yet, I simply don't define anything, and I put the transform function at the end of the file outside the guard header.
// This need to be fixed.
float4x4 glstate_matrix_inv_projection;
#define UNITY_MATRIX_M unity_ObjectToWorld
// These are updated per eye in VR

float4x4 GetWorldToHClipMatrix()
{
return UNITY_MATRIX_VP;
}
// Transform from clip space to homogenous world space
float4x4 GetClipToHWorldMatrix()
{
return glstate_matrix_inv_projection;
}
float GetOddNegativeScale()

15
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


// Texture utilities
// ----------------------------------------------------------------------------
float ComputeTextureLOD(float2 uv)
{
float2 ddx_ = ddx(uv);
float2 ddy_ = ddy(uv);
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
return max(0.5 * log2(d), 0.0);
}
// texelSize is Unity XXX_TexelSize feature parameters
// x contains 1.0/width, y contains 1.0 / height, z contains width, w contains height
float ComputeTextureLOD(float2 uv, float4 texelSize)

float2 ddx_ = ddx(uv);
float2 ddy_ = ddy(uv);
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
return max(0.5 * log2(d), 0.0);
return ComputeTextureLOD(uv);
}
// ----------------------------------------------------------------------------

17
Assets/TestScenes/HDTest/GraphicTest/LayeredTessellation/Layer-2-woord-rock.mat


m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Layer-2-woord-rock
m_Shader: {fileID: 4800000, guid: eab0538d9d5746246806a9611c04ac4d, type: 3}
m_Shader: {fileID: 4800000, guid: 81d02e8644315b742b154842a3a2f98c, type: 3}
_TESSELLATION_DISPLACEMENT _USEHEIGHTBASEDBLENDV2_OFF _USEHEIGHTBASEDBLEND_OFF
_TESSELLATION_DISPLACEMENT _USEDENSITYMODE_OFF _USEHEIGHTBASEDBLENDV2_OFF _USEHEIGHTBASEDBLEND_OFF
_USEMAINLAYERINFLUENCE_OFF
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_CustomRenderQueue: -1

- _HeightCenter1: 0.5
- _HeightCenter2: 0
- _HeightCenter3: 0
- _HeightCenterOffset0: 0
- _HeightFactor0: 1
- _HeightFactor1: 1
- _HeightFactor2: 1
- _HeightFactor3: 1

- _HorizonFade: 1
- _InheritBaseColor1: 0
- _InheritBaseColor2: 0
- _InheritBaseColor3: 0

- _InheritBaseNormal3: 0
- _LayerCount: 2
- _LayerMaskVertexColor: 0
- _LayerTiling0: 1
- _LayerTiling1: 1
- _LayerTiling2: 1
- _LayerTiling3: 1
- _MinimumOpacity0: 1
- _MinimumOpacity1: 1
- _MinimumOpacity2: 1
- _MinimumOpacity3: 1

- _NormalScale2: 1
- _NormalScale3: 1
- _OcclusionStrength: 1
- _OpacityAsDensity0: 0
- _OpacityAsDensity1: 0
- _OpacityAsDensity2: 0
- _OpacityAsDensity3: 0

- _UVMappingPlanar2: 0
- _UVMappingPlanar3: 0
- _UVSec: 0
- _UseDensityMode: 0
- _UseMainLayerInfluence: 0
- _VertexColorMode: 0
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:

105
Assets/ScriptableRenderLoop/ShaderLibrary/PerPixelDisplacement.hlsl


// This is implementation of parallax occlusion mapping (POM)
// This function require that the caller define a callback for the height sampling name ComputePerPixelHeightDisplacement
// A PerPixelHeightDisplacementParam is used to provide all data necessary to calculate the heights to ComputePerPixelHeightDisplacement it doesn't need to be
// visible by the POM algorithm.
// This function is compatible with tiled uv.
// it return the offset to apply to the UVSet provide in PerPixelHeightDisplacementParam
// viewDirTS is view vector in texture space matching the UVSet
// ref: https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
float2 ParallaxOcclusionMapping(float lod, float lodThreshold, int numSteps, float3 viewDirTS, float maxHeight, PerPixelHeightDisplacementParam ppdParam)
{
// Convention: 1.0 is top, 0.0 is bottom - POM is always inward, no extrusion
float stepSize = 1.0 / (float)numSteps;
// View vector is from the point to the camera, but we want to raymarch from camera to point, so reverse the sign
// The length of viewDirTS vector determines the furthest amount of displacement:
// float parallaxLimit = -length(viewDirTS.xy) / viewDirTS.z;
// float2 parallaxDir = normalize(Out.viewDirTS.xy);
// float2 parallaxMaxOffsetTS = parallaxDir * parallaxLimit;
// Above code simplify to
float2 parallaxMaxOffsetTS = (viewDirTS.xy / -viewDirTS.z) * maxHeight;
float2 texOffsetPerStep = stepSize * parallaxMaxOffsetTS;
// Do a first step before the loop to init all value correctly
float2 texOffsetCurrent = float2(0.0, 0.0);
float prevHeight = ComputePerPixelHeightDisplacement(texOffsetCurrent, lod, ppdParam);
texOffsetCurrent += texOffsetPerStep;
float currHeight = ComputePerPixelHeightDisplacement(texOffsetCurrent, lod, ppdParam);
float rayHeight = 1.0 - stepSize; // Start at top less one sample
// Linear search
for (int stepIndex = 0; stepIndex < numSteps; ++stepIndex)
{
// Have we found a height below our ray height ? then we have an intersection
if (currHeight > rayHeight)
break; // end the loop
prevHeight = currHeight;
rayHeight -= stepSize;
texOffsetCurrent += texOffsetPerStep;
// Sample height map which in this case is stored in the alpha channel of the normal map:
currHeight = ComputePerPixelHeightDisplacement(texOffsetCurrent, lod, ppdParam);
}
// Found below and above points, now perform line interesection (ray) with piecewise linear heightfield approximation
// Refine the search by adding few extra intersection
#define POM_REFINE 1
#if POM_REFINE
float pt0 = rayHeight + stepSize;
float pt1 = rayHeight;
float delta0 = pt0 - prevHeight;
float delta1 = pt1 - currHeight;
float2 offset = float2(0.0, 0.0);
float threshold = 1.0;
for (int i = 0; i < 5; ++i)
{
float t = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
offset = (1 - t) * texOffsetPerStep * numSteps;
currHeight = ComputePerPixelHeightDisplacement(offset, lod, ppdParam);
threshold = t - currHeight;
if (abs(threshold) <= 0.01)
break;
if (threshold < 0.0)
{
delta1 = threshold;
pt1 = t;
}
else
{
delta0 = threshold;
pt0 = t;
}
}
#else
//float pt0 = rayHeight + stepSize;
//float pt1 = rayHeight;
//float delta0 = pt0 - prevHeight;
//float delta1 = pt1 - currHeight;
//float t = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
//float2 offset = (1 - t) * texOffsetPerStep * numSteps;
// A bit more optimize
float delta0 = currHeight - rayHeight;
float delta1 = (rayHeight + stepSize) - prevHeight;
float ratio = delta0 / (delta0 + delta1);
float2 offset = texOffsetCurrent - ratio * texOffsetPerStep;
#endif
// Fade the effect with lod (allow to avoid pop when switching to a discrete LOD mesh)
offset *= (1.0 - saturate(lod - lodThreshold));
return offset;
}

9
Assets/ScriptableRenderLoop/ShaderLibrary/PerPixelDisplacement.hlsl.meta


fileFormatVersion: 2
guid: 0a40799d368cbbd4982d2f423cdd8595
timeCreated: 1486045136
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存