浏览代码

Merge branch 'Unity-2017.3' of https://github.com/Unity-Technologies/ScriptableRenderLoop into Unity-2017.3

/stochastic_alpha_test
Evgenii Golubev 7 年前
当前提交
86fe9ae4
共有 70 个文件被更改,包括 2316 次插入2639 次删除
  1. 41
      SampleScenes/HDTest/GraphicTest/Parallax Occlusion Mapping/Material/POM - Rock.mat
  2. 53
      SampleScenes/HDTest/GraphicTest/Parallax Occlusion Mapping/Material/POM - Wood triplanar.mat
  3. 27
      SampleScenes/HDTest/GraphicTest/Parallax Occlusion Mapping/Material/POM - Wood.mat
  4. 39
      SampleScenes/HDTest/GraphicTest/Tessellation/Material/Tessellation - Rock.mat
  5. 31
      SampleScenes/HDTest/GraphicTest/Tessellation/Material/Tessellation - Wood.mat
  6. 38
      SampleScenes/HDTest/GraphicTest/Triplanar/Material/Wood triplanar.mat
  7. 48
      SampleScenes/HDTest/HDRenderLoopTest.unity
  8. 4
      SampleScenes/OnTileDeferredTest/Common/MobileTestSceneManager.cs
  9. 8
      ScriptableRenderPipeline/Core/Debugging/DebugItemHandler.cs
  10. 2
      ScriptableRenderPipeline/Core/Debugging/DebugItemUI.cs
  11. 16
      ScriptableRenderPipeline/Core/Debugging/DebugMenuState.cs
  12. 2
      ScriptableRenderPipeline/Core/Debugging/DebugPanel.cs
  13. 41
      ScriptableRenderPipeline/Core/Debugging/DebugPanelUI.cs
  14. 38
      ScriptableRenderPipeline/Core/Editor/CoreEditorUtils.cs
  15. 58
      ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs
  16. 16
      ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  17. 9
      ScriptableRenderPipeline/Core/ShaderLibrary/PerPixelDisplacement.hlsl
  18. 3
      ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs
  19. 7
      ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs.hlsl
  20. 16
      ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.hlsl
  21. 4
      ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebugPanel.cs
  22. 250
      ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs
  23. 16
      ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs
  24. 26
      ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  25. 601
      ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.asset
  26. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.cs
  27. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs
  28. 42
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.cs
  29. 97
      ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs
  30. 45
      ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader
  31. 45
      ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader
  32. 140
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs
  33. 110
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs
  34. 5
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.Styles.cs
  35. 13
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  36. 29
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader
  37. 682
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl
  38. 42
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  39. 9
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl
  40. 43
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl
  41. 31
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader
  42. 6
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDepthPass.hlsl
  43. 4
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDistortionPass.hlsl
  44. 6
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitVelocityPass.hlsl
  45. 9
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/TessellationShare.hlsl
  46. 19
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl
  47. 18
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VertMesh.hlsl
  48. 4
      ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightStandardGUI.cs
  49. 27
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs
  50. 53
      ScriptableRenderPipeline/HDRenderPipeline/Editor/HDBaseEditor.cs
  51. 13
      ScriptableRenderPipeline/HDRenderPipeline/Editor/HDBaseEditor.cs.meta
  52. 56
      ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.Styles.cs
  53. 13
      ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.Styles.cs.meta
  54. 13
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.Styles.cs.meta
  55. 258
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.cs
  56. 13
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.cs.meta
  57. 85
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SSS Settings.asset
  58. 10
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SSS Settings.asset.meta
  59. 508
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs
  60. 13
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs.meta
  61. 13
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringProfileEditor.Styles.cs.meta
  62. 13
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringProfileEditor.cs.meta
  63. 171
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringProfileEditor.cs
  64. 9
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/FoliageSSSProfile.asset.meta
  65. 9
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SkinSSSProfile.asset.meta
  66. 116
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/FoliageSSSProfile.asset
  67. 116
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SkinSSSProfile.asset
  68. 12
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs.meta
  69. 637
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs
  70. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.Styles.cs

41
SampleScenes/HDTest/GraphicTest/Parallax Occlusion Mapping/Material/POM - Rock.mat


m_PrefabInternal: {fileID: 0}
m_Name: POM - Rock
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _HEIGHTMAP _NORMALMAP _NORMALMAP_TANGENT_SPACE _PER_PIXEL_DISPLACEMENT
m_ShaderKeywords: _DISPLACEMENT_LOCK_TILING_SCALE _HEIGHTMAP _NORMALMAP _NORMALMAP_TANGENT_SPACE
_PER_PIXEL_DISPLACEMENT _PER_PIXEL_DISPLACEMENT_OBJECT_SCALE _PER_PIXEL_DISPLACEMENT_TILING_SCALE
_PIXEL_DISPLACEMENT _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE _PIXEL_DISPLACEMENT_LOCK_TILING_SCALE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

m_Offset: {x: 0, y: 0}
- _BaseColorMap:
m_Texture: {fileID: 2800000, guid: 25f2c87d04c2d19479e747dc71259c7d, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BentNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BentNormalMapOS:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:

m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _ATDistance: 1
- _AlbedoAffectEmissive: 0
- _CoatCoverage: 1
- _CoatIOR: 0.5
- _CullMode: 2
- _Cutoff: 0.5
- _DepthOffsetEnable: 0

- _DetailNormalMapScale: 1
- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 2
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0

- _EmissiveColorMode: 1
- _EmissiveIntensity: 0
- _EnablePerPixelDisplacement: 1
- _EnableSpecularOcclusion: 0
- _EnableVertexDisplacement: 0
- _HeightAmplitude: 0.8
- _HeightCenter: 0.5
- _HeightAmplitude: 1
- _HeightCenter: 1
- _HeightMax: 100
- _HeightMin: 0
- _IOR: 1
- _InvTilingScale: 1
- _MaterialID: 1
- _Metallic: 0
- _Mode: 0

- _PPDLodThreshold: 5
- _PPDMaxSamples: 15
- _PPDMinSamples: 5
- _PPDPrimitiveLength: 10
- _PPDPrimitiveWidth: 10
- _PerPixelDisplacementObjectScale: 1
- _PerPixelDisplacementTilingScale: 1
- _RefractionMode: 0
- _SmoothnessRemapMax: 1
- _SmoothnessRemapMin: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

- _SurfaceType: 0
- _TexWorldScale: 1
- _Thickness: 1
- _ThicknessMultiplier: 1
- _VertexDisplacementObjectScale: 1
- _VertexDisplacementTilingScale: 1
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:

- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}
- _InvPrimScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _TransmittanceColor: {r: 1, g: 1, b: 1, a: 1}
- _UVDetailsMappingMask: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask: {r: 1, g: 0, b: 0, a: 0}

53
SampleScenes/HDTest/GraphicTest/Parallax Occlusion Mapping/Material/POM - Wood triplanar.mat


m_PrefabInternal: {fileID: 0}
m_Name: POM - Wood triplanar
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _HEIGHTMAP _MAPPING_TRIPLANAR _NORMALMAP _NORMALMAP_TANGENT_SPACE
m_ShaderKeywords: _DEPTHOFFSET_ON _HEIGHTMAP _MAPPING_TRIPLANAR _NORMALMAP _NORMALMAP_TANGENT_SPACE
_PER_PIXEL_DISPLACEMENT _PER_PIXEL_DISPLACEMENT_OBJECT_SCALE _PER_PIXEL_DISPLACEMENT_TILING_SCALE
_PIXEL_DISPLACEMENT _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE _PIXEL_DISPLACEMENT_LOCK_TILING_SCALE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

m_Offset: {x: 0, y: 0}
- _BaseColorMap:
m_Texture: {fileID: 2800000, guid: 927434958f610214aa6a4179f134f5fd, type: 3}
m_Scale: {x: 2, y: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BentNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BentNormalMapOS:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}

m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _ATDistance: 1
- _AlbedoAffectEmissive: 0
- _CoatCoverage: 1
- _CoatIOR: 0.5
- _DepthOffsetEnable: 0
- _DepthOffsetEnable: 1
- _DetailAOScale: 1
- _DetailAlbedoScale: 1
- _DetailHeightScale: 1

- _DetailSmoothnessScale: 1
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 2
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0

- _DstBlend: 0
- _EmissiveColorMode: 1
- _EmissiveIntensity: 0
- _EnablePerPixelDisplacement: 0
- _EnablePerPixelDisplacement: 1
- _EnableSpecularOcclusion: 0
- _EnableVertexDisplacement: 0
- _HeightAmplitude: 0.17
- _HeightAmplitude: 0.5
- _HeightMax: 50
- _HeightMin: 0
- _IOR: 1
- _InvTilingScale: 1
- _MaterialID: 1
- _Metallic: 0
- _Mode: 0

- _PPDLodThreshold: 5
- _PPDMaxSamples: 15
- _PPDMaxSamples: 64
- _PPDPrimitiveLength: 1
- _PPDPrimitiveWidth: 1
- _PerPixelDisplacementObjectScale: 1
- _PerPixelDisplacementTilingScale: 1
- _RefractionMode: 0
- _SmoothnessRemapMax: 1
- _SmoothnessRemapMin: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

- _SubsurfaceRadius: 1
- _SurfaceType: 0
- _TexWorldScale: 0.1
- _TexWorldScale: 0.2
- _UVBase: 2
- _ThicknessMultiplier: 1
- _UVBase: 5
- _VertexDisplacementObjectScale: 1
- _VertexDisplacementTilingScale: 1
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:

- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}
- _InvPrimScale: {r: 1, g: 1, b: 0, a: 0}
- _TransmittanceColor: {r: 1, g: 1, b: 1, a: 1}
- _UVMappingMask: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask: {r: 0, g: 0, b: 0, a: 0}

27
SampleScenes/HDTest/GraphicTest/Parallax Occlusion Mapping/Material/POM - Wood.mat


m_PrefabInternal: {fileID: 0}
m_Name: POM - Wood
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _DEPTHOFFSET_ON _HEIGHTMAP _NORMALMAP _NORMALMAP_TANGENT_SPACE
_PER_PIXEL_DISPLACEMENT
m_ShaderKeywords: _DEPTHOFFSET_ON _DISPLACEMENT_LOCK_TILING_SCALE _HEIGHTMAP _NORMALMAP
_NORMALMAP_TANGENT_SPACE _PER_PIXEL_DISPLACEMENT _PER_PIXEL_DISPLACEMENT_OBJECT_SCALE
_PER_PIXEL_DISPLACEMENT_TILING_SCALE _PIXEL_DISPLACEMENT _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE
_PIXEL_DISPLACEMENT_LOCK_TILING_SCALE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

m_Offset: {x: 0, y: 0}
- _BaseColorMap:
m_Texture: {fileID: 2800000, guid: 927434958f610214aa6a4179f134f5fd, type: 3}
m_Scale: {x: 2, y: 2}
m_Scale: {x: 3, y: 2}
m_Offset: {x: 0, y: 0}
- _BentNormalMap:
m_Texture: {fileID: 0}

m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _ATDistance: 1
- _AlbedoAffectEmissive: 0
- _AlphaCutoff: 0.5
- _AlphaCutoffEnable: 0

- _DetailNormalMapScale: 1
- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 2
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0

- _EmissiveIntensity: 0
- _EnablePerPixelDisplacement: 1
- _EnableSpecularOcclusion: 0
- _EnableVertexDisplacement: 0
- _EnableWind: 0
- _GlossMapScale: 1
- _Glossiness: 0.5

- _HeightMax: 100
- _HeightMin: 0
- _HorizonFade: 1
- _IOR: 1
- _InvTilingScale: 0.4
- _MaterialID: 1
- _Metallic: 0
- _Mode: 0

- _PPDLodThreshold: 5
- _PPDMaxSamples: 15
- _PPDMaxSamples: 64
- _PPDPrimitiveLength: 10
- _PPDPrimitiveWidth: 10
- _PerPixelDisplacementObjectScale: 1
- _PerPixelDisplacementTilingScale: 1
- _RefractionMode: 0
- _ShiverDirectionality: 0.5
- _ShiverDrag: 0.2
- _Smoothness: 0.5

- _SurfaceType: 0
- _TexWorldScale: 0.2
- _Thickness: 1
- _ThicknessMultiplier: 1
- _VertexDisplacementObjectScale: 1
- _VertexDisplacementTilingScale: 1
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:

- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}
- _InvPrimScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _TransmittanceColor: {r: 1, g: 1, b: 1, a: 1}
- _UVDetailsMappingMask: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask: {r: 1, g: 0, b: 0, a: 0}

39
SampleScenes/HDTest/GraphicTest/Tessellation/Material/Tessellation - Rock.mat


m_PrefabInternal: {fileID: 0}
m_Name: Tessellation - Rock
m_Shader: {fileID: 4800000, guid: 756bac9090102564582875f4c7e30202, type: 3}
m_ShaderKeywords: _EMISSIVE_COLOR _HEIGHTMAP _NORMALMAP _NORMALMAP_TANGENT_SPACE
_TESSELLATION_DISPLACEMENT _TESSELLATION_TILING_SCALE
m_ShaderKeywords: _DISPLACEMENT_LOCK_TILING_SCALE _EMISSIVE_COLOR _HEIGHTMAP _NORMALMAP
_NORMALMAP_TANGENT_SPACE _TESSELLATION_DISPLACEMENT _TESSELLATION_TILING_SCALE
_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE _VERTEX_DISPLACEMENT_LOCK_TILING_SCALE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

m_Offset: {x: 0, y: 0}
- _BaseColorMap:
m_Texture: {fileID: 2800000, guid: 25f2c87d04c2d19479e747dc71259c7d, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BentNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BentNormalMapOS:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:

m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _ATDistance: 1
- _AlbedoAffectEmissive: 0
- _CoatCoverage: 1
- _CoatIOR: 0.5
- _CullMode: 2
- _Cutoff: 0.5
- _DepthOffsetEnable: 0

- _DetailNormalMapScale: 1
- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 3
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0

- _EmissiveColorMode: 0
- _EmissiveIntensity: 0
- _EnablePerPixelDisplacement: 0
- _EnableSpecularOcclusion: 0
- _HeightAmplitude: 0.8
- _HeightCenter: 0.5
- _HeightAmplitude: 1
- _HeightCenter: 1
- _HeightMax: 100
- _HeightMin: 0
- _IOR: 1
- _InvTilingScale: 1
- _MaterialID: 1
- _Metallic: 0
- _Mode: 0

- _PPDLodThreshold: 5
- _PPDMaxSamples: 15
- _PPDMinSamples: 5
- _PPDPrimitiveLength: 1
- _PPDPrimitiveWidth: 1
- _RefractionMode: 0
- _SmoothnessRemapMax: 1
- _SmoothnessRemapMin: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

- _TessellationFactorMaxDistance: 50
- _TessellationFactorMinDistance: 20
- _TessellationFactorTriangleSize: 100
- _TessellationMode: 1
- _TessellationMode: 0
- _ThicknessMultiplier: 1
- _UVBase: 0
- _UVDetail: 0
- _UVMappingPlanar: 0

- _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}
- _InvPrimScale: {r: 1, g: 1, b: 0, a: 0}
- _TransmittanceColor: {r: 1, g: 1, b: 1, a: 1}
- _UVDetailsMappingMask: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask: {r: 1, g: 0, b: 0, a: 0}

31
SampleScenes/HDTest/GraphicTest/Tessellation/Material/Tessellation - Wood.mat


m_PrefabInternal: {fileID: 0}
m_Name: Tessellation - Wood
m_Shader: {fileID: 4800000, guid: 756bac9090102564582875f4c7e30202, type: 3}
m_ShaderKeywords: _HEIGHTMAP _NORMALMAP _NORMALMAP_TANGENT_SPACE _TESSELLATION_DISPLACEMENT
_TESSELLATION_OBJECT_SCALE _TESSELLATION_TILING_SCALE
m_ShaderKeywords: _DISPLACEMENT_LOCK_TILING_SCALE _HEIGHTMAP _NORMALMAP _NORMALMAP_TANGENT_SPACE
_TESSELLATION_DISPLACEMENT _TESSELLATION_OBJECT_SCALE _TESSELLATION_TILING_SCALE
_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE _VERTEX_DISPLACEMENT_LOCK_TILING_SCALE
_VERTEX_DISPLACEMENT_OBJECT_SCALE _VERTEX_DISPLACEMENT_TILING_SCALE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

m_Offset: {x: 0, y: 0}
- _BaseColorMap:
m_Texture: {fileID: 2800000, guid: 927434958f610214aa6a4179f134f5fd, type: 3}
m_Scale: {x: 2, y: 2}
m_Scale: {x: 3, y: 2}
m_Offset: {x: 0, y: 0}
- _BentNormalMap:
m_Texture: {fileID: 0}

m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _ATDistance: 1
- _AlbedoAffectEmissive: 0
- _AlphaCutoff: 0.5
- _AlphaCutoffEnable: 0

- _CoatIOR: 0.5
- _CullMode: 2
- _Cutoff: 0.5
- _DepthOffsetEnable: 0
- _DepthOffsetEnable: 1
- _DetailAOScale: 1
- _DetailAlbedoScale: 1
- _DetailHeightScale: 1

- _DetailSmoothnessScale: 1
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 3
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0

- _EmissiveIntensity: 0
- _EnablePerPixelDisplacement: 0
- _EnableSpecularOcclusion: 0
- _EnableVertexDisplacement: 1
- _EnableWind: 0
- _GlossMapScale: 1
- _Glossiness: 0.5

- _HeightMax: 100
- _HeightMin: 0
- _HorizonFade: 1
- _IOR: 1
- _InvTilingScale: 0.4
- _MaterialID: 1
- _Metallic: 0
- _Mode: 0

- _PPDLodThreshold: 5
- _PPDMaxSamples: 64
- _PPDMinSamples: 1
- _PPDPrimitiveLength: 10
- _PPDPrimitiveWidth: 10
- _PerPixelDisplacementObjectScale: 1
- _PerPixelDisplacementTilingScale: 1
- _RefractionMode: 0
- _ShiverDirectionality: 0.5
- _ShiverDrag: 0.2
- _Smoothness: 0.5

- _TessellationFactorMaxDistance: 50
- _TessellationFactorMinDistance: 20
- _TessellationFactorTriangleSize: 100
- _TessellationMode: 1
- _TessellationMode: 0
- _TexWorldScale: 1
- _TexWorldScale: 0.2
- _ThicknessMultiplier: 1
- _VertexDisplacementObjectScale: 1
- _VertexDisplacementTilingScale: 1
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:

- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}
- _InvPrimScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _TransmittanceColor: {r: 1, g: 1, b: 1, a: 1}
- _UVDetailsMappingMask: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask: {r: 1, g: 0, b: 0, a: 0}

38
SampleScenes/HDTest/GraphicTest/Triplanar/Material/Wood triplanar.mat


m_Name: Wood triplanar
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _HEIGHTMAP _MAPPING_TRIPLANAR _NORMALMAP _NORMALMAP_TANGENT_SPACE
_PER_PIXEL_DISPLACEMENT
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

- _BaseColorMap:
m_Texture: {fileID: 2800000, guid: 927434958f610214aa6a4179f134f5fd, type: 3}
m_Scale: {x: 2, y: 2}
m_Offset: {x: 0, y: 0}
- _BentNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BentNormalMapOS:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}

m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _ATDistance: 1
- _AlbedoAffectEmissive: 0
- _CoatCoverage: 1
- _CoatIOR: 0.5
- _CullMode: 2
- _Cutoff: 0.5
- _DepthOffsetEnable: 0

- _DetailNormalMapScale: 1
- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DisplacementLockObjectScale: 1
- _DisplacementLockTilingScale: 1
- _DisplacementMode: 0
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0

- _EmissiveColorMode: 1
- _EmissiveIntensity: 0
- _EnablePerPixelDisplacement: 1
- _EnableSpecularOcclusion: 0
- _EnableVertexDisplacement: 0
- _HeightAmplitude: 0.17
- _HeightAmplitude: 0.02
- _HeightMax: 1
- _HeightMin: -1
- _IOR: 1
- _InvTilingScale: 0.5
- _MaterialID: 1
- _Metallic: 0
- _Mode: 0

- _PPDLodThreshold: 5
- _PPDMaxSamples: 15
- _PPDMinSamples: 1
- _PPDPrimitiveLength: 1
- _PPDPrimitiveWidth: 1
- _RefractionMode: 0
- _SmoothnessRemapMax: 1
- _SmoothnessRemapMin: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

- _SurfaceType: 0
- _TexWorldScale: 0.1
- _Thickness: 1
- _UVBase: 2
- _ThicknessMultiplier: 1
- _UVBase: 5
- _VertexDisplacementObjectScale: 1
- _VertexDisplacementTilingScale: 1
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:

- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}
- _InvPrimScale: {r: 1, g: 1, b: 0, a: 0}
- _TransmittanceColor: {r: 1, g: 1, b: 1, a: 1}
- _UVMappingMask: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask: {r: 0, g: 0, b: 0, a: 0}

48
SampleScenes/HDTest/HDRenderLoopTest.unity


maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &113580756
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &192903506
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &269387786
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &476925264
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &563884888
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &580932149
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &682868819
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &710116622
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &726298023
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!114 &733865597
MonoBehaviour:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!114 &785457128
MonoBehaviour:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &827169275
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!114 &834722899
MonoBehaviour:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &858501141
Light:

m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 874252441}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 10, y: 1, z: -14}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
m_LocalPosition: {x: 12.5, y: 1, z: -16}
m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
m_Children:
- {fileID: 1950745466}
- {fileID: 122368351}

m_RootOrder: 13
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
--- !u!1 &885480687
GameObject:
m_ObjectHideFlags: 0

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &903116312
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &970745599
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &990293191
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1013563954
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1046252902
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1063426086
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1083738370
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1085128924
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1148469246
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1161056799
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!114 &1220024537
MonoBehaviour:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1235762390
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1308071701
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1309651670
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1352160402
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1555751258
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1559142270
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1640077385
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1737381190
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!114 &1854618468
MonoBehaviour:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1879857774
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1943835614
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1945509647
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1950745469
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &1988224188
Light:

maxSmoothness: 1
applyRangeAttenuation: 1
useOldInspector: 0
featuresFoldout: 1
showAdditionalSettings: 1
--- !u!108 &2015022936
Light:

4
SampleScenes/OnTileDeferredTest/Common/MobileTestSceneManager.cs


int detectSwipe() {
if (Input.touchCount == 1 && Input.GetTouch (0).phase == TouchPhase.Ended) {
Vector2 endPosition = Input.GetTouch (0).position;
Vector2 delta = endPosition - startPosition;
//Vector2 delta = endPosition - startPosition;
if (startPosition.x < endPosition.x)
return 1;

detectTouchBegan();
#endif
}
}
}

8
ScriptableRenderPipeline/Core/Debugging/DebugItemHandler.cs


m_DebugItem = item;
}
// Method user needs to override for specific value clamping.
public virtual void ClampValues(Func<object> getter, Action<object> setter) {}
// Method user needs to override for specific value validation.
public virtual void ValidateValues(Func<object> getter, Action<object> setter) {}
// Method that will create UI items for runtime debug menu.
public abstract DebugItemUI BuildGUI(GameObject parent);

m_Max = max;
}
public override void ClampValues(Func<object> getter, Action<object> setter)
public override void ValidateValues(Func<object> getter, Action<object> setter)
{
setter(Mathf.Clamp((float)getter(), m_Min, m_Max));
}

m_Max = max;
}
public override void ClampValues(Func<object> getter, Action<object> setter)
public override void ValidateValues(Func<object> getter, Action<object> setter)
{
setter(Math.Min(m_Max, Math.Max(m_Min, (uint)getter())));
}

2
ScriptableRenderPipeline/Core/Debugging/DebugItemUI.cs


public bool dynamicDisplay { get { return (m_DebugItem.flags & DebugItemFlag.DynamicDisplay) != 0; } }
public DebugItem debugItem { get { return m_DebugItem; } }
protected DebugItemUI(DebugItem debugItem)
{
m_DebugItem = debugItem;

16
ScriptableRenderPipeline/Core/Debugging/DebugMenuState.cs


namespace UnityEngine.Experimental.Rendering
{
[Serializable]
public abstract class DebugItemState
: ScriptableObject
{

if (debugItemState == null)
{
debugItemState = item.handler.CreateDebugItemState();
debugItemState.hideFlags = HideFlags.DontSave;
debugItemState.Initialize(item);
debugItemState.SetValue(item.GetValue());
AddDebugItemState(debugItemState);
if(debugItemState != null)
{
debugItemState.hideFlags = HideFlags.DontSave;
debugItemState.Initialize(item);
debugItemState.SetValue(item.GetValue());
AddDebugItemState(debugItemState);
}
else
{
Debug.LogWarning(String.Format("DebugItemState for item {0} of type {1} is not provided.\nDid you implement CreateDebugItemState in your custom Handler?", item.name, item.type));
}
}
}
}

2
ScriptableRenderPipeline/Core/Debugging/DebugPanel.cs


if(m_Setter != null)
{
m_Setter(value);
m_Handler.ClampValues(m_Getter, m_Setter);
m_Handler.ValidateValues(m_Getter, m_Setter);
}
if (record && OnItemDirty != null)

41
ScriptableRenderPipeline/Core/Debugging/DebugPanelUI.cs


GameObject.Destroy(child.gameObject);
}
m_ItemsUI.Clear();
protected void AddDebugItemUI(DebugItem item, GameObject parent)
{
#if UNITY_EDITOR
// We don't want runtime only items even in the "player" debug menu if we are in the editor.
if (item.runtimeOnly)
return;
#endif
if(item.editorOnly)
return;
DebugItemUI itemUI = item.handler.BuildGUI(parent);
if(itemUI == null)
{
Debug.LogWarning(String.Format("DebugItemUI not provided for item {0} of type {1}.\n Did you implement BuildGUI for your custom Handler?", item.name, item.type));
}
else
{
m_ItemsUI.Add(itemUI);
}
}
m_ItemsUI.Clear();
#if UNITY_EDITOR
// We don't want runtime only items even in the "player" debug menu if we are in the editor.
if (item.runtimeOnly)
continue;
#endif
if(!item.editorOnly)
{
DebugItemHandler handler = item.handler; // Should never be null, we have at least the default handler
m_ItemsUI.Add(handler.BuildGUI(parent));
}
AddDebugItemUI(item, parent);
}
}

{
if (m_SelectedItem != -1)
{
return m_DebugPanel.GetDebugItem(m_SelectedItem);
return m_ItemsUI[m_SelectedItem].debugItem;
}
return null;

public void OnMoveHorizontal(float value)
{
if (m_SelectedItem != -1 && !m_DebugPanel.GetDebugItem(m_SelectedItem).readOnly)
if (m_SelectedItem != -1 && !m_ItemsUI[m_SelectedItem].debugItem.readOnly)
{
if (value > 0.0f)
m_ItemsUI[m_SelectedItem].OnIncrement();

public void OnValidate()
{
if (m_SelectedItem != -1 && !m_DebugPanel.GetDebugItem(m_SelectedItem).readOnly)
if (m_SelectedItem != -1 && !m_ItemsUI[m_SelectedItem].debugItem.readOnly)
m_ItemsUI[m_SelectedItem].OnValidate();
}

38
ScriptableRenderPipeline/Core/Editor/CoreEditorUtils.cs


using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using UnityEngine;
// Serialization helpers
public static string FindProperty<T, TValue>(Expression<Func<T, TValue>> expr)
{
// Get the field path as a string
MemberExpression me;
switch (expr.Body.NodeType)
{
case ExpressionType.MemberAccess:
me = expr.Body as MemberExpression;
break;
default:
throw new InvalidOperationException();
}
var members = new List<string>();
while (me != null)
{
members.Add(me.Member.Name);
me = me.Expression as MemberExpression;
}
var sb = new StringBuilder();
for (int i = members.Count - 1; i >= 0; i--)
{
sb.Append(members[i]);
if (i > 0) sb.Append('.');
}
return sb.ToString();
}
// UI Helpers
public static void DrawSplitter()
{

// Title
EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel);
EditorGUILayout.Space();
}
public static bool DrawHeaderFoldout(string title, bool state)

58
ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs


using System;
using System.Collections.Generic;
using System.Text;
public class PropertyFetcher<T> : IDisposable
public sealed class PropertyFetcher<T> : IDisposable
{
public readonly SerializedObject obj;

this.obj = obj;
}
public SerializedProperty FindProperty(string str)
public SerializedProperty Find(string str)
public SerializedProperty FindProperty<TValue>(Expression<Func<T, TValue>> expr)
public SerializedProperty Find<TValue>(Expression<Func<T, TValue>> expr)
// Get the field path as a string
MemberExpression me;
switch (expr.Body.NodeType)
{
case ExpressionType.MemberAccess:
me = expr.Body as MemberExpression;
break;
default:
throw new InvalidOperationException();
}
string path = CoreEditorUtils.FindProperty(expr);
return obj.FindProperty(path);
}
var members = new List<string>();
while (me != null)
{
members.Add(me.Member.Name);
me = me.Expression as MemberExpression;
}
public void Dispose()
{
// Nothing to do here, still needed so we can rely on the using/IDisposable pattern
}
}
var sb = new StringBuilder();
for (int i = members.Count - 1; i >= 0; i--)
{
sb.Append(members[i]);
if (i > 0) sb.Append('.');
}
public sealed class RelativePropertyFetcher<T> : IDisposable
{
public readonly SerializedProperty obj;
public RelativePropertyFetcher(SerializedProperty obj)
{
Assert.IsNotNull(obj);
this.obj = obj;
}
var path = sb.ToString();
public SerializedProperty Find(string str)
{
return obj.FindPropertyRelative(str);
}
// Fetch the SerializedProperty using Unity's method
return obj.FindProperty(path);
public SerializedProperty Find<TValue>(Expression<Func<T, TValue>> expr)
{
string path = CoreEditorUtils.FindProperty(expr);
return obj.FindPropertyRelative(path);
}
public void Dispose()

16
ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


return x * x;
}
// Acos in 14 cycles.
// Ref: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/
float FastACos(float inX)
// Input [0, 1] and output [0, PI/2]
// 9 VALU
float FastACosPos(float inX)
return res;
}
// Ref: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/
// Input [-1, 1] and output [0, PI]
// 12 VALU
float FastACos(float inX)
{
float res = FastACosPos(inX);
return (inX >= 0) ? res : PI - res; // Undo range reduction
}

9
ScriptableRenderPipeline/Core/ShaderLibrary/PerPixelDisplacement.hlsl


// 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, out float outHeight)
float2 ParallaxOcclusionMapping(float lod, float lodThreshold, int numSteps, float3 viewDirTS, PerPixelHeightDisplacementParam ppdParam, out float outHeight)
// TODO: explain this factor! Necessary to achieve parity between tessellation and POM w.r.t. height.
maxHeight *= 0.1;
// Convention: 1.0 is top, 0.0 is bottom - POM is always inward, no extrusion
float stepSize = 1.0 / (float)numSteps;

// float2 parallaxDir = normalize(Out.viewDirTS.xy);
// float2 parallaxMaxOffsetTS = parallaxDir * parallaxLimit;
// Above code simplify to
float2 parallaxMaxOffsetTS = (viewDirTS.xy / -viewDirTS.z) * maxHeight;
float2 parallaxMaxOffsetTS = (viewDirTS.xy / -viewDirTS.z);
float2 texOffsetPerStep = stepSize * parallaxMaxOffsetTS;
// Do a first step before the loop to init all value correctly

// Secant method to affine the search
// Ref: Faster Relief Mapping Using the Secant Method - Eric Risser
for (int i = 0; i < 5; ++i)
for (int i = 0; i < 3; ++i)
{
// intersectionHeight is the height [0..1] for the intersection between view ray and heightfield line
float intersectionHeight = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);

3
ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs


{
None = 0,
Tessellation = DebugViewGbuffer.BakeDiffuseLightingWithAlbedoPlusEmissive + 1,
PerPixelDisplacement,
PixelDisplacement,
TessellationDisplacement,
DepthOffset,
Lightmap,
}

7
ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs.hlsl


//
#define DEBUGVIEWPROPERTIES_NONE (0)
#define DEBUGVIEWPROPERTIES_TESSELLATION (12)
#define DEBUGVIEWPROPERTIES_PER_PIXEL_DISPLACEMENT (13)
#define DEBUGVIEWPROPERTIES_PIXEL_DISPLACEMENT (13)
#define DEBUGVIEWPROPERTIES_DEPTH_OFFSET (15)
#define DEBUGVIEWPROPERTIES_LIGHTMAP (16)
#define DEBUGVIEWPROPERTIES_TESSELLATION_DISPLACEMENT (15)
#define DEBUGVIEWPROPERTIES_DEPTH_OFFSET (16)
#define DEBUGVIEWPROPERTIES_LIGHTMAP (17)
//
// UnityEngine.Experimental.Rendering.HDPipeline.FullScreenDebugMode: static fields

16
ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.hlsl


#endif
break;
case DEBUGVIEWPROPERTIES_PER_PIXEL_DISPLACEMENT:
#ifdef _PER_PIXEL_DISPLACEMENT // Caution: This define is related to a shader features (But it may become a standard features for HD
case DEBUGVIEWPROPERTIES_PIXEL_DISPLACEMENT:
#ifdef _PIXEL_DISPLACEMENT // Caution: This define is related to a shader features (But it may become a standard features for HD)
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);

case DEBUGVIEWPROPERTIES_VERTEX_DISPLACEMENT:
#ifdef _VERTEX_DISPLACEMENT // Caution: This define is related to a shader features (But it may become a standard features for HD
#ifdef _VERTEX_DISPLACEMENT // Caution: This define is related to a shader features (But it may become a standard features for HD)
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);
#endif
break;
case DEBUGVIEWPROPERTIES_TESSELLATION_DISPLACEMENT:
#ifdef _TESSELLATION_DISPLACEMENT // Caution: This define is related to a shader features (But it may become a standard features for HD)
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);

case DEBUGVIEWPROPERTIES_DEPTH_OFFSET:
#ifdef _DEPTHOFFSET_ON // Caution: This define is related to a shader features (But it may become a standard features for HD
#ifdef _DEPTHOFFSET_ON // Caution: This define is related to a shader features (But it may become a standard features for HD)
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);

4
ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebugPanel.cs


}
public override void ClampValues(Func<object> getter, Action<object> setter)
public override void ValidateValues(Func<object> getter, Action<object> setter)
{
HDRenderPipeline hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
m_Max = (uint)hdPipeline.GetShadowAtlasCount() - 1;

}
public override void ClampValues(Func<object> getter, Action<object> setter)
public override void ValidateValues(Func<object> getter, Action<object> setter)
{
HDRenderPipeline hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
m_Max = (uint)hdPipeline.GetCurrentShadowCount() - 1;

250
ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs


using System;
using UnityEditor;
using UnityEditor.Experimental.Rendering;
//using EditorGUIUtility=UnityEditor.EditorGUIUtility;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.Rendering.HDPipeline
namespace UnityEditor.Experimental.Rendering.HDPipeline
public class HDRenderPipelineInspector : Editor
public sealed partial class HDRenderPipelineInspector : HDBaseEditor<HDRenderPipelineAsset>
private class Styles
{
public static GUIContent defaults = new GUIContent("Defaults");
public static GUIContent defaultDiffuseMaterial = new GUIContent("Default Diffuse Material", "Material to use when creating objects");
public static GUIContent defaultShader = new GUIContent("Default Shader", "Shader to use when creating materials");
public readonly GUIContent settingsLabel = new GUIContent("Settings");
// Rendering Settings
public readonly GUIContent renderingSettingsLabel = new GUIContent("Rendering Settings");
public readonly GUIContent useForwardRenderingOnly = new GUIContent("Use Forward Rendering Only");
public readonly GUIContent useDepthPrepassWithDeferredRendering = new GUIContent("Use Depth Prepass with Deferred rendering");
public readonly GUIContent renderAlphaTestOnlyInDeferredPrepass = new GUIContent("Alpha Test only");
// Texture Settings
public readonly GUIContent textureSettings = new GUIContent("Texture Settings");
public readonly GUIContent spotCookieSize = new GUIContent("Spot cookie size");
public readonly GUIContent pointCookieSize = new GUIContent("Point cookie size");
public readonly GUIContent reflectionCubemapSize = new GUIContent("Reflection cubemap size");
public readonly GUIContent sssSettings = new GUIContent("Subsurface Scattering Settings");
// Shadow Settings
public readonly GUIContent shadowSettings = new GUIContent("Shadow Settings");
public readonly GUIContent shadowsAtlasWidth = new GUIContent("Atlas width");
public readonly GUIContent shadowsAtlasHeight = new GUIContent("Atlas height");
// Subsurface Scattering Settings
public readonly GUIContent[] sssProfiles = new GUIContent[SssConstants.SSS_N_PROFILES - 1] { new GUIContent("Profile #1"), new GUIContent("Profile #2"), new GUIContent("Profile #3"), new GUIContent("Profile #4"), new GUIContent("Profile #5"),
new GUIContent("Profile #6"), new GUIContent("Profile #7")/*, new GUIContent("Profile #8"), new GUIContent("Profile #9"), new GUIContent("Profile #10"),
new GUIContent("Profile #11"), new GUIContent("Profile #12"), new GUIContent("Profile #13"), new GUIContent("Profile #14"), new GUIContent("Profile #15")*/ };
public readonly GUIContent sssNumProfiles = new GUIContent("Number of profiles");
// Tile pass Settings
public readonly GUIContent tileLightLoopSettings = new GUIContent("Tile Light Loop Settings");
public readonly GUIContent enableTileAndCluster = new GUIContent("Enable tile/clustered");
public readonly GUIContent enableComputeLightEvaluation = new GUIContent("Enable Compute Light Evaluation");
public readonly GUIContent enableComputeLightVariants = new GUIContent("Enable Compute Light Variants");
public readonly GUIContent enableComputeMaterialVariants = new GUIContent("Enable Compute Material Variants");
public readonly GUIContent enableClustered = new GUIContent("Enable clustered");
public readonly GUIContent enableFptlForOpaqueWhenClustered = new GUIContent("Enable Fptl For Opaque When Clustered");
public readonly GUIContent enableBigTilePrepass = new GUIContent("Enable big tile prepass");
public readonly GUIContent tileDebugByCategory = new GUIContent("Enable Debug By Category");
// Sky Settings
public readonly GUIContent skyParams = new GUIContent("Sky Settings");
}
private static Styles s_Styles = null;
private static Styles styles
{
get
{
if (s_Styles == null)
s_Styles = new Styles();
return s_Styles;
}
}
private SerializedProperty m_DefaultDiffuseMaterial;
private SerializedProperty m_DefaultShader;
SerializedProperty m_DefaultDiffuseMaterial;
SerializedProperty m_DefaultShader;
// TilePass settings
SerializedProperty m_enableTileAndCluster;

SerializedProperty m_enableBigTilePrepass;
// Rendering Settings
SerializedProperty m_RenderingUseForwardOnly = null;
SerializedProperty m_RenderingUseDepthPrepass = null;
SerializedProperty m_RenderingUseDepthPrepassAlphaTestOnly = null;
SerializedProperty m_RenderingUseForwardOnly;
SerializedProperty m_RenderingUseDepthPrepass;
SerializedProperty m_RenderingUseDepthPrepassAlphaTestOnly;
// Old SSS Model >>>
SerializedProperty m_UseDisneySSS = null;
// <<< Old SSS Model
SerializedProperty m_Profiles = null;
SerializedProperty m_NumProfiles = null;
SerializedProperty m_SubsurfaceScatteringSettings;
SerializedProperty m_ShadowAtlasWidth = null;
SerializedProperty m_ShadowAtlasHeight = null;
SerializedProperty m_ShadowAtlasWidth;
SerializedProperty m_ShadowAtlasHeight;
SerializedProperty m_SpotCookieSize = null;
SerializedProperty m_PointCookieSize = null;
SerializedProperty m_ReflectionCubemapSize = null;
SerializedProperty m_SpotCookieSize;
SerializedProperty m_PointCookieSize;
SerializedProperty m_ReflectionCubemapSize;
using (var p = new PropertyFetcher<HDRenderPipelineAsset>(serializedObject))
{
m_DefaultDiffuseMaterial = p.FindProperty("m_DefaultDiffuseMaterial");
m_DefaultShader = p.FindProperty("m_DefaultShader");
m_DefaultDiffuseMaterial = properties.Find("m_DefaultDiffuseMaterial");
m_DefaultShader = properties.Find("m_DefaultShader");
// Tile settings
m_enableTileAndCluster = p.FindProperty(x => x.tileSettings.enableTileAndCluster);
m_enableComputeLightEvaluation = p.FindProperty(x => x.tileSettings.enableComputeLightEvaluation);
m_enableComputeLightVariants = p.FindProperty(x => x.tileSettings.enableComputeLightVariants);
m_enableComputeMaterialVariants = p.FindProperty(x => x.tileSettings.enableComputeMaterialVariants);
m_enableClustered = p.FindProperty(x => x.tileSettings.enableClustered);
m_enableFptlForOpaqueWhenClustered = p.FindProperty(x => x.tileSettings.enableFptlForOpaqueWhenClustered);
m_enableBigTilePrepass = p.FindProperty(x => x.tileSettings.enableBigTilePrepass);
// Tile settings
m_enableTileAndCluster = properties.Find(x => x.tileSettings.enableTileAndCluster);
m_enableComputeLightEvaluation = properties.Find(x => x.tileSettings.enableComputeLightEvaluation);
m_enableComputeLightVariants = properties.Find(x => x.tileSettings.enableComputeLightVariants);
m_enableComputeMaterialVariants = properties.Find(x => x.tileSettings.enableComputeMaterialVariants);
m_enableClustered = properties.Find(x => x.tileSettings.enableClustered);
m_enableFptlForOpaqueWhenClustered = properties.Find(x => x.tileSettings.enableFptlForOpaqueWhenClustered);
m_enableBigTilePrepass = properties.Find(x => x.tileSettings.enableBigTilePrepass);
// Shadow settings
m_ShadowAtlasWidth = p.FindProperty(x => x.shadowInitParams.shadowAtlasWidth);
m_ShadowAtlasHeight = p.FindProperty(x => x.shadowInitParams.shadowAtlasHeight);
// Shadow settings
m_ShadowAtlasWidth = properties.Find(x => x.shadowInitParams.shadowAtlasWidth);
m_ShadowAtlasHeight = properties.Find(x => x.shadowInitParams.shadowAtlasHeight);
// Texture settings
m_SpotCookieSize = p.FindProperty(x => x.textureSettings.spotCookieSize);
m_PointCookieSize = p.FindProperty(x => x.textureSettings.pointCookieSize);
m_ReflectionCubemapSize = p.FindProperty(x => x.textureSettings.reflectionCubemapSize);
// Texture settings
m_SpotCookieSize = properties.Find(x => x.textureSettings.spotCookieSize);
m_PointCookieSize = properties.Find(x => x.textureSettings.pointCookieSize);
m_ReflectionCubemapSize = properties.Find(x => x.textureSettings.reflectionCubemapSize);
// Rendering settings
m_RenderingUseForwardOnly = p.FindProperty(x => x.renderingSettings.useForwardRenderingOnly);
m_RenderingUseDepthPrepass = p.FindProperty(x => x.renderingSettings.useDepthPrepassWithDeferredRendering);
m_RenderingUseDepthPrepassAlphaTestOnly = p.FindProperty(x => x.renderingSettings.renderAlphaTestOnlyInDeferredPrepass);
// Rendering settings
m_RenderingUseForwardOnly = properties.Find(x => x.renderingSettings.useForwardRenderingOnly);
m_RenderingUseDepthPrepass = properties.Find(x => x.renderingSettings.useDepthPrepassWithDeferredRendering);
m_RenderingUseDepthPrepassAlphaTestOnly = properties.Find(x => x.renderingSettings.renderAlphaTestOnlyInDeferredPrepass);
// Subsurface Scattering Settings
// Old SSS Model >>>
m_UseDisneySSS = p.FindProperty(x => x.sssSettings.useDisneySSS);
// <<< Old SSS Model
m_Profiles = p.FindProperty(x => x.sssSettings.profiles);
m_NumProfiles = m_Profiles.FindPropertyRelative("Array.size");
}
// Subsurface Scattering Settings
m_SubsurfaceScatteringSettings = properties.Find(x => x.sssSettings);
}
static void HackSetDirty(RenderPipelineAsset asset)

method.Invoke(asset, new object[0]);
}
private void TileSettingsUI(HDRenderPipelineAsset renderContext)
void TileSettingsUI(HDRenderPipelineAsset renderContext)
EditorGUILayout.LabelField(styles.tileLightLoopSettings);
EditorGUILayout.LabelField(s_Styles.tileLightLoopSettings);
EditorGUILayout.PropertyField(m_enableTileAndCluster, styles.enableTileAndCluster);
EditorGUILayout.PropertyField(m_enableTileAndCluster, s_Styles.enableTileAndCluster);
EditorGUILayout.PropertyField(m_enableBigTilePrepass, styles.enableBigTilePrepass);
EditorGUILayout.PropertyField(m_enableClustered, styles.enableClustered);
EditorGUILayout.PropertyField(m_enableBigTilePrepass, s_Styles.enableBigTilePrepass);
EditorGUILayout.PropertyField(m_enableClustered, s_Styles.enableClustered);
// Tag: SUPPORT_COMPUTE_CLUSTER_OPAQUE - Uncomment this if you want to do cluster opaque with compute shader (by default we support only fptl on opaque)
// if (m_enableClustered.boolValue)

EditorGUILayout.PropertyField(m_enableFptlForOpaqueWhenClustered, styles.enableFptlForOpaqueWhenClustered);
EditorGUILayout.PropertyField(m_enableFptlForOpaqueWhenClustered, s_Styles.enableFptlForOpaqueWhenClustered);
EditorGUILayout.PropertyField(m_enableComputeLightEvaluation, styles.enableComputeLightEvaluation);
EditorGUILayout.PropertyField(m_enableComputeLightEvaluation, s_Styles.enableComputeLightEvaluation);
if (m_enableComputeLightEvaluation.boolValue)
{
// Tag: SUPPORT_COMPUTE_CLUSTER_OPAQUE - Uncomment this if you want to do cluster opaque with compute shader (by default we support only fptl on opaque)

EditorGUILayout.PropertyField(m_enableComputeLightVariants, styles.enableComputeLightVariants);
EditorGUILayout.PropertyField(m_enableComputeMaterialVariants, styles.enableComputeMaterialVariants);
EditorGUILayout.PropertyField(m_enableComputeLightVariants, s_Styles.enableComputeLightVariants);
EditorGUILayout.PropertyField(m_enableComputeMaterialVariants, s_Styles.enableComputeMaterialVariants);
if (EditorGUI.EndChangeCheck())
{

}
private void SssSettingsUI(HDRenderPipelineAsset renderContext)
void SssSettingsUI(HDRenderPipelineAsset renderContext)
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.sssSettings);
EditorGUI.BeginChangeCheck();
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
// Old SSS Model >>>
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_UseDisneySSS);
if (EditorGUI.EndChangeCheck())
{
HDRenderPipeline hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
hdPipeline.CreateSssMaterials(m_UseDisneySSS.boolValue);
}
// <<< Old SSS Model
EditorGUILayout.PropertyField(m_NumProfiles, styles.sssNumProfiles);
for (int i = 0, n = m_Profiles.arraySize; i < n; i++)
{
SerializedProperty profile = m_Profiles.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(profile, styles.sssProfiles[i]);
}
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(m_SubsurfaceScatteringSettings, s_Styles.sssSettings);
private void SettingsUI(HDRenderPipelineAsset renderContext)
void SettingsUI(HDRenderPipelineAsset renderContext)
EditorGUILayout.LabelField(styles.settingsLabel);
EditorGUILayout.LabelField(s_Styles.settingsLabel, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
SssSettingsUI(renderContext);

EditorGUI.indentLevel--;
}
private void ShadowSettingsUI(HDRenderPipelineAsset renderContext)
void ShadowSettingsUI(HDRenderPipelineAsset renderContext)
EditorGUILayout.LabelField(styles.shadowSettings);
EditorGUILayout.LabelField(s_Styles.shadowSettings);
EditorGUILayout.PropertyField(m_ShadowAtlasWidth, styles.shadowsAtlasWidth);
EditorGUILayout.PropertyField(m_ShadowAtlasHeight, styles.shadowsAtlasHeight);
EditorGUILayout.PropertyField(m_ShadowAtlasWidth, s_Styles.shadowsAtlasWidth);
EditorGUILayout.PropertyField(m_ShadowAtlasHeight, s_Styles.shadowsAtlasHeight);
if (EditorGUI.EndChangeCheck())
{

}
private void RendereringSettingsUI(HDRenderPipelineAsset renderContext)
void RendereringSettingsUI(HDRenderPipelineAsset renderContext)
EditorGUILayout.LabelField(styles.renderingSettingsLabel);
EditorGUILayout.LabelField(s_Styles.renderingSettingsLabel);
EditorGUILayout.PropertyField(m_RenderingUseForwardOnly, styles.useForwardRenderingOnly);
EditorGUILayout.PropertyField(m_RenderingUseForwardOnly, s_Styles.useForwardRenderingOnly);
EditorGUILayout.PropertyField(m_RenderingUseDepthPrepass, styles.useDepthPrepassWithDeferredRendering);
EditorGUILayout.PropertyField(m_RenderingUseDepthPrepass, s_Styles.useDepthPrepassWithDeferredRendering);
EditorGUILayout.PropertyField(m_RenderingUseDepthPrepassAlphaTestOnly, styles.renderAlphaTestOnlyInDeferredPrepass);
EditorGUILayout.PropertyField(m_RenderingUseDepthPrepassAlphaTestOnly, s_Styles.renderAlphaTestOnlyInDeferredPrepass);
EditorGUI.indentLevel--;
}
}

private void TextureSettingsUI(HDRenderPipelineAsset renderContext)
void TextureSettingsUI(HDRenderPipelineAsset renderContext)
EditorGUILayout.LabelField(styles.textureSettings);
EditorGUILayout.LabelField(s_Styles.textureSettings);
EditorGUILayout.PropertyField(m_SpotCookieSize, styles.spotCookieSize);
EditorGUILayout.PropertyField(m_PointCookieSize, styles.pointCookieSize);
EditorGUILayout.PropertyField(m_ReflectionCubemapSize, styles.reflectionCubemapSize);
EditorGUILayout.PropertyField(m_SpotCookieSize, s_Styles.spotCookieSize);
EditorGUILayout.PropertyField(m_PointCookieSize, s_Styles.pointCookieSize);
EditorGUILayout.PropertyField(m_ReflectionCubemapSize, s_Styles.reflectionCubemapSize);
if (EditorGUI.EndChangeCheck())
{

}
public void OnEnable()
protected override void OnEnable()
base.OnEnable();
var renderContext = target as HDRenderPipelineAsset;
HDRenderPipeline renderpipeline = UnityEngine.Experimental.Rendering.RenderPipelineManager.currentPipeline as HDRenderPipeline;
if (!renderContext || renderpipeline == null)
if (!m_Target || m_HDPipeline == null)
CheckStyles();
EditorGUILayout.LabelField(Styles.defaults, EditorStyles.boldLabel);
EditorGUILayout.LabelField(s_Styles.defaults, EditorStyles.boldLabel);
EditorGUILayout.PropertyField(m_DefaultDiffuseMaterial, Styles.defaultDiffuseMaterial);
EditorGUILayout.PropertyField(m_DefaultShader, Styles.defaultShader);
EditorGUILayout.PropertyField(m_DefaultDiffuseMaterial, s_Styles.defaultDiffuseMaterial);
EditorGUILayout.PropertyField(m_DefaultShader, s_Styles.defaultShader);
EditorGUILayout.Space();
SettingsUI(renderContext);
SettingsUI(m_Target);
serializedObject.ApplyModifiedProperties();
}

16
ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs


}
}
class DoCreateNewAssetSSSProfile : DoCreateNewAsset<SubsurfaceScatteringProfile> {}
[MenuItem("Assets/Create/HDRenderPipeline/Subsurface Scattering Profile", priority = 666)]
static void MenuCreateSubsurfaceScatteringProfile()
{
var icon = EditorGUIUtility.FindTexture("ScriptableObject Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAssetSSSProfile>(), "New SSS Profile.asset", icon, null);
}
class DoCreateNewAssetSubsurfaceScatteringSettings : DoCreateNewAsset<SubsurfaceScatteringSettings> {}
[MenuItem("Assets/Create/HDRenderPipeline/Common Settings", priority = 677)]
static void MenuCreateCommonSettings()

{
var icon = EditorGUIUtility.FindTexture("ScriptableObject Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAssetSSAOSettings>(), "New AmbientOcclusionSettings.asset", icon, null);
}
[MenuItem("Assets/Create/HDRenderPipeline/Subsurface Scattering Settings", priority = 681)]
static void MenuCreateSubsurfaceScatteringSettings()
{
var icon = EditorGUIUtility.FindTexture("ScriptableObject Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAssetSubsurfaceScatteringSettings>(), "New SSS Settings.asset", icon, null);
}
}
}

26
ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


int m_DebugFullScreenTempRT;
bool m_FullScreenDebugPushed;
SubsurfaceScatteringSettings m_InternalSSSAsset;
get { return m_Asset.sssSettings; }
get
{
// If no SSS asset is set, build / reuse an internal one for simplicity
var asset = m_Asset.sssSettings;
if (asset == null)
{
if (m_InternalSSSAsset == null)
m_InternalSSSAsset = ScriptableObject.CreateInstance<SubsurfaceScatteringSettings>();
asset = m_InternalSSSAsset;
}
return asset;
}
}
CommonSettings.Settings m_CommonSettings = CommonSettings.Settings.s_Defaultsettings;

m_CameraFilteringBuffer = HDShaderIDs._CameraFilteringBuffer;
m_CameraFilteringBufferRT = new RenderTargetIdentifier(m_CameraFilteringBuffer);
CreateSssMaterials(sssSettings.useDisneySSS);
CreateSssMaterials();
m_CopyStencilForSplitLighting = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/CopyStencilBuffer");
m_CopyStencilForSplitLighting.EnableKeyword("EXPORT_HTILE");

m_ErrorMaterial = CoreUtils.CreateEngineMaterial("Hidden/InternalErrorShader");
}
public void CreateSssMaterials(bool useDisneySSS)
public void CreateSssMaterials()
{
m_SubsurfaceScatteringKernel = m_SubsurfaceScatteringCS.FindKernel("SubsurfaceScattering");

CoreUtils.Destroy(m_DebugDisplayLatlong);
CoreUtils.Destroy(m_DebugFullScreen);
CoreUtils.Destroy(m_ErrorMaterial);
CoreUtils.Destroy(m_InternalSSSAsset);
m_SkyManager.Cleanup();

var postProcessLayer = camera.GetComponent<PostProcessLayer>();
var hdCamera = HDCamera.Get(camera, postProcessLayer);
PushGlobalParams(hdCamera, cmd, m_Asset.sssSettings);
PushGlobalParams(hdCamera, cmd, sssSettings);
// TODO: Find a correct place to bind these material textures
// We have to bind the material specific global parameters in this mode

// We compute subsurface scattering here. Therefore, no objects rendered afterwards will exhibit SSS.
// Currently, there is no efficient way to switch between SRT and MRT for the forward pass;
// therefore, forward-rendered objects do not output split lighting required for the SSS pass.
SubsurfaceScatteringPass(hdCamera, cmd, m_Asset.sssSettings);
SubsurfaceScatteringPass(hdCamera, cmd, sssSettings);
RenderForward(m_CullResults, camera, renderContext, cmd, true);
RenderForwardError(m_CullResults, camera, renderContext, cmd, true);

601
ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.asset


useForwardRenderingOnly: 0
useDepthPrepassWithDeferredRendering: 0
renderAlphaTestOnlyInDeferredPrepass: 0
sssSettings:
numProfiles: 2
profiles:
- {fileID: 11400000, guid: 906339bac2066fc4aa22a3652e1283ef, type: 2}
- {fileID: 11400000, guid: d6ee4403015766f4093158d69216c0bf, type: 2}
texturingModeFlags: 0
transmissionFlags: 5462
thicknessRemaps:
- {x: 0, y: 8.152544, z: 0, w: 0}
- {x: 0, y: 0.2873168, z: 0, w: 0}
- {x: 0, y: 5, z: 0, w: 0}
- {x: 0, y: 12.031147, z: 0, w: 0}
- {x: 0, y: 12.031147, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
worldScales:
- {x: 1, y: 0, z: 0, w: 0}
- {x: 1, y: 0, z: 0, w: 0}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
shapeParams:
- {x: 1.3192612, y: 3.1152647, z: 4.9751244, w: 7.84603}
- {x: 1.3203883, y: 1.4268992, z: 4.0812, w: 7.839332}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
transmissionTints:
- {x: 0.1892157, y: 0.08039216, z: 0.050000004, w: 0.25}
- {x: 0.25, y: 0.25, z: 0.25, w: 0.25}
- {x: 100, y: 0, z: 100, w: 1}
- {x: 100, y: 0, z: 100, w: 1}
- {x: 100, y: 0, z: 100, w: 1}
- {x: 100, y: 0, z: 100, w: 1}
- {x: 100, y: 0, z: 100, w: 1}
- {x: 0, y: 0, z: 0, w: 0}
filterKernels:
- {x: 0.013865918, y: 1.5345725, z: 0.03667902, w: 1.5654991}
- {x: 0.04211352, y: 1.5729346, z: 0.11374626, w: 1.6734134}
- {x: 0.07107388, y: 1.6130018, z: 0.19626758, w: 1.7949444}
- {x: 0.100779116, y: 1.6548817, z: 0.28494877, w: 1.9325867}
- {x: 0.13126306, y: 1.6986896, z: 0.38062802, w: 2.0894418}
- {x: 0.16256203, y: 1.7445502, z: 0.48430943, w: 2.2694077}
- {x: 0.1947145, y: 1.7925992, z: 0.59720695, w: 2.4774427}
- {x: 0.22776169, y: 1.8429838, z: 0.72080237, w: 2.7199378}
- {x: 0.26174724, y: 1.8958628, z: 0.8569269, w: 3.005264}
- {x: 0.29671827, y: 1.9514104, z: 1.007873, w: 3.3445888}
- {x: 0.33272493, y: 2.0098157, z: 1.1765549, w: 3.7531407}
- {x: 0.369821, y: 2.0712852, z: 1.3667475, w: 4.252257}
- {x: 0.40806437, y: 2.1360447, z: 1.5834517, w: 4.872841}
- {x: 0.44751683, y: 2.2043417, z: 1.8334827, w: 5.6615734}
- {x: 0.48824534, y: 2.276447, z: 2.126473, w: 6.692844}
- {x: 0.5303216, y: 2.3526597, z: 2.4767098, w: 8.093767}
- {x: 0.5738235, y: 2.433308, z: 2.9068332, w: 10.102725}
- {x: 0.61883456, y: 2.5187542, z: 3.4562516, w: 13.228675}
- {x: 0.665446, y: 2.609401, z: 4.2041187, w: 18.793621}
- {x: 0.713756, y: 2.7056925, z: 5.3538504, w: 31.646347}
- {x: 0.763872, y: 2.808125, z: 7.84603, w: 95.44374}
- {x: 0.8159103, y: 2.91725, z: 0, w: 1}
- {x: 0.8699981, y: 3.0336854, z: 0, w: 1}
- {x: 0.9262747, y: 3.1581244, z: 0, w: 1}
- {x: 0.98489225, y: 3.2913465, z: 0, w: 1}
- {x: 1.0460185, y: 3.434234, z: 0, w: 1}
- {x: 1.1098381, y: 3.5877857, z: 0, w: 1}
- {x: 1.1765549, y: 3.7531407, z: 0, w: 1}
- {x: 1.2463952, y: 3.9316032, z: 0, w: 1}
- {x: 1.319611, y: 4.124672, z: 0, w: 1}
- {x: 1.3964823, y: 4.3340797, z: 0, w: 1}
- {x: 1.4773248, y: 4.561845, z: 0, w: 1}
- {x: 1.5624928, y: 4.810328, z: 0, w: 1}
- {x: 1.6523882, y: 5.082317, z: 0, w: 1}
- {x: 1.747467, y: 5.381122, z: 0, w: 1}
- {x: 1.8482518, y: 5.710715, z: 0, w: 1}
- {x: 1.9553448, y: 6.0759025, z: 0, w: 1}
- {x: 2.069445, y: 6.482568, z: 0, w: 1}
- {x: 2.1913698, y: 6.9379897, z: 0, w: 1}
- {x: 2.3220856, y: 7.4513016, z: 0, w: 1}
- {x: 2.4627466, y: 8.0341215, z: 0, w: 1}
- {x: 2.614747, y: 8.701484, z: 0, w: 1}
- {x: 2.7797952, y: 9.473195, z: 0, w: 1}
- {x: 2.9600194, y: 10.375936, z: 0, w: 1}
- {x: 3.1581159, y: 11.446505, z: 0, w: 1}
- {x: 3.3775842, y: 12.737201, z: 0, w: 1}
- {x: 3.6230793, y: 14.324919, z: 0, w: 1}
- {x: 3.9009922, y: 16.327562, z: 0, w: 1}
- {x: 4.220452, y: 18.935623, z: 0, w: 1}
- {x: 4.5951686, y: 22.478209, z: 0, w: 1}
- {x: 5.047148, y: 27.57712, z: 0, w: 1}
- {x: 5.615129, y: 35.564823, z: 0, w: 1}
- {x: 6.3776174, y: 49.90625, z: 0, w: 1}
- {x: 7.5374603, y: 83.30668, z: 0, w: 1}
- {x: 10.03481, y: 250.11497, z: 0, w: 1}
- {x: 0.013854082, y: 1.5332626, z: 0.036647703, w: 1.5641627}
- {x: 0.04207757, y: 1.5715919, z: 0.113649175, w: 1.671985}
- {x: 0.07101321, y: 1.611625, z: 0.19610003, w: 1.7934121}
- {x: 0.10069309, y: 1.653469, z: 0.28470552, w: 1.9309369}
- {x: 0.13115102, y: 1.6972395, z: 0.38030306, w: 2.0876582}
- {x: 0.16242325, y: 1.743061, z: 0.48389605, w: 2.2674706}
- {x: 0.19454831, y: 1.791069, z: 0.5966971, w: 2.4753277}
- {x: 0.22756726, y: 1.8414105, z: 0.72018707, w: 2.717616}
- {x: 0.2615238, y: 1.8942443, z: 0.85619545, w: 3.0026984}
- {x: 0.29646498, y: 1.9497447, z: 1.0070126, w: 3.3417335}
- {x: 0.33244094, y: 2.0081, z: 1.1755506, w: 3.749937}
- {x: 0.36950532, y: 2.069517, z: 1.3655809, w: 4.248627}
- {x: 0.40771604, y: 2.1342213, z: 1.5821002, w: 4.868682}
- {x: 0.44713485, y: 2.2024598, z: 1.8319175, w: 5.6567397}
- {x: 0.48782852, y: 2.274504, z: 2.1246579, w: 6.6871305}
- {x: 0.5298689, y: 2.3506513, z: 2.4745958, w: 8.086858}
- {x: 0.5733336, y: 2.4312308, z: 2.9043517, w: 10.094101}
- {x: 0.6183063, y: 2.5166042, z: 3.4533012, w: 13.217383}
- {x: 0.66487795, y: 2.6071734, z: 4.20053, w: 18.777578}
- {x: 0.71314675, y: 2.703383, z: 5.349281, w: 31.61934}
- {x: 0.76321995, y: 2.805728, z: 7.839332, w: 95.36225}
- {x: 0.81521386, y: 2.9147599, z: 0, w: 1}
- {x: 0.86925554, y: 3.031096, z: 0, w: 1}
- {x: 0.92548406, y: 3.1554284, z: 0, w: 1}
- {x: 0.9840515, y: 3.288537, z: 0, w: 1}
- {x: 1.0451256, y: 3.431302, z: 0, w: 1}
- {x: 1.1088905, y: 3.5847225, z: 0, w: 1}
- {x: 1.1755506, y: 3.749937, z: 0, w: 1}
- {x: 1.2453312, y: 3.9282467, z: 0, w: 1}
- {x: 1.3184844, y: 4.1211514, z: 0, w: 1}
- {x: 1.3952904, y: 4.3303804, z: 0, w: 1}
- {x: 1.4760638, y: 4.5579505, z: 0, w: 1}
- {x: 1.5611593, y: 4.8062224, z: 0, w: 1}
- {x: 1.650978, y: 5.0779796, z: 0, w: 1}
- {x: 1.7459753, y: 5.3765287, z: 0, w: 1}
- {x: 1.8466738, y: 5.7058387, z: 0, w: 1}
- {x: 1.9536757, y: 6.070716, z: 0, w: 1}
- {x: 2.0676782, y: 6.4770336, z: 0, w: 1}
- {x: 2.189499, y: 6.9320674, z: 0, w: 1}
- {x: 2.3201032, y: 7.4449396, z: 0, w: 1}
- {x: 2.4606442, y: 8.027264, z: 0, w: 1}
- {x: 2.612515, y: 8.694056, z: 0, w: 1}
- {x: 2.777422, y: 9.465107, z: 0, w: 1}
- {x: 2.9574924, y: 10.367077, z: 0, w: 1}
- {x: 3.1554203, y: 11.436736, z: 0, w: 1}
- {x: 3.3747015, y: 12.726331, z: 0, w: 1}
- {x: 3.6199868, y: 14.312694, z: 0, w: 1}
- {x: 3.897662, y: 16.313623, z: 0, w: 1}
- {x: 4.2168484, y: 18.919455, z: 0, w: 1}
- {x: 4.5912457, y: 22.459015, z: 0, w: 1}
- {x: 5.042839, y: 27.553566, z: 0, w: 1}
- {x: 5.610336, y: 35.534466, z: 0, w: 1}
- {x: 6.3721733, y: 49.863647, z: 0, w: 1}
- {x: 7.53103, y: 83.235695, z: 0, w: 1}
- {x: 10.026244, y: 249.90146, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
- {x: 0, y: 1, z: 0, w: 1}
useDisneySSS: 1
halfRcpWeightedVariances:
- {x: 2.4691355, y: 12.5, z: 12.5, w: 2.4691355}
- {x: 2.4691355, y: 2.4691355, z: 2.4691355, w: 2.4691355}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
halfRcpVariancesAndWeights:
- {x: 0.5, y: 1.125, z: 1.125, w: 2}
- {x: 0.125, y: 1.125, z: 1.125, w: 2}
- {x: 0.5, y: 0.5, z: 0.5, w: 2}
- {x: 0.125, y: 0.125, z: 0.125, w: 2}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 1, y: 1, z: 1, w: 1}
- {x: 0, y: 0, z: 0, w: 0}
- {x: 0, y: 0, z: 0, w: 0}
filterKernelsBasic:
- {x: 0.09090909, y: 0.21162307, z: 0.21162307, w: -0.000000048879357}
- {x: 0.09090909, y: 0.18990478, z: 0.18990478, w: -0.11381993}
- {x: 0.09090909, y: 0.13233659, z: 0.13233659, w: -0.23580086}
- {x: 0.09090909, y: 0.061445467, z: 0.061445467, w: -0.37865555}
- {x: 0.09090909, y: 0.010501689, z: 0.010501689, w: -0.57677805}
- {x: 0.09090909, y: 2.9458339e-10, z: 2.9458339e-10, w: -1.3907351}
- {x: 0.09090909, y: 0.18990476, z: 0.18990476, w: 0.11382001}
- {x: 0.09090909, y: 0.13233659, z: 0.13233659, w: 0.23580086}
- {x: 0.09090909, y: 0.061445467, z: 0.061445467, w: 0.37865555}
- {x: 0.09090909, y: 0.010501689, z: 0.010501689, w: 0.57677805}
- {x: 0.09090909, y: 2.9456845e-10, z: 2.9456845e-10, w: 1.3907368}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.000000048879357}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.11381993}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.23580086}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.37865555}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.57677805}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -1.3907351}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.11382001}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.23580086}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.37865555}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.57677805}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 1.3907368}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
- {x: 1, y: 1, z: 1, w: 0}
sssSettings: {fileID: 11400000, guid: 873499ce7a6f749408981f512a9683f7, type: 2}
tileSettings:
enableTileAndCluster: 1
enableComputeLightEvaluation: 1

3
ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.cs


// Renderer Settings
public RenderingSettings renderingSettings = new RenderingSettings();
public SubsurfaceScatteringSettings sssSettings = new SubsurfaceScatteringSettings();
public SubsurfaceScatteringSettings sssSettings;
public TileSettings tileSettings = new TileSettings();
// Shadow Settings

public void OnValidate()
{
sssSettings.OnValidate();
}
}
}

1
ScriptableRenderPipeline/HDRenderPipeline/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 _MaxRadius = Shader.PropertyToID("_MaxRadius");
public static readonly int _ShapeParam = Shader.PropertyToID("_ShapeParam");
public static readonly int _StdDev1 = Shader.PropertyToID("_StdDev1");

42
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Editor/HDLightEditor.cs


using (var o = new PropertyFetcher<HDAdditionalLightData>(m_SerializedAdditionalLightData))
m_AdditionalLightData = new SerializedLightData
{
spotInnerPercent = o.FindProperty(x => x.m_InnerSpotPercent),
lightDimmer = o.FindProperty(x => x.lightDimmer),
fadeDistance = o.FindProperty(x => x.fadeDistance),
affectDiffuse = o.FindProperty(x => x.affectDiffuse),
affectSpecular = o.FindProperty(x => x.affectSpecular),
lightTypeExtent = o.FindProperty(x => x.lightTypeExtent),
spotLightShape = o.FindProperty(x => x.spotLightShape),
shapeLength = o.FindProperty(x => x.shapeLength),
shapeWidth = o.FindProperty(x => x.shapeWidth),
shapeRadius = o.FindProperty(x => x.shapeRadius),
maxSmoothness = o.FindProperty(x => x.maxSmoothness),
applyRangeAttenuation = o.FindProperty(x => x.applyRangeAttenuation),
spotInnerPercent = o.Find(x => x.m_InnerSpotPercent),
lightDimmer = o.Find(x => x.lightDimmer),
fadeDistance = o.Find(x => x.fadeDistance),
affectDiffuse = o.Find(x => x.affectDiffuse),
affectSpecular = o.Find(x => x.affectSpecular),
lightTypeExtent = o.Find(x => x.lightTypeExtent),
spotLightShape = o.Find(x => x.spotLightShape),
shapeLength = o.Find(x => x.shapeLength),
shapeWidth = o.Find(x => x.shapeWidth),
shapeRadius = o.Find(x => x.shapeRadius),
maxSmoothness = o.Find(x => x.maxSmoothness),
applyRangeAttenuation = o.Find(x => x.applyRangeAttenuation),
useOldInspector = o.FindProperty(x => x.useOldInspector),
showFeatures = o.FindProperty(x => x.featuresFoldout),
showAdditionalSettings = o.FindProperty(x => x.showAdditionalSettings)
useOldInspector = o.Find(x => x.useOldInspector),
showFeatures = o.Find(x => x.featuresFoldout),
showAdditionalSettings = o.Find(x => x.showAdditionalSettings)
};
// TODO: Review this once AdditionalShadowData is refactored

dimmer = o.FindProperty(x => x.shadowDimmer),
fadeDistance = o.FindProperty(x => x.shadowFadeDistance),
cascadeCount = o.FindProperty("shadowCascadeCount"),
cascadeRatios = o.FindProperty("shadowCascadeRatios"),
cascadeBorders = o.FindProperty("shadowCascadeBorders"),
resolution = o.FindProperty(x => x.shadowResolution)
dimmer = o.Find(x => x.shadowDimmer),
fadeDistance = o.Find(x => x.shadowFadeDistance),
cascadeCount = o.Find("shadowCascadeCount"),
cascadeRatios = o.Find("shadowCascadeRatios"),
cascadeBorders = o.Find("shadowCascadeBorders"),
resolution = o.Find(x => x.shadowResolution)
};
}

97
ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs


public readonly GUIContent heightOffset = new GUIContent("Height Offset", "Offset applied to the height before layering.");
public readonly GUIContent heightTransition = new GUIContent("Height Transition", "Size in world units of the smooth transition between layers.");
public readonly GUIContent perPixelDisplacementLayersWarning = new GUIContent("For pixel displacement to work correctly, all layers with a heightmap must use the same UV mapping");
public readonly GUIContent materialReferencesText = new GUIContent("Material References");
public StylesLayer()

bool mainLayerInfluenceEnable = useMainLayerInfluence.floatValue > 0.0f;
bool heightBasedBlend = useHeightBasedBlend.floatValue > 0.0f;
EditorGUILayout.LabelField(styles.layeringOptionText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
if(layerIndex > 0 || heightBasedBlend )
if (layerIndex > 0)
EditorGUILayout.LabelField(styles.layeringOptionText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
// influence
if (layerIndex > 0)
{
int paramIndex = layerIndex - 1;
int paramIndex = layerIndex - 1;
m_MaterialEditor.ShaderProperty(opacityAsDensity[layerIndex], styles.opacityAsDensityText);
m_MaterialEditor.ShaderProperty(opacityAsDensity[layerIndex], styles.opacityAsDensityText);
if (mainLayerInfluenceEnable)
{
m_MaterialEditor.ShaderProperty(inheritBaseColor[paramIndex], styles.inheritBaseColorText);
m_MaterialEditor.ShaderProperty(inheritBaseNormal[paramIndex], styles.inheritBaseNormalText);
// Main height influence is only available if the shader use the heightmap for displacement (per vertex or per level)
// We always display it as it can be tricky to know when per pixel displacement is enabled or not
m_MaterialEditor.ShaderProperty(inheritBaseHeight[paramIndex], styles.inheritBaseHeightText);
}
if (mainLayerInfluenceEnable)
{
m_MaterialEditor.ShaderProperty(inheritBaseColor[paramIndex], styles.inheritBaseColorText);
m_MaterialEditor.ShaderProperty(inheritBaseNormal[paramIndex], styles.inheritBaseNormalText);
// Main height influence is only available if the shader use the heightmap for displacement (per vertex or per level)
// We always display it as it can be tricky to know when per pixel displacement is enabled or not
m_MaterialEditor.ShaderProperty(inheritBaseHeight[paramIndex], styles.inheritBaseHeightText);
if (heightBasedBlend)
}
else
{
if (!useMainLayerInfluence.hasMixedValue && useMainLayerInfluence.floatValue != 0.0f)
m_MaterialEditor.ShaderProperty(heightOffset[layerIndex], styles.heightOffset);
m_MaterialEditor.TexturePropertySingleLine(styles.layerInfluenceMapMaskText, layerInfluenceMaskMap);
}
EditorGUI.indentLevel--;
EditorGUILayout.Space();
if (heightBasedBlend)
{
m_MaterialEditor.ShaderProperty(heightOffset[layerIndex], styles.heightOffset);
EditorGUI.indentLevel--;
EditorGUILayout.Space();
DoLayerGUI(material, layerIndex);

{
useMainLayerInfluence.floatValue = mainLayerModeInfluenceEnable ? 1.0f : 0.0f;
}
if (!useMainLayerInfluence.hasMixedValue && useMainLayerInfluence.floatValue != 0.0f)
{
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine(styles.layerInfluenceMapMaskText, layerInfluenceMaskMap);
EditorGUI.indentLevel--;
}
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = useHeightBasedBlend.hasMixedValue;

SetKeyword(material, "_HEIGHTMAP" + i, material.GetTexture(kHeightMap + i));
}
SetKeyword(material, "_INFLUENCEMASK_MAP", material.GetTexture(kLayerInfluenceMaskMap) && material.GetFloat(kkUseMainLayerInfluence) != 0.0f);
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_ENABLESPECULAROCCLUSION", material.GetFloat(kEnableSpecularOcclusion) > 0.0f);

{
optionsChanged = true;
}
// In case of pixel displacement and layered shader, all layers must used the same texture mapping for layer that have a heightmap
// (Else the algorithm will not work correctly)
if ((DisplacementMode)displacementMode.floatValue == DisplacementMode.Pixel)
{
float compareValue = -1.0f;
bool match = true;
if (material.GetTexture(kHeightMap + 0))
{
compareValue = UVBase[0].floatValue;
}
if (material.GetTexture(kHeightMap + 1))
{
if (compareValue == -1.0f)
compareValue = UVBase[1].floatValue;
else if (compareValue != UVBase[1].floatValue)
match = false;
}
if (material.GetTexture(kHeightMap + 2))
{
if (compareValue == -1.0f)
compareValue = UVBase[2].floatValue;
else if (compareValue != UVBase[2].floatValue)
match = false;
}
if (material.GetTexture(kHeightMap + 3))
{
if (compareValue == -1.0f)
compareValue = UVBase[3].floatValue;
else if (compareValue != UVBase[3].floatValue)
match = false;
}
if (!match)
{
EditorGUILayout.HelpBox(styles.perPixelDisplacementLayersWarning.text, MessageType.Warning);
}
}
bool layerChanged = DoLayersGUI(materialImporter);
DoEmissiveGUI(material);

45
ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader


_DetailMap2("DetailMap2", 2D) = "black" {}
_DetailMap3("DetailMap3", 2D) = "black" {}
_DetailAlbedoScale0("_DetailAlbedoScale0", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale1("_DetailAlbedoScale1", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale2("_DetailAlbedoScale2", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale3("_DetailAlbedoScale3", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale0("_DetailAlbedoScale0", Range(0.0, 2.0)) = 1
_DetailAlbedoScale1("_DetailAlbedoScale1", Range(0.0, 2.0)) = 1
_DetailAlbedoScale2("_DetailAlbedoScale2", Range(0.0, 2.0)) = 1
_DetailAlbedoScale3("_DetailAlbedoScale3", Range(0.0, 2.0)) = 1
_DetailNormalScale0("_DetailNormalScale0", Range(0.0, 2.0)) = 1
_DetailNormalScale1("_DetailNormalScale1", Range(0.0, 2.0)) = 1

_DetailSmoothnessScale0("_DetailSmoothnessScale0", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale1("_DetailSmoothnessScale1", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale2("_DetailSmoothnessScale2", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale3("_DetailSmoothnessScale3", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale0("_DetailSmoothnessScale0", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale1("_DetailSmoothnessScale1", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale2("_DetailSmoothnessScale2", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale3("_DetailSmoothnessScale3", Range(0.0, 2.0)) = 1
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace0("NormalMap space", Float) = 0
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace1("NormalMap space", Float) = 0

[Enum(None, 0, Mirror, 1, Flip, 2)] _DoubleSidedNormalMode("Double sided normal mode", Float) = 1
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
[Enum(None, 0, Vertex displacement, 1, Pixel displacement, 2)] _DisplacementMode("DisplacementMode", Int) = 0
[ToggleOff] _DisplacementLockObjectScale("displacement lock object scale", Float) = 1.0
[ToggleOff] _DisplacementLockTilingScale("displacement lock tiling scale", Float) = 1.0
[ToggleOff] _PerPixelDisplacementObjectScale("Per pixel displacement object scale", Float) = 1.0
_PPDPrimitiveLength("Primitive length for POM", Float) = 1
_PPDPrimitiveWidth("Primitive width for POM", Float) = 1
[HideInInspector] _InvPrimScale("Inverse primitive scale for non-planar POM", Vector) = (1, 1, 0, 0)
// Displacement map
[ToggleOff] _EnableVertexDisplacement("Enable vertex displacement", Float) = 0.0
[ToggleOff] _VertexDisplacementObjectScale("Vertex displacement object scale", Float) = 1.0
[ToggleOff] _VertexDisplacementTilingScale("Vertex displacement tiling height scale", Float) = 1.0
// Wind
[ToggleOff] _EnableWind("Enable Wind", Float) = 0.0

_TexWorldScale2("Tiling", Float) = 1.0
_TexWorldScale3("Tiling", Float) = 1.0
[HideInInspector] _InvTilingScale0("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[HideInInspector] _InvTilingScale1("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[HideInInspector] _InvTilingScale2("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[HideInInspector] _InvTilingScale3("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, 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

#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _PER_PIXEL_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT_TILING_SCALE
#pragma shader_feature _ _VERTEX_DISPLACEMENT _PIXEL_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _DISPLACEMENT_LOCK_TILING_SCALE
#pragma shader_feature _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _VERTEX_WIND
#pragma shader_feature _LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE

#pragma shader_feature _DETAIL_MAP3
#pragma shader_feature _ _LAYER_MASK_VERTEX_COLOR_MUL _LAYER_MASK_VERTEX_COLOR_ADD
#pragma shader_feature _MAIN_LAYER_INFLUENCE_MODE
#pragma shader_feature _INFLUENCEMASK_MAP
#pragma shader_feature _DENSITY_MODE
#pragma shader_feature _HEIGHT_BASED_BLEND
#pragma shader_feature _ _LAYEREDLIT_3_LAYERS _LAYEREDLIT_4_LAYERS

45
ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader


_DetailMap2("DetailMap2", 2D) = "black" {}
_DetailMap3("DetailMap3", 2D) = "black" {}
_DetailAlbedoScale0("_DetailAlbedoScale0", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale1("_DetailAlbedoScale1", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale2("_DetailAlbedoScale2", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale3("_DetailAlbedoScale3", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale0("_DetailAlbedoScale0", Range(0.0, 2.0)) = 1
_DetailAlbedoScale1("_DetailAlbedoScale1", Range(0.0, 2.0)) = 1
_DetailAlbedoScale2("_DetailAlbedoScale2", Range(0.0, 2.0)) = 1
_DetailAlbedoScale3("_DetailAlbedoScale3", Range(0.0, 2.0)) = 1
_DetailNormalScale0("_DetailNormalScale0", Range(0.0, 2.0)) = 1
_DetailNormalScale1("_DetailNormalScale1", Range(0.0, 2.0)) = 1

_DetailSmoothnessScale0("_DetailSmoothnessScale0", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale1("_DetailSmoothnessScale1", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale2("_DetailSmoothnessScale2", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale3("_DetailSmoothnessScale3", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale0("_DetailSmoothnessScale0", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale1("_DetailSmoothnessScale1", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale2("_DetailSmoothnessScale2", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale3("_DetailSmoothnessScale3", Range(0.0, 2.0)) = 1
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace0("NormalMap space", Float) = 0
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace1("NormalMap space", Float) = 0

[Enum(None, 0, Mirror, 1, Flip, 2)] _DoubleSidedNormalMode("Double sided normal mode", Float) = 1
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
[Enum(None, 0, Vertex displacement, 1, Pixel displacement, 2, Tessellation displacement, 3)] _DisplacementMode("DisplacementMode", Int) = 0
[ToggleOff] _DisplacementLockObjectScale("displacement lock object scale", Float) = 1.0
[ToggleOff] _DisplacementLockTilingScale("displacement lock tiling scale", Float) = 1.0
[ToggleOff] _PerPixelDisplacementObjectScale("Per pixel displacement object scale", Float) = 1.0
_PPDPrimitiveLength("Primitive length for POM", Float) = 1
_PPDPrimitiveWidth("Primitive width for POM", Float) = 1
[HideInInspector] _InvPrimScale("Inverse primitive scale for non-planar POM", Vector) = (1, 1, 0, 0)
// Displacement map
[ToggleOff] _EnableVertexDisplacement("Enable vertex displacement", Float) = 0.0
[ToggleOff] _VertexDisplacementObjectScale("Vertex displacement object scale", Float) = 1.0
[ToggleOff] _VertexDisplacementTilingScale("Vertex displacement tiling height scale", Float) = 1.0
// Wind
[ToggleOff] _EnableWind("Enable Wind", Float) = 0.0

_TexWorldScale2("Tiling", Float) = 1.0
_TexWorldScale3("Tiling", Float) = 1.0
[HideInInspector] _InvTilingScale0("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[HideInInspector] _InvTilingScale1("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[HideInInspector] _InvTilingScale2("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[HideInInspector] _InvTilingScale3("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, 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

#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _PER_PIXEL_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT_TILING_SCALE
#pragma shader_feature _ _VERTEX_DISPLACEMENT _PIXEL_DISPLACEMENT _TESSELLATION_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _DISPLACEMENT_LOCK_TILING_SCALE
#pragma shader_feature _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _VERTEX_WIND
#pragma shader_feature _TESSELLATION_PHONG

#pragma shader_feature _DETAIL_MAP3
#pragma shader_feature _ _LAYER_MASK_VERTEX_COLOR_MUL _LAYER_MASK_VERTEX_COLOR_ADD
#pragma shader_feature _MAIN_LAYER_INFLUENCE_MODE
#pragma shader_feature _INFLUENCEMASK_MAP
#pragma shader_feature _DENSITY_MODE
#pragma shader_feature _HEIGHT_BASED_BLEND
#pragma shader_feature _ _LAYEREDLIT_3_LAYERS _LAYEREDLIT_4_LAYERS

140
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs


public static GUIContent doubleSidedNormalModeText = new GUIContent("Normal mode", "This will modify the normal base on the selected mode. None: untouch, Mirror: Mirror the normal with vertex normal plane, Flip: Flip the normal");
public static GUIContent depthOffsetEnableText = new GUIContent("Enable Depth Offset", "EnableDepthOffset on this shader (Use with heightmap)");
// Displacement mapping (POM, tessellation, per vertex)
//public static GUIContent enablePerPixelDisplacementText = new GUIContent("Enable Per Pixel Displacement", "");
public static GUIContent displacementModeText = new GUIContent("Displacement mode", "Apply heightmap displacement to the selected element: Vertex, pixel or tessellated vertex. Pixel displacement must be use with flat surfaces, it is an expensive features and typical usage is paved road.");
public static GUIContent lockWithObjectScaleText = new GUIContent("Lock with object scale", "Displacement mapping will take the absolute value of the scale of the object into account.");
public static GUIContent lockWithTilingRateText = new GUIContent("Lock with height map tiling rate", "Displacement mapping will take the absolute value of the tiling rate of the height map into account.");
// Per pixel displacement
public static GUIContent enablePerPixelDisplacementText = new GUIContent("Enable Per Pixel Displacement", "Per pixel displacement work best with flat surfaces. This is an expensive features and should be enable wisely. Typical use case is paved road.");
// Per pixel displacement
public static GUIContent perPixelDisplacementObjectScaleText = new GUIContent("Lock with object scale", "Per Pixel displacement will take into account the tiling scale - Only work with uniform positive scale");
// Vertex displacement
public static string vertexDisplacementText = "Vertex displacement";
public static GUIContent enableVertexDisplacementText = new GUIContent("Enable vertex displacement", "Use heightmap as a displacement map. Displacement map is use to move vertex position in local space");
public static GUIContent vertexDisplacementObjectScaleText = new GUIContent("Lock with object scale", "Vertex displacement will take into account the object scale - Only work with uniform positive scale");
public static GUIContent vertexDisplacementTilingScaleText = new GUIContent("Lock with heightmap tiling", "Vertex displacement will take into account the tiling scale - Only work with uniform positive scale");
public static GUIContent ppdPrimitiveLength = new GUIContent("Primitive length", "Dimensions of the primitive (with the scale of 1) to which the per-pixel displacement mapping is being applied. For example, the standard quad is 1 x 1 meter, while the standard plane is 10 x 10 meters.");
public static GUIContent ppdPrimitiveWidth = new GUIContent("Primitive width", "Dimensions of the primitive (with the scale of 1) to which the per-pixel displacement mapping is being applied. For example, the standard quad is 1 x 1 meter, while the standard plane is 10 x 10 meters.");
public static string tessellationModeText = "Tessellation Mode";
public static string tessellationModeStr = "Tessellation Mode";
public static readonly string[] tessellationModeNames = Enum.GetNames(typeof(TessellationMode));
public static GUIContent tessellationText = new GUIContent("Tessellation options", "Tessellation options");

Phong
}
public enum DisplacementMode
{
None,
Vertex,
Pixel,
Tessellation
}
protected MaterialProperty doubleSidedNormalMode = null;
protected const string kDoubleSidedNormalMode = "_DoubleSidedNormalMode";
protected MaterialProperty depthOffsetEnable = null;

protected const string kStencilRef = "_StencilRef";
protected MaterialProperty displacementMode = null;
protected const string kDisplacementMode = "_DisplacementMode";
protected MaterialProperty displacementLockObjectScale = null;
protected const string kDisplacementLockObjectScale = "_DisplacementLockObjectScale";
protected MaterialProperty displacementLockTilingScale = null;
protected const string kDisplacementLockTilingScale = "_DisplacementLockTilingScale";
protected MaterialProperty enablePerPixelDisplacement = null;
protected const string kEnablePerPixelDisplacement = "_EnablePerPixelDisplacement";
protected MaterialProperty ppdMinSamples = null;
protected const string kPpdMinSamples = "_PPDMinSamples";
protected MaterialProperty ppdMaxSamples = null;

protected MaterialProperty perPixelDisplacementObjectScale = null;
protected const string kPerPixelDisplacementObjectScale = "_PerPixelDisplacementObjectScale";
// Vertex displacement
protected MaterialProperty enableVertexDisplacement = null;
protected const string kEnableVertexDisplacement = "_EnableVertexDisplacement";
protected MaterialProperty vertexDisplacementObjectScale = null;
protected const string kVertexDisplacementObjectScale = "_VertexDisplacementObjectScale";
protected MaterialProperty vertexDisplacementTilingScale = null;
protected const string kVertexDisplacementTilingScale = "_VertexDisplacementTilingScale";
protected MaterialProperty ppdPrimitiveLength = null;
protected const string kPpdPrimitiveLength = "_PPDPrimitiveLength";
protected MaterialProperty ppdPrimitiveWidth = null;
protected const string kPpdPrimitiveWidth = "_PPDPrimitiveWidth";
protected MaterialProperty invPrimScale = null;
protected const string kInvPrimScale = "_InvPrimScale";
// Wind
protected MaterialProperty windEnable = null;

// MaterialID
materialID = FindProperty(kMaterialID, props, false); // LayeredLit is force to be standard for now, so materialID could not exist
displacementMode = FindProperty(kDisplacementMode, props);
displacementLockObjectScale = FindProperty(kDisplacementLockObjectScale, props);
displacementLockTilingScale = FindProperty(kDisplacementLockTilingScale, props);
enablePerPixelDisplacement = FindProperty(kEnablePerPixelDisplacement, props);
perPixelDisplacementObjectScale = FindProperty(kPerPixelDisplacementObjectScale, props);
// vertex displacement
enableVertexDisplacement = FindProperty(kEnableVertexDisplacement, props);
vertexDisplacementObjectScale = FindProperty(kVertexDisplacementObjectScale, props);
vertexDisplacementTilingScale = FindProperty(kVertexDisplacementTilingScale, props);
ppdPrimitiveLength = FindProperty(kPpdPrimitiveLength, props);
ppdPrimitiveWidth = FindProperty(kPpdPrimitiveWidth, props);
invPrimScale = FindProperty(kInvPrimScale, props);
// tessellation specific, silent if not found
tessellationMode = FindProperty(kTessellationMode, props, false);

var mode = (TessellationMode)tessellationMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (TessellationMode)EditorGUILayout.Popup(StylesBaseLit.tessellationModeText, (int)mode, StylesBaseLit.tessellationModeNames);
mode = (TessellationMode)EditorGUILayout.Popup(StylesBaseLit.tessellationModeStr, (int)mode, StylesBaseLit.tessellationModeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Tessellation Mode");

if (materialID != null)
m_MaterialEditor.ShaderProperty(materialID, StylesBaseLit.materialIDText);
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, StylesBaseLit.enablePerPixelDisplacementText);
if (enablePerPixelDisplacement.floatValue > 0.0f)
m_MaterialEditor.ShaderProperty(displacementMode, StylesBaseLit.displacementModeText);
if ((DisplacementMode)displacementMode.floatValue != DisplacementMode.None)
m_MaterialEditor.ShaderProperty(ppdMinSamples, StylesBaseLit.ppdMinSamplesText);
m_MaterialEditor.ShaderProperty(ppdMaxSamples, StylesBaseLit.ppdMaxSamplesText);
ppdMinSamples.floatValue = Mathf.Min(ppdMinSamples.floatValue, ppdMaxSamples.floatValue);
m_MaterialEditor.ShaderProperty(ppdLodThreshold, StylesBaseLit.ppdLodThresholdText);
//m_MaterialEditor.ShaderProperty(perPixelDisplacementObjectScale, StylesBaseLit.perPixelDisplacementObjectScaleText);
m_MaterialEditor.ShaderProperty(depthOffsetEnable, StylesBaseLit.depthOffsetEnableText);
m_MaterialEditor.ShaderProperty(displacementLockObjectScale, StylesBaseLit.lockWithObjectScaleText);
m_MaterialEditor.ShaderProperty(displacementLockTilingScale, StylesBaseLit.lockWithTilingRateText);
EditorGUI.indentLevel--;
// Vertex displacement options
EditorGUILayout.Space();
EditorGUILayout.LabelField(StylesBaseLit.vertexDisplacementText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(enableVertexDisplacement, StylesBaseLit.enableVertexDisplacementText);
if (enableVertexDisplacement.floatValue > 0.0f)
if ((DisplacementMode)displacementMode.floatValue == DisplacementMode.Pixel)
EditorGUILayout.Space();
m_MaterialEditor.ShaderProperty(vertexDisplacementObjectScale, StylesBaseLit.vertexDisplacementObjectScaleText);
m_MaterialEditor.ShaderProperty(vertexDisplacementTilingScale, StylesBaseLit.vertexDisplacementTilingScaleText);
m_MaterialEditor.ShaderProperty(ppdMinSamples, StylesBaseLit.ppdMinSamplesText);
m_MaterialEditor.ShaderProperty(ppdMaxSamples, StylesBaseLit.ppdMaxSamplesText);
ppdMinSamples.floatValue = Mathf.Min(ppdMinSamples.floatValue, ppdMaxSamples.floatValue);
m_MaterialEditor.ShaderProperty(ppdLodThreshold, StylesBaseLit.ppdLodThresholdText);
m_MaterialEditor.ShaderProperty(ppdPrimitiveLength, StylesBaseLit.ppdPrimitiveLength);
ppdPrimitiveLength.floatValue = Mathf.Max(0.01f, ppdPrimitiveLength.floatValue);
m_MaterialEditor.ShaderProperty(ppdPrimitiveWidth, StylesBaseLit.ppdPrimitiveWidth);
ppdPrimitiveWidth.floatValue = Mathf.Max(0.01f, ppdPrimitiveWidth.floatValue);
invPrimScale.vectorValue = new Vector4(1.0f / ppdPrimitiveLength.floatValue, 1.0f / ppdPrimitiveWidth.floatValue); // Precompute
m_MaterialEditor.ShaderProperty(depthOffsetEnable, StylesBaseLit.depthOffsetEnableText);
EditorGUI.indentLevel--;
}

}
}
// Depth offset is only enabled if per pixel displacement is
bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && (material.GetFloat(kEnablePerPixelDisplacement) > 0.0f);
SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable);
// Set the reference value for the stencil test.
int stencilRef = (int)StencilLightingUsage.RegularLighting;
if (material.HasProperty(kMaterialID))

}
material.SetInt(kStencilRef, stencilRef);
bool enablePerPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) > 0.0f;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", enablePerPixelDisplacement);
bool perPixelDisplacementObjectScale = material.GetFloat(kPerPixelDisplacementObjectScale) > 0.0;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT_OBJECT_SCALE", perPixelDisplacementObjectScale && enablePerPixelDisplacement);
bool enableDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) != DisplacementMode.None;
bool enableVertexDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Vertex;
bool enablePixelDisplacement = (DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Pixel;
bool enableTessellationDisplacement = ((DisplacementMode)material.GetFloat(kDisplacementMode) == DisplacementMode.Tessellation) && material.HasProperty(kTessellationMode);
bool enableVertexDisplacement = material.GetFloat(kEnableVertexDisplacement) > 0.0f;
bool vertexDisplacementObjectScaleEnable = material.GetFloat(kVertexDisplacementObjectScale) > 0.0;
SetKeyword(material, "_VERTEX_DISPLACEMENT_OBJECT_SCALE", vertexDisplacementObjectScaleEnable && enableVertexDisplacement);
SetKeyword(material, "_PIXEL_DISPLACEMENT", enablePixelDisplacement);
// Only set if tessellation exist
SetKeyword(material, "_TESSELLATION_DISPLACEMENT", enableTessellationDisplacement);
bool vertexDisplacementTilingScaleEnable = material.GetFloat(kVertexDisplacementTilingScale) > 0.0;
SetKeyword(material, "_VERTEX_DISPLACEMENT_TILING_SCALE", vertexDisplacementTilingScaleEnable && enableVertexDisplacement);
bool displacementLockObjectScale = material.GetFloat(kDisplacementLockObjectScale) > 0.0;
bool displacementLockTilingScale = material.GetFloat(kDisplacementLockTilingScale) > 0.0;
// Tessellation reuse vertex flag.
SetKeyword(material, "_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && (enableVertexDisplacement || enableTessellationDisplacement));
SetKeyword(material, "_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE", displacementLockObjectScale && enablePixelDisplacement);
SetKeyword(material, "_DISPLACEMENT_LOCK_TILING_SCALE", displacementLockTilingScale && enableDisplacement);
// Depth offset is only enabled if per pixel displacement is
bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && enablePixelDisplacement;
SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable);
if (material.HasProperty(kTessellationMode))
{

110
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs


using System;
using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;

public static GUIContent detailAlbedoScaleText = new GUIContent("Detail AlbedoScale", "Detail Albedo Scale factor");
public static GUIContent detailNormalScaleText = new GUIContent("Detail NormalScale", "Normal Scale factor");
public static GUIContent detailSmoothnessScaleText = new GUIContent("Detail SmoothnessScale", "Smoothness Scale factor");
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.");

// Transparency absorption
public static GUIContent transmittanceColorText = new GUIContent("Transmittance Color", "Absorption color (RGB)");
public static GUIContent atDistanceText = new GUIContent("Transmittance Absorption Distance", "Absorption distance reference");
public static GUIContent perPixelDisplacementDetailsWarning = new GUIContent("For pixel displacement to work correctly, details and base map must use same UV mapping");
}
// Lit shader is not layered but some layered materials inherit from it. In order to share code we need LitUI to account for this.

protected const string kUVBase = "_UVBase";
protected MaterialProperty[] TexWorldScale = new MaterialProperty[kMaxLayerCount];
protected const string kTexWorldScale = "_TexWorldScale";
protected MaterialProperty[] InvTilingScale = new MaterialProperty[kMaxLayerCount];
protected const string kInvTilingScale = "_InvTilingScale";
protected MaterialProperty[] UVMappingMask = new MaterialProperty[kMaxLayerCount];
protected const string kUVMappingMask = "_UVMappingMask";

protected const string kUVDetailsMappingMask = "_UVDetailsMappingMask";
protected MaterialProperty[] detailMap = new MaterialProperty[kMaxLayerCount];
protected const string kDetailMap = "_DetailMap";
protected MaterialProperty[] linkDetailsWithBase = new MaterialProperty[kMaxLayerCount];
protected const string kLinkDetailsWithBase = "_LinkDetailsWithBase";
protected MaterialProperty[] detailAlbedoScale = new MaterialProperty[kMaxLayerCount];
protected const string kDetailAlbedoScale = "_DetailAlbedoScale";
protected MaterialProperty[] detailNormalScale = new MaterialProperty[kMaxLayerCount];

protected MaterialProperty anisotropyMap = null;
protected const string kAnisotropyMap = "_AnisotropyMap";
protected SubsurfaceScatteringProfile subsurfaceProfile = null;
protected MaterialProperty subsurfaceProfileID = null;
protected const string kSubsurfaceProfileID = "_SubsurfaceProfile";
protected MaterialProperty subsurfaceRadius = null;

{
UVBase[i] = FindProperty(string.Format("{0}{1}", kUVBase, m_PropertySuffixes[i]), props);
TexWorldScale[i] = FindProperty(string.Format("{0}{1}", kTexWorldScale, m_PropertySuffixes[i]), props);
InvTilingScale[i] = FindProperty(string.Format("{0}{1}", kInvTilingScale, m_PropertySuffixes[i]), props);
UVMappingMask[i] = FindProperty(string.Format("{0}{1}", kUVMappingMask, m_PropertySuffixes[i]), props);
baseColor[i] = FindProperty(string.Format("{0}{1}", kBaseColor, m_PropertySuffixes[i]), props);

// Details
UVDetail[i] = FindProperty(string.Format("{0}{1}", kUVDetail, m_PropertySuffixes[i]), props);
UVDetailsMappingMask[i] = FindProperty(string.Format("{0}{1}", kUVDetailsMappingMask, m_PropertySuffixes[i]), props);
linkDetailsWithBase[i] = FindProperty(string.Format("{0}{1}", kLinkDetailsWithBase, m_PropertySuffixes[i]), props);
detailMap[i] = FindProperty(string.Format("{0}{1}", kDetailMap, m_PropertySuffixes[i]), props);
detailAlbedoScale[i] = FindProperty(string.Format("{0}{1}", kDetailAlbedoScale, m_PropertySuffixes[i]), props);
detailNormalScale[i] = FindProperty(string.Format("{0}{1}", kDetailNormalScale, m_PropertySuffixes[i]), props);

protected void ShaderSSSInputGUI(Material material)
{
HDRenderPipeline hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
var hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
var sssSettings = hdPipeline.sssSettings;
if (subsurfaceProfile == null)
if (sssSettings == null)
// Attempt to load the profile from the SSS Settings.
int profileID = (int)subsurfaceProfileID.floatValue;
if (0 <= profileID && profileID < hdPipeline.sssSettings.profiles.Length &&
hdPipeline.sssSettings.profiles[profileID] != null)
{
// This is a valid profile ID.
subsurfaceProfile = hdPipeline.sssSettings.profiles[profileID];
// Refresh the ID of the profile.
hdPipeline.sssSettings.OnValidate();
}
EditorGUILayout.HelpBox("No Subsurface Scattering Settings have been assigned to the render pipeline asset.", MessageType.Warning);
return;
subsurfaceProfile = EditorGUILayout.ObjectField(Styles.subsurfaceProfileText, subsurfaceProfile, typeof(SubsurfaceScatteringProfile), false) as SubsurfaceScatteringProfile;
// TODO: Optimize me
var profiles = hdPipeline.sssSettings.profiles;
var names = new GUIContent[profiles.Length + 1];
names[0] = new GUIContent("None");
bool validProfile = false;
var values = new int[names.Length];
values[0] = SssConstants.SSS_NEUTRAL_PROFILE_ID;
// Set the profile ID.
if (subsurfaceProfile != null)
for (int i = 0; i < profiles.Length; i++)
// Load the profile from the GUI field.
int profileID = subsurfaceProfile.settingsIndex;
names[i + 1] = new GUIContent(profiles[i].name);
values[i + 1] = i;
}
if (0 <= profileID && profileID < hdPipeline.sssSettings.profiles.Length &&
hdPipeline.sssSettings.profiles[profileID] != null &&
hdPipeline.sssSettings.profiles[profileID] == subsurfaceProfile)
{
validProfile = true;
material.SetInt("_SubsurfaceProfile", profileID);
}
else
using (var scope = new EditorGUI.ChangeCheckScope())
{
int profileID = (int)subsurfaceProfileID.floatValue;
using (new EditorGUILayout.HorizontalScope())
subsurfaceProfile = null;
Debug.LogError("The SSS Profile assigned to the material has an invalid index. First, add the Profile to the SSS Settings, and then reassign it to the material.");
EditorGUILayout.PrefixLabel(Styles.subsurfaceProfileText);
using (new EditorGUILayout.HorizontalScope())
{
profileID = EditorGUILayout.IntPopup(profileID, names, values);
if (GUILayout.Button("Goto", EditorStyles.miniButton, GUILayout.Width(50f)))
Selection.activeObject = sssSettings;
}
}
if (!validProfile)
{
// Disable SSS for this object.
material.SetInt("_SubsurfaceProfile", SssConstants.SSS_NEUTRAL_PROFILE_ID);
if (scope.changed)
subsurfaceProfileID.floatValue = profileID;
}
m_MaterialEditor.ShaderProperty(subsurfaceRadius, Styles.subsurfaceRadiusText);

if (!heightMap[layerIndex].hasMixedValue && heightMap[layerIndex].textureValue != null)
{
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
heightAmplitude[layerIndex].floatValue = (heightMax[layerIndex].floatValue - heightMin[layerIndex].floatValue) * 0.01f; // Conversion centimeters to meters.
if (EditorGUI.EndChangeCheck())
{
heightAmplitude[layerIndex].floatValue = (heightMax[layerIndex].floatValue - heightMin[layerIndex].floatValue) * 0.01f; // Conversion centimeters to meters.
}
m_MaterialEditor.ShaderProperty(heightCenter[layerIndex], Styles.heightMapCenterText);
EditorGUI.showMixedValue = false;
EditorGUI.indentLevel--;

}
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
m_MaterialEditor.ShaderProperty(UVBase[layerIndex], Styles.UVBaseMappingText);
UVBaseMapping uvBaseMapping = (UVBaseMapping)UVBase[layerIndex].floatValue;

W = (uvBaseMapping == UVBaseMapping.UV3) ? 1.0f : 0.0f;
UVMappingMask[layerIndex].colorValue = new Color(X, Y, Z, W);
if (EditorGUI.EndChangeCheck())
{
// Precompute.
InvTilingScale[layerIndex].floatValue = 2.0f / (Mathf.Abs(baseColorMap[layerIndex].textureScaleAndOffset.x) + Mathf.Abs(baseColorMap[layerIndex].textureScaleAndOffset.y));
if ((uvBaseMapping == UVBaseMapping.Planar) || (uvBaseMapping == UVBaseMapping.Triplanar))
{
InvTilingScale[layerIndex].floatValue = InvTilingScale[layerIndex].floatValue / TexWorldScale[layerIndex].floatValue;
}
}
EditorGUI.indentLevel--;
EditorGUILayout.Space();

else
{
m_MaterialEditor.ShaderProperty(UVDetail[layerIndex], Styles.UVDetailMappingText);
}
}
// Setup the UVSet for detail, if planar/triplanar is use for base, it will override the mapping of detail (See shader code)
X = ((UVDetailMapping)UVDetail[layerIndex].floatValue == UVDetailMapping.UV0) ? 1.0f : 0.0f;

UVDetailsMappingMask[layerIndex].colorValue = new Color(X, Y, Z, W);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(linkDetailsWithBase[layerIndex], Styles.linkDetailsWithBaseText);
EditorGUI.indentLevel--;
if ((DisplacementMode)displacementMode.floatValue == DisplacementMode.Pixel && (UVDetail[layerIndex].floatValue != UVBase[layerIndex].floatValue))
{
if (material.GetTexture(kDetailMap + m_PropertySuffixes[layerIndex]))
EditorGUILayout.HelpBox(Styles.perPixelDisplacementDetailsWarning.text, MessageType.Warning);
}
m_MaterialEditor.ShaderProperty(detailAlbedoScale[layerIndex], Styles.detailAlbedoScaleText);
m_MaterialEditor.ShaderProperty(detailNormalScale[layerIndex], Styles.detailNormalScaleText);
m_MaterialEditor.ShaderProperty(detailSmoothnessScale[layerIndex], Styles.detailSmoothnessScaleText);

// TODO: display warning if we don't have bent normal (either OS or TS) and ambient occlusion
//if (enableSpecularOcclusion.floatValue > 0.0f)
{
//EditorGUILayout.HelpBox(Styles.specularOcclusionWarning.text, MessageType.Error);
//EditorGUILayout.HelpBox(Styles.specularOcclusionWarning.text, MessageType.Error);
EditorGUI.indentLevel++;
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
m_MaterialEditor.ShaderProperty(albedoAffectEmissive, Styles.albedoAffectEmissiveText);

5
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.Styles.cs


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
partial class SubsurfaceScatteringProfileEditor
public sealed partial class SubsurfaceScatteringSettingsEditor
// TODO: missing tooltips
public readonly GUIContent useDisneySSS = new GUIContent("Use Disney SSS");
public readonly GUIContent profilePreview0 = new GUIContent("Profile Preview");
public readonly GUIContent profilePreview1 = new GUIContent("Shows the fraction of light scattered from the source (center).");
public readonly GUIContent profilePreview2 = new GUIContent("The distance to the boundary of the image corresponds to the Max Radius.");

13
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


// Clear coat IBL
// In the case of IBL we want shift a bit the normal that are not toward the viewver to reduce artifact
float3 coatIblNormalWS = GetViewShiftedNormal(bsdfData.coatNormalWS, V, preLightData.coatNdotV, MIN_N_DOT_V);
float3 coatIblNormalWS = GetViewShiftedNormal(bsdfData.coatNormalWS, V, preLightData.coatNdotV, MIN_N_DOT_V); // Use non-clamped NdotV
float coatNdotV = max(preLightData.coatNdotV, MIN_N_DOT_V); // Use the modified (clamped) version
float theta = FastACos(preLightData.coatNdotV);
float theta = FastACosPos(coatNdotV);
float2 uv = LTC_LUT_OFFSET + LTC_LUT_SCALE * float2(0.0, theta * INV_HALF_PI); // Use Roughness of 0.0 for clearCoat roughness
// Get the inverse LTC matrix for GGX

}
preLightData.NdotV = dot(bsdfData.normalWS, V); // Store the unaltered (geometric) version
float NdotV = preLightData.NdotV;
float3 iblNormalWS = GetViewShiftedNormal(bsdfData.normalWS, V, NdotV, MIN_N_DOT_V); // Use non clamped NdotV
float3 iblNormalWS = GetViewShiftedNormal(bsdfData.normalWS, V, preLightData.NdotV, MIN_N_DOT_V); // Use non-clamped NdotV
NdotV = max(NdotV, MIN_N_DOT_V); // Use the modified (clamped) version
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V); // Use the modified (clamped) version
// GGX iso
preLightData.ggxPreLambdaV = GetSmithJointGGXPreLambdaV(NdotV, bsdfData.roughness);

// Area light
// UVs for sampling the LUTs
float theta = FastACos(NdotV); // For Area light - UVs for sampling the LUTs
float theta = FastACosPos(NdotV); // For Area light - UVs for sampling the LUTs
float2 uv = LTC_LUT_OFFSET + LTC_LUT_SCALE * float2(bsdfData.perceptualRoughness, theta * INV_HALF_PI);
// Note we load the matrix transpose (avoid to have to transpose it in shader)

29
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader


_HeightCenter("Height Center", Range(0.0, 1.0)) = 0.5 // In texture space
_DetailMap("DetailMap", 2D) = "black" {}
_DetailAlbedoScale("_DetailAlbedoScale", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale("_DetailAlbedoScale", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale("_DetailSmoothnessScale", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale("_DetailSmoothnessScale", Range(0.0, 2.0)) = 1
_TangentMap("TangentMap", 2D) = "bump" {}
_TangentMapOS("TangentMapOS", 2D) = "white" {}

[Enum(UV0, 0, Planar, 4, TriPlanar, 5)] _UVBase("UV Set for base", Float) = 0
_TexWorldScale("Scale to apply on world coordinate", Float) = 1.0
[HideInInspector] _InvTilingScale("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
[Enum(None, 0, Vertex displacement, 1, Pixel displacement, 2)] _DisplacementMode("DisplacementMode", Int) = 0
[ToggleOff] _DisplacementLockObjectScale("displacement lock object scale", Float) = 1.0
[ToggleOff] _DisplacementLockTilingScale("displacement lock tiling scale", Float) = 1.0
[ToggleOff] _PerPixelDisplacementObjectScale("Per pixel displacement object scale", Float) = 1.0
_PPDPrimitiveLength("Primitive length for POM", Float) = 1
_PPDPrimitiveWidth("Primitive width for POM", Float) = 1
[HideInInspector] _InvPrimScale("Inverse primitive scale for non-planar POM", Vector) = (1, 1, 0, 0)
[ToggleOff] _LinkDetailsWithBase("LinkDetailsWithBase", Float) = 1.0
// Displacement map
[ToggleOff] _EnableVertexDisplacement("Enable vertex displacement", Float) = 0.0
[ToggleOff] _VertexDisplacementObjectScale("Vertex displacement object scale", Float) = 1.0
[ToggleOff] _VertexDisplacementTilingScale("Vertex displacement tiling height scale", Float) = 1.0
// Wind
[ToggleOff] _EnableWind("Enable Wind", Float) = 0.0

#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _PER_PIXEL_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT_TILING_SCALE
#pragma shader_feature _ _VERTEX_DISPLACEMENT _PIXEL_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _DISPLACEMENT_LOCK_TILING_SCALE
#pragma shader_feature _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _VERTEX_WIND
#pragma shader_feature _ _REFRACTION_THINPLANE _REFRACTION_THICKPLANE _REFRACTION_THICKSPHERE

682
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl


}
#endif
// Share by Lit and LayeredLit. Return object scaling for displacement map depends if it is vertex (affect vertex displacement) or pixel displacement (affect tiling)
float3 GetDisplacementObjectScale(bool vertexDisplacement)
{
float3 objectScale = float3(1.0, 1.0, 1.0);
// TODO: This should be an uniform for the object, this code should be remove once we have it. - Workaround for now
// To handle object scaling with pixel displacement we need to multiply the view vector by the inverse scale.
// To Handle object scaling with vertex/tessellation displacement we must multiply displacement by object scale
// Currently we extract either the scale (ObjectToWorld) or the inverse scale (worldToObject) directly by taking the transform matrix
float4x4 worldTransform;
if (vertexDisplacement)
{
worldTransform = GetObjectToWorldMatrix();
}
else
{
worldTransform = GetWorldToObjectMatrix();
}
objectScale.x = length(float3(worldTransform._m00, worldTransform._m01, worldTransform._m02));
// In the specific case of pixel displacement mapping, to get a consistent behavior compare to tessellation we require to not take into account y scale if lock object scale is not enabled
#if !defined(_PIXEL_DISPLACEMENT) || (defined(_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE))
objectScale.y = length(float3(worldTransform._m10, worldTransform._m11, worldTransform._m12));
#endif
objectScale.z = length(float3(worldTransform._m20, worldTransform._m21, worldTransform._m22));
return objectScale;
}
#ifndef LAYERED_LIT_SHADER

// Be sure that the compiler is aware that we don't use UV1 to UV3 for main layer so it can optimize code
ComputeLayerTexCoord( texCoord0, texCoord1, texCoord2, texCoord3, float4(1.0, 0.0, 0.0, 0.0), _UVDetailsMappingMask,
_BaseColorMap_ST.xy, _BaseColorMap_ST.zw, _DetailMap_ST.xy, _DetailMap_ST.zw, 1.0,
_BaseColorMap_ST.xy, _BaseColorMap_ST.zw, _DetailMap_ST.xy, _DetailMap_ST.zw, 1.0, _LinkDetailsWithBase,
positionWS, _TexWorldScale,
mappingType, layerTexCoord);
}

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

#include "../../../Core/ShaderLibrary/PerPixelDisplacement.hlsl"
void ApplyDisplacementTileScale(inout float height)
{
// Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y)
// Inverse tiling scale *= (1 / _TexWorldScale) if planar or triplanar
#ifdef _DISPLACEMENT_LOCK_TILING_SCALE
height *= _InvTilingScale;
#endif
}
bool ppdEnable = false;
bool isPlanar = false;
bool isTriplanar = false;
#if defined(_PIXEL_DISPLACEMENT) && defined(_HEIGHTMAP)
// These variables are known at the compile time.
bool isPlanar = layerTexCoord.base.mappingType == UV_MAPPING_PLANAR;
bool isTriplanar = layerTexCoord.base.mappingType == UV_MAPPING_TRIPLANAR;
#if defined(_PER_PIXEL_DISPLACEMENT) && defined(_HEIGHTMAP)
// All variable are compile time value
ppdEnable = true;
isPlanar = layerTexCoord.base.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base.mappingType == UV_MAPPING_TRIPLANAR;
#endif
// See comment in layered version for details
float maxHeight = GetMaxDisplacement();
ApplyDisplacementTileScale(maxHeight);
float2 minUvSize = GetMinUvSize(layerTexCoord);
float lod = ComputeTextureLOD(minUvSize);
if (ppdEnable)
{
// See comment in layered version for details
float maxHeight = GetMaxDisplacement();
float2 minUvSize = GetMinUvSize(layerTexCoord);
float lod = ComputeTextureLOD(minUvSize);
// TODO: precompute uvSpaceScale
float2 invPrimScale = (isPlanar || isTriplanar) ? float2(1.0, 1.0) : _InvPrimScale.xy;
float worldScale = (isPlanar || isTriplanar) ? _TexWorldScale : 1.0;
float2 uvSpaceScale = invPrimScale * _BaseColorMap_ST.xy * (worldScale * maxHeight);
float2 scaleOffsetDetails = _DetailMap_ST.xy;
PerPixelHeightDisplacementParam ppdParam;
PerPixelHeightDisplacementParam ppdParam;
float height = 0; // final height processed
float NdotV = 0;
float height; // final height processed
float NdotV;
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
// TODO: support object space planar/triplanar ?
// TODO: support object space planar/triplanar ?
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
float planeHeight;
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
// Perform a POM in each direction and modify appropriate texture coordinate
[branch] if (layerTexCoord.triplanarWeights.x >= 0.001)
float3 viewDirTS;
float planeHeight;
int numSteps;
// Perform a POM in each direction and modify appropriate texture coordinate
ppdParam.uv = layerTexCoord.base.uvZY;
viewDirTS = float3(V.x > 0.0 ? uvZY : -uvZY, V.x);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetZY = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
ppdParam.uv = layerTexCoord.base.uvZY;
float3 viewDirTS = float3(uvZY, abs(V.x));
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, ppdParam, planeHeight);
layerTexCoord.base.uvZY += offsetZY;
layerTexCoord.details.uvZY += offsetZY;
height = layerTexCoord.triplanarWeights.x * planeHeight;
layerTexCoord.base.uvZY += offset;
layerTexCoord.details.uvZY += offset * scaleOffsetDetails;
height += layerTexCoord.triplanarWeights.x * planeHeight;
NdotV += layerTexCoord.triplanarWeights.x * viewDirTS.z;
}
ppdParam.uv = layerTexCoord.base.uvXZ;
viewDirTS = float3(V.y > 0.0 ? uvXZ : -uvXZ, V.y);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetXZ = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
[branch] if (layerTexCoord.triplanarWeights.y >= 0.001)
{
ppdParam.uv = layerTexCoord.base.uvXZ;
float3 viewDirTS = float3(uvXZ, abs(V.y));
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, ppdParam, planeHeight);
layerTexCoord.base.uvXZ += offsetXZ;
layerTexCoord.details.uvXZ += offsetXZ;
layerTexCoord.base.uvXZ += offset;
layerTexCoord.details.uvXZ += offset * scaleOffsetDetails;
NdotV += layerTexCoord.triplanarWeights.y * viewDirTS.z;
}
ppdParam.uv = layerTexCoord.base.uvXY;
viewDirTS = float3(V.z > 0.0 ? uvXY : -uvXY, V.z);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetXY = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
[branch] if (layerTexCoord.triplanarWeights.z >= 0.001)
{
ppdParam.uv = layerTexCoord.base.uvXY;
float3 viewDirTS = float3(uvXY, abs(V.z));
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, ppdParam, planeHeight);
layerTexCoord.base.uvXY += offsetXY;
layerTexCoord.details.uvXY += offsetXY;
layerTexCoord.base.uvXY += offset;
layerTexCoord.details.uvXY += offset * scaleOffsetDetails;
NdotV = 1; // TODO.
NdotV += layerTexCoord.triplanarWeights.z * viewDirTS.z;
else
{
ppdParam.uv = layerTexCoord.base.uv; // For planar it is uv too, not uvXZ
}
else
{
ppdParam.uv = layerTexCoord.base.uv; // For planar it is uv too, not uvXZ
float3x3 worldToTangent = input.worldToTangent;
// Note: The TBN is not normalize as it is based on mikkt. We should normalize it, but POM is always use on simple enough surfarce that mean it is not required (save 2 normalize). Tag: SURFACE_GRADIENT
float3 viewDirTS = isPlanar ? float3(uvXZ, V.y) : TransformWorldToTangent(V, input.worldToTangent) * GetDisplacementObjectScale(false).xzy; // Switch from Y-up to Z-up (as we move to tangent space)
NdotV = viewDirTS.z;
// Note: The TBN is not normalize as it is based on mikkt. We should normalize it, but POM is always use on simple enough surfarce that mean it is not required (save 2 normalize). Tag: SURFACE_GRADIENT
float3 viewDirTS = isPlanar ? float3(uvXZ, V.y) : TransformWorldToTangent(V, worldToTangent);
NdotV = viewDirTS.z;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);
// Apply offset to all UVSet0 / planar
layerTexCoord.base.uv += offset;
layerTexCoord.details.uv += isPlanar ? offset : _UVDetailsMappingMask.x * offset; // Only apply offset if details map use UVSet0 _UVDetailsMappingMask.x will be 1 in this case, else 0
}
// Transform the view vector into the UV space.
float3 viewDirUV = normalize(float3(viewDirTS.xy * uvSpaceScale, viewDirTS.z)); // TODO: skip normalize
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, ppdParam, height);
// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
float verticalDisplacement = maxHeight - height * maxHeight;
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap_ST.x, _BaseColorMap_ST.y));
return tilingScale * verticalDisplacement / NdotV;
// Apply offset to all UVSet0 / planar
layerTexCoord.base.uv += offset;
// Note: Applying offset on detail uv is only correct if it use the same UVSet or is planar or triplanar. It is up to the user to do the correct thing.
layerTexCoord.details.uv += offset * scaleOffsetDetails;
// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
float verticalDisplacement = maxHeight - height * maxHeight;
return verticalDisplacement / max(NdotV, 0.001);
#else
#endif
float ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
float3 ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
#ifdef _VERTEX_DISPLACEMENT_TILING_SCALE
// When we change the tiling, we have want to conserve the ratio with the displacement (and this is consistent with per pixel displacement)
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap_ST.x, _BaseColorMap_ST.y));
height *= tilingScale;
#endif
return height;
// Height is affected by tiling property and by object scale (depends on option).
// Apply scaling from tiling properties (TexWorldScale and tiling from BaseColor)
ApplyDisplacementTileScale(height);
// Applying scaling of the object if requested
#ifdef _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE
float3 objectScale = GetDisplacementObjectScale(true);
// Reminder: mappingType is know statically, so code below is optimize by the compiler
// Planar and Triplanar are in world space thus it is independent of object scale
return height.xxx * ((layerTexCoord.base.mappingType == UV_MAPPING_UVSET) ? objectScale : float3(1.0, 1.0, 1.0));
#else
return height.xxx;
#endif
}
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)

GetBuiltinData(input, surfaceData, alpha, bentNormalWS, depthOffset, builtinData);
}
#else
#else // if LAYERED_LIT_SHADER
#define LAYERS_HEIGHTMAP_ENABLE (defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || (_LAYER_COUNT > 2 && defined(_HEIGHTMAP2)) || (_LAYER_COUNT > 3 && defined(_HEIGHTMAP3)))
// Number of sampler are limited, we need to share sampler as much as possible with lit material
// for this we put the constraint that the sampler are the same in a layered material for all textures of the same type

#endif
// Define a helper macro
#define ADD_ZERO_IDX(Name) Name##0

// Note: Blend mask have its dedicated mapping and tiling.
// To share code, we simply call the regular code from the main layer for it then save the result, then do regular call for all layers.
ComputeLayerTexCoord0( texCoord0, texCoord1, texCoord2, texCoord3, _UVMappingMaskBlendMask, _UVMappingMaskBlendMask,
_LayerMaskMap_ST.xy, _LayerMaskMap_ST.zw, float2(0.0, 0.0), float2(0.0, 0.0), 1.0,
_LayerMaskMap_ST.xy, _LayerMaskMap_ST.zw, float2(0.0, 0.0), float2(0.0, 0.0), 1.0, false,
positionWS, _TexWorldScaleBlendMask,
mappingType, layerTexCoord);

#if !defined(_MAIN_LAYER_INFLUENCE_MODE)
* tileObjectScale // We only affect layer0 in case we are not in influence mode (i.e we should not change the base object)
#endif
, _LinkDetailsWithBase0
, positionWS, _TexWorldScale0,
mappingType, layerTexCoord);

mappingType = UV_MAPPING_TRIPLANAR;
#endif
ComputeLayerTexCoord1( texCoord0, texCoord1, texCoord2, texCoord3, _UVMappingMask1, _UVDetailsMappingMask1,
_BaseColorMap1_ST.xy, _BaseColorMap1_ST.zw, _DetailMap1_ST.xy, _DetailMap1_ST.zw, tileObjectScale,
_BaseColorMap1_ST.xy, _BaseColorMap1_ST.zw, _DetailMap1_ST.xy, _DetailMap1_ST.zw, tileObjectScale, _LinkDetailsWithBase1,
positionWS, _TexWorldScale1,
mappingType, layerTexCoord);

mappingType = UV_MAPPING_TRIPLANAR;
#endif
ComputeLayerTexCoord2( texCoord0, texCoord1, texCoord2, texCoord3, _UVMappingMask2, _UVDetailsMappingMask2,
_BaseColorMap2_ST.xy, _BaseColorMap2_ST.zw, _DetailMap2_ST.xy, _DetailMap2_ST.zw, tileObjectScale,
_BaseColorMap2_ST.xy, _BaseColorMap2_ST.zw, _DetailMap2_ST.xy, _DetailMap2_ST.zw, tileObjectScale, _LinkDetailsWithBase2,
positionWS, _TexWorldScale2,
mappingType, layerTexCoord);

mappingType = UV_MAPPING_TRIPLANAR;
#endif
ComputeLayerTexCoord3( texCoord0, texCoord1, texCoord2, texCoord3, _UVMappingMask3, _UVDetailsMappingMask3,
_BaseColorMap3_ST.xy, _BaseColorMap3_ST.zw, _DetailMap3_ST.xy, _DetailMap3_ST.zw, tileObjectScale,
_BaseColorMap3_ST.xy, _BaseColorMap3_ST.zw, _DetailMap3_ST.xy, _DetailMap3_ST.zw, tileObjectScale, _LinkDetailsWithBase3,
positionWS, _TexWorldScale3,
mappingType, layerTexCoord);
}

void ApplyDisplacementTileScale(inout float height0, inout float height1, inout float height2, inout float height3)
{
// When we change the tiling, we have want to conserve the ratio with the displacement (and this is consistent with per pixel displacement)
#ifdef _VERTEX_DISPLACEMENT_TILING_SCALE
#ifdef _DISPLACEMENT_LOCK_TILING_SCALE
float tileObjectScale = 1.0;
#ifdef _LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE
// Extract scaling from world transform

#endif
height0 /= max(_BaseColorMap0_ST.x, _BaseColorMap0_ST.y);
// TODO: precompute all these scaling factors!
height0 *= _InvTilingScale0;
height0 *= tileObjectScale; // We only affect layer0 in case we are not in influence mode (i.e we should not change the base object)
height0 /= tileObjectScale; // We only affect layer0 in case we are not in influence mode (i.e we should not change the base object)
height1 /= tileObjectScale * max(_BaseColorMap1_ST.x, _BaseColorMap1_ST.y);
height2 /= tileObjectScale * max(_BaseColorMap2_ST.x, _BaseColorMap2_ST.y);
height3 /= tileObjectScale * max(_BaseColorMap3_ST.x, _BaseColorMap3_ST.y);
height1 = (height1 / tileObjectScale) * _InvTilingScale1;
height2 = (height2 / tileObjectScale) * _InvTilingScale2;
height3 = (height3 / tileObjectScale) * _InvTilingScale3;
#endif
}

float GetInfluenceMask(LayerTexCoord layerTexCoord, bool useLodSampling = false, float lod = 0)
{
return useLodSampling ? SAMPLE_UVMAPPING_TEXTURE2D_LOD(_LayerInfluenceMaskMap, sampler_LayerMaskMap, layerTexCoord.blendMask, lod).r : SAMPLE_UVMAPPING_TEXTURE2D(_LayerInfluenceMaskMap, sampler_LayerMaskMap, layerTexCoord.blendMask).r;
// Sample influence mask with same mapping as Main layer
return useLodSampling ? SAMPLE_UVMAPPING_TEXTURE2D_LOD(_LayerInfluenceMaskMap, sampler_LayerInfluenceMaskMap, layerTexCoord.base0, lod).r : SAMPLE_UVMAPPING_TEXTURE2D(_LayerInfluenceMaskMap, sampler_LayerInfluenceMaskMap, layerTexCoord.base0).r;
}
float GetMaxHeight(float4 heights)
{
float maxHeight = max(heights.r, heights.g);
#ifdef _LAYEREDLIT_4_LAYERS
maxHeight = max(Max3(heights.r, heights.g, heights.b), heights.a);
#endif
#ifdef _LAYEREDLIT_3_LAYERS
maxHeight = Max3(heights.r, heights.g, heights.b);
#endif
return maxHeight;
}
// Returns layering blend mask after application of height based blend.
float4 ApplyHeightBlend(float4 heights, float4 blendMask)
{
// Add offsets for all the layers.
heights = heights + float4(_HeightOffset0, _HeightOffset1, _HeightOffset2, _HeightOffset3);
// We need to mask out inactive layers so that their height does not impact the result.
float4 maskedHeights = heights * blendMask.argb;
float maxHeight = GetMaxHeight(maskedHeights);
// Make sure that transition is not zero otherwise the next computation will be wrong.
// The epsilon here also has to be bigger than the epsilon in the next computation.
float transition = max(_HeightTransition, 1e-5);
// The goal here is to have all but the highest layer at negative heights, then we add the transition so that if the next highest layer is near transition it will have a positive value.
// Then we clamp this to zero and normalize everything so that highest layer has a value of 1.
maskedHeights = maskedHeights - maxHeight.xxxx;
// We need to add an epsilon here for active layers (hence the blendMask again) so that at least a layer shows up if everything's too low.
maskedHeights = (max(0, maskedHeights + transition) + 1e-6) * blendMask.argb;
// Normalize
maxHeight = GetMaxHeight(maskedHeights);
maskedHeights = maskedHeights / maxHeight.xxxx;
return maskedHeights.yzwx;
}
// Return the maximun amplitude use by all enabled heightmap

return minUvSize;
}
#if defined(_PIXEL_DISPLACEMENT) && LAYERS_HEIGHTMAP_ENABLE
float weights[_MAX_LAYER];
float4 blendMasks;
float mainHeightInfluence;
float2 uvSpaceScale[_MAX_LAYER];
#if defined(_MAIN_LAYER_INFLUENCE_MODE) && defined(_HEIGHTMAP0)
float heightInfluence[_MAX_LAYER];
#endif
#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_HEIGHTMAP_IDX, param.uv[0] + texOffsetCurrent, lod).r;
float height1 = SAMPLE_TEXTURE2D_LOD(_HeightMap1, SAMPLER_HEIGHTMAP_IDX, param.uv[1] + texOffsetCurrent, lod).r;
float height2 = SAMPLE_TEXTURE2D_LOD(_HeightMap2, SAMPLER_HEIGHTMAP_IDX, param.uv[2] + texOffsetCurrent, lod).r;
float height3 = SAMPLE_TEXTURE2D_LOD(_HeightMap3, SAMPLER_HEIGHTMAP_IDX, 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;
// See function ComputePerVertexDisplacement() for comment about the weights/influenceMask/BlendMask
// Note: Amplitude is handled in uvSpaceScale, no need to multiply by it here.
float height0 = SAMPLE_TEXTURE2D_LOD(_HeightMap0, SAMPLER_HEIGHTMAP_IDX, param.uv[0] + texOffsetCurrent * param.uvSpaceScale[0], lod).r;
float height1 = SAMPLE_TEXTURE2D_LOD(_HeightMap1, SAMPLER_HEIGHTMAP_IDX, param.uv[1] + texOffsetCurrent * param.uvSpaceScale[1], lod).r;
float height2 = SAMPLE_TEXTURE2D_LOD(_HeightMap2, SAMPLER_HEIGHTMAP_IDX, param.uv[2] + texOffsetCurrent * param.uvSpaceScale[2], lod).r;
float height3 = SAMPLE_TEXTURE2D_LOD(_HeightMap3, SAMPLER_HEIGHTMAP_IDX, param.uv[3] + texOffsetCurrent * param.uvSpaceScale[3], lod).r;
SetEnabledHeightByLayer(height0, height1, height2, height3);
float4 blendMasks = param.blendMasks;
#if defined(_HEIGHT_BASED_BLEND)
// Modify blendMask to take into account the height of the layer. Higher height should be more visible.
blendMasks = ApplyHeightBlend(float4(height0, height1, height2, height3), param.blendMasks);
float weights[_MAX_LAYER];
ComputeMaskWeights(blendMasks, weights);
#if defined(_MAIN_LAYER_INFLUENCE_MODE) && defined(_HEIGHTMAP0)
float influenceMask = blendMasks.a;
#ifdef _INFLUENCEMASK_MAP
influenceMask *= SAMPLE_TEXTURE2D_LOD(_LayerInfluenceMaskMap, sampler_BaseColorMap0, param.uv[0], lod).r;
#endif
height1 += height0 * _InheritBaseHeight1 * influenceMask;
height2 += height0 * _InheritBaseHeight2 * influenceMask;
height3 += height0 * _InheritBaseHeight3 * influenceMask;
#endif
return BlendLayeredScalar(height0, height1, height2, height3, weights);
#endif // defined(_PIXEL_DISPLACEMENT) && LAYERS_HEIGHTMAP_ENABLE
// 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)

// - 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.
float ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord, float influenceMask)
float ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord, float4 blendMasks)
bool ppdEnable = false;
#if defined(_PIXEL_DISPLACEMENT) && LAYERS_HEIGHTMAP_ENABLE
#ifdef _PER_PIXEL_DISPLACEMENT
ppdEnable = true;
ppdEnable = true;
isPlanar = layerTexCoord.base1.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base1.mappingType == UV_MAPPING_TRIPLANAR;
#endif

ppdEnable = true;
isPlanar = layerTexCoord.base2.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base2.mappingType == UV_MAPPING_TRIPLANAR;
#endif

#if defined(_HEIGHTMAP3)
ppdEnable = true;
#endif // _PER_PIXEL_DISPLACEMENT
// 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);
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] * (_HeightAmplitude0) / maxHeight;
ppdParam.weights[1] = weights[1] * (_HeightAmplitude1 + _HeightAmplitude0 * _InheritBaseHeight1) / maxHeight;
ppdParam.weights[2] = weights[2] * (_HeightAmplitude2 + _HeightAmplitude0 * _InheritBaseHeight2) / maxHeight;
ppdParam.weights[3] = weights[3] * (_HeightAmplitude3 + _HeightAmplitude0 * _InheritBaseHeight3) / maxHeight;
// TODO: Here we calculate the scale transform from world to UV space , which is what we have done in GetLayerTexCoord but without the texBias.
// Mean we must also apply the same "additionalTiling", currently not apply Also precompute all this!
float maxHeight0 = abs(_HeightAmplitude0);
float maxHeight1 = abs(_HeightAmplitude1);
float maxHeight2 = abs(_HeightAmplitude2);
float maxHeight3 = abs(_HeightAmplitude3);
// 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) * influenceMask;
ppdParam.mainHeightInfluence = mainHeightInfluence;
#else
[unroll]
for (int i = 0; i < _MAX_LAYER; ++i)
{
ppdParam.weights[i] = weights[i];
}
ppdParam.mainHeightInfluence = 0.0;
ApplyDisplacementTileScale(maxHeight0, maxHeight1, maxHeight2, maxHeight3);
#if defined(_MAIN_LAYER_INFLUENCE_MODE) && defined(_HEIGHTMAP0)
maxHeight1 += abs(_HeightAmplitude0) * _InheritBaseHeight1;
maxHeight2 += abs(_HeightAmplitude0) * _InheritBaseHeight2;
maxHeight3 += abs(_HeightAmplitude0) * _InheritBaseHeight3;
float height; // final height processed
float NdotV;
float weights[_MAX_LAYER];
ComputeMaskWeights(blendMasks, weights);
float maxHeight = BlendLayeredScalar(maxHeight0, maxHeight1, maxHeight2, maxHeight3, weights);
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
float2 worldScale0 = (isPlanar || isTriplanar) ? _TexWorldScale0.xx : _InvPrimScale.xy;
float2 worldScale1 = (isPlanar || isTriplanar) ? _TexWorldScale1.xx : _InvPrimScale.xy;
float2 worldScale2 = (isPlanar || isTriplanar) ? _TexWorldScale2.xx : _InvPrimScale.xy;
float2 worldScale3 = (isPlanar || isTriplanar) ? _TexWorldScale3.xx : _InvPrimScale.xy;
// 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
/*
PerPixelHeightDisplacementParam ppdParam;
ppdParam.blendMasks = blendMasks;
ppdParam.uvSpaceScale[0] = _BaseColorMap0_ST.xy * worldScale0;// *maxHeight0;
ppdParam.uvSpaceScale[1] = _BaseColorMap1_ST.xy * worldScale1;// *maxHeight1;
ppdParam.uvSpaceScale[2] = _BaseColorMap2_ST.xy * worldScale2;// *maxHeight2;
ppdParam.uvSpaceScale[3] = _BaseColorMap3_ST.xy * worldScale3;// *maxHeight3;
ppdParam.uv[0] = layerTexCoord.base0.uvZY;
ppdParam.uv[1] = layerTexCoord.base1.uvYZ;
ppdParam.uv[2] = layerTexCoord.base2.uvYZ;
ppdParam.uv[3] = layerTexCoord.base3.uvYZ;
float uvSpaceScale = BlendLayeredScalar(ppdParam.uvSpaceScale[0], ppdParam.uvSpaceScale[1], ppdParam.uvSpaceScale[2], ppdParam.uvSpaceScale[3], weights);
float3 viewDirTS = ;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, abs(viewDirTS.z));
ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
float2 scaleOffsetDetails0 =_DetailMap0_ST.xy;
float2 scaleOffsetDetails1 =_DetailMap1_ST.xy;
float2 scaleOffsetDetails2 =_DetailMap2_ST.xy;
float2 scaleOffsetDetails3 =_DetailMap3_ST.xy;
// Apply to all uvZY
float height; // final height processed
float NdotV;
// Repeat for uvXZ
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
// Repeat for uvXY
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
// This is not supported currently
height = 1.0;
NdotV = 1.0;
}
else
{
// For planar it is uv too, not uvXZ
ppdParam.uv[0] = layerTexCoord.base0.uv;
ppdParam.uv[1] = layerTexCoord.base1.uv;
ppdParam.uv[2] = layerTexCoord.base2.uv;
ppdParam.uv[3] = layerTexCoord.base3.uv;
// Apply to all layer that used triplanar
*/
height = 1;
NdotV = 1;
}
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;
// Note: The TBN is not normalize as it is based on mikkt. We should normalize it, but POM is always use on simple enough surface that mean it is not required (save 2 normalize). Tag: SURFACE_GRADIENT
// Note: worldToTangent is only define for UVSet0, so we expect that layer that use POM have UVSet0
float3 viewDirTS = isPlanar ? float3(uvXZ, V.y) : TransformWorldToTangent(V, input.worldToTangent) * GetDisplacementObjectScale(false).xzy; // Switch from Y-up to Z-up (as we move to tangent space)
NdotV = viewDirTS.z;
float3x3 worldToTangent = input.worldToTangent;
// Transform the view vector into the UV space.
float3 viewDirUV = normalize(float3(viewDirTS.xy * maxHeight, viewDirTS.z));
float unitAngle = saturate(FastACosPos(viewDirUV.z) * INV_HALF_PI); // TODO: optimize
int numSteps = (int)lerp(_PPDMinSamples, _PPDMaxSamples, unitAngle);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirUV, ppdParam, height);
offset *= uvSpaceScale;
// Note: The TBN is not normalize as it is based on mikkt. We should normalize it, but POM is always use on simple enough surfarce that mean it is not required (save 2 normalize). Tag: SURFACE_GRADIENT
// 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(uvXZ, V.y) : TransformWorldToTangent(V, worldToTangent);
NdotV = viewDirTS.z;
layerTexCoord.base0.uv += offset;
layerTexCoord.base1.uv += offset;
layerTexCoord.base2.uv += offset;
layerTexCoord.base3.uv += offset;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
layerTexCoord.details0.uv += offset * scaleOffsetDetails0;
layerTexCoord.details1.uv += offset * scaleOffsetDetails1;
layerTexCoord.details2.uv += offset * scaleOffsetDetails2;
layerTexCoord.details3.uv += offset * scaleOffsetDetails3;
}
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);
// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign. { height = -height + 1 }.
// Apply offset to all planar UV if applicable
float4 planarWeight = float4( layerTexCoord.base0.mappingType == UV_MAPPING_PLANAR ? 1.0 : 0.0,
layerTexCoord.base1.mappingType == UV_MAPPING_PLANAR ? 1.0 : 0.0,
layerTexCoord.base2.mappingType == UV_MAPPING_PLANAR ? 1.0 : 0.0,
layerTexCoord.base3.mappingType == UV_MAPPING_PLANAR ? 1.0 : 0.0);
// _UVMappingMask0.x will be 1.0 is UVSet0 is used;
float4 offsetWeights = isPlanar ? planarWeight : 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 ? planarWeight : 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;
}
// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
float verticalDisplacement = maxHeight - height * maxHeight;
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap0_ST.x, _BaseColorMap0_ST.y));
return tilingScale * verticalDisplacement / max(NdotV, 0.001);
}
float verticalDisplacement = maxHeight - height * maxHeight;
return verticalDisplacement / max(NdotV, 0.001);
#else
}
float GetMaxHeight(float4 heights)
{
float maxHeight = max(heights.r, heights.g);
#ifdef _LAYEREDLIT_4_LAYERS
maxHeight = max(Max3(heights.r, heights.g, heights.b), heights.a);
#endif
#ifdef _LAYEREDLIT_3_LAYERS
maxHeight = Max3(heights.r, heights.g, heights.b);
#endif
return maxHeight;
}
// Returns layering blend mask after application of height based blend.
float4 ApplyHeightBlend(float4 heights, float4 blendMask)
{
// Add offsets for all the layers.
heights = heights + float4(_HeightOffset0, _HeightOffset1, _HeightOffset2, _HeightOffset3);
// We need to mask out inactive layers so that their height does not impact the result.
float4 maskedHeights = heights * blendMask.argb;
float maxHeight = GetMaxHeight(maskedHeights);
// Make sure that transition is not zero otherwise the next computation will be wrong.
// The epsilon here also has to be bigger than the epsilon in the next computation.
float transition = max(_HeightTransition, 1e-5);
// The goal here is to have all but the highest layer at negative heights, then we add the transition so that if the next highest layer is near transition it will have a positive value.
// Then we clamp this to zero and normalize everything so that highest layer has a value of 1.
maskedHeights = maskedHeights - maxHeight.xxxx;
// We need to add an epsilon here for active layers (hence the blendMask again) so that at least a layer shows up if everything's too low.
maskedHeights = (max(0, maskedHeights + transition) + 1e-6) * blendMask.argb;
// Normalize
maxHeight = GetMaxHeight(maskedHeights);
maskedHeights = maskedHeights / maxHeight.xxxx;
return maskedHeights.yzwx;
#endif
float ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
float3 ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
#if defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || defined(_HEIGHTMAP2) || defined(_HEIGHTMAP3)
#if LAYERS_HEIGHTMAP_ENABLE
ApplyDisplacementTileScale(height0, height1, height2, height3); // Only apply with per vertex displacement
// Height is affected by tiling property and by object scale (depends on option).
// Apply scaling from tiling properties (TexWorldScale and tiling from BaseColor)
ApplyDisplacementTileScale(height0, height1, height2, height3);
// Nullify height that are not used, so compiler can remove unused case
SetEnabledHeightByLayer(height0, height1, height2, height3);
float4 blendMask = GetBlendMask(layerTexCoord, vertexColor, true, lod);
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
float4 blendMasks = GetBlendMask(layerTexCoord, vertexColor, true, lod);
#if defined(_HEIGHT_BASED_BLEND)
// Modify blendMask to take into account the height of the layer. Higher height should be more visible.
blendMasks = ApplyHeightBlend(float4(height0, height1, height2, height3), blendMasks);
#endif
float weights[_MAX_LAYER];
ComputeMaskWeights(blendMasks, weights);
// _MAIN_LAYER_INFLUENCE_MODE is a pure visual mode that doesn't contribute to the weights of a layer
// The motivation is like this: if a layer is visible, then we will apply influence on top of it (so it is only visual).
// This is what is done for normal and baseColor and we do the same for height.
// Note that if we apply influence before ApplyHeightBlend, then have a different behavior.
#if defined(_MAIN_LAYER_INFLUENCE_MODE) && defined(_HEIGHTMAP0)
float influenceMask = blendMask.a * GetInfluenceMask(layerTexCoord, true, lod);
float influenceMask = blendMasks.a;
#ifdef _INFLUENCEMASK_MAP
influenceMask *= GetInfluenceMask(layerTexCoord, true, lod);
#endif
#endif
#endif
SetEnabledHeightByLayer(height0, height1, height2, height3);
float heightResult = BlendLayeredScalar(height0, height1, height2, height3, weights).xxx;
#if defined(_HEIGHT_BASED_BLEND)
blendMask = ApplyHeightBlend(float4(height0, height1, height2, height3), blendMask);
// Applying scaling of the object if requested
#ifdef _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE
float3 objectScale = GetDisplacementObjectScale(true);
// Reminder: mappingType is know statically, so code below is optimize by the compiler
// Planar and Triplanar are in world space thus it is independent of object scale
return heightResult.xxx * BlendLayeredVector3( ((layerTexCoord.base0.mappingType == UV_MAPPING_UVSET) ? objectScale : float3(1.0, 1.0, 1.0)),
((layerTexCoord.base1.mappingType == UV_MAPPING_UVSET) ? objectScale : float3(1.0, 1.0, 1.0)),
((layerTexCoord.base2.mappingType == UV_MAPPING_UVSET) ? objectScale : float3(1.0, 1.0, 1.0)),
((layerTexCoord.base3.mappingType == UV_MAPPING_UVSET) ? objectScale : float3(1.0, 1.0, 1.0)), weights);
#else
return heightResult.xxx;
float weights[_MAX_LAYER];
ComputeMaskWeights(blendMask, weights);
return BlendLayeredScalar(height0, height1, height2, height3, weights);
return 0.0;
return float3(0.0, 0.0, 0.0);
#endif
}

outWeights[i] = 0.0f;
}
#if defined(_DENSITY_MODE)
// Note: blendMasks.argb because a is main layer
float4 opacityAsDensity = saturate((inputAlphaMask - (float4(1.0, 1.0, 1.0, 1.0) - blendMasks.argb)) * 20.0); // 20.0 is the number of steps in inputAlphaMask (Density mask. We decided 20 empirically)

#if defined(_HEIGHT_BASED_BLEND)
#if defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || defined(_HEIGHTMAP2) || defined(_HEIGHTMAP3)
#if LAYERS_HEIGHTMAP_ENABLE
// Height is affected by tiling property and by object scale (depends on option).
// Apply scaling from tiling properties (TexWorldScale and tiling from BaseColor)
ApplyDisplacementTileScale(height0, height1, height2, height3);
// Nullify height that are not used, so compiler can remove unused case
float4 heights = float4(height0, height1, height2, height3);
// HACK: use height0 to avoid compiler error for unused sampler - To remove when we can have a sampler without a textures
#if !defined(_PER_PIXEL_DISPLACEMENT)
// We don't use height 0 for the height blend based mode
heights.y += (heights.x * 0.0001);
#endif
// Reminder: _MAIN_LAYER_INFLUENCE_MODE is a purely visual mode, it is not take into account for the blendMasks
// As it is purely visual, it is not apply in ComputeLayerWeights
blendMasks = ApplyHeightBlend(heights, blendMasks);
#endif
// If no heightmap is set on any layer, we don't need to try and blend them based on height...
#if defined(_HEIGHT_BASED_BLEND)
// Modify blendMask to take into account the height of the layer. Higher height should be more visible.
blendMasks = ApplyHeightBlend(float4(height0, height1, height2, height3), blendMasks);
#endif
#endif
ComputeMaskWeights(blendMasks, outWeights);

ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
GetLayerTexCoord(input, layerTexCoord);
float influenceMask = 0.0f;
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
influenceMask = GetInfluenceMask(layerTexCoord);
#endif
float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord, influenceMask);
float4 blendMasks = GetBlendMask(layerTexCoord, input.color);
float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord, blendMasks);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);

float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3, normalTS3, bentNormalTS3);
// 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.
float4 blendMasks = GetBlendMask(layerTexCoord, input.color);
float weights[_MAX_LAYER];
ComputeLayerWeights(input, layerTexCoord, float4(alpha0, alpha1, alpha2, alpha3), blendMasks, weights);

float3 bentNormalTS;
float3 bentNormalWS;
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
#ifdef _INFLUENCEMASK_MAP
float influenceMask = GetInfluenceMask(layerTexCoord);
#else
float influenceMask = 0.0;
#endif
if (influenceMask > 0.0f)
{
surfaceData.baseColor = ComputeMainBaseColorInfluence(influenceMask, surfaceData0.baseColor, surfaceData1.baseColor, surfaceData2.baseColor, surfaceData3.baseColor, layerTexCoord, blendMasks.a, weights);

42
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


void ADD_IDX(ComputeLayerTexCoord)( // Uv related parameters
void ADD_IDX(ComputeLayerTexCoord)( // Uv related parameters
float2 texScale, float2 texBias, float2 texScaleDetails, float2 texBiasDetails, float additionalTiling,
float2 texScale, float2 texBias, float2 texScaleDetails, float2 texBiasDetails, float additionalTiling, float linkDetailsWithBase,
// parameter for planar/triplanar
float3 positionWS, float worldScale,
// mapping type and output

// Apply tiling options
ADD_IDX(layerTexCoord.base).uv = uvBase * texScale + texBias;
// Detail map tiling option inherit from the tiling of the base
ADD_IDX(layerTexCoord.details).uv = (uvDetails * texScaleDetails + texBiasDetails) * texScale + texBias;
ADD_IDX(layerTexCoord.details).uv = uvDetails * texScaleDetails + texBiasDetails;
if (linkDetailsWithBase > 0.0)
{
ADD_IDX(layerTexCoord.details).uv = ADD_IDX(layerTexCoord.details).uv * texScale + texBias;
}
ADD_IDX(layerTexCoord.details).uvXZ = (uvXZ * texScaleDetails + texBiasDetails) * texScale + texBias;
ADD_IDX(layerTexCoord.details).uvXY = (uvXY * texScaleDetails + texBiasDetails) * texScale + texBias;
ADD_IDX(layerTexCoord.details).uvZY = (uvZY * texScaleDetails + texBiasDetails) * texScale + texBias;
ADD_IDX(layerTexCoord.details).uvXZ = uvXZ * texScaleDetails + texBiasDetails;
ADD_IDX(layerTexCoord.details).uvXY = uvXY * texScaleDetails + texBiasDetails;
ADD_IDX(layerTexCoord.details).uvZY = uvZY * texScaleDetails + texBiasDetails;
if (linkDetailsWithBase > 0.0)
{
ADD_IDX(layerTexCoord.details).uvXZ = ADD_IDX(layerTexCoord.details).uvXZ * texScale + texBias;
ADD_IDX(layerTexCoord.details).uvXY = ADD_IDX(layerTexCoord.details).uvXY * texScale + texBias;
ADD_IDX(layerTexCoord.details).uvZY = ADD_IDX(layerTexCoord.details).uvZY * texScale + texBias;
}
#ifdef SURFACE_GRADIENT
// This part is only relevant for normal mapping with UV_MAPPING_UVSET

surfaceData.baseColor = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).rgb * ADD_IDX(_BaseColor).rgb;
#ifdef _DETAIL_MAP_IDX
surfaceData.baseColor *= LerpWhiteTo(2.0 * detailAlbedo, detailMask * ADD_IDX(_DetailAlbedoScale));
// we saturate to avoid to have a smoothness value above 1
surfaceData.baseColor = saturate(surfaceData.baseColor);
// Use overlay blend mode for detail abledo: (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))
float baseColorOverlay = (detailAlbedo < 0.5) ?
surfaceData.baseColor * PositivePow(2.0 * detailAlbedo, ADD_IDX(_DetailAlbedoScale)) :
1.0 - 2.0 * (1.0 - surfaceData.baseColor) * (1.0 - (detailAlbedo * ADD_IDX(_DetailAlbedoScale)));
// Lerp with details mask
surfaceData.baseColor = lerp(surfaceData.baseColor, saturate(baseColorOverlay), detailMask);
#endif
surfaceData.specularOcclusion = 1.0; // Will be setup outside of this function

#endif
#ifdef _DETAIL_MAP_IDX
surfaceData.perceptualSmoothness *= LerpWhiteTo(2.0 * detailSmoothness, detailMask * ADD_IDX(_DetailSmoothnessScale));
// we saturate to avoid to have a smoothness value above 1
surfaceData.perceptualSmoothness = saturate(surfaceData.perceptualSmoothness);
// Use overlay blend mode for detail abledo: (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))
float smoothnessOverlay = (detailSmoothness < 0.5) ?
surfaceData.perceptualSmoothness * PositivePow(2.0 * detailSmoothness, ADD_IDX(_DetailSmoothnessScale)) :
1.0 - 2.0 * (1.0 - surfaceData.baseColor) * (1.0 - (detailSmoothness * ADD_IDX(_DetailSmoothnessScale)));
// Lerp with details mask
surfaceData.perceptualSmoothness = lerp(surfaceData.perceptualSmoothness, saturate(smoothnessOverlay), detailMask);
#endif
// MaskMap is RGBA: Metallic, Ambient Occlusion (Optional), emissive Mask (Optional), Smoothness

9
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl


PROP_DECL_TEX2D(_DetailMap);
TEXTURE2D(_LayerMaskMap);
SAMPLER2D(sampler_LayerMaskMap);
SAMPLER2D(sampler_LayerMaskMap);
SAMPLER2D(sampler_LayerInfluenceMaskMap);
#endif

// In our case we don't use such a mechanism but need to keep the code quiet. We declare the value and always enable it.
// TODO: Fix the code in legacy unity so we can customize the beahvior for GI
float3 _EmissionColor;
float4 _InvPrimScale; // Only XY are used
// Wind
float _InitialBend;

float4 _SpecularColor;
float _TexWorldScale;
float _InvTilingScale;
float _LinkDetailsWithBase;
#else // LAYERED_LIT_SHADER

float4 _LayerMaskMap_ST;
float _TexWorldScaleBlendMask;
PROP_DECL(float, _TexWorldScale);
PROP_DECL(float, _InvTilingScale);
PROP_DECL(float, _LinkDetailsWithBase);
#endif // LAYERED_LIT_SHADER

43
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl


float3 GetVertexDisplacement(float3 positionWS, float3 normalWS, float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3, float4 vertexColor, float3 objectScale)
float3 GetVertexDisplacement(float3 positionWS, float3 normalWS, float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3, float4 vertexColor)
{
// This call will work for both LayeredLit and Lit shader
LayerTexCoord layerTexCoord;

// TODO: do this algorithm for lod fetching as lod not available in vertex/domain shader
// http://www.sebastiansylvan.com/post/the-problem-with-tessellation-in-directx-11/
float lod = 0.0;
float height = ComputePerVertexDisplacement(layerTexCoord, vertexColor, lod);
float3 displ = height * normalWS;
// Applying scaling of the object if requested
displ *= objectScale;
return displ;
return ComputePerVertexDisplacement(layerTexCoord, vertexColor, lod) * normalWS;
void ApplyVertexModification(AttributesMesh input, float3 normalWS, float3 objectScale, inout float3 positionWS)
void ApplyVertexModification(AttributesMesh input, float3 normalWS, inout float3 positionWS)
// If tessellation is enabled we apply displacement map after tessellation
#if defined(_VERTEX_DISPLACEMENT) && !defined(TESSELLATION_ON)
#if defined(_VERTEX_DISPLACEMENT)
positionWS += GetVertexDisplacement(positionWS, normalWS,
#ifdef ATTRIBUTES_NEED_TEXCOORD0
input.uv0,

float2(0.0, 0.0),
#endif
#ifdef ATTRIBUTES_NEED_COLOR
input.color,
input.color
float4(0.0, 0.0, 0.0, 0.0),
float4(0.0, 0.0, 0.0, 0.0)
objectScale);
);
#endif
#ifdef _VERTEX_WIND

bool faceCull = false;
#ifndef _DOUBLESIDED_ON
// TODO: Handle inverse culling (for mirror)!
faceCull = BackFaceCullTriangle(p0, p1, p2, _TessellationBackFaceCullEpsilon, GetCurrentViewPosition()); // Use shadow view
// Handle transform mirroring (like negative scaling)
// Caution: don't change p1/p2 directly as it is use later
float3 backfaceP1 = unity_WorldTransformParams.w < 0.0 ? p2 : p1;
float3 backfaceP2 = unity_WorldTransformParams.w < 0.0 ? p1 : p2;
faceCull = BackFaceCullTriangle(p0, backfaceP1, backfaceP2, _TessellationBackFaceCullEpsilon, GetCurrentViewPosition()); // Use shadow view
}
#endif

// y - 2->0 edge
// z - 0->1 edge
// w - inside tessellation factor
void ApplyTessellationModification(VaryingsMeshToDS input, float3 normalWS, float3 objectScale, inout float3 positionWS)
void ApplyTessellationModification(VaryingsMeshToDS input, float3 normalWS, inout float3 positionWS)
#if defined(_VERTEX_DISPLACEMENT)
#if defined(_TESSELLATION_DISPLACEMENT)
positionWS += GetVertexDisplacement(positionWS, normalWS,
#ifdef VARYINGS_DS_NEED_TEXCOORD0
input.texCoord0,

float2(0.0, 0.0),
#endif
#ifdef VARYINGS_DS_NEED_COLOR
input.color,
input.color
float4(0.0, 0.0, 0.0, 0.0),
float4(0.0, 0.0, 0.0, 0.0)
objectScale);
#endif // _VERTEX_DISPLACEMENT
);
#endif // _TESSELLATION_DISPLACEMENT
}
#endif // #ifdef TESSELLATION_ON

31
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader


_HeightMax("Heightmap Max", Float) = 1
_DetailMap("DetailMap", 2D) = "black" {}
_DetailAlbedoScale("_DetailAlbedoScale", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale("_DetailAlbedoScale", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale("_DetailSmoothnessScale", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale("_DetailSmoothnessScale", Range(0.0, 2.0)) = 1
_TangentMap("TangentMap", 2D) = "bump" {}
_TangentMapOS("TangentMapOS", 2D) = "white" {}

[Enum(UV0, 0, Planar, 4, TriPlanar, 5)] _UVBase("UV Set for base", Float) = 0
_TexWorldScale("Scale to apply on world coordinate", Float) = 1.0
[HideInInspector] _InvTilingScale("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
[Enum(None, 0, Vertex displacement, 1, Pixel displacement, 2, Tessellation displacement, 3)] _DisplacementMode("DisplacementMode", Int) = 0
[ToggleOff] _DisplacementLockObjectScale("displacement lock object scale", Float) = 1.0
[ToggleOff] _DisplacementLockTilingScale("displacement lock tiling scale", Float) = 1.0
[ToggleOff] _PerPixelDisplacementObjectScale("Per pixel displacement object scale", Float) = 1.0
_PPDPrimitiveLength("Primitive length for POM", Float) = 1
_PPDPrimitiveWidth("Primitive width for POM", Float) = 1
[HideInInspector] _InvPrimScale("Inverse primitive scale for non-planar POM", Vector) = (1, 1, 0, 0)
[ToggleOff] _LinkDetailsWithBase("LinkDetailsWithBase", Float) = 1.0
// Displacement map
[ToggleOff] _EnableVertexDisplacement("Enable vertex displacement", Float) = 0.0
[ToggleOff] _VertexDisplacementObjectScale("Vertex displacement object scale", Float) = 1.0
[ToggleOff] _VertexDisplacementTilingScale("Vertex displacement tiling height scale", Float) = 1.0
// Wind
[ToggleOff] _EnableWind("Enable Wind", Float) = 0.0
_InitialBend("Initial Bend", float) = 1.0

#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _PER_PIXEL_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_OBJECT_SCALE
#pragma shader_feature _VERTEX_DISPLACEMENT_TILING_SCALE
#pragma shader_feature _ _VERTEX_DISPLACEMENT _PIXEL_DISPLACEMENT _TESSELLATION_DISPLACEMENT
#pragma shader_feature _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _DISPLACEMENT_LOCK_TILING_SCALE
#pragma shader_feature _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE
#pragma shader_feature _TESSELLATION_PHONG
#pragma shader_feature _ _TESSELLATION_PHONG
#pragma shader_feature _ _MAPPING_PLANAR _MAPPING_TRIPLANAR
#pragma shader_feature _NORMALMAP_TANGENT_SPACE

6
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDepthPass.hlsl


#endif
// Attributes
#define REQUIRE_TANGENT_TO_WORLD (defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT))
#define REQUIRE_TANGENT_TO_WORLD defined(_PIXEL_DISPLACEMENT)
#define REQUIRE_VERTEX_COLOR (defined(_VERTEX_DISPLACEMENT) && defined(LAYERED_LIT_SHADER) && (defined(_LAYER_MASK_VERTEX_COLOR_MUL) || defined(_LAYER_MASK_VERTEX_COLOR_ADD))) || defined(_VERTEX_WIND)
#define REQUIRE_VERTEX_COLOR ((defined(_VERTEX_DISPLACEMENT) || defined(_TESSELLATION_DISPLACEMENT)) && defined(LAYERED_LIT_SHADER) && (defined(_LAYER_MASK_VERTEX_COLOR_MUL) || defined(_LAYER_MASK_VERTEX_COLOR_ADD))) || defined(_VERTEX_WIND)
// This first set of define allow to say which attributes will be use by the mesh in the vertex and domain shader (for tesselation)

// If we have a layered shader, any UV can be use for this. To reduce the number of variant we groupt UV0/UV1 and UV2/UV3 instead of having variant for UV0/UV1/UV2/UV3
// When UVX is present, we assume that UVX - 1 ... UV0 is present
#if defined(_VERTEX_DISPLACEMENT) || REQUIRE_TANGENT_TO_WORLD || defined(_ALPHATEST_ON)
#if defined(_VERTEX_DISPLACEMENT) || REQUIRE_TANGENT_TO_WORLD || defined(_ALPHATEST_ON) || defined(_TESSELLATION_DISPLACEMENT)
#define ATTRIBUTES_NEED_TEXCOORD0
#ifdef LAYERED_LIT_SHADER
#define ATTRIBUTES_NEED_TEXCOORD1

4
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDistortionPass.hlsl


#endif
// Attributes
#define REQUIRE_UV_FOR_TESSELATION (defined(TESSELLATION_ON) && (defined(_TESSELLATION_DISPLACEMENT) || defined(_TESSELLATION_DISPLACEMENT_PHONG)))
#define REQUIRE_UV_FOR_TESSELATION (defined(TESSELLATION_ON) && defined(_TESSELLATION_DISPLACEMENT))
#define REQUIRE_TANGENT_TO_WORLD (defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT))
#define REQUIRE_TANGENT_TO_WORLD (defined(_HEIGHTMAP) && defined(_PIXEL_DISPLACEMENT))
// This first set of define allow to say which attributes will be use by the mesh in the vertex and domain shader (for tesselation)

6
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitVelocityPass.hlsl


// conflict with the normal in the semantic. This need to be fix! Also no per pixel displacement is possible either.
// Attributes
#define REQUIRE_TANGENT_TO_WORLD 0 /* (defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT)) */
#define REQUIRE_TANGENT_TO_WORLD 0 /* defined(_PIXEL_DISPLACEMENT) */
#define REQUIRE_VERTEX_COLOR (defined(_VERTEX_DISPLACEMENT) && defined(LAYERED_LIT_SHADER) && (defined(_LAYER_MASK_VERTEX_COLOR_MUL) || defined(_LAYER_MASK_VERTEX_COLOR_ADD))) || defined(_VERTEX_WIND)
#define REQUIRE_VERTEX_COLOR ((defined(_VERTEX_DISPLACEMENT) || defined(_TESSELLATION_DISPLACEMENT)) && defined(LAYERED_LIT_SHADER) && (defined(_LAYER_MASK_VERTEX_COLOR_MUL) || defined(_LAYER_MASK_VERTEX_COLOR_ADD))) || defined(_VERTEX_WIND)
// This first set of define allow to say which attributes will be use by the mesh in the vertex and domain shader (for tesselation)

// If we have a layered shader, any UV can be use for this. To reduce the number of variant we groupt UV0/UV1 and UV2/UV3 instead of having variant for UV0/UV1/UV2/UV3
// When UVX is present, we assume that UVX - 1 ... UV0 is present
#if defined(_VERTEX_DISPLACEMENT) || REQUIRE_TANGENT_TO_WORLD || defined(_ALPHATEST_ON)
#if defined(_VERTEX_DISPLACEMENT) || REQUIRE_TANGENT_TO_WORLD || defined(_ALPHATEST_ON) || defined(_TESSELLATION_DISPLACEMENT)
#define ATTRIBUTES_NEED_TEXCOORD0
#ifdef LAYERED_LIT_SHADER
#define ATTRIBUTES_NEED_TEXCOORD1

9
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/TessellationShare.hlsl


#endif
#ifdef HAVE_TESSELLATION_MODIFICATION
// TODO: This should be an uniform for the object, this code should be remove (and is specific to Lit.shader) once we have it. - Workaround for now
// Extract scaling from world transform
#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
float3 objectScale = varying.vmesh.objectScale;
#else
float3 objectScale = float3(1.0, 1.0, 1.0);
#endif
ApplyTessellationModification(varying.vmesh, varying.vmesh.normalWS, objectScale, varying.vmesh.positionWS);
ApplyTessellationModification(varying.vmesh, varying.vmesh.normalWS, varying.vmesh.positionWS);
#endif
return VertTesselation(varying);

19
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl


#ifdef VARYINGS_DS_NEED_COLOR
float4 color;
#endif
#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
float3 objectScale;
#endif
};
struct PackedVaryingsMeshToDS

#ifdef VARYINGS_DS_NEED_COLOR
float4 interpolators5 : TEXCOORD2;
#endif
#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
float3 interpolators6 : TEXCOORD3;
#endif
};
// Functions to pack data to use as few interpolator as possible, the ShaderGraph should generate these functions

#endif
#ifdef VARYINGS_DS_NEED_COLOR
output.interpolators5 = input.color;
#endif
#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
output.interpolators6 = input.objectScale;
#endif
return output;

#ifdef VARYINGS_DS_NEED_COLOR
output.color = input.interpolators5;
#endif
#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
output.objectScale = input.interpolators6;
#endif
return output;
}

#endif
#ifdef VARYINGS_DS_NEED_COLOR
TESSELLATION_INTERPOLATE_BARY(color, baryCoords);
#endif
#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
// objectScale doesn't change for the whole object.
ouput.objectScale = input0.objectScale;
#endif
return ouput;

18
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VertMesh.hlsl


float4 tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
#endif
// TODO: This should be an uniform for the object, this code should be remove (and is specific to Lit.shader) once we have it. - Workaround for now
// Extract scaling from world transform
#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
float3 objectScale;
float4x4 worldTransform = GetObjectToWorldMatrix();
objectScale.x = length(float3(worldTransform._m00, worldTransform._m01, worldTransform._m02));
objectScale.y = length(float3(worldTransform._m10, worldTransform._m11, worldTransform._m12));
objectScale.z = length(float3(worldTransform._m20, worldTransform._m21, worldTransform._m22));
#else
float3 objectScale = float3(1.0, 1.0, 1.0);
#endif
ApplyVertexModification(input, normalWS, objectScale, positionWS);
ApplyVertexModification(input, normalWS, positionWS);
#endif
positionWS = GetCameraRelativePositionWS(positionWS);

#ifdef _VERTEX_DISPLACEMENT_OBJECT_SCALE
// TODO: This should be an uniform for the object, this code should be remove (and is specific to Lit.shader) once we have it. - Workaround for now
output.objectScale = objectScale;
#endif
// TODO: TEMP: Velocity has a flow as it doens't have normal. This need to be fix. In the mean time, generate fix normal so compiler doesn't complain - When fix, think to also enable ATTRIBUTES_NEED_NORMAL in LitVelocityPass.hlsl
#if (SHADERPASS == SHADERPASS_VELOCITY)
output.normalWS = float3(0.0, 0.0, 1.0);

4
ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightStandardGUI.cs


public static readonly string[] specularSmoothnessChannelNames = {"Specular Alpha", "Albedo Alpha"};
}
#pragma warning disable CS0414
#pragma warning disable 0414
private MaterialProperty workflowMode = null;
private MaterialProperty blendMode = null;

private ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, kMaxfp16, 1 / kMaxfp16, 3f);
private bool m_FirstTimeApply = true;
#pragma warning restore CS0414
#pragma warning restore 0414
public void FindProperties(MaterialProperty[] props)
{

27
ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs


private Camera m_CurrCamera = null;
private int m_LightIndicesCount = 0;
private ComputeBuffer m_LightIndexListBuffer;
private static readonly int kMaxCascades = 4;

private RenderTargetIdentifier m_CameraColorRT;
private RenderTargetIdentifier m_CameraDepthRT;
private bool m_RenderToIntermediateTarget = false;
private bool m_IntermediateTextureArray = false;
private const int kShadowDepthBufferBits = 16;

{
m_LightIndexListBuffer.Dispose();
m_LightIndexListBuffer = null;
m_LightIndicesCount = 0;
}
}

private void ShadowPass(VisibleLight[] visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
{
if (m_Asset.AreShadowsEnabled() && lightData.mainLightIndex != -1)
if (m_Asset.AreShadowsEnabled() && lightData.mainLightIndex != -1)
{
VisibleLight mainLight = visibleLights[lightData.mainLightIndex];
if (mainLight.light.shadows != LightShadows.None)

// Setup camera matrices
context.SetupCameraProperties(m_CurrCamera, stereoEnabled);
RendererConfiguration rendererSettings = GetRendererSettings(ref lightData);
BeginForwardRendering(ref context, renderingConfig);

// shadow lights types.
// Lightweight pipeline only supports 1 single directional shadow light.
// Any additional pixel lights don't cast shadows.
//
//
// 2) If shadows are disabled or no shadow light is present then main light is the main brighest directional
// 3) If neither a shadow light or main light is first visible light.
private int GetMainLightIndex(VisibleLight[] lights)

int mainShadowLight = -1;
for (int i = 0; i < lights.Length; ++i)
for (int i = 0; i < lights.Length; ++i)
if (shadowsEnabled && LightweightUtils.IsSupportedShadowType (lights[i].lightType) && lights[i].light.shadows != LightShadows.None)
if (shadowsEnabled && LightweightUtils.IsSupportedShadowType (lights[i].lightType) && lights[i].light.shadows != LightShadows.None)
{
// Shadow Type priority: Soft > Hard > None
if (mainShadowLight < 0 || lights[i].light.shadows > lights[mainShadowLight].light.shadows)

if (lights[i].lightType == LightType.Directional)
if (lights[i].lightType == LightType.Directional)
{
if (mainDirectional < 0 || lights[i].light.intensity > lights[mainDirectional].light.intensity)
mainDirectional = i;

if (mainShadowLight >= 0)
if (mainShadowLight >= 0)
}
}
return 0;
}

{
// Main light has an optimized shader path for main light. This will benefit games that only care about a single light.
// Lightweight pipeline also supports only a single shadow light, if available it will be the main light.
if (lightData.mainLightIndex != -1)
if (lightData.mainLightIndex != -1)
{
SetupMainLightConstants (cmd, lights, lightData.mainLightIndex, ref context);
if (lightData.shadowsRendered)

int[] lightIndexMap = m_CullResults.GetLightIndexMap();
int lightIter = 0;
for (int i = 0; i < totalLightCount; ++i)
for (int i = 0; i < totalLightCount; ++i)
if (i == lightData.mainLightIndex || lightIter >= maxLights)
if (i == lightData.mainLightIndex || lightIter >= maxLights)
{
lightIndexMap[i] = -1;
continue;

53
ScriptableRenderPipeline/HDRenderPipeline/Editor/HDBaseEditor.cs


using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
using UnityObject = UnityEngine.Object;
//
// Sample use:
//
// [CustomEditor(typeof(TestComponent)]
// class TestEditor : HDBaseEditor<TestComponent>
// {
// SerializedProperty m_MyFloat;
//
// protected override void OnEnable()
// {
// base.OnEnable();
// m_MyFloat = properties.Find(x => x.myFloat);
// }
//
// public override void OnInspectorGUI()
// {
// EditorGUILayout.PropertyField(m_MyFloat);
// }
// }
//
public class HDBaseEditor<T> : Editor
where T : UnityObject
{
internal PropertyFetcher<T> properties { get; private set; }
protected T m_Target
{
get { return target as T; }
}
protected T[] m_Targets
{
get { return targets as T[]; }
}
protected HDRenderPipeline m_HDPipeline
{
get { return RenderPipelineManager.currentPipeline as HDRenderPipeline; }
}
protected virtual void OnEnable()
{
properties = new PropertyFetcher<T>(serializedObject);
}
}
}

13
ScriptableRenderPipeline/HDRenderPipeline/Editor/HDBaseEditor.cs.meta


fileFormatVersion: 2
guid: 4db007e1d2c155d4a80e2a38f39b39ff
timeCreated: 1507624455
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

56
ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.Styles.cs


using UnityEngine;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public sealed partial class HDRenderPipelineInspector
{
// TODO: missing tooltips
sealed class Styles
{
public readonly GUIContent defaults = new GUIContent("Defaults");
public readonly GUIContent defaultDiffuseMaterial = new GUIContent("Default Diffuse Material", "Material to use when creating objects");
public readonly GUIContent defaultShader = new GUIContent("Default Shader", "Shader to use when creating materials");
public readonly GUIContent settingsLabel = new GUIContent("Settings");
// Rendering Settings
public readonly GUIContent renderingSettingsLabel = new GUIContent("Rendering Settings");
public readonly GUIContent useForwardRenderingOnly = new GUIContent("Use Forward Rendering Only");
public readonly GUIContent useDepthPrepassWithDeferredRendering = new GUIContent("Use Depth Prepass with Deferred rendering");
public readonly GUIContent renderAlphaTestOnlyInDeferredPrepass = new GUIContent("Alpha Test Only");
// Texture Settings
public readonly GUIContent textureSettings = new GUIContent("Texture Settings");
public readonly GUIContent spotCookieSize = new GUIContent("Spot Cookie Size");
public readonly GUIContent pointCookieSize = new GUIContent("Point Cookie Size");
public readonly GUIContent reflectionCubemapSize = new GUIContent("Reflection Cubemap Size");
public readonly GUIContent sssSettings = new GUIContent("Subsurface Scattering Settings");
// Shadow Settings
public readonly GUIContent shadowSettings = new GUIContent("Shadow Settings");
public readonly GUIContent shadowsAtlasWidth = new GUIContent("Atlas Width");
public readonly GUIContent shadowsAtlasHeight = new GUIContent("Atlas Height");
// Tile pass Settings
public readonly GUIContent tileLightLoopSettings = new GUIContent("Tile Light Loop Settings");
public readonly GUIContent enableTileAndCluster = new GUIContent("Tile/Clustered");
public readonly GUIContent enableComputeLightEvaluation = new GUIContent("Compute Light Evaluation");
public readonly GUIContent enableComputeLightVariants = new GUIContent("Compute Light Variants");
public readonly GUIContent enableComputeMaterialVariants = new GUIContent("Compute Material Variants");
public readonly GUIContent enableClustered = new GUIContent("Clustered");
public readonly GUIContent enableFptlForOpaqueWhenClustered = new GUIContent("Fptl For Opaque When Clustered");
public readonly GUIContent enableBigTilePrepass = new GUIContent("Big tile prepass");
}
static Styles s_Styles;
// Can't use a static initializer in case we need to create GUIStyle in the Styles class as
// these can only be created with an active GUI rendering context
void CheckStyles()
{
if (s_Styles == null)
s_Styles = new Styles();
}
}
}

13
ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.Styles.cs.meta


fileFormatVersion: 2
guid: eaef7e9439aa2fb4093fa259575623d4
timeCreated: 1507717754
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

13
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.Styles.cs.meta


fileFormatVersion: 2
guid: 95517c3b2f4a014468289c3f5eb6d03c
timeCreated: 1507562538
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

258
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.cs


using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
[CustomEditor(typeof(SubsurfaceScatteringSettings))]
public sealed partial class SubsurfaceScatteringSettingsEditor : HDBaseEditor<SubsurfaceScatteringSettings>
{
sealed class Profile
{
internal SerializedProperty self;
internal SubsurfaceScatteringProfile objReference;
internal SerializedProperty name;
internal SerializedProperty scatteringDistance;
internal SerializedProperty transmissionTint;
internal SerializedProperty texturingMode;
internal SerializedProperty transmissionMode;
internal SerializedProperty thicknessRemap;
internal SerializedProperty worldScale;
// Old SSS Model >>>
internal SerializedProperty scatterDistance1;
internal SerializedProperty scatterDistance2;
internal SerializedProperty lerpWeight;
// <<< Old SSS Model
// Render preview
internal RenderTexture profileRT;
internal RenderTexture transmittanceRT;
internal Profile()
{
profileRT = new RenderTexture(256, 256, 0, RenderTextureFormat.DefaultHDR);
transmittanceRT = new RenderTexture( 16, 256, 0, RenderTextureFormat.DefaultHDR);
}
internal void Release()
{
CoreUtils.Destroy(profileRT);
CoreUtils.Destroy(transmittanceRT);
}
}
SerializedProperty m_UseDisneySSS;
List<Profile> m_Profiles;
Material m_ProfileMaterial;
Material m_TransmittanceMaterial;
protected override void OnEnable()
{
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_TransmittanceMaterial = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/DrawTransmittanceGraph");
int count = SssConstants.SSS_N_PROFILES - 1;
m_Profiles = new List<Profile>();
m_UseDisneySSS = properties.Find(x => x.useDisneySSS);
var serializedProfiles = properties.Find(x => x.profiles);
for (int i = 0; i < count; i++)
{
var serializedProfile = serializedProfiles.GetArrayElementAtIndex(i);
var rp = new RelativePropertyFetcher<SubsurfaceScatteringProfile>(serializedProfile);
var profile = new Profile
{
self = serializedProfile,
objReference = m_Target.profiles[i],
name = rp.Find(x => x.name),
scatteringDistance = rp.Find(x => x.scatteringDistance),
transmissionTint = rp.Find(x => x.transmissionTint),
texturingMode = rp.Find(x => x.texturingMode),
transmissionMode = rp.Find(x => x.transmissionMode),
thicknessRemap = rp.Find(x => x.thicknessRemap),
worldScale = rp.Find(x => x.worldScale),
scatterDistance1 = rp.Find(x => x.scatterDistance1),
scatterDistance2 = rp.Find(x => x.scatterDistance2),
lerpWeight = rp.Find(x => x.lerpWeight)
};
m_Profiles.Add(profile);
}
}
void OnDisable()
{
CoreUtils.Destroy(m_ProfileMaterial);
CoreUtils.Destroy(m_TransmittanceMaterial);
foreach (var profile in m_Profiles)
profile.Release();
m_Profiles = null;
}
public override void OnInspectorGUI()
{
CheckStyles();
// Display a warning if this settings asset is not currently in use
if (m_HDPipeline == null || m_HDPipeline.sssSettings != 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();
using (var scope = new EditorGUI.ChangeCheckScope())
{
EditorGUILayout.PropertyField(m_UseDisneySSS, s_Styles.useDisneySSS);
if (scope.changed && m_HDPipeline != null)
m_HDPipeline.CreateSssMaterials();
}
EditorGUILayout.Space();
if (m_Profiles == null || m_Profiles.Count == 0)
return;
bool useDisneySSS = m_UseDisneySSS.boolValue;
for (int i = 0; i < m_Profiles.Count; i++)
{
var profile = m_Profiles[i];
CoreEditorUtils.DrawSplitter();
bool state = profile.self.isExpanded;
state = CoreEditorUtils.DrawHeaderFoldout(profile.name.stringValue, state);
if (state)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(profile.name);
using (var scope = new EditorGUI.ChangeCheckScope())
{
if (useDisneySSS)
{
EditorGUILayout.PropertyField(profile.scatteringDistance, s_Styles.profileScatteringDistance);
using (new EditorGUI.DisabledScope(true))
EditorGUILayout.FloatField(s_Styles.profileMaxRadius, profile.objReference.maxRadius);
}
else
{
EditorGUILayout.PropertyField(profile.scatterDistance1, s_Styles.profileScatterDistance1);
EditorGUILayout.PropertyField(profile.scatterDistance2, s_Styles.profileScatterDistance2);
EditorGUILayout.PropertyField(profile.lerpWeight, s_Styles.profileLerpWeight);
}
profile.texturingMode.intValue = EditorGUILayout.Popup(s_Styles.texturingMode, profile.texturingMode.intValue, s_Styles.texturingModeOptions);
profile.transmissionMode.intValue = EditorGUILayout.Popup(s_Styles.profileTransmissionMode, profile.transmissionMode.intValue, s_Styles.transmissionModeOptions);
EditorGUILayout.PropertyField(profile.transmissionTint, s_Styles.profileTransmissionTint);
EditorGUILayout.PropertyField(profile.thicknessRemap, s_Styles.profileMinMaxThickness);
var thicknessRemap = profile.thicknessRemap.vector2Value;
EditorGUILayout.MinMaxSlider(s_Styles.profileThicknessRemap, ref thicknessRemap.x, ref thicknessRemap.y, 0f, 50f);
profile.thicknessRemap.vector2Value = thicknessRemap;
EditorGUILayout.PropertyField(profile.worldScale, s_Styles.profileWorldScale);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.profilePreview0, s_Styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(s_Styles.profilePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(s_Styles.profilePreview2, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(s_Styles.profilePreview3, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
if (scope.changed)
{
// Validate and update the cache for this profile only
profile.objReference.Validate();
m_Target.UpdateCache(i);
}
}
RenderPreview(profile, useDisneySSS);
EditorGUILayout.Space();
EditorGUI.indentLevel--;
}
profile.self.isExpanded = state;
}
CoreEditorUtils.DrawSplitter();
serializedObject.ApplyModifiedProperties();
}
void RenderPreview(Profile profile, bool useDisneySSS)
{
var obj = profile.objReference;
float r = obj.maxRadius;
var S = obj.shapeParam;
var T = (Vector4)profile.transmissionTint.colorValue;
var R = profile.thicknessRemap.vector2Value;
bool transmissionEnabled = profile.transmissionMode.intValue != (int)SubsurfaceScatteringProfile.TransmissionMode.None;
m_ProfileMaterial.SetFloat(HDShaderIDs._MaxRadius, r);
m_ProfileMaterial.SetVector(HDShaderIDs._ShapeParam, S);
// Old SSS Model >>>
CoreUtils.SelectKeyword(m_ProfileMaterial, "SSS_MODEL_DISNEY", "SSS_MODEL_BASIC", useDisneySSS);
// Apply the three-sigma rule, and rescale.
float s = (1f / 3f) * SssConstants.SSS_BASIC_DISTANCE_SCALE;
var scatterDist1 = profile.scatterDistance1.colorValue;
var scatterDist2 = profile.scatterDistance2.colorValue;
float rMax = Mathf.Max(scatterDist1.r, scatterDist1.g, scatterDist1.b,
scatterDist2.r, scatterDist2.g, scatterDist2.b);
var stdDev1 = s * (Vector4)scatterDist1;
var stdDev2 = s * (Vector4)scatterDist2;
m_ProfileMaterial.SetVector(HDShaderIDs._StdDev1, stdDev1);
m_ProfileMaterial.SetVector(HDShaderIDs._StdDev2, stdDev2);
m_ProfileMaterial.SetFloat(HDShaderIDs._LerpWeight, profile.lerpWeight.floatValue);
m_ProfileMaterial.SetFloat(HDShaderIDs._MaxRadius, rMax);
// <<< Old SSS Model
// Draw the profile.
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(256f, 256f), profile.profileRT, m_ProfileMaterial, ScaleMode.ScaleToFit, 1f);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.transmittancePreview0, s_Styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(s_Styles.transmittancePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(s_Styles.transmittancePreview2, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
// 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;
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);
m_TransmittanceMaterial.SetVector(HDShaderIDs._HalfRcpVarianceAndWeight2, halfRcpVarianceAndWeight2);
// <<< Old SSS Model
m_TransmittanceMaterial.SetVector(HDShaderIDs._ShapeParam, S);
m_TransmittanceMaterial.SetVector(HDShaderIDs._TransmissionTint, transmissionEnabled ? T : Vector4.zero);
m_TransmittanceMaterial.SetVector(HDShaderIDs._ThicknessRemap, R);
// Draw the transmittance graph.
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(16f, 16f), profile.transmittanceRT, m_TransmittanceMaterial, ScaleMode.ScaleToFit, 16f);
}
}
}

13
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.cs.meta


fileFormatVersion: 2
guid: a61a2437dcee4e54393f8f65ccf726ab
timeCreated: 1507562486
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

85
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SSS Settings.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3418a08abd15e9a49af3ccbc9e15b5ea, type: 3}
m_Name: SSS Settings
m_EditorClassIdentifier:
useDisneySSS: 1
profiles:
- name: Skin
scatteringDistance: {r: 0.7568628, g: 0.32156864, b: 0.20000002, a: 1}
transmissionTint: {r: 0.7568628, g: 0.32156864, b: 0.20000002, a: 1}
texturingMode: 0
transmissionMode: 2
thicknessRemap: {x: 0, y: 8.152544}
worldScale: 1
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
- name: Foliage
scatteringDistance: {r: 0.7568628, g: 0.7019608, b: 0.24313727, a: 1}
transmissionTint: {r: 1, g: 1, b: 1, a: 1}
texturingMode: 0
transmissionMode: 1
thicknessRemap: {x: 0, y: 0.2873168}
worldScale: 1
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
- name: Profile 2
scatteringDistance: {r: 0.5, g: 0.5, b: 0.5, a: 1}
transmissionTint: {r: 1, g: 1, b: 1, a: 1}
texturingMode: 0
transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
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
- name: Profile 3
scatteringDistance: {r: 0.5, g: 0.5, b: 0.5, a: 1}
transmissionTint: {r: 1, g: 1, b: 1, a: 1}
texturingMode: 0
transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
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
- name: Profile 4
scatteringDistance: {r: 0.5, g: 0.5, b: 0.5, a: 1}
transmissionTint: {r: 1, g: 1, b: 1, a: 1}
texturingMode: 0
transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
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
- name: Profile 5
scatteringDistance: {r: 0.5, g: 0.5, b: 0.5, a: 1}
transmissionTint: {r: 1, g: 1, b: 1, a: 1}
texturingMode: 0
transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
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
- name: Profile 6
scatteringDistance: {r: 0.5, g: 0.5, b: 0.5, a: 1}
transmissionTint: {r: 1, g: 1, b: 1, a: 1}
texturingMode: 0
transmissionMode: 0
thicknessRemap: {x: 0, y: 5}
worldScale: 1
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

10
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SSS Settings.asset.meta


fileFormatVersion: 2
guid: 873499ce7a6f749408981f512a9683f7
timeCreated: 1507649491
licenseType: Pro
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

508
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs


using System;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[GenerateHLSL]
public class SssConstants
{
public const int SSS_N_PROFILES = 8; // Max. number of profiles, including the slot taken by the neutral profile
public const int SSS_NEUTRAL_PROFILE_ID = SSS_N_PROFILES - 1; // 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, 0f, 8f, 0.125f, 3f)]
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
// Old SSS Model >>>
[ColorUsage(false, true, 0f, 8f, 0.125f, 3f)]
public Color scatterDistance1;
[ColorUsage(false, true, 0f, 8f, 0.125f, 3f)]
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;
// 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);
// 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 diffusion profile for the computed value of 's'.
// ------------------------------------------------------------------------------------
// R(r, s) = s * (Exp[-r * s] + Exp[-r * s / 3]) / (8 * Pi * r)
// PDF(r, s) = s * (Exp[-r * s] + Exp[-r * s / 3]) / 4
// 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 = KernelCdfInverse(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 / KernelPdf(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 = KernelCdfInverse(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 / KernelPdf(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.
halfRcpWeightedVariances.Set(
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 KernelVal(float r, float s)
{
return s * (Mathf.Exp(-r * s) + Mathf.Exp(-r * s * (1.0f / 3.0f))) / (8.0f * Mathf.PI * r);
}
// Computes the value of the integrand over a disk: (2 * PI * r) * KernelVal().
static float KernelValCircle(float r, float s)
{
return 0.25f * s * (Mathf.Exp(-r * s) + Mathf.Exp(-r * s * (1.0f / 3.0f)));
}
static float KernelPdf(float r, float s)
{
return KernelValCircle(r, s);
}
static float KernelCdf(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 KernelCdfDerivative1(float r, float s)
{
return 0.25f * s * Mathf.Exp(-r * s) * (1.0f + Mathf.Exp(r * s * (2.0f / 3.0f)));
}
static float KernelCdfDerivative2(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 KernelCdfInverse(float p, float s)
{
// Supply the initial guess.
float r = (Mathf.Pow(10f, p) - 1f) / s;
float t = float.MaxValue;
while (true)
{
float f0 = KernelCdf(r, s) - p;
float f1 = KernelCdfDerivative1(r, s);
float f2 = KernelCdfDerivative2(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 bool useDisneySSS = true;
public SubsurfaceScatteringProfile[] profiles;
[NonSerialized] public int texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
[NonSerialized] public int 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; // Size of the world unit in meters (only the X component is used)
[NonSerialized] public Vector4[] shapeParams; // RGB = S = 1 / D, A = filter radius
[NonSerialized] public Vector4[] transmissionTints; // RGB = color, A = unused
[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()
{
if (profiles != null && profiles.Length != SssConstants.SSS_NEUTRAL_PROFILE_ID)
Array.Resize(ref profiles, SssConstants.SSS_NEUTRAL_PROFILE_ID);
if (profiles == null)
profiles = new SubsurfaceScatteringProfile[SssConstants.SSS_NEUTRAL_PROFILE_ID];
for (int i = 0; i < SssConstants.SSS_NEUTRAL_PROFILE_ID; i++)
{
if (profiles[i] == null)
profiles[i] = new SubsurfaceScatteringProfile("Profile " + i);
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 transmissionTints, 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.");
UpdateCache();
}
static void ValidateArray<T>(ref T[] array, int len)
{
if (array == null || array.Length != len)
array = new T[len];
}
public void UpdateCache()
{
texturingModeFlags = transmissionFlags = 0;
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 i)
{
texturingModeFlags |= (int)profiles[i].texturingMode << i;
transmissionFlags |= (int)profiles[i].transmissionMode << i * 2;
thicknessRemaps[i] = new Vector4(profiles[i].thicknessRemap.x, profiles[i].thicknessRemap.y - profiles[i].thicknessRemap.x, 0f, 0f);
worldScales[i] = new Vector4(profiles[i].worldScale, 0f, 0f, 0f);
shapeParams[i] = profiles[i].shapeParam;
shapeParams[i].w = profiles[i].maxRadius;
transmissionTints[i] = profiles[i].transmissionTint * 0.25f; // Premultiplied
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * i + j].x = profiles[i].filterKernelNearField[j].x;
filterKernels[n * i + j].y = profiles[i].filterKernelNearField[j].y;
if (j < SssConstants.SSS_N_SAMPLES_FAR_FIELD)
{
filterKernels[n * i + j].z = profiles[i].filterKernelFarField[j].x;
filterKernels[n * i + j].w = profiles[i].filterKernelFarField[j].y;
}
}
// Old SSS Model >>>
halfRcpWeightedVariances[i] = profiles[i].halfRcpWeightedVariances;
var stdDev1 = ((1f / 3f) * SssConstants.SSS_BASIC_DISTANCE_SCALE) * (Vector4)profiles[i].scatterDistance1;
var stdDev2 = ((1f / 3f) * SssConstants.SSS_BASIC_DISTANCE_SCALE) * (Vector4)profiles[i].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[i].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[i].lerpWeight);
for (int j = 0, n = SssConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * i + j] = profiles[i].filterKernelBasic[j];
}
// <<< Old SSS Model
}
}
}

13
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs.meta


fileFormatVersion: 2
guid: 3418a08abd15e9a49af3ccbc9e15b5ea
timeCreated: 1507538042
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

13
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringProfileEditor.Styles.cs.meta


fileFormatVersion: 2
guid: fcb1bb4049093ff41855e3951f22e9cf
timeCreated: 1507119569
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

13
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringProfileEditor.cs.meta


fileFormatVersion: 2
guid: 4e87e719e85a91846ad1d5aa15793685
timeCreated: 1507118957
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

171
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringProfileEditor.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
[CustomEditor(typeof(SubsurfaceScatteringProfile))]
public partial class SubsurfaceScatteringProfileEditor : Editor
{
RenderTexture m_ProfileImage;
RenderTexture m_TransmittanceImage;
Material m_ProfileMaterial;
Material m_TransmittanceMaterial;
SerializedProperty m_ScatteringDistance;
SerializedProperty m_MaxRadius;
SerializedProperty m_ShapeParam;
SerializedProperty m_TransmissionTint;
SerializedProperty m_TexturingMode;
SerializedProperty m_TransmissionMode;
SerializedProperty m_ThicknessRemap;
SerializedProperty m_WorldScale;
// Old SSS Model >>>
SerializedProperty m_ScatterDistance1;
SerializedProperty m_ScatterDistance2;
SerializedProperty m_LerpWeight;
// <<< Old SSS Model
void OnEnable()
{
using (var o = new PropertyFetcher<SubsurfaceScatteringProfile>(serializedObject))
{
m_ScatteringDistance = o.FindProperty(x => x.scatteringDistance);
m_MaxRadius = o.FindProperty("m_MaxRadius");
m_ShapeParam = o.FindProperty("m_ShapeParam");
m_TransmissionTint = o.FindProperty(x => x.transmissionTint);
m_TexturingMode = o.FindProperty(x => x.texturingMode);
m_TransmissionMode = o.FindProperty(x => x.transmissionMode);
m_ThicknessRemap = o.FindProperty(x => x.thicknessRemap);
m_WorldScale = o.FindProperty(x => x.worldScale);
// Old SSS Model >>>
m_ScatterDistance1 = o.FindProperty(x => x.scatterDistance1);
m_ScatterDistance2 = o.FindProperty(x => x.scatterDistance2);
m_LerpWeight = o.FindProperty(x => x.lerpWeight);
// <<< Old SSS Model
}
// 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_TransmittanceMaterial = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/DrawTransmittanceGraph");
m_ProfileImage = new RenderTexture(256, 256, 0, RenderTextureFormat.DefaultHDR);
m_TransmittanceImage = new RenderTexture( 16, 256, 0, RenderTextureFormat.DefaultHDR);
}
void OnDisable()
{
CoreUtils.Destroy(m_ProfileMaterial);
CoreUtils.Destroy(m_TransmittanceMaterial);
CoreUtils.Destroy(m_ProfileImage);
CoreUtils.Destroy(m_TransmittanceImage);
}
public override void OnInspectorGUI()
{
var hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
if (hdPipeline == null)
return;
serializedObject.Update();
CheckStyles();
// Old SSS Model >>>
bool useDisneySSS = hdPipeline.sssSettings.useDisneySSS;
// <<< Old SSS Model
using (var scope = new EditorGUI.ChangeCheckScope())
{
if (useDisneySSS)
{
EditorGUILayout.PropertyField(m_ScatteringDistance, s_Styles.profileScatteringDistance);
using (new EditorGUI.DisabledScope(true))
EditorGUILayout.PropertyField(m_MaxRadius, s_Styles.profileMaxRadius);
}
else
{
EditorGUILayout.PropertyField(m_ScatterDistance1, s_Styles.profileScatterDistance1);
EditorGUILayout.PropertyField(m_ScatterDistance2, s_Styles.profileScatterDistance2);
EditorGUILayout.PropertyField(m_LerpWeight, s_Styles.profileLerpWeight);
}
m_TexturingMode.intValue = EditorGUILayout.Popup(s_Styles.texturingMode, m_TexturingMode.intValue, s_Styles.texturingModeOptions);
m_TransmissionMode.intValue = EditorGUILayout.Popup(s_Styles.profileTransmissionMode, m_TransmissionMode.intValue, s_Styles.transmissionModeOptions);
EditorGUILayout.PropertyField(m_TransmissionTint, s_Styles.profileTransmissionTint);
EditorGUILayout.PropertyField(m_ThicknessRemap, s_Styles.profileMinMaxThickness);
Vector2 thicknessRemap = m_ThicknessRemap.vector2Value;
EditorGUILayout.MinMaxSlider(s_Styles.profileThicknessRemap, ref thicknessRemap.x, ref thicknessRemap.y, 0.0f, 50.0f);
m_ThicknessRemap.vector2Value = thicknessRemap;
EditorGUILayout.PropertyField(m_WorldScale, s_Styles.profileWorldScale);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.profilePreview0, s_Styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(s_Styles.profilePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(s_Styles.profilePreview2, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(s_Styles.profilePreview3, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
if (scope.changed)
{
// Validate each individual asset and update caches.
((SubsurfaceScatteringProfile)target).Validate();
hdPipeline.sssSettings.UpdateCache();
}
}
float r = m_MaxRadius.floatValue;
Vector3 S = m_ShapeParam.vector3Value;
Vector4 T = m_TransmissionTint.colorValue;
Vector2 R = m_ThicknessRemap.vector2Value;
bool transmissionEnabled = m_TransmissionMode.intValue != (int)SubsurfaceScatteringProfile.TransmissionMode.None;
m_ProfileMaterial.SetFloat(HDShaderIDs._MaxRadius, r);
m_ProfileMaterial.SetVector(HDShaderIDs._ShapeParam, S);
// Old SSS Model >>>
CoreUtils.SelectKeyword(m_ProfileMaterial, "SSS_MODEL_DISNEY", "SSS_MODEL_BASIC", useDisneySSS);
// Apply the three-sigma rule, and rescale.
float s = (1.0f / 3.0f) * SssConstants.SSS_BASIC_DISTANCE_SCALE;
float rMax = Mathf.Max(m_ScatterDistance1.colorValue.r, m_ScatterDistance1.colorValue.g, m_ScatterDistance1.colorValue.b,
m_ScatterDistance2.colorValue.r, m_ScatterDistance2.colorValue.g, m_ScatterDistance2.colorValue.b);
Vector4 stdDev1 = s * m_ScatterDistance1.colorValue;
Vector4 stdDev2 = s * m_ScatterDistance2.colorValue;
m_ProfileMaterial.SetVector(HDShaderIDs._StdDev1, stdDev1);
m_ProfileMaterial.SetVector(HDShaderIDs._StdDev2, stdDev2);
m_ProfileMaterial.SetFloat(HDShaderIDs._LerpWeight, m_LerpWeight.floatValue);
m_ProfileMaterial.SetFloat(HDShaderIDs._MaxRadius, rMax);
// <<< Old SSS Model
// Draw the profile.
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(256, 256), m_ProfileImage, m_ProfileMaterial, ScaleMode.ScaleToFit, 1.0f);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.transmittancePreview0, s_Styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(s_Styles.transmittancePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(s_Styles.transmittancePreview2, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
// 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;
Vector4 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), 4 * (1.0f - m_LerpWeight.floatValue));
Vector4 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), 4 * m_LerpWeight.floatValue);
m_TransmittanceMaterial.SetVector(HDShaderIDs._HalfRcpVarianceAndWeight1, halfRcpVarianceAndWeight1);
m_TransmittanceMaterial.SetVector(HDShaderIDs._HalfRcpVarianceAndWeight2, halfRcpVarianceAndWeight2);
// <<< Old SSS Model
m_TransmittanceMaterial.SetVector(HDShaderIDs._ShapeParam, S);
m_TransmittanceMaterial.SetVector(HDShaderIDs._TransmissionTint, transmissionEnabled ? T : Vector4.zero);
m_TransmittanceMaterial.SetVector(HDShaderIDs._ThicknessRemap, R);
// Draw the transmittance graph.
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(16, 16), m_TransmittanceImage, m_TransmittanceMaterial, ScaleMode.ScaleToFit, 16.0f);
}
}
}

9
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/FoliageSSSProfile.asset.meta


fileFormatVersion: 2
guid: d6ee4403015766f4093158d69216c0bf
timeCreated: 1493161911
licenseType: Pro
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

9
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SkinSSSProfile.asset.meta


fileFormatVersion: 2
guid: 906339bac2066fc4aa22a3652e1283ef
timeCreated: 1493291209
licenseType: Pro
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

116
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/FoliageSSSProfile.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a6e7465350bf0d248b4799d98e18cd24, type: 3}
m_Name: FoliageSSSProfile
m_EditorClassIdentifier:
scatteringDistance: {r: 0.75735295, g: 0.7008203, b: 0.24502596, a: 1}
transmissionTint: {r: 1, g: 1, b: 1, a: 1}
texturingMode: 0
transmissionMode: 1
thicknessRemap: {x: 0, y: 0.2873168}
worldScale: 1
settingsIndex: 1
m_ShapeParam: {x: 1.3203883, y: 1.4268992, z: 4.0812}
m_MaxRadius: 7.839332
m_FilterKernelNearField:
- {x: 0.013854082, y: 1.5332626}
- {x: 0.04207757, y: 1.5715919}
- {x: 0.07101321, y: 1.611625}
- {x: 0.10069309, y: 1.653469}
- {x: 0.13115102, y: 1.6972395}
- {x: 0.16242325, y: 1.743061}
- {x: 0.19454831, y: 1.791069}
- {x: 0.22756726, y: 1.8414105}
- {x: 0.2615238, y: 1.8942443}
- {x: 0.29646498, y: 1.9497447}
- {x: 0.33244094, y: 2.0081}
- {x: 0.36950532, y: 2.069517}
- {x: 0.40771604, y: 2.1342213}
- {x: 0.44713485, y: 2.2024598}
- {x: 0.48782852, y: 2.274504}
- {x: 0.5298689, y: 2.3506513}
- {x: 0.5733336, y: 2.4312308}
- {x: 0.6183063, y: 2.5166042}
- {x: 0.66487795, y: 2.6071734}
- {x: 0.71314675, y: 2.703383}
- {x: 0.76321995, y: 2.805728}
- {x: 0.81521386, y: 2.9147599}
- {x: 0.86925554, y: 3.031096}
- {x: 0.92548406, y: 3.1554284}
- {x: 0.9840515, y: 3.288537}
- {x: 1.0451256, y: 3.431302}
- {x: 1.1088905, y: 3.5847225}
- {x: 1.1755506, y: 3.749937}
- {x: 1.2453312, y: 3.9282467}
- {x: 1.3184844, y: 4.1211514}
- {x: 1.3952904, y: 4.3303804}
- {x: 1.4760638, y: 4.5579505}
- {x: 1.5611593, y: 4.8062224}
- {x: 1.650978, y: 5.0779796}
- {x: 1.7459753, y: 5.3765287}
- {x: 1.8466738, y: 5.7058387}
- {x: 1.9536757, y: 6.070716}
- {x: 2.0676782, y: 6.4770336}
- {x: 2.189499, y: 6.9320674}
- {x: 2.3201032, y: 7.4449396}
- {x: 2.4606442, y: 8.027264}
- {x: 2.612515, y: 8.694056}
- {x: 2.777422, y: 9.465107}
- {x: 2.9574924, y: 10.367077}
- {x: 3.1554203, y: 11.436736}
- {x: 3.3747015, y: 12.726331}
- {x: 3.6199868, y: 14.312694}
- {x: 3.897662, y: 16.313623}
- {x: 4.2168484, y: 18.919455}
- {x: 4.5912457, y: 22.459015}
- {x: 5.042839, y: 27.553566}
- {x: 5.610336, y: 35.534466}
- {x: 6.3721733, y: 49.863647}
- {x: 7.53103, y: 83.235695}
- {x: 10.026244, y: 249.90146}
m_FilterKernelFarField:
- {x: 0.036647703, y: 1.5641627}
- {x: 0.113649175, y: 1.671985}
- {x: 0.19610003, y: 1.7934121}
- {x: 0.28470552, y: 1.9309369}
- {x: 0.38030306, y: 2.0876582}
- {x: 0.48389605, y: 2.2674706}
- {x: 0.5966971, y: 2.4753277}
- {x: 0.72018707, y: 2.717616}
- {x: 0.85619545, y: 3.0026984}
- {x: 1.0070126, y: 3.3417335}
- {x: 1.1755506, y: 3.749937}
- {x: 1.3655809, y: 4.248627}
- {x: 1.5821002, y: 4.868682}
- {x: 1.8319175, y: 5.6567397}
- {x: 2.1246579, y: 6.6871305}
- {x: 2.4745958, y: 8.086858}
- {x: 2.9043517, y: 10.094101}
- {x: 3.4533012, y: 13.217383}
- {x: 4.20053, y: 18.777578}
- {x: 5.349281, y: 31.61934}
- {x: 7.839332, y: 95.36225}
scatterDistance1: {r: 0.3, g: 0.3, b: 0.3, a: 0}
scatterDistance2: {r: 0.6, g: 0.6, b: 0.6, a: 0}
lerpWeight: 0.5
m_HalfRcpWeightedVariances: {x: 2.4691355, y: 2.4691355, z: 2.4691355, w: 2.4691355}
m_FilterKernelBasic:
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.000000048879357}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.11381993}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.23580086}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.37865555}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.57677805}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -1.3907351}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.11382001}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.23580086}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.37865555}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.57677805}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 1.3907368}

116
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SkinSSSProfile.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a6e7465350bf0d248b4799d98e18cd24, type: 3}
m_Name: SkinSSSProfile
m_EditorClassIdentifier:
scatteringDistance: {r: 0.758, g: 0.321, b: 0.201, a: 1}
transmissionTint: {r: 0.7568628, g: 0.32156864, b: 0.20000002, a: 1}
texturingMode: 0
transmissionMode: 2
thicknessRemap: {x: 0, y: 8.152544}
worldScale: 1
settingsIndex: 0
m_ShapeParam: {x: 1.3192612, y: 3.1152647, z: 4.9751244}
m_MaxRadius: 7.84603
m_FilterKernelNearField:
- {x: 0.013865918, y: 1.5345725}
- {x: 0.04211352, y: 1.5729346}
- {x: 0.07107388, y: 1.6130018}
- {x: 0.100779116, y: 1.6548817}
- {x: 0.13126306, y: 1.6986896}
- {x: 0.16256203, y: 1.7445502}
- {x: 0.1947145, y: 1.7925992}
- {x: 0.22776169, y: 1.8429838}
- {x: 0.26174724, y: 1.8958628}
- {x: 0.29671827, y: 1.9514104}
- {x: 0.33272493, y: 2.0098157}
- {x: 0.369821, y: 2.0712852}
- {x: 0.40806437, y: 2.1360447}
- {x: 0.44751683, y: 2.2043417}
- {x: 0.48824534, y: 2.276447}
- {x: 0.5303216, y: 2.3526597}
- {x: 0.5738235, y: 2.433308}
- {x: 0.61883456, y: 2.5187542}
- {x: 0.665446, y: 2.609401}
- {x: 0.713756, y: 2.7056925}
- {x: 0.763872, y: 2.808125}
- {x: 0.8159103, y: 2.91725}
- {x: 0.8699981, y: 3.0336854}
- {x: 0.9262747, y: 3.1581244}
- {x: 0.98489225, y: 3.2913465}
- {x: 1.0460185, y: 3.434234}
- {x: 1.1098381, y: 3.5877857}
- {x: 1.1765549, y: 3.7531407}
- {x: 1.2463952, y: 3.9316032}
- {x: 1.319611, y: 4.124672}
- {x: 1.3964823, y: 4.3340797}
- {x: 1.4773248, y: 4.561845}
- {x: 1.5624928, y: 4.810328}
- {x: 1.6523882, y: 5.082317}
- {x: 1.747467, y: 5.381122}
- {x: 1.8482518, y: 5.710715}
- {x: 1.9553448, y: 6.0759025}
- {x: 2.069445, y: 6.482568}
- {x: 2.1913698, y: 6.9379897}
- {x: 2.3220856, y: 7.4513016}
- {x: 2.4627466, y: 8.0341215}
- {x: 2.614747, y: 8.701484}
- {x: 2.7797952, y: 9.473195}
- {x: 2.9600194, y: 10.375936}
- {x: 3.1581159, y: 11.446505}
- {x: 3.3775842, y: 12.737201}
- {x: 3.6230793, y: 14.324919}
- {x: 3.9009922, y: 16.327562}
- {x: 4.220452, y: 18.935623}
- {x: 4.5951686, y: 22.478209}
- {x: 5.047148, y: 27.57712}
- {x: 5.615129, y: 35.564823}
- {x: 6.3776174, y: 49.90625}
- {x: 7.5374603, y: 83.30668}
- {x: 10.03481, y: 250.11497}
m_FilterKernelFarField:
- {x: 0.03667902, y: 1.5654991}
- {x: 0.11374626, y: 1.6734134}
- {x: 0.19626758, y: 1.7949444}
- {x: 0.28494877, y: 1.9325867}
- {x: 0.38062802, y: 2.0894418}
- {x: 0.48430943, y: 2.2694077}
- {x: 0.59720695, y: 2.4774427}
- {x: 0.72080237, y: 2.7199378}
- {x: 0.8569269, y: 3.005264}
- {x: 1.007873, y: 3.3445888}
- {x: 1.1765549, y: 3.7531407}
- {x: 1.3667475, y: 4.252257}
- {x: 1.5834517, y: 4.872841}
- {x: 1.8334827, y: 5.6615734}
- {x: 2.126473, y: 6.692844}
- {x: 2.4767098, y: 8.093767}
- {x: 2.9068332, y: 10.102725}
- {x: 3.4562516, y: 13.228675}
- {x: 4.2041187, y: 18.793621}
- {x: 5.3538504, y: 31.646347}
- {x: 7.84603, y: 95.44374}
scatterDistance1: {r: 0.3, g: 0.2, b: 0.2, a: 0}
scatterDistance2: {r: 0.6, g: 0.2, b: 0.2, a: 0}
lerpWeight: 0.5
m_HalfRcpWeightedVariances: {x: 2.4691355, y: 12.5, z: 12.5, w: 2.4691355}
m_FilterKernelBasic:
- {x: 0.09090909, y: 0.21162307, z: 0.21162307, w: -0.000000048879357}
- {x: 0.09090909, y: 0.18990478, z: 0.18990478, w: -0.11381993}
- {x: 0.09090909, y: 0.13233659, z: 0.13233659, w: -0.23580086}
- {x: 0.09090909, y: 0.061445467, z: 0.061445467, w: -0.37865555}
- {x: 0.09090909, y: 0.010501689, z: 0.010501689, w: -0.57677805}
- {x: 0.09090909, y: 2.9458339e-10, z: 2.9458339e-10, w: -1.3907351}
- {x: 0.09090909, y: 0.18990476, z: 0.18990476, w: 0.11382001}
- {x: 0.09090909, y: 0.13233659, z: 0.13233659, w: 0.23580086}
- {x: 0.09090909, y: 0.061445467, z: 0.061445467, w: 0.37865555}
- {x: 0.09090909, y: 0.010501689, z: 0.010501689, w: 0.57677805}
- {x: 0.09090909, y: 2.9456845e-10, z: 2.9456845e-10, w: 1.3907368}

12
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs.meta


fileFormatVersion: 2
guid: a6e7465350bf0d248b4799d98e18cd24
timeCreated: 1490016484
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

637
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs


using System;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[GenerateHLSL]
public class SssConstants
{
public const int SSS_N_PROFILES = 8; // Max. number of profiles, including the slot taken by the neutral profile
public const int SSS_NEUTRAL_PROFILE_ID = SSS_N_PROFILES - 1; // 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 class SubsurfaceScatteringProfile : ScriptableObject
{
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 };
[ColorUsage(false, true, 0f, 8f, 0.125f, 3f)]
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
[HideInInspector]
public int settingsIndex; // SubsurfaceScatteringSettings.profiles[i]
[SerializeField]
Vector3 m_ShapeParam; // RGB = shape parameter: S = 1 / D
[SerializeField]
float m_MaxRadius; // In millimeters
[SerializeField]
Vector2[] m_FilterKernelNearField; // X = radius, Y = reciprocal of the PDF
[SerializeField]
Vector2[] m_FilterKernelFarField; // X = radius, Y = reciprocal of the PDF
// Old SSS Model >>>
[ColorUsage(false, true, 0f, 8f, 0.125f, 3f)]
public Color scatterDistance1;
[ColorUsage(false, true, 0f, 8f, 0.125f, 3f)]
public Color scatterDistance2;
[Range(0f, 1f)]
public float lerpWeight;
[SerializeField]
Vector4 m_HalfRcpWeightedVariances;
[SerializeField]
Vector4[] m_FilterKernelBasic;
// <<< Old SSS Model
// --- Public Methods ---
public SubsurfaceScatteringProfile()
{
scatteringDistance = Color.grey;
transmissionTint = Color.white;
texturingMode = TexturingMode.PreAndPostScatter;
transmissionMode = TransmissionMode.None;
thicknessRemap = new Vector2(0.0f, 5.0f);
worldScale = 1.0f;
settingsIndex = SssConstants.SSS_NEUTRAL_PROFILE_ID; // Updated by SubsurfaceScatteringSettings.OnValidate() once assigned
// Old SSS Model >>>
scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0.0f);
scatterDistance2 = new Color(0.5f, 0.5f, 0.5f, 0.0f);
lerpWeight = 1.0f;
// <<< Old SSS Model
BuildKernel();
}
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);
// Old SSS Model >>>
var c = new Color();
c.r = Mathf.Max(0.05f, scatterDistance1.r);
c.g = Mathf.Max(0.05f, scatterDistance1.g);
c.b = Mathf.Max(0.05f, scatterDistance1.b);
c.a = 0.0f;
scatterDistance1 = c;
c.r = Mathf.Max(0.05f, scatterDistance2.r);
c.g = Mathf.Max(0.05f, scatterDistance2.g);
c.b = Mathf.Max(0.05f, scatterDistance2.b);
c.a = 0.0f;
scatterDistance2 = c;
// <<< Old SSS Model
BuildKernel();
}
// Ref: Approximate Reflectance Profiles for Efficient Subsurface Scattering by Pixar.
public void BuildKernel()
{
if (m_FilterKernelNearField == null || m_FilterKernelNearField.Length != SssConstants.SSS_N_SAMPLES_NEAR_FIELD)
{
m_FilterKernelNearField = new Vector2[SssConstants.SSS_N_SAMPLES_NEAR_FIELD];
}
if (m_FilterKernelFarField == null || m_FilterKernelFarField.Length != SssConstants.SSS_N_SAMPLES_FAR_FIELD)
{
m_FilterKernelFarField = new Vector2[SssConstants.SSS_N_SAMPLES_FAR_FIELD];
}
// Clamp to avoid artifacts.
m_ShapeParam.x = 1.0f / Mathf.Max(0.001f, scatteringDistance.r);
m_ShapeParam.y = 1.0f / Mathf.Max(0.001f, scatteringDistance.g);
m_ShapeParam.z = 1.0f / Mathf.Max(0.001f, scatteringDistance.b);
// We importance sample the color channel with the widest scattering distance.
float s = Mathf.Min(m_ShapeParam.x, m_ShapeParam.y, m_ShapeParam.z);
// Importance sample the normalized diffusion profile for the computed value of 's'.
// ------------------------------------------------------------------------------------
// R(r, s) = s * (Exp[-r * s] + Exp[-r * s / 3]) / (8 * Pi * r)
// PDF(r, s) = s * (Exp[-r * s] + Exp[-r * s / 3]) / 4
// 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) * (1.0f / n);
float r = KernelCdfInverse(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).
m_FilterKernelNearField[i].x = r;
m_FilterKernelNearField[i].y = 1.0f / KernelPdf(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) * (1.0f / n);
float r = KernelCdfInverse(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).
m_FilterKernelFarField[i].x = r;
m_FilterKernelFarField[i].y = 1.0f / KernelPdf(r, s);
}
m_MaxRadius = m_FilterKernelFarField[SssConstants.SSS_N_SAMPLES_FAR_FIELD - 1].x;
// Old SSS Model >>>
UpdateKernelAndVarianceData();
// <<< Old SSS Model
}
// Old SSS Model >>>
public void UpdateKernelAndVarianceData()
{
const int numSamples = SssConstants.SSS_BASIC_N_SAMPLES;
const int distanceScale = SssConstants.SSS_BASIC_DISTANCE_SCALE;
if (m_FilterKernelBasic == null || m_FilterKernelBasic.Length != numSamples)
{
m_FilterKernelBasic = new Vector4[numSamples];
}
// Apply the three-sigma rule, and rescale.
Color stdDev1 = ((1.0f / 3.0f) * distanceScale) * scatterDistance1;
Color stdDev2 = ((1.0f / 3.0f) * distanceScale) * 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);
Vector3 weightSum = new Vector3(0, 0, 0);
float step = 1.0f / (numSamples - 1);
// Importance sample the linear combination of two Gaussians.
for (int i = 0; i < numSamples; i++)
{
// Generate 'u' on (0, 0.5] and (0.5, 1).
float u = (i <= numSamples / 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.
m_FilterKernelBasic[i].x = val.x * (1 / pdf);
m_FilterKernelBasic[i].y = val.y * (1 / pdf);
m_FilterKernelBasic[i].z = val.z * (1 / pdf);
m_FilterKernelBasic[i].w = pos;
weightSum.x += m_FilterKernelBasic[i].x;
weightSum.y += m_FilterKernelBasic[i].y;
weightSum.z += m_FilterKernelBasic[i].z;
}
// Renormalize the weights to conserve energy.
for (int i = 0; i < numSamples; i++)
{
m_FilterKernelBasic[i].x *= 1 / weightSum.x;
m_FilterKernelBasic[i].y *= 1 / weightSum.y;
m_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.
m_HalfRcpWeightedVariances.x = 0.5f / (weightedStdDev.x * weightedStdDev.x);
m_HalfRcpWeightedVariances.y = 0.5f / (weightedStdDev.y * weightedStdDev.y);
m_HalfRcpWeightedVariances.z = 0.5f / (weightedStdDev.z * weightedStdDev.z);
m_HalfRcpWeightedVariances.w = 0.5f / (weightedStdDev.w * weightedStdDev.w);
}
// <<< Old SSS Model
public Vector3 shapeParameter
{
// Set in BuildKernel().
get { return m_ShapeParam; }
}
public float maxRadius
{
// Set in BuildKernel().
get { return m_MaxRadius; }
}
public Vector2[] filterKernelNearField
{
// Set in BuildKernel().
get { return m_FilterKernelNearField; }
}
public Vector2[] filterKernelFarField
{
// Set in BuildKernel().
get { return m_FilterKernelFarField; }
}
// Old SSS Model >>>
public Vector4[] filterKernelBasic
{
// Set via UpdateKernelAndVarianceData().
get { return m_FilterKernelBasic; }
}
public Vector4 halfRcpWeightedVariances
{
// Set via UpdateKernelAndVarianceData().
get { return m_HalfRcpWeightedVariances; }
}
// <<< Old SSS Model
// --- Private Methods ---
static float KernelVal(float r, float s)
{
return s * (Mathf.Exp(-r * s) + Mathf.Exp(-r * s * (1.0f / 3.0f))) / (8.0f * Mathf.PI * r);
}
// Computes the value of the integrand over a disk: (2 * PI * r) * KernelVal().
static float KernelValCircle(float r, float s)
{
return 0.25f * s * (Mathf.Exp(-r * s) + Mathf.Exp(-r * s * (1.0f / 3.0f)));
}
static float KernelPdf(float r, float s)
{
return KernelValCircle(r, s);
}
static float KernelCdf(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 KernelCdfDerivative1(float r, float s)
{
return 0.25f * s * Mathf.Exp(-r * s) * (1.0f + Mathf.Exp(r * s * (2.0f / 3.0f)));
}
static float KernelCdfDerivative2(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 KernelCdfInverse(float p, float s)
{
// Supply the initial guess.
float r = (Mathf.Pow(10.0f, p) - 1.0f) / s;
float t = float.MaxValue;
while (true)
{
float f0 = KernelCdf(r, s) - p;
float f1 = KernelCdfDerivative1(r, s);
float f2 = KernelCdfDerivative2(r, s);
float dr = f0 / (f1 * (1.0f - f0 * f2 / (2.0f * 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(-2.0f * Mathf.Log(p)));
}
else
{
// F^-1(p) = G^-1(1-p)
x = RationalApproximation(Mathf.Sqrt(-2.0f * Mathf.Log(1.0f - 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
}
[Serializable]
public class SubsurfaceScatteringSettings : ISerializationCallbackReceiver
{
public int numProfiles; // Excluding the neutral profile
public SubsurfaceScatteringProfile[] profiles;
// Below are the cached values. TODO: uncomment when SSS profile asset serialization is fixed.
/*[NonSerialized]*/ public int texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
/*[NonSerialized]*/ public int 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; // Size of the world unit in meters (only the X component is used)
/*[NonSerialized]*/ public Vector4[] shapeParams; // RGB = S = 1 / D, A = filter radius
/*[NonSerialized]*/ public Vector4[] transmissionTints; // RGB = color, A = unused
/*[NonSerialized]*/ public Vector4[] filterKernels; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
// Old SSS Model >>>
public bool useDisneySSS;
/*[NonSerialized]*/ public Vector4[] halfRcpWeightedVariances;
/*[NonSerialized]*/ public Vector4[] halfRcpVariancesAndWeights;
/*[NonSerialized]*/ public Vector4[] filterKernelsBasic;
// <<< Old SSS Model
// --- Public Methods ---
public SubsurfaceScatteringSettings()
{
numProfiles = 1;
profiles = new SubsurfaceScatteringProfile[numProfiles];
profiles[0] = null;
texturingModeFlags = 0;
transmissionFlags = 0;
thicknessRemaps = null;
worldScales = null;
shapeParams = null;
transmissionTints = null;
filterKernels = null;
// Old SSS Model >>>
useDisneySSS = true;
halfRcpWeightedVariances = null;
halfRcpVariancesAndWeights = null;
filterKernelsBasic = null;
// <<< Old SSS Model
UpdateCache();
}
public void OnValidate()
{
// Reserve one slot for the neutral profile.
numProfiles = Math.Min(profiles.Length, SssConstants.SSS_N_PROFILES - 1);
if (profiles.Length != numProfiles)
{
Array.Resize(ref profiles, numProfiles);
}
for (int i = 0; i < numProfiles; i++)
{
if (profiles[i] != null)
{
// Assign the profile IDs.
profiles[i].settingsIndex = i;
}
}
foreach (var profile in profiles)
{
if (profile != null)
profile.Validate();
}
UpdateCache();
}
public void UpdateCache()
{
texturingModeFlags = transmissionFlags = 0;
if (thicknessRemaps == null || thicknessRemaps.Length != SssConstants.SSS_N_PROFILES)
{
thicknessRemaps = new Vector4[SssConstants.SSS_N_PROFILES];
}
if (worldScales == null || worldScales.Length != SssConstants.SSS_N_PROFILES)
{
worldScales = new Vector4[SssConstants.SSS_N_PROFILES];
}
if (shapeParams == null || shapeParams.Length != SssConstants.SSS_N_PROFILES)
{
shapeParams = new Vector4[SssConstants.SSS_N_PROFILES];
}
if (transmissionTints == null || transmissionTints.Length != SssConstants.SSS_N_PROFILES)
{
transmissionTints = new Vector4[SssConstants.SSS_N_PROFILES];
}
const int filterKernelsNearFieldLen = SssConstants.SSS_N_PROFILES * SssConstants.SSS_N_SAMPLES_NEAR_FIELD;
if (filterKernels == null || filterKernels.Length != filterKernelsNearFieldLen)
{
filterKernels = new Vector4[filterKernelsNearFieldLen];
}
// Old SSS Model >>>
if (halfRcpWeightedVariances == null || halfRcpWeightedVariances.Length != SssConstants.SSS_N_PROFILES)
{
halfRcpWeightedVariances = new Vector4[SssConstants.SSS_N_PROFILES];
}
if (halfRcpVariancesAndWeights == null || halfRcpVariancesAndWeights.Length != 2 * SssConstants.SSS_N_PROFILES)
{
halfRcpVariancesAndWeights = new Vector4[2 * SssConstants.SSS_N_PROFILES];
}
const int filterKernelsLen = SssConstants.SSS_N_PROFILES * SssConstants.SSS_BASIC_N_SAMPLES;
if (filterKernelsBasic == null || filterKernelsBasic.Length != filterKernelsLen)
{
filterKernelsBasic = new Vector4[filterKernelsLen];
}
// <<< Old SSS Model
for (int i = 0; i < SssConstants.SSS_N_PROFILES - 1; i++)
{
// If a profile is null, it means that it was never set in the HDRenderPipeline Asset or that the profile asset has been deleted.
// In this case we want the users to be warned if a material uses one of those. This is why we fill the profile with pink transmission values.
if (i >= numProfiles || profiles[i] == null)
{
// Pink transmission
transmissionFlags |= 1 << i * 2;
transmissionTints[i] = new Vector4(100.0f, 0.0f, 100.0f, 1.0f);
// Default neutral values for the rest
worldScales[i] = Vector4.one;
shapeParams[i] = Vector4.zero;
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * i + j].x = 0.0f;
filterKernels[n * i + j].y = 1.0f;
filterKernels[n * i + j].z = 0.0f;
filterKernels[n * i + j].w = 1.0f;
}
// Old SSS Model >>>
halfRcpWeightedVariances[i] = Vector4.one;
halfRcpVariancesAndWeights[2 * i + 0] = Vector4.one;
halfRcpVariancesAndWeights[2 * i + 1] = Vector4.one;
for (int j = 0, n = SssConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * i + j] = Vector4.one;
filterKernelsBasic[n * i + j].w = 0.0f;
}
continue;
}
Debug.Assert(numProfiles < 16, "Transmission flags (32-bit integer) cannot support more than 16 profiles.");
texturingModeFlags |= (int)profiles[i].texturingMode << i;
transmissionFlags |= (int)profiles[i].transmissionMode << i * 2;
thicknessRemaps[i] = new Vector4(profiles[i].thicknessRemap.x, profiles[i].thicknessRemap.y - profiles[i].thicknessRemap.x, 0.0f, 0.0f);
worldScales[i] = new Vector4(profiles[i].worldScale, 0, 0, 0);
shapeParams[i] = profiles[i].shapeParameter;
shapeParams[i].w = profiles[i].maxRadius;
transmissionTints[i] = profiles[i].transmissionTint * 0.25f; // Premultiplied
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * i + j].x = profiles[i].filterKernelNearField[j].x;
filterKernels[n * i + j].y = profiles[i].filterKernelNearField[j].y;
if (j < SssConstants.SSS_N_SAMPLES_FAR_FIELD)
{
filterKernels[n * i + j].z = profiles[i].filterKernelFarField[j].x;
filterKernels[n * i + j].w = profiles[i].filterKernelFarField[j].y;
}
}
// Old SSS Model >>>
halfRcpWeightedVariances[i] = profiles[i].halfRcpWeightedVariances;
Vector4 stdDev1 = ((1.0f / 3.0f) * SssConstants.SSS_BASIC_DISTANCE_SCALE) * profiles[i].scatterDistance1;
Vector4 stdDev2 = ((1.0f / 3.0f) * SssConstants.SSS_BASIC_DISTANCE_SCALE) * profiles[i].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), 4 * (1.0f - profiles[i].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), 4 * profiles[i].lerpWeight);
for (int j = 0, n = SssConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * i + j] = profiles[i].filterKernelBasic[j];
}
// <<< Old SSS Model
}
// Fill the neutral profile.
{
int i = SssConstants.SSS_NEUTRAL_PROFILE_ID;
worldScales[i] = Vector4.one;
shapeParams[i] = Vector4.zero;
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{
filterKernels[n * i + j].x = 0.0f;
filterKernels[n * i + j].y = 1.0f;
filterKernels[n * i + j].z = 0.0f;
filterKernels[n * i + j].w = 1.0f;
}
// Old SSS Model >>>
halfRcpWeightedVariances[i] = Vector4.one;
for (int j = 0, n = SssConstants.SSS_BASIC_N_SAMPLES; j < n; j++)
{
filterKernelsBasic[n * i + j] = Vector4.one;
filterKernelsBasic[n * i + j].w = 0.0f;
}
// <<< Old SSS Model
}
}
public void OnBeforeSerialize()
{
// No special action required.
}
public void OnAfterDeserialize()
{
// TODO: uncomment when SSS profile asset serialization is fixed.
// UpdateCache();
}
}
}

/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringProfileEditor.Styles.cs → /ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/SubsurfaceScatteringSettingsEditor.Styles.cs

正在加载...
取消
保存