浏览代码

Merge branch 'master' into lowendmobile

# Conflicts:
#	Assets/LowEndMobilePipeline/TestScenes/Materials.meta
#	Assets/ScriptableRenderPipeline/Editor/MaterialUpgrader.cs
#	Assets/TestScenes/HDTest/GraphicTest/LayeredTessellation/Material.meta
#	Assets/TestScenes/HDTest/LayeredLitTest/Mesh/Materials.meta
/vr_sandbox
Felipe Lira 8 年前
当前提交
557acdfd
共有 470 个文件被更改,包括 4056 次插入4092 次删除
  1. 2
      Assets/ScriptableRenderPipeline.meta
  2. 6
      Assets/ScriptableRenderPipeline/AdditionalLightData.cs
  3. 29
      Assets/ScriptableRenderPipeline/Editor/MaterialUpgrader.cs
  4. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline.meta
  5. 28
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/HDRenderPipelineDebug.cs
  6. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl
  7. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/Resources/DebugDisplayShadowMap.shader
  8. 18
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/Resources/DebugViewMaterialGBuffer.shader
  9. 409
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/Resources/DebugViewTiles.shader
  10. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor.meta
  11. 172
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs
  12. 92
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs
  13. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/UpgradeStandardShaderMaterials.cs
  14. 160
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.asset
  15. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.asset.meta
  16. 535
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  17. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs.meta
  18. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting.meta
  19. 9
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop.cs
  20. 23
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Lighting.hlsl
  21. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources.meta
  22. 47
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources/Deferred.shader
  23. 25
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TileLightLoopProducer.cs
  24. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass.meta
  25. 16
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute
  26. 50
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild-clustered.compute
  27. 925
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild.compute
  28. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/scrbound.compute
  29. 185
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/shadeopaque.compute
  30. 1001
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  31. 14
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl
  32. 62
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl
  33. 700
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  34. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassProducer.asset
  35. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassProducer.asset.meta
  36. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassResources.asset
  37. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassResources.cs
  38. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material.meta
  39. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Builtin/BuiltinData.hlsl
  40. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit.meta
  41. 296
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs
  42. 79
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader
  43. 118
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader
  44. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit.meta
  45. 558
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs
  46. 206
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs
  47. 17
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/StandardSpecularToHDLitMaterialUpgrader.cs
  48. 17
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/StandardToHDLitMaterialUpgrader.cs
  49. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  50. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl
  51. 238
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  52. 62
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader
  53. 466
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl
  54. 153
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  55. 69
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl
  56. 13
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl
  57. 69
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader
  58. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LtcData.DisneyDiffuse.cs
  59. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LtcData.GGX.cs
  60. 81
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader
  61. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/PreIntegratedFGD.shader
  62. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDepthPass.hlsl
  63. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDistortionPass.hlsl
  64. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitVelocityPass.hlsl
  65. 18
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Material.hlsl
  66. 34
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/MaterialUtilities.hlsl
  67. 278
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs
  68. 58
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/UnlitUI.cs
  69. 18
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Unlit.shader
  70. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/UnlitProperties.hlsl
  71. 68
      Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Editor/PostProcessingSRPEditor.cs
  72. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.shader
  73. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/EyeHistogram.compute
  74. 32
      Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/FinalPass.shader
  75. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/LutGen.shader
  76. 157
      Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/PostProcessingSRP.cs
  77. 19
      Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/PostProcessingSRP.Settings.cs
  78. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass.meta
  79. 22
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/FragInputs.hlsl
  80. 15
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDebugViewMaterial.hlsl
  81. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl
  82. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDistortion.hlsl
  83. 5
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl
  84. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl
  85. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl
  86. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl
  87. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl
  88. 34
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl
  89. 104
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl
  90. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow.meta
  91. 135
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl
  92. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky.meta
  93. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/Editor/HDRISkyEditor.cs
  94. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/HDRISkyRenderer.cs
  95. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/Resources/SkyHDRI.shader
  96. 31
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkyRenderer.cs
  97. 18
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/Resources/AtmosphericScattering.hlsl
  98. 11
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/Resources/SkyProcedural.shader
  99. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkySettings.cs
  100. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/Resources.meta

2
Assets/ScriptableRenderPipeline.meta


fileFormatVersion: 2
guid: 7f2fa2efb8ce343069fc5393536094ad
guid: 403e54624681147459c529bbda90360e
folderAsset: yes
timeCreated: 1466769773
licenseType: Pro

6
Assets/ScriptableRenderPipeline/AdditionalLightData.cs


[Range(0.0F, 1.0F)]
public float shadowDimmer = 1.0f;
[Range(0.0F, 1.0F)]
public float lightDimmer = 1.0f;
// Not used for directional lights.
public float fadeDistance = 10000.0f;
public float shadowFadeDistance = 10000.0f;
public bool affectDiffuse = true;
public bool affectSpecular = true;

29
Assets/ScriptableRenderPipeline/Editor/MaterialUpgrader.cs


{
public class MaterialUpgrader
{
public delegate void MaterialFinalizer(Material mat);
MaterialFinalizer m_Finalizer;
Dictionary<string, string> m_TextureRename = new Dictionary<string, string>();
Dictionary<string, string> m_FloatRename = new Dictionary<string, string>();

Dictionary<string, Color> m_ColorPropertiesToSet = new Dictionary<string, Color>();
List<string> m_TexturesToRemove = new List<string>();
class KeywordFloatRename
{
public string keyword;
public string property;
public float setVal, unsetVal;
}
List<KeywordFloatRename> m_KeywordFloatRename = new List<KeywordFloatRename>();
[Flags]
public enum UpgradeFlags

material.CopyPropertiesFromMaterial(newMaterial);
UnityEngine.Object.DestroyImmediate(newMaterial);
material.shaderKeywords = new string[0];
var matEditor = Editor.CreateEditor(material) as MaterialEditor;
matEditor.SetShader(material.shader, false);
matEditor.serializedObject.ApplyModifiedPropertiesWithoutUndo();
if(m_Finalizer != null)
m_Finalizer(material);
}
// Overridable function to implement custom material upgrading functionality

foreach (var prop in m_ColorPropertiesToSet)
dstMaterial.SetColor(prop.Key, prop.Value);
foreach (var t in m_KeywordFloatRename)
dstMaterial.SetFloat(t.property, srcMaterial.IsKeywordEnabled(t.keyword) ? t.setVal : t.unsetVal);
public void RenameShader(string oldName, string newName)
public void RenameShader(string oldName, string newName, MaterialFinalizer finalizer)
m_Finalizer = finalizer;
}
public void RenameTexture(string oldName, string newName)

public void SetColor(string propertyName, Color value)
{
m_ColorPropertiesToSet[propertyName] = value;
}
public void RenameKeywordToFloat(string oldName, string newName, float setVal, float unsetVal)
{
m_KeywordFloatRename.Add(new KeywordFloatRename { keyword = oldName, property = newName, setVal = setVal, unsetVal = unsetVal });
}
static bool IsMaterialPath(string path)

2
Assets/ScriptableRenderPipeline/HDRenderPipeline.meta


fileFormatVersion: 2
guid: 4c38eac64d0e8344d85c9f309419d619
guid: a75de3f722a762f4daf65be08cd9c5c6
folderAsset: yes
timeCreated: 1483548930
licenseType: Pro

28
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/HDRenderPipelineDebug.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[Serializable]
public class GlobalDebugParameters
public class GlobalDebugSettings
{
public float debugOverlayRatio = 0.33f;
public bool displayMaterialDebug = false;

public MaterialDebugParameters materialDebugParameters = new MaterialDebugParameters();
public LightingDebugParameters lightingDebugParameters = new LightingDebugParameters();
public RenderingDebugParameters renderingDebugParametrs = new RenderingDebugParameters();
public MaterialDebugSettings materialDebugSettings = new MaterialDebugSettings();
public LightingDebugSettings lightingDebugSettings = new LightingDebugSettings();
public RenderingDebugSettings renderingDebugSettings = new RenderingDebugSettings();
lightingDebugParameters.OnValidate();
lightingDebugSettings.OnValidate();
public class MaterialDebugParameters
public class MaterialDebugSettings
public class RenderingDebugParameters
public class RenderingDebugSettings
public bool enableSSS = true;
public enum ShadowDebugMode
public enum ShadowMapDebugMode
{
None,
VisualizeAtlas,

{
None,
DiffuseLighting,
SpecularLighting
SpecularLighting,
VisualizeCascade
public class LightingDebugParameters
public class LightingDebugSettings
public ShadowDebugMode shadowDebugMode = ShadowDebugMode.None;
public ShadowMapDebugMode shadowDebugMode = ShadowMapDebugMode.None;
public uint shadowMapIndex = 0;
public LightingDebugMode lightingDebugMode = LightingDebugMode.None;

public bool displaySkyReflection = false;
public float skyReflectionMipmap = 0.0f;
skyReflectionMipmap = Mathf.Clamp(skyReflectionMipmap, 0.0f, 1.0f);
}
}
}

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl


#define LIGHTINGDEBUGMODE_NONE (0)
#define LIGHTINGDEBUGMODE_DIFFUSE_LIGHTING (1)
#define LIGHTINGDEBUGMODE_SPECULAR_LIGHTING (2)
#define LIGHTINGDEBUGMODE_VISUALIZE_CASCADE (3)
#endif

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/Resources/DebugDisplayShadowMap.shader


#pragma vertex Vert
#pragma fragment Frag
#include "ShaderLibrary/Common.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
TEXTURE2D_FLOAT(g_tShadowBuffer);

18
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/Resources/DebugViewMaterialGBuffer.shader


#pragma vertex Vert
#pragma fragment Frag
#include "ShaderLibrary/Common.hlsl"
#include "ShaderLibrary/Color.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
#include "../../../ShaderLibrary/Color.hlsl"
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/Debug/DebugViewMaterial.cs.hlsl"
#include "HDRenderPipeline/Material/Material.hlsl"
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../Debug/DebugViewMaterial.cs.hlsl"
#include "../../Material/Material.hlsl"
TEXTURE2D_FLOAT(_CameraDepthTexture);
SAMPLER2D(sampler_CameraDepthTexture);
int _DebugViewMaterial;
struct Attributes

float4 Frag(Varyings input) : SV_Target
{
// input.positionCS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(0, 0));
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).x;
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
FETCH_GBUFFER(gbuffer, _GBufferTexture, posInput.unPositionSS);

409
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/Resources/DebugViewTiles.shader


Shader "Hidden/HDRenderPipeline/DebugViewTiles"
{
SubShader
{
Pass
{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#pragma vertex Vert
#pragma fragment Frag
#define LIGHTLOOP_TILE_PASS
#define LIGHTLOOP_TILE_ALL
#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------
#include "ShaderLibrary/Common.hlsl"
// Note: We have fix as guidelines that we have only one deferred material (with control of GBuffer enabled). Mean a users that add a new
// deferred material must replace the old one here. If in the future we want to support multiple layout (cause a lot of consistency problem),
// the deferred shader will require to use multicompile.
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/Lighting/Lighting.hlsl" // This include Material.hlsl
//-------------------------------------------------------------------------------------
// variable declaration
//-------------------------------------------------------------------------------------
TEXTURE2D_FLOAT(_CameraDepthTexture);
SAMPLER2D(sampler_CameraDepthTexture);
uint _ViewTilesFlags;
float2 _MousePixelCoord;
float4 Vert(float3 positionOS : POSITION): SV_POSITION
{
return TransformWorldToHClip(TransformObjectToWorld(positionOS));
}
float4 AlphaBlend(float4 c0, float4 c1) // c1 over c0
{
return float4(lerp(c0.rgb, c1.rgb, c1.a), c0.a + c1.a - c0.a * c1.a);
}
float4 OverlayHeatMap(uint2 pixCoord, uint numLights)
{
const float4 kRadarColors[12] =
{
float4(0.0, 0.0, 0.0, 0.0), // black
float4(0.0, 0.0, 0.6, 0.5), // dark blue
float4(0.0, 0.0, 0.9, 0.5), // blue
float4(0.0, 0.6, 0.9, 0.5), // light blue
float4(0.0, 0.9, 0.9, 0.5), // cyan
float4(0.0, 0.9, 0.6, 0.5), // blueish green
float4(0.0, 0.9, 0.0, 0.5), // green
float4(0.6, 0.9, 0.0, 0.5), // yellowish green
float4(0.9, 0.9, 0.0, 0.5), // yellow
float4(0.9, 0.6, 0.0, 0.5), // orange
float4(0.9, 0.0, 0.0, 0.5), // red
float4(1.0, 0.0, 0.0, 0.9) // strong red
};
float maxNrLightsPerTile = 31; // TODO: setup a constant for that
int colorIndex = numLights == 0 ? 0 : (1 + (int)floor(10 * (log2((float)numLights) / log2(maxNrLightsPerTile))));
colorIndex = colorIndex < 0 ? 0 : colorIndex;
float4 col = colorIndex > 11 ? float4(1.0, 1.0, 1.0, 1.0) : kRadarColors[colorIndex];
int2 coord = pixCoord - int2(1, 1);
float4 color = float4(PositivePow(col.xyz, 2.2), 0.3 * col.w);
if (numLights > 0)
{
if (SampleDebugFontNumber(coord, numLights)) // Shadow
color = float4(0, 0, 0, 1);
if (SampleDebugFontNumber(coord + 1, numLights)) // Text
color = float4(1, 1, 1, 1);
}
return color;
}
float4 Frag(float4 positionCS : SV_POSITION) : SV_Target
{
// positionCS is SV_Position
PositionInputs posInput = GetPositionInput(positionCS.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).x;
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
int2 pixelCoord = posInput.unPositionSS.xy;
int2 tileCoord = (float2)pixelCoord / TILE_SIZE;
int2 mouseTileCoord = _MousePixelCoord / TILE_SIZE;
int2 offsetInTile = pixelCoord - tileCoord * TILE_SIZE;
int n = 0;
for (int category = 0; category < LIGHTCATEGORY_COUNT; category++)
{
uint mask = 1u << category;
if (mask & _ViewTilesFlags)
{
uint start;
uint count;
GetCountAndStart(posInput, category, start, count);
n += count;
}
}
float4 result = float4(0.0, 0.0, 0.0, 0.0);
// Tile overlap counter
if (n > 0)
{
result = OverlayHeatMap(int2(posInput.unPositionSS.xy) & (TILE_SIZE - 1), n);
}
// Highlight selected tile
if (all(mouseTileCoord == tileCoord))
{
bool border = any(offsetInTile == 0 || offsetInTile == TILE_SIZE - 1);
float4 result2 = float4(1.0, 1.0, 1.0, border ? 1.0 : 0.5);
result = AlphaBlend(result, result2);
}
// Print light lists for selected tile at the bottom of the screen
int maxLights = 32;
if (tileCoord.y < LIGHTCATEGORY_COUNT && tileCoord.x < maxLights + 3)
{
PositionInputs mousePosInput = GetPositionInput(_MousePixelCoord, _ScreenSize.zw);
float depthMouse = LOAD_TEXTURE2D(_CameraDepthTexture, mousePosInput.unPositionSS).x;
UpdatePositionInput(depthMouse, _InvViewProjMatrix, _ViewProjMatrix, mousePosInput);
uint category = (LIGHTCATEGORY_COUNT - 1) - tileCoord.y;
uint start;
uint count;
GetCountAndStart(mousePosInput, category, start, count);
float4 result2 = float4(.1,.1,.1,.9);
int2 fontCoord = int2(pixelCoord.x, offsetInTile.y);
int lightListIndex = tileCoord.x - 2;
int n = -1;
if(tileCoord.x == 0)
{
n = (int)count;
}
else if(lightListIndex >= 0 && lightListIndex < (int)count)
{
n = FetchIndex(start, lightListIndex);
}
if (n >= 0)
{
if (SampleDebugFontNumber(offsetInTile, n))
result2 = float4(0.0, 0.0, 0.0, 1.0);
if (SampleDebugFontNumber(offsetInTile + 1, n))
result2 = float4(1.0, 1.0, 1.0, 1.0);
}
result = AlphaBlend(result, result2);
}
return result;
}
ENDHLSL
}
}
Fallback Off
}
Shader "Hidden/HDRenderPipeline/DebugViewTiles"
{
SubShader
{
Pass
{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#pragma vertex Vert
#pragma fragment Frag
#define LIGHTLOOP_TILE_PASS
#define LIGHTLOOP_TILE_ALL
#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#pragma multi_compile SHOW_LIGHT_CATEGORIES SHOW_FEATURE_VARIANTS
//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------
#include "../../../ShaderLibrary/Common.hlsl"
// Note: We have fix as guidelines that we have only one deferred material (with control of GBuffer enabled). Mean a users that add a new
// deferred material must replace the old one here. If in the future we want to support multiple layout (cause a lot of consistency problem),
// the deferred shader will require to use multicompile.
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../Lighting/Lighting.hlsl" // This include Material.hlsl
//-------------------------------------------------------------------------------------
// variable declaration
//-------------------------------------------------------------------------------------
uint _ViewTilesFlags;
uint _NumTiles;
float2 _MousePixelCoord;
StructuredBuffer<uint> g_TileList;
Buffer<uint> g_DispatchIndirectBuffer;
struct VSOut
{
float4 Pos : SV_POSITION;
int Variant : TEXCOORD0;
};
#if SHOW_FEATURE_VARIANTS
VSOut Vert(uint vertexID : SV_VertexID)
{
uint quadIndex = vertexID / 6;
uint quadVertex = vertexID - quadIndex * 6;
quadVertex = (0x312210 >> (quadVertex<<2)) & 3; //remap [0,5]->[0,3]
uint2 tileSize = GetTileSize();
uint variant = 0;
while (quadIndex >= g_DispatchIndirectBuffer[variant * 3 + 0] && variant < NUM_FEATURE_VARIANTS)
{
quadIndex -= g_DispatchIndirectBuffer[variant * 3 + 0];
variant++;
}
uint tileIndex = g_TileList[variant * _NumTiles + quadIndex];
uint2 tileCoord = uint2(tileIndex & 0xFFFF, tileIndex >> 16);
uint2 pixelCoord = (tileCoord + uint2((quadVertex+1) & 1, (quadVertex >> 1) & 1)) * tileSize;
float2 clipCoord = (pixelCoord / _ScreenParams.xy) * 2.0 - 1.0;
clipCoord.y *= -1;
VSOut Out;
Out.Pos = float4(clipCoord, 0, 1.0);
Out.Variant = variant;
return Out;
}
#else
VSOut Vert(float3 positionOS : POSITION)
{
VSOut Out;
Out.Pos = TransformWorldToHClip(TransformObjectToWorld(positionOS));
Out.Variant = 0;
return Out;
}
#endif
float4 AlphaBlend(float4 c0, float4 c1) // c1 over c0
{
return float4(lerp(c0.rgb, c1.rgb, c1.a), c0.a + c1.a - c0.a * c1.a);
}
float4 OverlayHeatMap(uint2 pixCoord, uint n)
{
const float4 kRadarColors[12] =
{
float4(0.0, 0.0, 0.0, 0.0), // black
float4(0.0, 0.0, 0.6, 0.5), // dark blue
float4(0.0, 0.0, 0.9, 0.5), // blue
float4(0.0, 0.6, 0.9, 0.5), // light blue
float4(0.0, 0.9, 0.9, 0.5), // cyan
float4(0.0, 0.9, 0.6, 0.5), // blueish green
float4(0.0, 0.9, 0.0, 0.5), // green
float4(0.6, 0.9, 0.0, 0.5), // yellowish green
float4(0.9, 0.9, 0.0, 0.5), // yellow
float4(0.9, 0.6, 0.0, 0.5), // orange
float4(0.9, 0.0, 0.0, 0.5), // red
float4(1.0, 0.0, 0.0, 0.9) // strong red
};
float maxNrLightsPerTile = 31; // TODO: setup a constant for that
int colorIndex = n == 0 ? 0 : (1 + (int)floor(10 * (log2((float)n) / log2(maxNrLightsPerTile))));
colorIndex = colorIndex < 0 ? 0 : colorIndex;
float4 col = colorIndex > 11 ? float4(1.0, 1.0, 1.0, 1.0) : kRadarColors[colorIndex];
int2 coord = pixCoord - int2(1, 1);
float4 color = float4(PositivePow(col.xyz, 2.2), 0.3 * col.w);
if (n >= 0)
{
if (SampleDebugFontNumber(coord, n)) // Shadow
color = float4(0, 0, 0, 1);
if (SampleDebugFontNumber(coord + 1, n)) // Text
color = float4(1, 1, 1, 1);
}
return color;
}
float4 Frag(float4 positionCS : SV_POSITION, int Variant : TEXCOORD0) : SV_Target
{
// positionCS is SV_Position
PositionInputs posInput = GetPositionInput(positionCS.xy, _ScreenSize.zw, uint2(positionCS.xy) / GetTileSize());
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).x;
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
int2 pixelCoord = posInput.unPositionSS.xy;
int2 tileCoord = (float2)pixelCoord / TILE_SIZE;
int2 mouseTileCoord = _MousePixelCoord / TILE_SIZE;
int2 offsetInTile = pixelCoord - tileCoord * TILE_SIZE;
int n = 0;
#ifdef SHOW_LIGHT_CATEGORIES
for (int category = 0; category < LIGHTCATEGORY_COUNT; category++)
{
uint mask = 1u << category;
if (mask & _ViewTilesFlags)
{
uint start;
uint count;
GetCountAndStart(posInput, category, start, count);
n += count;
}
}
if(n == 0) n = -1;
#else
n = Variant;
#endif
float4 result = float4(0.0, 0.0, 0.0, 0.0);
// Tile overlap counter
if (n >= 0)
{
result = OverlayHeatMap(int2(posInput.unPositionSS.xy) & (TILE_SIZE - 1), n);
}
#ifdef SHOW_LIGHT_CATEGORIES
// Highlight selected tile
if (all(mouseTileCoord == tileCoord))
{
bool border = any(offsetInTile == 0 || offsetInTile == TILE_SIZE - 1);
float4 result2 = float4(1.0, 1.0, 1.0, border ? 1.0 : 0.5);
result = AlphaBlend(result, result2);
}
// Print light lists for selected tile at the bottom of the screen
int maxLights = 32;
if (tileCoord.y < LIGHTCATEGORY_COUNT && tileCoord.x < maxLights + 3)
{
PositionInputs mousePosInput = GetPositionInput(_MousePixelCoord, _ScreenSize.zw, uint2(0,0));
float depthMouse = LOAD_TEXTURE2D(_MainDepthTexture, mousePosInput.unPositionSS).x;
UpdatePositionInput(depthMouse, _InvViewProjMatrix, _ViewProjMatrix, mousePosInput);
uint category = (LIGHTCATEGORY_COUNT - 1) - tileCoord.y;
uint start;
uint count;
GetCountAndStart(mousePosInput, category, start, count);
float4 result2 = float4(.1,.1,.1,.9);
int2 fontCoord = int2(pixelCoord.x, offsetInTile.y);
int lightListIndex = tileCoord.x - 2;
int n = -1;
if(tileCoord.x == 0)
{
n = (int)count;
}
else if(lightListIndex >= 0 && lightListIndex < (int)count)
{
n = FetchIndex(start, lightListIndex);
}
if (n >= 0)
{
if (SampleDebugFontNumber(offsetInTile, n))
result2 = float4(0.0, 0.0, 0.0, 1.0);
if (SampleDebugFontNumber(offsetInTile + 1, n))
result2 = float4(1.0, 1.0, 1.0, 1.0);
}
result = AlphaBlend(result, result2);
}
#endif
return result;
}
ENDHLSL
}
}
Fallback Off
}

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor.meta


fileFormatVersion: 2
guid: ab51b986e84ae98449eab2308fbe74db
guid: 6170264326b703040b82caf4f14a7567
folderAsset: yes
timeCreated: 1479127051
licenseType: Pro

172
Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs


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[SubsurfaceScatteringSettings.maxNumProfiles] { new GUIContent("Profile #0"), 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") };
public readonly GUIContent sssNumProfiles = new GUIContent("Number of profiles");
public readonly GUIContent sssTexturingMode = new GUIContent("Texturing mode", "Specifies when the diffuse texture should be applied.");
public readonly GUIContent[] sssTexturingModeOptions = new GUIContent[3] { new GUIContent("Pre-scatter", "Before the blurring pass. Effectively results in the diffuse texture getting blurred together with the lighting."), new GUIContent("Post-scatter", "After the blurring pass. Effectively preserves the sharpness of the diffuse texture."), new GUIContent("Pre- and post-scatter", "Both before and after the blurring pass.") };
// Tile pass Settings
public readonly GUIContent tileLightLoopSettings = new GUIContent("Tile Light Loop Settings");
public readonly string[] tileLightLoopDebugTileFlagStrings = new string[] { "Punctual Light", "Area Light", "Env Light"};

public readonly GUIContent disableTileAndCluster = new GUIContent("Disable Tile/clustered", "Toggle");
public readonly GUIContent disableDeferredShadingInCompute = new GUIContent("Disable deferred shading in compute", "Toggle");
public readonly GUIContent enableTileAndCluster = new GUIContent("Enable Tile/clustered", "Toggle");
public readonly GUIContent enableComputeLightEvaluation = new GUIContent("Enable Compute Light Evaluation", "Toggle");
// Global debug parameters
// Global debug Settings
public readonly GUIContent debugging = new GUIContent("Debugging");
public readonly GUIContent debugOverlayRatio = new GUIContent("Overlay Ratio");

public int[] debugViewMaterialValues = null;
// Rendering Debug
public readonly GUIContent renderingDebugParameters = new GUIContent("Rendering Debug");
public readonly GUIContent renderingDebugSettings = new GUIContent("Rendering Debug");
public readonly GUIContent enableSSS = new GUIContent("Enable Subsurface Scattering");
public readonly GUIContent lightingDebugParameters = new GUIContent("Lighting Debug");
public readonly GUIContent lightingDebugSettings = new GUIContent("Lighting Debug");
public readonly GUIContent shadowDebugVisualizationMode = new GUIContent("Shadow Debug Mode");
public readonly GUIContent shadowDebugVisualizationMode = new GUIContent("Shadow Maps Debug Mode");
public readonly GUIContent lightingDisplaySkyReflection = new GUIContent("Display Sky Reflection");
public readonly GUIContent lightingDisplaySkyReflectionMipmap = new GUIContent("Reflection Mipmap");
}
private static Styles s_Styles = null;

SerializedProperty m_ShowRenderingDebug = null;
SerializedProperty m_DebugOverlayRatio = null;
// Rendering Debug
// Material Debug
SerializedProperty m_MaterialDebugMode = null;
// Rendering Debug

SerializedProperty m_EnableSSS = null;
// Lighting debug
SerializedProperty m_DebugShadowEnabled = null;

SerializedProperty m_LightingDebugOverrideSmoothness = null;
SerializedProperty m_LightingDebugOverrideSmoothnessValue = null;
SerializedProperty m_LightingDebugAlbedo = null;
SerializedProperty m_LightingDebugDisplaySkyReflection = null;
SerializedProperty m_LightingDebugDisplaySkyReflectionMipmap = null;
// Rendering Parameters
// Rendering Settings
// Subsurface Scattering Settings
SerializedProperty m_TexturingMode = null;
SerializedProperty m_Profiles = null;
SerializedProperty m_NumProfiles = null;
m_DebugOverlayRatio = FindProperty(x => x.globalDebugParameters.debugOverlayRatio);
m_ShowLightingDebug = FindProperty(x => x.globalDebugParameters.displayLightingDebug);
m_ShowRenderingDebug = FindProperty(x => x.globalDebugParameters.displayRenderingDebug);
m_ShowMaterialDebug = FindProperty(x => x.globalDebugParameters.displayMaterialDebug);
m_DebugOverlayRatio = FindProperty(x => x.globalDebugSettings.debugOverlayRatio);
m_ShowLightingDebug = FindProperty(x => x.globalDebugSettings.displayLightingDebug);
m_ShowRenderingDebug = FindProperty(x => x.globalDebugSettings.displayRenderingDebug);
m_ShowMaterialDebug = FindProperty(x => x.globalDebugSettings.displayMaterialDebug);
m_MaterialDebugMode = FindProperty(x => x.globalDebugParameters.materialDebugParameters.debugViewMaterial);
m_MaterialDebugMode = FindProperty(x => x.globalDebugSettings.materialDebugSettings.debugViewMaterial);
m_DisplayOpaqueObjects = FindProperty(x => x.globalDebugParameters.renderingDebugParametrs.displayOpaqueObjects);
m_DisplayTransparentObjects = FindProperty(x => x.globalDebugParameters.renderingDebugParametrs.displayTransparentObjects);
m_EnableDistortion = FindProperty(x => x.globalDebugParameters.renderingDebugParametrs.enableDistortion);
m_DisplayOpaqueObjects = FindProperty(x => x.globalDebugSettings.renderingDebugSettings.displayOpaqueObjects);
m_DisplayTransparentObjects = FindProperty(x => x.globalDebugSettings.renderingDebugSettings.displayTransparentObjects);
m_EnableDistortion = FindProperty(x => x.globalDebugSettings.renderingDebugSettings.enableDistortion);
m_EnableSSS = FindProperty(x => x.globalDebugSettings.renderingDebugSettings.enableSSS);
m_DebugShadowEnabled = FindProperty(x => x.globalDebugParameters.lightingDebugParameters.enableShadows);
m_ShadowDebugMode = FindProperty(x => x.globalDebugParameters.lightingDebugParameters.shadowDebugMode);
m_ShadowDebugShadowMapIndex = FindProperty(x => x.globalDebugParameters.lightingDebugParameters.shadowMapIndex);
m_LightingDebugMode = FindProperty(x => x.globalDebugParameters.lightingDebugParameters.lightingDebugMode);
m_LightingDebugOverrideSmoothness = FindProperty(x => x.globalDebugParameters.lightingDebugParameters.overrideSmoothness);
m_LightingDebugOverrideSmoothnessValue = FindProperty(x => x.globalDebugParameters.lightingDebugParameters.overrideSmoothnessValue);
m_LightingDebugAlbedo = FindProperty(x => x.globalDebugParameters.lightingDebugParameters.debugLightingAlbedo);
m_DebugShadowEnabled = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.enableShadows);
m_ShadowDebugMode = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.shadowDebugMode);
m_ShadowDebugShadowMapIndex = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.shadowMapIndex);
m_LightingDebugMode = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.lightingDebugMode);
m_LightingDebugOverrideSmoothness = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.overrideSmoothness);
m_LightingDebugOverrideSmoothnessValue = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.overrideSmoothnessValue);
m_LightingDebugAlbedo = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.debugLightingAlbedo);
m_LightingDebugDisplaySkyReflection = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.displaySkyReflection);
m_LightingDebugDisplaySkyReflectionMipmap = FindProperty(x => x.globalDebugSettings.lightingDebugSettings.skyReflectionMipmap);
m_RenderingUseForwardOnly = FindProperty(x => x.renderingParameters.useForwardRenderingOnly);
m_RenderingUseDepthPrepass = FindProperty(x => x.renderingParameters.useDepthPrepass);
m_RenderingUseForwardOnly = FindProperty(x => x.renderingSettings.useForwardRenderingOnly);
m_RenderingUseDepthPrepass = FindProperty(x => x.renderingSettings.useDepthPrepass);
// Subsurface Scattering Settings
m_TexturingMode = FindProperty(x => x.sssSettings.texturingMode);
m_Profiles = FindProperty(x => x.sssSettings.profiles);
m_NumProfiles = m_Profiles.FindPropertyRelative("Array.size");
}
SerializedProperty FindProperty<TValue>(Expression<Func<HDRenderPipeline, TValue>> expr)

{
EditorGUILayout.LabelField(styles.debugging);
// Global debug parameters
// Global debug settings
MaterialDebugParametersUI(renderContext);
RenderingDebugParametersUI(renderContext);
LightingDebugParametersUI(renderContext, renderpipelineInstance);
MaterialDebugSettingsUI(renderContext);
RenderingDebugSettingsUI(renderContext);
LightingDebugSettingsUI(renderContext, renderpipelineInstance);
EditorGUILayout.Space();

private void MaterialDebugParametersUI(HDRenderPipeline renderContext)
private void MaterialDebugSettingsUI(HDRenderPipeline renderContext)
{
m_ShowMaterialDebug.boolValue = EditorGUILayout.Foldout(m_ShowMaterialDebug.boolValue, styles.materialDebugLabel);
if (!m_ShowMaterialDebug.boolValue)

EditorGUI.indentLevel--;
}
private void RenderingDebugParametersUI(HDRenderPipeline renderContext)
private void RenderingDebugSettingsUI(HDRenderPipeline renderContext)
m_ShowRenderingDebug.boolValue = EditorGUILayout.Foldout(m_ShowRenderingDebug.boolValue, styles.renderingDebugParameters);
m_ShowRenderingDebug.boolValue = EditorGUILayout.Foldout(m_ShowRenderingDebug.boolValue, styles.renderingDebugSettings);
if (!m_ShowRenderingDebug.boolValue)
return;

EditorGUILayout.PropertyField(m_EnableDistortion, styles.enableDistortion);
EditorGUILayout.PropertyField(m_EnableSSS, styles.enableSSS);
EditorGUI.indentLevel--;
}

EditorGUILayout.LabelField(styles.sssSettings);
EditorGUI.BeginChangeCheck();
EditorGUI.indentLevel++;
pipe.localSssParameters = (SubsurfaceScatteringParameters) EditorGUILayout.ObjectField(new GUIContent("Subsurface Scattering Parameters"), pipe.localSssParameters, typeof(SubsurfaceScatteringParameters), false);
EditorGUI.indentLevel--;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_NumProfiles, styles.sssNumProfiles);
m_TexturingMode.intValue = EditorGUILayout.Popup(styles.sssTexturingMode, m_TexturingMode.intValue, styles.sssTexturingModeOptions, (GUILayoutOption[])null);
if (EditorGUI.EndChangeCheck())
for (int i = 0, n = Math.Min(m_Profiles.arraySize, SubsurfaceScatteringSettings.maxNumProfiles); i < n; i++)
HackSetDirty(pipe); // Repaint
SerializedProperty profile = m_Profiles.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(profile, styles.sssProfiles[i]);
EditorGUI.indentLevel--;
private void LightingDebugParametersUI(HDRenderPipeline renderContext, HDRenderPipelineInstance renderpipelineInstance)
private void LightingDebugSettingsUI(HDRenderPipeline renderContext, HDRenderPipelineInstance renderpipelineInstance)
m_ShowLightingDebug.boolValue = EditorGUILayout.Foldout(m_ShowLightingDebug.boolValue, styles.lightingDebugParameters);
m_ShowLightingDebug.boolValue = EditorGUILayout.Foldout(m_ShowLightingDebug.boolValue, styles.lightingDebugSettings);
if (!m_ShowLightingDebug.boolValue)
return;

EditorGUILayout.PropertyField(m_ShadowDebugMode, styles.shadowDebugVisualizationMode);
if (!m_ShadowDebugMode.hasMultipleDifferentValues)
{
if ((ShadowDebugMode)m_ShadowDebugMode.intValue == ShadowDebugMode.VisualizeShadowMap)
if ((ShadowMapDebugMode)m_ShadowDebugMode.intValue == ShadowMapDebugMode.VisualizeShadowMap)
{
EditorGUILayout.IntSlider(m_ShadowDebugShadowMapIndex, 0, renderpipelineInstance.GetCurrentShadowCount() - 1, styles.shadowDebugVisualizeShadowIndex);
}

{
if ((LightingDebugMode)m_LightingDebugMode.intValue != LightingDebugMode.None)
{
{
{
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(m_LightingDebugOverrideSmoothnessValue, styles.lightingDebugOverrideSmoothnessValue);
EditorGUI.indentLevel--;

}
EditorGUILayout.PropertyField(m_LightingDebugDisplaySkyReflection, styles.lightingDisplaySkyReflection);
if (!m_LightingDebugDisplaySkyReflection.hasMultipleDifferentValues && m_LightingDebugDisplaySkyReflection.boolValue == true)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(m_LightingDebugDisplaySkyReflectionMipmap, styles.lightingDisplaySkyReflectionMipmap);
EditorGUI.indentLevel--;
}
EditorGUI.indentLevel--;
if (EditorGUI.EndChangeCheck())

HackSetDirty(renderContext); // Repaint
}
SkySettingsUI(renderContext);
ShadowParametersUI(renderContext);
TextureParametersUI(renderContext);
RendereringParametersUI(renderContext);
ShadowSettingsUI(renderContext);
TextureSettingsUI(renderContext);
RendereringSettingsUI(renderContext);
private void SkySettingsUI(HDRenderPipeline pipe)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.skyParams);
EditorGUI.BeginChangeCheck();
EditorGUI.indentLevel++;
pipe.skyParameters = (SkyParameters)EditorGUILayout.ObjectField(new GUIContent("Sky Settings"), pipe.skyParameters, typeof(SkyParameters), false);
EditorGUI.indentLevel--;
if (EditorGUI.EndChangeCheck())
{
HackSetDirty(pipe); // Repaint
}
}
private void ShadowParametersUI(HDRenderPipeline renderContext)
private void ShadowSettingsUI(HDRenderPipeline renderContext)
var shadowParameters = renderContext.shadowSettings;
var shadowSettings = renderContext.shadowSettings;
shadowParameters.shadowAtlasWidth = Mathf.Max(0, EditorGUILayout.IntField(styles.shadowsAtlasWidth, shadowParameters.shadowAtlasWidth));
shadowParameters.shadowAtlasHeight = Mathf.Max(0, EditorGUILayout.IntField(styles.shadowsAtlasHeight, shadowParameters.shadowAtlasHeight));
shadowSettings.shadowAtlasWidth = Mathf.Max(0, EditorGUILayout.IntField(styles.shadowsAtlasWidth, shadowSettings.shadowAtlasWidth));
shadowSettings.shadowAtlasHeight = Mathf.Max(0, EditorGUILayout.IntField(styles.shadowsAtlasHeight, shadowSettings.shadowAtlasHeight));
if (EditorGUI.EndChangeCheck())
{

}
private void RendereringParametersUI(HDRenderPipeline renderContext)
private void RendereringSettingsUI(HDRenderPipeline renderContext)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.renderingSettingsLabel);

EditorGUI.indentLevel--;
}
private void TextureParametersUI(HDRenderPipeline renderContext)
private void TextureSettingsUI(HDRenderPipeline renderContext)
var textureParameters = renderContext.textureSettings;
var textureSettings = renderContext.textureSettings;
textureParameters.spotCookieSize = Mathf.NextPowerOfTwo(Mathf.Clamp(EditorGUILayout.IntField(styles.spotCookieSize, textureParameters.spotCookieSize), 16, 1024));
textureParameters.pointCookieSize = Mathf.NextPowerOfTwo(Mathf.Clamp(EditorGUILayout.IntField(styles.pointCookieSize, textureParameters.pointCookieSize), 16, 1024));
textureParameters.reflectionCubemapSize = Mathf.NextPowerOfTwo(Mathf.Clamp(EditorGUILayout.IntField(styles.reflectionCubemapSize, textureParameters.reflectionCubemapSize), 64, 1024));
textureSettings.spotCookieSize = Mathf.NextPowerOfTwo(Mathf.Clamp(EditorGUILayout.IntField(styles.spotCookieSize, textureSettings.spotCookieSize), 16, 1024));
textureSettings.pointCookieSize = Mathf.NextPowerOfTwo(Mathf.Clamp(EditorGUILayout.IntField(styles.pointCookieSize, textureSettings.pointCookieSize), 16, 1024));
textureSettings.reflectionCubemapSize = Mathf.NextPowerOfTwo(Mathf.Clamp(EditorGUILayout.IntField(styles.reflectionCubemapSize, textureSettings.reflectionCubemapSize), 64, 1024));
renderContext.textureSettings = textureParameters;
renderContext.textureSettings = textureSettings;
HackSetDirty(renderContext); // Repaint
}
EditorGUI.indentLevel--;

tilePass.debugViewTilesFlags = EditorGUILayout.MaskField("DebugView Tiles", tilePass.debugViewTilesFlags, styles.tileLightLoopDebugTileFlagStrings);
tilePass.enableSplitLightEvaluation = EditorGUILayout.Toggle(styles.splitLightEvaluation, tilePass.enableSplitLightEvaluation);
tilePass.disableTileAndCluster = EditorGUILayout.Toggle(styles.disableTileAndCluster, tilePass.disableTileAndCluster);
tilePass.disableDeferredShadingInCompute = EditorGUILayout.Toggle(styles.disableDeferredShadingInCompute, tilePass.disableDeferredShadingInCompute);
tilePass.enableTileAndCluster = EditorGUILayout.Toggle(styles.enableTileAndCluster, tilePass.enableTileAndCluster);
tilePass.enableComputeLightEvaluation = EditorGUILayout.Toggle(styles.enableComputeLightEvaluation, tilePass.enableComputeLightEvaluation);
if (EditorGUI.EndChangeCheck())
{

92
Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs


using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEngine.Experimental.Rendering.HDPipeline;
// This script is a helper for the artits to re-synchronise all layered materials
[MenuItem("HDRenderPipeline/Synchronize all Layered materials")]
static void SynchronizeAllLayeredMaterial()
{

if (mat.shader.name == "HDRenderPipeline/LayeredLit" || mat.shader.name == "HDRenderPipeline/LayeredLitTessellation")
{
LayeredLitGUI.SynchronizeAllLayers(mat);
EditorUtility.SetDirty(mat);
}
}
}
static void RemoveMaterialKeywords(Material material)
{
string[] keywordsToRemove = material.shaderKeywords;
foreach (var keyword in keywordsToRemove)
{
material.DisableKeyword(keyword);
}
}
// The goal of this script is to help maintenance of data that have already been produced but need to update to the latest shader code change.
// In case the shader code have change and the inspector have been update with new kind of keywords we need to regenerate the set of keywords use by the material.
// This script will remove all keyword of a material and trigger the inspector that will re-setup all the used keywords.
// It require that the inspector of the material have a static function call that update all keyword based on material properties.
[MenuItem("HDRenderPipeline/Reset all materials keywords")]
static void ResetAllMaterialKeywords()
{
try
{
Object[] materials = Resources.FindObjectsOfTypeAll<Material>();
for (int i = 0, length = materials.Length; i < length; i++)
{
Material mat = materials[i] as Material;
EditorUtility.DisplayProgressBar(
"Setup materials Keywords...",
string.Format("{0} / {1} materials cleaned.", i, length),
i / (float)(length - 1));
if (mat.shader.name == "HDRenderPipeline/LayeredLit" || mat.shader.name == "HDRenderPipeline/LayeredLitTessellation")
{
// We remove all keyword already present
RemoveMaterialKeywords(mat);
LayeredLitGUI.SetupMaterialKeywordsAndPass(mat);
EditorUtility.SetDirty(mat);
}
else if (mat.shader.name == "HDRenderPipeline/Lit" || mat.shader.name == "HDRenderPipeline/LitTessellation")
{
// We remove all keyword already present
RemoveMaterialKeywords(mat);
LitGUI.SetupMaterialKeywordsAndPass(mat);
EditorUtility.SetDirty(mat);
}
else if (mat.shader.name == "HDRenderPipeline/Unlit")
{
// We remove all keyword already present
RemoveMaterialKeywords(mat);
UnlitGUI.SetupMaterialKeywordsAndPass(mat);
EditorUtility.SetDirty(mat);
}
}
}
finally
{
EditorUtility.ClearProgressBar();
}
}
[MenuItem("HDRenderPipeline/Debug/Remove tessellation materials (not reversible)")]
static void RemoveTessellationMaterials()
{
Object[] materials = Resources.FindObjectsOfTypeAll<Material>();
Shader litShader = Shader.Find("HDRenderPipeline/Lit");
Shader layeredLitShader = Shader.Find("HDRenderPipeline/LayeredLit");
foreach (Object obj in materials)
{
Material mat = obj as Material;
if (mat.shader.name == "HDRenderPipeline/LitTessellation")
{
mat.shader = litShader;
// We remove all keyword already present
RemoveMaterialKeywords(mat);
LitGUI.SetupMaterialKeywordsAndPass(mat);
EditorUtility.SetDirty(mat);
}
else if (mat.shader.name == "HDRenderPipeline/LayeredLitTessellation")
{
mat.shader = layeredLitShader;
// We remove all keyword already present
RemoveMaterialKeywords(mat);
LayeredLitGUI.SetupMaterialKeywordsAndPass(mat);
EditorUtility.SetDirty(mat);
}
}
}

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/UpgradeStandardShaderMaterials.cs


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public class UpgradeStandardShaderMaterials
public class UpgradeStandardShaderMaterials
upgraders.Add(new StandardToHDLitMaterialUpgrader());
upgraders.Add(new StandardSpecularToHDLitMaterialUpgrader());
upgraders.Add(new StandardToHDLitMaterialUpgrader("Standard", "HDRenderPipeline/Lit", LitGUI.SetupMaterialKeywordsAndPass));
upgraders.Add(new StandardSpecularToHDLitMaterialUpgrader("Standard (Specular setup)", "HDRenderPipeline/Lit", LitGUI.SetupMaterialKeywordsAndPass));
return upgraders;
}

160
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.asset


m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d440c0deec24a2f478b3e9021cb66c29, type: 3}
m_Script: {fileID: 11500000, guid: f365a473b136bef4797c7281a02cd510, type: 3}
globalDebugParameters:
globalDebugSettings:
displayMaterialDebug: 0
displayRenderingDebug: 0
displayMaterialDebug: 1
displayRenderingDebug: 1
materialDebugParameters:
materialDebugSettings:
lightingDebugParameters:
lightingDebugSettings:
enableShadows: 1
shadowDebugMode: 0
shadowMapIndex: 0

debugLightingAlbedo: {r: 0.5, g: 0.5, b: 0.5, a: 1}
renderingDebugParametrs:
displaySkyReflection: 0
skyReflectionMipmap: 0
renderingDebugSettings:
renderingParameters:
enableSSS: 1
renderingSettings:
sssSettings:
numProfiles: 1
texturingMode: 0
transmissionFlags: 0
profiles:
- {fileID: 11400000, guid: 09521380d86baee43bf09b32473ea5f3, type: 2}
thicknessRemaps:
- 0
- 1
- 0
- 1
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
halfRcpVariancesAndLerpWeights:
- {x: 5.5555553, y: 5.5555553, z: 5.5555553, w: 0.5}
- {x: 1.3888888, y: 1.3888888, z: 1.3888888, w: 0.5}
- {x: 5.5555553, y: 5.5555553, z: 5.5555553, w: 0.5}
- {x: 1.3888888, y: 1.3888888, z: 1.3888888, w: 0.5}
- {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}
- {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}
halfRcpWeightedVariances:
- {x: 2.4691355, y: 2.4691355, z: 2.4691355, w: 2.4691355}
- {x: 2.4691355, y: 2.4691355, z: 2.4691355, w: 2.4691355}
- {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}
filterKernels:
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.7609476}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.49358216}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.33642715}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.21256521}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.10326859}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.000000048879357}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.10326859}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.21256521}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.33642715}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.4935822}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.7609475}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.7609476}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.49358216}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.33642715}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.21256521}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.10326859}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: -0.000000048879357}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.10326859}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.21256521}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.33642715}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.4935822}
- {x: 0.09090909, y: 0.09090909, z: 0.09090909, w: 0.7609475}
- {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}
- {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}
- {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}
- {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}
- {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}
- {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}
- {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}
- {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}
- {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}
- {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}
- {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}
m_ShadowSettings:
enabled: 1
shadowAtlasWidth: 4096

directionalLightCascades: {x: 0.05, y: 0.2, z: 0.3}
directionalLightNearPlaneOffset: 5
localSssParameters: {fileID: 0}
m_TextureSettings:
spotCookieSize: 128
pointCookieSize: 512

m_ShadowCascadeSplit1: 0.2
m_ShadowCascadeSplit2: 0.3
m_ShadowNearPlaneOffset: 5
m_SkyParameters: {fileID: 0}
m_SkySettings: {fileID: 0}

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.asset.meta


fileFormatVersion: 2
guid: e185fecca3c73cd47a09f1092663ef32
timeCreated: 1486896330
timeCreated: 1487689448
licenseType: Pro
NativeFormatImporter:
mainObjectFileID: 11400000

535
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


// NOTE:
// All those properties are public because of how HDRenderPipelineInspector retrieve those properties via serialization/reflection
// Those that are not will be refatored later.
public GlobalDebugParameters globalDebugParameters = new GlobalDebugParameters();
public GlobalDebugSettings globalDebugSettings = new GlobalDebugSettings();
public RenderingParameters renderingParameters = new RenderingParameters();
[SerializeField] ShadowSettings m_ShadowSettings = ShadowSettings.Default;
public SubsurfaceScatteringParameters localSssParameters;
[SerializeField] TextureSettings m_TextureSettings = TextureSettings.Default;
public RenderingSettings renderingSettings = new RenderingSettings();
public SubsurfaceScatteringSettings sssSettings = new SubsurfaceScatteringSettings();
[SerializeField]
ShadowSettings m_ShadowSettings = ShadowSettings.Default;
[SerializeField]
TextureSettings m_TextureSettings = TextureSettings.Default;
public ShadowSettings shadowSettings { get { return m_ShadowSettings; } }
public TextureSettings textureSettings { get { return m_TextureSettings; } set { m_TextureSettings = value; } }

[SerializeField] private SkyParameters m_SkyParameters;
[SerializeField] private SkySettings m_SkySettings;
public CommonSettings.Settings commonSettingsToUse
{

}
}
public SkyParameters skyParameters
public SkySettings skySettings
get { return m_SkyParameters; }
set { m_SkyParameters = value; }
get { return m_SkySettings; }
set { m_SkySettings = value; }
public SkyParameters skyParametersToUse
public SkySettings skySettingsToUse
if (SkyParametersSingleton.overrideSettings)
return SkyParametersSingleton.overrideSettings;
if (SkySettingsSingleton.overrideSettings)
return SkySettingsSingleton.overrideSettings;
return m_SkyParameters;
return m_SkySettings;
public SubsurfaceScatteringParameters sssParameters
{
get
{
if (SubsurfaceScatteringSettings.overrideSettings != null)
{
return SubsurfaceScatteringSettings.overrideSettings;
}
if (localSssParameters == null)
{
localSssParameters = CreateInstance<SubsurfaceScatteringParameters>();
}
return localSssParameters;
}
}
public void ApplyDebugParameters()
public void ApplyDebugSettings()
m_ShadowSettings.enabled = globalDebugParameters.lightingDebugParameters.enableShadows;
m_ShadowSettings.enabled = globalDebugSettings.lightingDebugSettings.enableShadows;
LightingDebugParameters lightDebugParameters = globalDebugParameters.lightingDebugParameters;
Vector4 debugModeAndAlbedo = new Vector4((float)lightDebugParameters.lightingDebugMode, lightDebugParameters.debugLightingAlbedo.r, lightDebugParameters.debugLightingAlbedo.g, lightDebugParameters.debugLightingAlbedo.b);
Vector4 debugSmoothness = new Vector4(lightDebugParameters.overrideSmoothness ? 1.0f : 0.0f, lightDebugParameters.overrideSmoothnessValue, 0.0f, 0.0f);
LightingDebugSettings lightDebugSettings = globalDebugSettings.lightingDebugSettings;
Vector4 debugModeAndAlbedo = new Vector4((float)lightDebugSettings.lightingDebugMode, lightDebugSettings.debugLightingAlbedo.r, lightDebugSettings.debugLightingAlbedo.g, lightDebugSettings.debugLightingAlbedo.b);
Vector4 debugSmoothness = new Vector4(lightDebugSettings.overrideSmoothness ? 1.0f : 0.0f, lightDebugSettings.overrideSmoothnessValue, 0.0f, 0.0f);
Shader.SetGlobalVector("_DebugLightModeAndAlbedo", debugModeAndAlbedo);
Shader.SetGlobalVector("_DebugLightingSmoothness", debugSmoothness);

public void OnValidate()
{
globalDebugParameters.OnValidate();
globalDebugSettings.OnValidate();
sssSettings.OnValidate();
public class RenderingParameters
public class RenderingSettings
{
public bool useForwardRenderingOnly = false; // TODO: Currently there is no way to strip the extra forward shaders generated by the shaders compiler, so we can switch dynamically.
public bool useDepthPrepass = false;

public struct HDCamera
{
public Camera camera;
public Vector4 screenSize;
public Camera camera;
public Vector4 screenSize;
}
public Vector4 invProjectionParam;
}
public class GBufferManager
public class GBufferManager
{
public const int MaxGbuffer = 8;
public void SetBufferDescription(int index, string stringId, RenderTextureFormat inFormat, RenderTextureReadWrite inSRGBWrite)
public const int MaxGbuffer = 8;
IDs[index] = Shader.PropertyToID(stringId);
RTIDs[index] = new RenderTargetIdentifier(IDs[index]);
formats[index] = inFormat;
sRGBWrites[index] = inSRGBWrite;
}
public void SetBufferDescription(int index, string stringId, RenderTextureFormat inFormat, RenderTextureReadWrite inSRGBWrite)
public void InitGBuffers(int width, int height, CommandBuffer cmd)
{
for (int index = 0; index < gbufferCount; index++)
IDs[index] = Shader.PropertyToID(stringId);
RTIDs[index] = new RenderTargetIdentifier(IDs[index]);
formats[index] = inFormat;
sRGBWrites[index] = inSRGBWrite;
/* RTs[index] = */
cmd.GetTemporaryRT(IDs[index], width, height, 0, FilterMode.Point, formats[index], sRGBWrites[index]);
}
public void InitGBuffers(int width, int height, CommandBuffer cmd)
public RenderTargetIdentifier[] GetGBuffers()
{
var colorMRTs = new RenderTargetIdentifier[gbufferCount];
for (int index = 0; index < gbufferCount; index++)
for (int index = 0; index < gbufferCount; index++)
{
/* RTs[index] = */
cmd.GetTemporaryRT(IDs[index], width, height, 0, FilterMode.Point, formats[index], sRGBWrites[index]);
}
colorMRTs[index] = RTIDs[index];
public RenderTargetIdentifier[] GetGBuffers()
{
var colorMRTs = new RenderTargetIdentifier[gbufferCount];
for (int index = 0; index < gbufferCount; index++)
{
colorMRTs[index] = RTIDs[index];
}
return colorMRTs;
}
return colorMRTs;
}
/*
public void BindBuffers(Material mat)
/*
public void BindBuffers(Material mat)
{
for (int index = 0; index < gbufferCount; index++)
for (int index = 0; index < gbufferCount; index++)
{
mat.SetTexture(IDs[index], RTs[index]);
}
mat.SetTexture(IDs[index], RTs[index]);
*/
public int gbufferCount { get; set; }
int[] IDs = new int[MaxGbuffer];
RenderTargetIdentifier[] RTIDs = new RenderTargetIdentifier[MaxGbuffer];
RenderTextureFormat[] formats = new RenderTextureFormat[MaxGbuffer];
RenderTextureReadWrite[] sRGBWrites = new RenderTextureReadWrite[MaxGbuffer];
*/
public int gbufferCount { get; set; }
int[] IDs = new int[MaxGbuffer];
RenderTargetIdentifier[] RTIDs = new RenderTargetIdentifier[MaxGbuffer];
RenderTextureFormat[] formats = new RenderTextureFormat[MaxGbuffer];
RenderTextureReadWrite[] sRGBWrites = new RenderTextureReadWrite[MaxGbuffer];
}
{
{
private readonly HDRenderPipeline m_Owner;
// TODO: Find a way to automatically create/iterate through deferred material

readonly GBufferManager m_gbufferManager = new GBufferManager();
// Various set of material use in render loop
readonly Material m_DebugViewMaterialGBuffer;
readonly Material m_DebugDisplayShadowMap;
private Material m_DebugDisplayShadowMap;
private Material m_DebugViewMaterialGBuffer;
private Material m_DebugDisplayLatlong;
readonly int m_CameraDepthStencilBuffer;
readonly int m_CameraDepthStencilBufferCopy; // This is temporary, we will need to provide the correct opaque depth buffer to transparent without needing a copy
readonly int m_CameraStencilBuffer;
readonly int m_VelocityBuffer;
readonly int m_DistortionBuffer;

readonly RenderTargetIdentifier m_CameraSubsurfaceBufferRT;
readonly RenderTargetIdentifier m_CameraFilteringBufferRT;
readonly RenderTargetIdentifier m_CameraDepthStencilBufferRT;
readonly RenderTargetIdentifier m_CameraDepthStencilBufferCopyRT;
// 'm_CameraStencilBufferRT' is a temporary copy of the stencil buffer and should be removed
// once we are able to read from the depth buffer and perform the stencil test simultaneously.
readonly RenderTargetIdentifier m_CameraStencilBufferRT;
private RenderTexture m_CameraDepthStencilBuffer = null;
private RenderTexture m_CameraDepthStencilBufferCopy = null;
private RenderTargetIdentifier m_CameraDepthStencilBufferRT;
private RenderTargetIdentifier m_CameraDepthStencilBufferCopyRT;
// Detect when windows size is changing
int m_CurrentWidth;
int m_CurrentHeight;

readonly SkyManager m_SkyManager = new SkyManager();
private readonly BaseLightLoop m_LightLoop;
private GlobalDebugParameters globalDebugParameters
private GlobalDebugSettings globalDebugSettings
get { return m_Owner.globalDebugParameters; }
get { return m_Owner.globalDebugSettings; }
public SubsurfaceScatteringSettings sssSettings
{
get { return m_Owner.sssSettings; }
}
public HDRenderPipelineInstance(HDRenderPipeline owner)
{
m_Owner = owner;

m_CameraFilteringBuffer = Shader.PropertyToID("_CameraFilteringBuffer");
m_CameraDepthStencilBuffer = Shader.PropertyToID("_CameraDepthTexture");
m_CameraDepthStencilBufferCopy = Shader.PropertyToID("_CameraDepthTextureCopy");
m_CameraStencilBuffer = Shader.PropertyToID("_CameraStencilTexture");
m_CameraDepthStencilBufferRT = new RenderTargetIdentifier(m_CameraDepthStencilBuffer);
m_CameraDepthStencilBufferCopyRT = new RenderTargetIdentifier(m_CameraDepthStencilBufferCopy);
m_CameraStencilBufferRT = new RenderTargetIdentifier(m_CameraStencilBuffer);
m_DebugViewMaterialGBuffer = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/DebugViewMaterialGBuffer");
m_FilterSubsurfaceScattering.DisableKeyword("FILTER_HORIZONTAL");
m_FilterSubsurfaceScattering.DisableKeyword("FILTER_HORIZONTAL_AND_COMBINE");
m_FilterSubsurfaceScattering.EnableKeyword("FILTER_HORIZONTAL");
m_FilterAndCombineSubsurfaceScattering.EnableKeyword("FILTER_HORIZONTAL_AND_COMBINE");
m_DebugDisplayShadowMap = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/DebugDisplayShadowMap");
InitializeDebugMaterials();
m_ShadowPass = new ShadowRenderPass(owner.shadowSettings);

if(m_LightLoop != null)
m_LightLoop.Build(owner.textureSettings);
m_SkyManager.skyParameters = owner.skyParametersToUse;
m_SkyManager.Build();
m_SkyManager.skySettings = owner.skySettingsToUse;
}
void InitializeDebugMaterials()
{
m_DebugDisplayShadowMap = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/DebugDisplayShadowMap");
m_DebugViewMaterialGBuffer = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/DebugViewMaterialGBuffer");
m_DebugDisplayLatlong = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/DebugDisplayLatlong");
}
public override void Dispose()

};
#endif
void CreateDepthBuffer(Camera camera)
{
if (m_CameraDepthStencilBuffer != null)
{
m_CameraDepthStencilBuffer.Release();
}
m_CameraDepthStencilBuffer = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 24, RenderTextureFormat.Depth);
m_CameraDepthStencilBuffer.filterMode = FilterMode.Point;
m_CameraDepthStencilBuffer.Create();
m_CameraDepthStencilBufferRT = new RenderTargetIdentifier(m_CameraDepthStencilBuffer);
if (NeedDepthBufferCopy())
{
if (m_CameraDepthStencilBufferCopy != null)
{
m_CameraDepthStencilBufferCopy.Release();
}
m_CameraDepthStencilBufferCopy = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 24, RenderTextureFormat.Depth);
m_CameraDepthStencilBufferCopy.filterMode = FilterMode.Point;
m_CameraDepthStencilBufferCopy.Create();
m_CameraDepthStencilBufferCopyRT = new RenderTargetIdentifier(m_CameraDepthStencilBufferCopy);
}
}
void Resize(Camera camera)
{
// TODO: Detect if renderdoc just load and force a resize in this case, as often renderdoc require to realloc resource.

// For now consider we have only one camera that go to this code, the main one.
m_SkyManager.skyParameters = m_Owner.skyParametersToUse;
m_SkyManager.skySettings = m_Owner.skySettingsToUse;
if (camera.pixelWidth != m_CurrentWidth || camera.pixelHeight != m_CurrentHeight || m_LightLoop.NeedResize())
bool resolutionChanged = camera.pixelWidth != m_CurrentWidth || camera.pixelHeight != m_CurrentHeight;
if (resolutionChanged || m_CameraDepthStencilBuffer == null)
{
CreateDepthBuffer(camera);
}
if (resolutionChanged || m_LightLoop.NeedResize())
{
if (m_CurrentWidth > 0 && m_CurrentHeight > 0)
{

m_LightLoop.AllocResolutionDependentBuffers(camera.pixelWidth, camera.pixelHeight);
}
// update recorded window resolution
m_CurrentWidth = camera.pixelWidth;
m_CurrentHeight = camera.pixelHeight;
}
// update recorded window resolution
m_CurrentWidth = camera.pixelWidth;
m_CurrentHeight = camera.pixelHeight;
public void PushGlobalParams(HDCamera hdCamera, ScriptableRenderContext renderContext)
public void PushGlobalParams(HDCamera hdCamera, ScriptableRenderContext renderContext, SubsurfaceScatteringSettings sssParameters)
var cmd = new CommandBuffer {name = "Push Global Parameters"};
cmd.SetGlobalVector("_ScreenSize", hdCamera.screenSize);
cmd.SetGlobalMatrix("_ViewProjMatrix", hdCamera.viewProjectionMatrix);
cmd.SetGlobalMatrix("_InvViewProjMatrix", hdCamera.invViewProjectionMatrix);
cmd.SetGlobalMatrix("_InvProjMatrix", hdCamera.invProjectionMatrix);
cmd.SetGlobalVector("_InvProjParam", hdCamera.invProjectionParam);
// TODO: cmd.SetGlobalInt() does not exist, so we are forced to use Shader.SetGlobalInt() instead.
if (m_SkyManager.IsSkyValid())
{
m_SkyManager.SetGlobalSkyTexture();

Shader.SetGlobalInt("_EnvLightSkyEnabled", 0);
}
var cmd = new CommandBuffer {name = "Push Global Parameters"};
// Broadcast SSS parameters to all shaders.
Shader.SetGlobalInt("_TransmissionFlags", sssParameters.transmissionFlags);
cmd.SetGlobalFloatArray("_ThicknessRemaps", sssParameters.thicknessRemaps);
cmd.SetGlobalVectorArray("_HalfRcpVariancesAndLerpWeights", sssParameters.halfRcpVariancesAndLerpWeights);
switch (sssParameters.texturingMode)
{
case SubsurfaceScatteringSettings.TexturingMode.PreScatter:
cmd.EnableShaderKeyword("SSS_PRE_SCATTER_TEXTURING");
cmd.DisableShaderKeyword("SSS_POST_SCATTER_TEXTURING");
break;
case SubsurfaceScatteringSettings.TexturingMode.PostScatter:
cmd.DisableShaderKeyword("SSS_PRE_SCATTER_TEXTURING");
cmd.EnableShaderKeyword("SSS_POST_SCATTER_TEXTURING");
break;
case SubsurfaceScatteringSettings.TexturingMode.PreAndPostScatter:
cmd.DisableShaderKeyword("SSS_PRE_SCATTER_TEXTURING");
cmd.DisableShaderKeyword("SSS_POST_SCATTER_TEXTURING");
break;
}
cmd.SetGlobalVector("_ScreenSize", hdCamera.screenSize);
cmd.SetGlobalMatrix("_ViewProjMatrix", hdCamera.viewProjectionMatrix);
cmd.SetGlobalMatrix("_InvViewProjMatrix", hdCamera.invViewProjectionMatrix);
if (globalDebugSettings.renderingDebugSettings.enableSSS)
{
cmd.EnableShaderKeyword("_SUBSURFACE_SCATTERING");
}
else
{
cmd.DisableShaderKeyword("_SUBSURFACE_SCATTERING");
}
}
if (m_LightLoop != null)
m_LightLoop.PushGlobalParams(hdCamera.camera, renderContext);
bool NeedDepthBufferCopy()
{
// For now we consider only PS4 to be able to read from a bound depth buffer. Need to test/implement for other platforms.
return SystemInfo.graphicsDeviceType != GraphicsDeviceType.PlayStation4;
}
Texture GetDepthTexture()
{
if (NeedDepthBufferCopy())
return m_CameraDepthStencilBufferCopy;
else
return m_CameraDepthStencilBuffer;
}
private void CopyDepthBufferIfNeeded(ScriptableRenderContext renderContext)
{
var cmd = new CommandBuffer();
if (NeedDepthBufferCopy())
{
using (new Utilities.ProfilingSample("Copy depth-stencil buffer", renderContext))
{
cmd.CopyTexture(m_CameraDepthStencilBufferRT, m_CameraDepthStencilBufferCopyRT);
}
}
cmd.SetGlobalTexture("_MainDepthTexture", GetDepthTexture());
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
public override void Render(ScriptableRenderContext renderContext, Camera[] cameras)

GraphicsSettings.lightsUseLinearIntensity = true;
GraphicsSettings.lightsUseColorTemperature = true;
m_SkyManager.Build();
if (!m_LitRenderLoop.isInit)
m_LitRenderLoop.RenderInit(renderContext);

m_LightLoop.NewFrame();
m_Owner.ApplyDebugParameters();
m_Owner.ApplyDebugSettings();
m_Owner.UpdateCommonSettings();
// Set Frame constant buffer

RenderForwardOnlyOpaqueDepthPrepass(cullResults, camera, renderContext);
RenderGBuffer(cullResults, camera, renderContext);
// 'm_CameraStencilBufferRT' is a temporary copy of the stencil buffer and should be removed
// once we are able to read from the depth buffer and perform the stencil test simultaneously.
using (new Utilities.ProfilingSample("Copy depth-stencil buffer", renderContext))
// If full forward rendering, we did not do any rendering yet, so don't need to copy the buffer.
// If Deferred then the depth buffer is full (regular GBuffer + ForwardOnly depth prepass are done so we can copy it safely.
if(!m_Owner.renderingSettings.useForwardRenderingOnly)
var cmd = new CommandBuffer();
cmd.CopyTexture(m_CameraDepthStencilBufferRT, m_CameraStencilBufferRT);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
CopyDepthBufferIfNeeded(renderContext);
if (globalDebugParameters.materialDebugParameters.debugViewMaterial != 0)
if (globalDebugSettings.materialDebugSettings.debugViewMaterial != 0)
using (new Utilities.ProfilingSample("Shadow Pass", renderContext))
{
m_ShadowPass.Render(renderContext, cullResults, out m_ShadowsResult);
}
using (new Utilities.ProfilingSample("Shadow Pass", renderContext))
{
m_ShadowPass.Render(renderContext, cullResults, out m_ShadowsResult);
}
renderContext.SetupCameraProperties(camera); // Need to recall SetupCameraProperties after m_ShadowPass.Render
renderContext.SetupCameraProperties(camera); // Need to recall SetupCameraProperties after m_ShadowPass.Render
if (m_LightLoop != null)
{
using (new Utilities.ProfilingSample("Build Light list", renderContext))
if (m_LightLoop != null)
m_LightLoop.PrepareLightsForGPU(m_Owner.shadowSettings, cullResults, camera, ref m_ShadowsResult);
m_LightLoop.BuildGPULightLists(camera, renderContext, m_CameraDepthStencilBufferRT); // TODO: Use async compute here to run light culling during shadow
using (new Utilities.ProfilingSample("Build Light list", renderContext))
{
m_LightLoop.PrepareLightsForGPU(m_Owner.shadowSettings, cullResults, camera, ref m_ShadowsResult);
m_LightLoop.RenderShadows(renderContext, cullResults);
renderContext.SetupCameraProperties(camera); // Need to recall SetupCameraProperties after m_ShadowPass.Render
m_LightLoop.BuildGPULightLists(camera, renderContext, m_CameraDepthStencilBufferRT); // TODO: Use async compute here to run light culling during shadow
}
}
PushGlobalParams(hdCamera, renderContext);
PushGlobalParams(hdCamera, renderContext, m_Owner.sssSettings);
// Caution: We require sun light here as some sky use the sun light to render, mean UpdateSkyEnvironment
// must be call after BuildGPULightLists.
// TODO: Try to arrange code so we can trigger this call earlier and use async compute here to run sky convolution during other passes (once we move convolution shader to compute).
UpdateSkyEnvironment(hdCamera, renderContext);
// Caution: We require sun light here as some sky use the sun light to render, mean UpdateSkyEnvironment
// must be call after BuildGPULightLists.
// TODO: Try to arrange code so we can trigger this call earlier and use async compute here to run sky convolution during other passes (once we move convolution shader to compute).
UpdateSkyEnvironment(hdCamera, renderContext);
RenderDeferredLighting(hdCamera, renderContext);
RenderDeferredLighting(hdCamera, renderContext, m_Owner.globalDebugSettings.renderingDebugSettings.enableSSS);
// 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.
CombineSubsurfaceScattering(hdCamera, renderContext, m_Owner.sssParameters);
// 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.
CombineSubsurfaceScattering(hdCamera, renderContext, m_Owner.sssSettings);
// For opaque forward we have split rendering in two categories
// Material that are always forward and material that can be deferred or forward depends on render pipeline options (like switch to rendering forward only mode)
// Material that are always forward are unlit and complex (Like Hair) and don't require sorting, so it is ok to split them.
RenderForward(cullResults, camera, renderContext, true); // Render deferred or forward opaque
RenderForwardOnlyOpaque(cullResults, camera, renderContext);
// For opaque forward we have split rendering in two categories
// Material that are always forward and material that can be deferred or forward depends on render pipeline options (like switch to rendering forward only mode)
// Material that are always forward are unlit and complex (Like Hair) and don't require sorting, so it is ok to split them.
RenderForward(cullResults, camera, renderContext, true); // Render deferred or forward opaque
RenderForwardOnlyOpaque(cullResults, camera, renderContext);
// 'm_CameraDepthStencilBufferCopyRT' is a temporary copy of the depth textureand should be removed
// once we are able to read from the depth buffer during transparent pass.
using (new Utilities.ProfilingSample("Copy depth-stencil buffer after all opaque", renderContext))
{
var cmd = new CommandBuffer();
cmd.CopyTexture(m_CameraDepthStencilBufferRT, m_CameraDepthStencilBufferCopyRT);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
// If full forward rendering, we did just rendered everything, so we can copy the depth buffer
// If Deferred nothing needs copying anymore.
if(m_Owner.renderingSettings.useForwardRenderingOnly)
{
CopyDepthBufferIfNeeded(renderContext);
}
RenderSky(hdCamera, renderContext);
RenderSky(hdCamera, renderContext);
// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForward(cullResults, camera, renderContext, false);
// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForward(cullResults, camera, renderContext, false);
RenderVelocity(cullResults, camera, renderContext); // Note we may have to render velocity earlier if we do temporalAO, temporal volumetric etc... Mean we will not take into account forward opaque in case of deferred rendering ?
// Planar and real time cubemap doesn't need post process and render in FP16
if (camera.cameraType == CameraType.Reflection)
{
// Simple blit
var cmd = new CommandBuffer { name = "Blit to final RT" };
cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
else
{
RenderVelocity(cullResults, camera, renderContext); // Note we may have to render velocity earlier if we do temporalAO, temporal volumetric etc... Mean we will not take into account forward opaque in case of deferred rendering ?
// TODO: Check with VFX team.
// Rendering distortion here have off course lot of artifact.
// But resolving at each objects that write in distortion is not possible (need to sort transparent, render those that do not distort, then resolve, then etc...)
// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness. This
RenderDistortion(cullResults, camera, renderContext);
// TODO: Check with VFX team.
// Rendering distortion here have off course lot of artifact.
// But resolving at each objects that write in distortion is not possible (need to sort transparent, render those that do not distort, then resolve, then etc...)
// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness. This
RenderDistortion(cullResults, camera, renderContext);
FinalPass(camera, renderContext);
FinalPass(camera, renderContext);
}
}
RenderDebugOverlay(camera, renderContext);

void RenderOpaqueRenderList(CullResults cull, Camera camera, ScriptableRenderContext renderContext, string passName, RendererConfiguration rendererConfiguration = 0)
{
if (!globalDebugParameters.renderingDebugParametrs.displayOpaqueObjects)
if (!globalDebugSettings.renderingDebugSettings.displayOpaqueObjects)
return;
var settings = new DrawRendererSettings(cull, camera, new ShaderPassName(passName))

void RenderTransparentRenderList(CullResults cull, Camera camera, ScriptableRenderContext renderContext, string passName, RendererConfiguration rendererConfiguration = 0)
{
if (!globalDebugParameters.renderingDebugParametrs.displayTransparentObjects)
if (!globalDebugSettings.renderingDebugSettings.displayTransparentObjects)
return;
var settings = new DrawRendererSettings(cull, camera, new ShaderPassName(passName))

{
// If we are forward only we will do a depth prepass
// TODO: Depth prepass should be enabled based on light loop settings. LightLoop define if they need a depth prepass + forward only...
if (!m_Owner.renderingParameters.useDepthPrepass)
if (!m_Owner.renderingSettings.useDepthPrepass)
return;
using (new Utilities.ProfilingSample("Depth Prepass", renderContext))

void RenderGBuffer(CullResults cull, Camera camera, ScriptableRenderContext renderContext)
{
if (m_Owner.renderingParameters.ShouldUseForwardRenderingOnly())
if (m_Owner.renderingSettings.ShouldUseForwardRenderingOnly())
{
return ;
}

bool debugLighting = globalDebugParameters.lightingDebugParameters.lightingDebugMode != LightingDebugMode.None;
bool debugLighting = globalDebugSettings.lightingDebugSettings.lightingDebugMode != LightingDebugMode.None;
// setup GBuffer for rendering
Utilities.SetRenderTarget(renderContext, m_gbufferManager.GetGBuffers(), m_CameraDepthStencilBufferRT);

{
// If we are forward only we don't need to render ForwardOnlyOpaqueDepthOnly object
// But in case we request a prepass we render it
if (m_Owner.renderingParameters.ShouldUseForwardRenderingOnly() && !m_Owner.renderingParameters.useDepthPrepass)
if (m_Owner.renderingSettings.ShouldUseForwardRenderingOnly() && !m_Owner.renderingSettings.useDepthPrepass)
return;
using (new Utilities.ProfilingSample("Forward opaque depth", renderContext))

{
Utilities.SetRenderTarget(renderContext, m_CameraColorBufferRT, m_CameraDepthStencilBufferRT, Utilities.kClearAll, Color.black);
Shader.SetGlobalInt("_DebugViewMaterial", (int)globalDebugParameters.materialDebugParameters.debugViewMaterial);
Shader.SetGlobalInt("_DebugViewMaterial", (int)globalDebugSettings.materialDebugSettings.debugViewMaterial);
if (!m_Owner.renderingParameters.ShouldUseForwardRenderingOnly())
if (!m_Owner.renderingSettings.ShouldUseForwardRenderingOnly())
m_DebugViewMaterialGBuffer.SetFloat("_DebugViewMaterial", (float)globalDebugParameters.materialDebugParameters.debugViewMaterial);
m_DebugViewMaterialGBuffer.SetFloat("_DebugViewMaterial", (float)globalDebugSettings.materialDebugSettings.debugViewMaterial);
// m_gbufferManager.BindBuffers(m_DebugViewMaterialGBuffer);
// TODO: Bind depth textures

}
}
void RenderDeferredLighting(HDCamera hdCamera, ScriptableRenderContext renderContext)
void RenderDeferredLighting(HDCamera hdCamera, ScriptableRenderContext renderContext, bool enableSSS)
if (m_Owner.renderingParameters.ShouldUseForwardRenderingOnly() || m_LightLoop == null)
if (m_Owner.renderingSettings.ShouldUseForwardRenderingOnly() || m_LightLoop == null)
{
return ;
}

// Output split lighting for materials tagged with the SSS stencil bit.
m_LightLoop.RenderDeferredLighting(hdCamera, renderContext, globalDebugParameters.lightingDebugParameters, colorRTs, m_CameraStencilBufferRT, true);
if (enableSSS)
{
// Output split lighting for materials tagged with the SSS stencil bit.
m_LightLoop.RenderDeferredLighting(hdCamera, renderContext, globalDebugSettings.lightingDebugSettings, colorRTs, m_CameraDepthStencilBufferRT, new RenderTargetIdentifier(GetDepthTexture()), true, enableSSS);
}
m_LightLoop.RenderDeferredLighting(hdCamera, renderContext, globalDebugParameters.lightingDebugParameters, colorRTs, m_CameraStencilBufferRT, false);
m_LightLoop.RenderDeferredLighting(hdCamera, renderContext, globalDebugSettings.lightingDebugSettings, colorRTs, m_CameraDepthStencilBufferRT, new RenderTargetIdentifier(GetDepthTexture()), false, enableSSS);
void CombineSubsurfaceScattering(HDCamera hdCamera, ScriptableRenderContext context, SubsurfaceScatteringParameters sssParameters)
void CombineSubsurfaceScattering(HDCamera hdCamera, ScriptableRenderContext context, SubsurfaceScatteringSettings sssParameters)
if (m_Owner.renderingParameters.ShouldUseForwardRenderingOnly()) return;
if (m_Owner.renderingSettings.ShouldUseForwardRenderingOnly()) return;
// Load the kernel data.
Vector4[] kernelData = new Vector4[SubsurfaceScatteringParameters.maxNumProfiles * SubsurfaceScatteringProfile.numVectors];
for (int j = 0, m = sssParameters.profiles.Length; j < m; j++)
{
for (int i = 0, n = SubsurfaceScatteringProfile.numVectors; i < n; i++)
{
kernelData[n * j + i] = sssParameters.profiles[j].filterKernel[i];
}
}
if (!globalDebugSettings.renderingDebugSettings.enableSSS) return;
m_FilterSubsurfaceScattering.SetMatrix("_InvProjMatrix", hdCamera.invProjectionMatrix);
m_FilterSubsurfaceScattering.SetVectorArray("_FilterKernels", kernelData);
m_FilterSubsurfaceScattering.SetVectorArray("_FilterKernels", sssParameters.filterKernels);
m_FilterSubsurfaceScattering.SetVectorArray("_HalfRcpWeightedVariances", sssParameters.halfRcpWeightedVariances);
m_CameraFilteringBufferRT, m_CameraStencilBufferRT);
m_CameraFilteringBufferRT, m_CameraDepthStencilBufferRT);
m_FilterAndCombineSubsurfaceScattering.SetMatrix("_InvProjMatrix", hdCamera.invProjectionMatrix);
m_FilterAndCombineSubsurfaceScattering.SetVectorArray("_FilterKernels", kernelData);
m_FilterAndCombineSubsurfaceScattering.SetVectorArray("_FilterKernels", sssParameters.filterKernels);
m_FilterAndCombineSubsurfaceScattering.SetVectorArray("_HalfRcpWeightedVariances", sssParameters.halfRcpWeightedVariances);
m_CameraColorBufferRT, m_CameraStencilBufferRT);
m_CameraColorBufferRT, m_CameraDepthStencilBufferRT);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();

{
// TODO: Currently we can't render opaque object forward when deferred is enabled
// miss option
if (!m_Owner.renderingParameters.ShouldUseForwardRenderingOnly() && renderOpaque)
if (!m_Owner.renderingSettings.ShouldUseForwardRenderingOnly() && renderOpaque)
return;
using (new Utilities.ProfilingSample("Forward Pass", renderContext))

if (m_LightLoop != null)
m_LightLoop.RenderForward(camera, renderContext, renderOpaque);
bool debugLighting = globalDebugParameters.lightingDebugParameters.lightingDebugMode != LightingDebugMode.None;
bool debugLighting = globalDebugSettings.lightingDebugSettings.lightingDebugMode != LightingDebugMode.None;
string forwardPassName = debugLighting ? "ForwardDebugLighting" : "Forward";
if (renderOpaque)

if (m_LightLoop != null)
m_LightLoop.RenderForward(camera, renderContext, true);
bool debugLighting = globalDebugParameters.lightingDebugParameters.lightingDebugMode != LightingDebugMode.None;
bool debugLighting = globalDebugSettings.lightingDebugSettings.lightingDebugMode != LightingDebugMode.None;
RenderOpaqueRenderList(cullResults, camera, renderContext, debugLighting ? "ForwardOnlyOpaqueDebugLighting" : "ForwardOnlyOpaque", Utilities.kRendererConfigurationBakedLighting);
}
}

using (new Utilities.ProfilingSample("Velocity Pass", renderContext))
{
// If opaque velocity have been render during GBuffer no need to render it here
if ((ShaderConfig.s_VelocityInGbuffer == 1) || m_Owner.renderingParameters.ShouldUseForwardRenderingOnly())
if ((ShaderConfig.s_VelocityInGbuffer == 1) || m_Owner.renderingSettings.ShouldUseForwardRenderingOnly())
return ;
int w = camera.pixelWidth;

void RenderDistortion(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext)
{
if (!globalDebugParameters.renderingDebugParametrs.enableDistortion)
if (!globalDebugSettings.renderingDebugSettings.enableDistortion)
return ;
using (new Utilities.ProfilingSample("Distortion Pass", renderContext))

// All of this is temporary, sub-optimal and quickly hacked together but is necessary
// for artists to do lighting work until the fully-featured framework is ready
var localPostProcess = camera.GetComponent<PostProcessing>();
var localPostProcess = camera.GetComponent<PostProcessingSRP>();
bool localActive = localPostProcess != null && localPostProcess.enabled;

void RenderDebugOverlay(Camera camera, ScriptableRenderContext renderContext)
{
// We don't want any overlay for these kind of rendering
if (camera.cameraType == CameraType.Reflection || camera.cameraType == CameraType.Preview)
return;
float overlayRatio = globalDebugParameters.debugOverlayRatio;
float overlayRatio = globalDebugSettings.debugOverlayRatio;
LightingDebugParameters shadowDebug = globalDebugParameters.lightingDebugParameters;
LightingDebugSettings lightingDebug = globalDebugSettings.lightingDebugSettings;
if (shadowDebug.shadowDebugMode != ShadowDebugMode.None)
if (lightingDebug.shadowDebugMode != ShadowMapDebugMode.None)
if (shadowDebug.shadowDebugMode == ShadowDebugMode.VisualizeShadowMap)
if (lightingDebug.shadowDebugMode == ShadowMapDebugMode.VisualizeShadowMap)
uint visualizeShadowIndex = Math.Min(shadowDebug.shadowMapIndex, (uint)(GetCurrentShadowCount() - 1));
uint visualizeShadowIndex = Math.Min(lightingDebug.shadowMapIndex, (uint)(GetCurrentShadowCount() - 1));
ShadowLight shadowLight = m_ShadowsResult.shadowLights[visualizeShadowIndex];
for (int slice = 0; slice < shadowLight.shadowSliceCount; ++slice)
{

NextOverlayCoord(ref x, ref y, overlaySize, camera.pixelWidth);
}
}
else if (shadowDebug.shadowDebugMode == ShadowDebugMode.VisualizeAtlas)
else if (lightingDebug.shadowDebugMode == ShadowMapDebugMode.VisualizeAtlas)
{
propertyBlock.SetVector("_TextureScaleBias", new Vector4(1.0f, 1.0f, 0.0f, 0.0f));

}
}
if(lightingDebug.displaySkyReflection)
{
Texture skyReflection = m_SkyManager.skyReflection;
propertyBlock.SetTexture("_InputCubemap", skyReflection);
propertyBlock.SetFloat("_Mipmap", lightingDebug.skyReflectionMipmap);
debugCB.SetViewport(new Rect(x, y, overlaySize, overlaySize));
debugCB.DrawProcedural(Matrix4x4.identity, m_DebugDisplayLatlong, 0, MeshTopology.Triangles, 3, 1, propertyBlock);
NextOverlayCoord(ref x, ref y, overlaySize, camera.pixelWidth);
}
renderContext.ExecuteCommandBuffer(debugCB);
}

cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraSubsurfaceBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraFilteringBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraDepthStencilBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
cmd.GetTemporaryRT(m_CameraDepthStencilBufferCopy, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
cmd.GetTemporaryRT(m_CameraStencilBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
if (!m_Owner.renderingParameters.ShouldUseForwardRenderingOnly())
if (!m_Owner.renderingSettings.ShouldUseForwardRenderingOnly())
{
m_gbufferManager.InitGBuffers(w, h, cmd);
}

}
// Clear GBuffers
if (!m_Owner.renderingParameters.ShouldUseForwardRenderingOnly())
if (!m_Owner.renderingSettings.ShouldUseForwardRenderingOnly())
{
using (new Utilities.ProfilingSample("Clear GBuffer", renderContext))
{

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs.meta


fileFormatVersion: 2
guid: d440c0deec24a2f478b3e9021cb66c29
guid: f365a473b136bef4797c7281a02cd510
timeCreated: 1483605696
licenseType: Pro
MonoImporter:

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting.meta


fileFormatVersion: 2
guid: 1c14e71d397fce047b1675fc26d0bb48
guid: 3002976b0b09954499dd1f6e00169b06
folderAsset: yes
timeCreated: 1474297943
licenseType: Pro

9
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop.cs


public virtual void NewFrame() {}
public virtual void PrepareLightsForGPU(ShadowSettings shadowSettings, CullResults cullResults, Camera camera, ref ShadowOutput shadowOutput) { }
public virtual void RenderShadows( ScriptableRenderContext renderContext, CullResults cullResults ) { }
public virtual void PushGlobalParams(Camera camera, ScriptableRenderContext loop) {}
LightingDebugParameters lightDebugParameters,
RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier stencilBuffer,
bool outputSplitLighting) {}
LightingDebugSettings lightDebugParameters,
RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthStencilBuffer, RenderTargetIdentifier depthStencilTexture,
bool outputSplitLightingForSSS, bool enableSSS) {}
public virtual void RenderForward(Camera camera, ScriptableRenderContext renderContext, bool renderOpaque) {}

23
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Lighting.hlsl


#ifndef UNITY_LIGHTING_INCLUDED
#define UNITY_LIGHTING_INCLUDED
#include "ShaderLibrary/CommonLighting.hlsl"
#include "ShaderLibrary/CommonShadow.hlsl"
#include "ShaderLibrary/Sampling.hlsl"
#include "ShaderLibrary/AreaLighting.hlsl"
#include "ShaderLibrary/ImageBasedLighting.hlsl"
#include "../../ShaderLibrary/CommonLighting.hlsl"
#include "../../ShaderLibrary/CommonShadow.hlsl"
#include "../../ShaderLibrary/Sampling.hlsl"
#include "../../ShaderLibrary/AreaLighting.hlsl"
#include "../../ShaderLibrary/ImageBasedLighting.hlsl"
// The light loop (or lighting architecture) is in charge to:
// - Define light list

#define HAS_LIGHTLOOP // Allow to not define LightLoop related function in Material.hlsl
#include "HDRenderPipeline/Lighting/LightDefinition.cs.hlsl"
#include "HDRenderPipeline/Lighting/LightUtilities.hlsl"
#include "../Lighting/LightDefinition.cs.hlsl"
#include "../Lighting/LightUtilities.hlsl"
#include "../Shadow/Shadow.hlsl"
#include "HDRenderPipeline/Lighting/TilePass/TilePass.hlsl"
#include "../Lighting/TilePass/TilePass.hlsl"
#include "HDRenderPipeline/Shadow/Shadow.hlsl"
#include "HDRenderPipeline/Material/Material.hlsl"
#include "../Material/Material.hlsl"
#include "HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl"
#include "../Lighting/TilePass/TilePassLoop.hlsl"
#endif

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources.meta


fileFormatVersion: 2
guid: 8d7b73e3debb13b46a544563ce8f4a64
guid: 0823a45531ce4ee45ab39bcbe1ea52a6
folderAsset: yes
timeCreated: 1479129942
licenseType: Pro

47
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources/Deferred.shader


_SrcBlend("", Float) = 1
_DstBlend("", Float) = 1
_StencilRef("_StencilRef", Int) = 0
_StencilRef("", Int) = 0
_StencilCmp("", Int) = 3
}
SubShader

Stencil
{
Ref [_StencilRef]
Comp Equal
Comp [_StencilCmp]
Pass Keep
}

HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
// #pragma enable_d3d11_debug_symbols
#pragma vertex Vert
#pragma fragment Frag

// Split lighting is utilized during the SSS pass.
#pragma multi_compile _ OUTPUT_SPLIT_LIGHTING
// #ifdef OUTPUT_SPLIT_LIGHTING
#pragma shader_feature _ SSS_PRE_SCATTER_TEXTURING SSS_POST_SCATTER_TEXTURING
// #endif
#pragma multi_compile _ LIGHTING_DEBUG
//-------------------------------------------------------------------------------------

#include "ShaderLibrary/Common.hlsl"
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/Lighting/Lighting.hlsl" // This include Material.hlsl
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../Lighting/Lighting.hlsl" // This include Material.hlsl
//-------------------------------------------------------------------------------------
// variable declaration

TEXTURE2D_FLOAT(_CameraDepthTexture);
SAMPLER2D(sampler_CameraDepthTexture);
struct Attributes
{
uint vertexID : SV_VertexID;

Outputs Frag(Varyings input)
{
// input.positionCS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(input.positionCS.xy) / GetTileSize());
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).x;
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);

PreLightData preLightData = GetPreLightData(V, posInput, bsdfData);
float3 diffuseLighting = float3(0, 0, 0);
float3 specularLighting = float3(0, 0, 0);
#if UNITY_REVERSED_Z
float clearDepth = 0;
#else
float clearDepth = 1;
#endif
// Do not shade the far plane - wastes cycles and produces wrong results.
if (depth != clearDepth)
{
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, diffuseLighting, specularLighting);
}
uint featureFlags = 0xFFFFFFFF;
float3 diffuseLighting;
float3 specularLighting;
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, featureFlags, diffuseLighting, specularLighting);
Outputs outputs;
#ifdef OUTPUT_SPLIT_LIGHTING

25
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TileLightLoopProducer.cs


[Serializable]
public class TileSettings
{
public bool enableDrawLightBoundsDebug;
public bool disableTileAndCluster; // For debug / test
public bool disableDeferredShadingInCompute;
public bool enableTileAndCluster; // For debug / test
public bool enableComputeFeatureVariants;
public int debugViewTilesFlags;
public bool disableFptlWhenClustered; // still useful on opaques. Should be false by default to force tile on opaque.
public bool enableFptlForOpaqueWhenClustered; // still useful on opaques. Should be true by default to force tile on opaque.
[Range(0.0f, 1.0f)]
public float diffuseGlobalDimmer = 1.0f;
[Range(0.0f, 1.0f)]
public float specularGlobalDimmer = 1.0f;
public enum TileDebug : int { None = 0, Punctual = 1, Area = 2, AreaAndPunctual = 3, Environment = 4, EnvironmentAndPunctual = 5, EnvironmentAndArea = 6, EnvironmentAndAreaAndPunctual = 7, FeatureVariants = 8 };
public TileDebug tileDebugByCategory;
enableDrawLightBoundsDebug = false,
disableTileAndCluster = false,
disableDeferredShadingInCompute = true,
enableTileAndCluster = true,
enableComputeFeatureVariants = false,
debugViewTilesFlags = 0,
tileDebugByCategory = TileDebug.None,
disableFptlWhenClustered = false,
enableFptlForOpaqueWhenClustered = true,
enableBigTilePrepass = true,
};
}

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass.meta


fileFormatVersion: 2
guid: 8a355c056864a5d4cb26d9c3168ae0bb
guid: 8d0d2ae5d51ae6e42a81b92e8693272f
folderAsset: yes
timeCreated: 1479218330
licenseType: Pro

16
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute


#pragma kernel BigTileLightListGen
#include "ShaderLibrary/common.hlsl"
#include "../../../../ShaderLibrary/common.hlsl"
#if !defined(SHADER_API_XBOXONE)
#endif
#define EXACT_EDGE_TESTS
#define PERFORM_SPHERICAL_INTERSECTION_TESTS

}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
#if /*!defined(SHADER_API_XBOXONE) && */!defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif

if(t==0) lightOffs = 0;
GroupMemoryBarrierWithGroupSync();
int i;
int i;
for(i=t; i<iNrCoarseLights; i+=NR_THREADS) if((int)lightsListLDS[i]<g_iNrVisibLights) InterlockedAdd(lightOffs, 1);
GroupMemoryBarrierWithGroupSync();
iNrCoarseLights = lightOffs;

int i=iSwizzle + (2*(iSection&0x2)); // offset by 4 at section 2
vP0 = GetTileVertex(uint2(viTilLL.x, viTilUR.y), uint2(viTilUR.x, viTilLL.y), i, fTileFarPlane);
vE0 = iSection == 0 ? vP0 : (((iSwizzle & 0x2) == 0 ? 1.0f : (-1.0f)) * ((int)(iSwizzle & 0x1) == (iSwizzle >> 1) ? float3(1, 0, 0) : float3(0, 1, 0)));
vE0 = iSection == 0 ? vP0 : (((iSwizzle & 0x2) == 0 ? 1.0f : (-1.0f)) * ((int)(iSwizzle & 0x1) == (iSwizzle >> 1) ? float3(1, 0, 0) : float3(0, 1, 0)));
}
void CullByExactEdgeTests(uint threadID, int iNrCoarseLights, uint2 viTilLL, uint2 viTilUR)

{
const uint idxCoarse = lightsListLDS[l];
bool canEnter = idxCoarse<(uint)g_iNrVisibLights;
bool canEnter = idxCoarse<(uint) g_iNrVisibLights;
[branch]if(canEnter)
[branch]if(canEnter)
const float3 boxZ = -lgtDat.boxAxisZ.xyz; // flip axis (so it points away from the light direction for a spot-light)
const float3 boxZ = -lgtDat.boxAxisZ.xyz; // flip axis (so it points away from the light direction for a spot-light)
const float3 center = lgtDat.center.xyz;
const float2 scaleXY = lgtDat.scaleXY;

50
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild-clustered.compute


#pragma kernel TileLightListGen_DepthRT_MSAA_SrcBigTile LIGHTLISTGEN=TileLightListGen_DepthRT_MSAA_SrcBigTile ENABLE_DEPTH_TEXTURE_BACKPLANE MSAA_ENABLED USE_TWO_PASS_TILED_LIGHTING
#pragma kernel ClearAtomic
#include "ShaderLibrary/common.hlsl"
#include "../../../../ShaderLibrary/common.hlsl"
//#define EXACT_EDGE_TESTS
#define PERFORM_SPHERICAL_INTERSECTION_TESTS

#else
g_depth_tex.GetDimensions(iWidth, iHeight);
#endif
uint nrTilesX = (iWidth+15)/16;
uint nrTilesY = (iHeight+15)/16;
const uint log2TileSize = firstbithigh(TILE_SIZE_CLUSTERED);
uint nrTilesX = (iWidth+(TILE_SIZE_CLUSTERED-1))>>log2TileSize;
uint nrTilesY = (iHeight+(TILE_SIZE_CLUSTERED-1))>>log2TileSize;
uint2 viTilLL = 16*tileIDX;
uint2 viTilUR = min( viTilLL+uint2(16,16), uint2(iWidth, iHeight) ); // not width and height minus 1 since viTilUR represents the end of the tile corner.
uint2 viTilLL = TILE_SIZE_CLUSTERED*tileIDX;
uint2 viTilUR = min( viTilLL+uint2(TILE_SIZE_CLUSTERED,TILE_SIZE_CLUSTERED), uint2(iWidth, iHeight) ); // not width and height minus 1 since viTilUR represents the end of the tile corner.
if(t==0)
{

// establish min and max depth first
dpt_ma=0.0;
for(int idx=t; idx<256; idx+=NR_THREADS)
for(int idx=t; idx<(TILE_SIZE_CLUSTERED*TILE_SIZE_CLUSTERED); idx+=NR_THREADS)
uint2 uPixCrd = min( uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1) );
uint2 uPixCrd = min( uint2(viTilLL.x+(idx&(TILE_SIZE_CLUSTERED-1)), viTilLL.y+(idx>>log2TileSize)), uint2(iWidth-1, iHeight-1) );
#ifdef MSAA_ENABLED
for(uint i=0; i<iNumSamplesMSAA; i++)
{

dpt_ma = asfloat(ldsZMax);
#endif
float3 vTileLL = float3(viTilLL.x/(float) iWidth, viTilLL.y/(float) iHeight, 0.0);
float3 vTileUR = float3(viTilUR.x/(float) iWidth, viTilUR.y/(float) iHeight, 1.0);
float2 vTileLL = float2(viTilLL.x/(float) iWidth, viTilLL.y/(float) iHeight);
float2 vTileUR = float2(viTilUR.x/(float) iWidth, viTilUR.y/(float) iHeight);
int NrBigTilesX = (nrTilesX+3)>>2;
const int bigTileIdx = (tileIDX.y>>2)*NrBigTilesX + (tileIDX.x>>2); // map the idx to 64x64 tiles
const uint log2BigTileToClustTileRatio = firstbithigh(64) - log2TileSize;
int NrBigTilesX = (nrTilesX+((1<<log2BigTileToClustTileRatio)-1))>>log2BigTileToClustTileRatio;
const int bigTileIdx = (tileIDX.y>>log2BigTileToClustTileRatio)*NrBigTilesX + (tileIDX.x>>log2BigTileToClustTileRatio); // map the idx to 64x64 tiles
int nrBigTileLights = g_vBigTileLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*bigTileIdx+0];
for(int l0=(int) t; l0<(int) nrBigTileLights; l0 += NR_THREADS)
{

{
#endif
const float3 vMi = g_vBoundsBuffer[l];
const float3 vMa = g_vBoundsBuffer[l+g_iNrVisibLights];
const float2 vMi = g_vBoundsBuffer[l].xy;
const float2 vMa = g_vBoundsBuffer[l+g_iNrVisibLights].xy;
if( all(vMa.xy>vTileLL.xy) && all(vMi.xy<vTileUR.xy))
if( all(vMa>vTileLL) && all(vMi<vTileUR))
{
unsigned int uInc = 1;
unsigned int uIndex;

int iNrCoarseLights = min(lightOffs,MAX_NR_COARSE_ENTRIES);
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
iNrCoarseLights = SphericalIntersectionTests( t, iNrCoarseLights, float2(min(viTilLL.xy+uint2(16/2,16/2), uint2(iWidth-1, iHeight-1))) );
iNrCoarseLights = SphericalIntersectionTests( t, iNrCoarseLights, float2(min(viTilLL.xy+uint2(TILE_SIZE_CLUSTERED/2,TILE_SIZE_CLUSTERED/2), uint2(iWidth-1, iHeight-1))) );
#endif
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE

InterlockedAdd(g_LayeredSingleIdxBuffer[0], (uint) iSpaceAvail, start); // alloc list memory
}
// All our cull data are in the same list, but at render time envLights are separated so we need to shit the index
// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT] = {0, 0, _EnvLightIndexShift}; // 3 for now, will throw an error if we change LIGHTCATEGORY_COUNT
// All our cull data are in the same list, but at render time envLights are separated so we need to shit the index
// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT] = {0, 0, _EnvLightIndexShift}; // 3 for now, will throw an error if we change LIGHTCATEGORY_COUNT
int categoryListCount[LIGHTCATEGORY_COUNT]={0,0,0}; // direct light count and reflection lights
uint offs = start;

{
if(offs<(start+iSpaceAvail) && i<nrClusters && CheckIntersection(l, i, viTilLL.xy, viTilUR.xy, suggestedBase) )
{
uint lightCategory = _LightVolumeData[coarseList[l]].lightCategory;
++categoryListCount[lightCategory];
uint lightCategory = _LightVolumeData[coarseList[l]].lightCategory;
++categoryListCount[lightCategory];
g_vLayeredLightList[offs++] = coarseList[l] - shiftIndex[lightCategory]; // reflection lights will be last since we sorted
}
}

#endif
float onePixDiagDist = GetOnePixDiagWorldDistAtDepthOne();
float halfTileSizeAtZDistOne = 8*onePixDiagDist; // scale by half a tile
float halfTileSizeAtZDistOne = (TILE_SIZE_CLUSTERED/2)*onePixDiagDist; // scale by half a tile
for(int l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
{

GroupMemoryBarrierWithGroupSync();
#endif
const int idxCoarse = coarseList[l];
[branch]if (_LightVolumeData[idxCoarse].lightVolume != LIGHTVOLUMETYPE_SPHERE) // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
[branch]if (_LightVolumeData[idxCoarse].lightVolume != LIGHTVOLUMETYPE_SPHERE) // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
{
SFiniteLightBound lgtDat = g_data[idxCoarse];

925
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild.compute


// The implementation is based on the demo on "fine pruned tiled lighting" published in GPU Pro 7.
// https://github.com/wolfgangfengel/GPU-Pro-7
#pragma kernel TileLightListGen LIGHTLISTGEN=TileLightListGen
#pragma kernel TileLightListGen_SrcBigTile LIGHTLISTGEN=TileLightListGen_SrcBigTile USE_TWO_PASS_TILED_LIGHTING
#include "ShaderLibrary/common.hlsl"
#include "../ShaderBase.hlsl"
#include "../TilePass.cs.hlsl"
#include "../LightingConvexHullUtils.hlsl"
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
#include "../SortingComputeUtils.hlsl"
#endif
#define FINE_PRUNING_ENABLED
#define PERFORM_SPHERICAL_INTERSECTION_TESTS
uniform int g_iNrVisibLights;
uniform uint2 g_viDimensions;
uniform float4x4 g_mInvScrProjection;
uniform float4x4 g_mScrProjection;
uniform int _EnvLightIndexShift;
Texture2D g_depth_tex : register( t0 );
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<LightVolumeData> _LightVolumeData : register(t2);
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );
#ifdef USE_TWO_PASS_TILED_LIGHTING
StructuredBuffer<uint> g_vBigTileLightList : register( t4 ); // don't support Buffer yet in unity
#endif
#define NR_THREADS 64
// output buffer
RWStructuredBuffer<uint> g_vLightList : register( u0 ); // don't support RWBuffer yet in unity
#define MAX_NR_COARSE_ENTRIES 64
#define MAX_NR_PRUNED_ENTRIES 24
groupshared unsigned int coarseList[MAX_NR_COARSE_ENTRIES];
groupshared unsigned int prunedList[MAX_NR_COARSE_ENTRIES]; // temporarily support room for all 64 while in LDS
groupshared uint ldsZMin;
groupshared uint ldsZMax;
groupshared uint lightOffs;
#ifdef FINE_PRUNING_ENABLED
groupshared uint ldsDoesLightIntersect[2];
#endif
groupshared int ldsNrLightsFinal;
groupshared int ldsCategoryListCount[LIGHTCATEGORY_COUNT]; // since LIGHTCATEGORY_COUNT is 3
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
groupshared uint lightOffsSph;
#endif
//float GetLinearDepth(float3 vP)
//{
// float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
// return v4Pres.z / v4Pres.w;
//}
float GetLinearDepth(float zDptBufSpace) // 0 is near 1 is far
{
float3 vP = float3(0.0f,0.0f,zDptBufSpace);
float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
return v4Pres.z / v4Pres.w;
}
float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
float fSx = g_mScrProjection[0].x;
float fCx = g_mScrProjection[0].z;
float fSy = g_mScrProjection[1].y;
float fCy = g_mScrProjection[1].z;
#if USE_LEFTHAND_CAMERASPACE
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
#else
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
#endif
}
float GetOnePixDiagWorldDistAtDepthOne()
{
float fSx = g_mScrProjection[0].x;
float fSy = g_mScrProjection[1].y;
return length( float2(1.0/fSx,1.0/fSy) );
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate);
#endif
#ifdef FINE_PRUNING_ENABLED
void FinePruneLights(uint threadID, int iNrCoarseLights, uint2 viTilLL, float4 vLinDepths);
#endif
[numthreads(NR_THREADS, 1, 1)]
void LIGHTLISTGEN(uint threadID : SV_GroupIndex, uint3 u3GroupID : SV_GroupID)
{
uint2 tileIDX = u3GroupID.xy;
uint t=threadID;
if(t<MAX_NR_COARSE_ENTRIES)
prunedList[t]=0;
uint iWidth = g_viDimensions.x;
uint iHeight = g_viDimensions.y;
uint nrTilesX = (iWidth+15)/16;
uint nrTilesY = (iHeight+15)/16;
// build tile scr boundary
const uint uFltMax = 0x7f7fffff; // FLT_MAX as a uint
if(t==0)
{
ldsZMin = uFltMax;
ldsZMax = 0;
lightOffs = 0;
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
uint2 viTilLL = 16*tileIDX;
// establish min and max depth first
float dpt_mi=asfloat(uFltMax), dpt_ma=0.0;
float4 vLinDepths;
{
// Fetch depths and calculate min/max
[unroll]
for(int i = 0; i < 4; i++)
{
int idx = i * NR_THREADS + t;
uint2 uCrd = min( uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1) );
const float fDepth = FetchDepth(g_depth_tex, uCrd);
vLinDepths[i] = GetLinearDepth(fDepth);
if(fDepth<VIEWPORT_SCALE_Z) // if not skydome
{
dpt_mi = min(fDepth, dpt_mi);
dpt_ma = max(fDepth, dpt_ma);
}
}
InterlockedMax(ldsZMax, asuint(dpt_ma));
InterlockedMin(ldsZMin, asuint(dpt_mi));
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
}
float3 vTileLL = float3(viTilLL.x/(float) iWidth, viTilLL.y/(float) iHeight, asfloat(ldsZMin));
float3 vTileUR = float3((viTilLL.x+16)/(float) iWidth, (viTilLL.y+16)/(float) iHeight, asfloat(ldsZMax));
vTileUR.xy = min(vTileUR.xy,float2(1.0,1.0)).xy;
// build coarse list using AABB
#ifdef USE_TWO_PASS_TILED_LIGHTING
int NrBigTilesX = (nrTilesX+3)>>2;
const int bigTileIdx = (tileIDX.y>>2)*NrBigTilesX + (tileIDX.x>>2); // map the idx to 64x64 tiles
int nrBigTileLights = g_vBigTileLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*bigTileIdx+0];
for(int l0=(int) t; l0<(int) nrBigTileLights; l0 += NR_THREADS)
{
int l = g_vBigTileLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*bigTileIdx+l0+1];
#else
for(int l=(int) t; l<(int) g_iNrVisibLights; l += NR_THREADS)
{
#endif
const float3 vMi = g_vBoundsBuffer[l];
const float3 vMa = g_vBoundsBuffer[l+g_iNrVisibLights];
if( all(vMa>vTileLL) && all(vMi<vTileUR))
{
unsigned int uInc = 1;
unsigned int uIndex;
InterlockedAdd(lightOffs, uInc, uIndex);
if(uIndex<MAX_NR_COARSE_ENTRIES) coarseList[uIndex] = l; // add to light list
}
}
#ifdef FINE_PRUNING_ENABLED
if(t<2) ldsDoesLightIntersect[t] = 0;
#endif
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
int iNrCoarseLights = min(lightOffs,MAX_NR_COARSE_ENTRIES);
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
iNrCoarseLights = SphericalIntersectionTests( t, iNrCoarseLights, float2(min(viTilLL.xy+uint2(16/2,16/2), uint2(iWidth-1, iHeight-1))) );
#endif
#ifndef FINE_PRUNING_ENABLED
{
if((int)t<iNrCoarseLights) prunedList[t] = coarseList[t];
if(t==0) ldsNrLightsFinal=iNrCoarseLights;
}
#else
{
// initializes ldsNrLightsFinal with the number of accepted lights.
// all accepted entries delivered in prunedList[].
FinePruneLights(t, iNrCoarseLights, viTilLL, vLinDepths);
}
#endif
//
if(t<LIGHTCATEGORY_COUNT) ldsCategoryListCount[t]=0;
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
int nrLightsCombinedList = min(ldsNrLightsFinal,MAX_NR_COARSE_ENTRIES);
for(int i=t; i<nrLightsCombinedList; i+=NR_THREADS)
{
InterlockedAdd(ldsCategoryListCount[_LightVolumeData[prunedList[i]].lightCategory], 1);
}
// sort lights (gives a more efficient execution in both deferred and tiled forward lighting).
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
SORTLIST(prunedList, nrLightsCombinedList, MAX_NR_COARSE_ENTRIES, t, NR_THREADS);
//MERGESORTLIST(prunedList, coarseList, nrLightsCombinedList, t, NR_THREADS);
#endif
// write lights to global buffers
int localOffs=0;
int offs = tileIDX.y*nrTilesX + tileIDX.x;
// All our cull data are in the same list, but at render time envLights are separated so we need to shit the index
// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT] = {0, 0, _EnvLightIndexShift}; // 3 for now, will throw an error if we change LIGHTCATEGORY_COUNT
for(int category=0; category<LIGHTCATEGORY_COUNT; category++)
{
int nrLightsFinal = ldsCategoryListCount[category];
int nrLightsFinalClamped = nrLightsFinal<MAX_NR_PRUNED_ENTRIES ? nrLightsFinal : MAX_NR_PRUNED_ENTRIES;
const int nrDWords = ((nrLightsFinalClamped+1)+1)>>1;
for(int l=(int) t; l<(int) nrDWords; l += NR_THREADS)
{
// We remap the prunedList index to the original LightData / EnvLightData indices
uint uLow = l==0 ? nrLightsFinalClamped : prunedList[2*l-1+localOffs] - shiftIndex[category];
uint uHigh = prunedList[2 * l + 0 + localOffs] - shiftIndex[category];
g_vLightList[16*offs + l] = (uLow&0xffff) | (uHigh<<16);
}
localOffs += nrLightsFinal;
offs += (nrTilesX*nrTilesY);
}
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate)
{
if(threadID==0) lightOffsSph = 0;
// make a copy of coarseList in prunedList.
int l;
for(l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
prunedList[l]=coarseList[l];
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
#if USE_LEFTHAND_CAMERASPACE
float3 V = GetViewPosFromLinDepth( screenCoordinate, 1.0);
#else
float3 V = GetViewPosFromLinDepth( screenCoordinate, -1.0);
#endif
float onePixDiagDist = GetOnePixDiagWorldDistAtDepthOne();
float halfTileSizeAtZDistOne = 8*onePixDiagDist; // scale by half a tile
for(l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
{
SFiniteLightBound lightData = g_data[prunedList[l]];
if( DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lightData.center.xyz, lightData.radius) )
{
unsigned int uIndex;
InterlockedAdd(lightOffsSph, 1, uIndex);
coarseList[uIndex]=prunedList[l]; // read from the original copy of coarseList which is backed up in prunedList
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
return lightOffsSph;
}
#endif
#ifdef FINE_PRUNING_ENABLED
// initializes ldsNrLightsFinal with the number of accepted lights.
// all accepted entries delivered in prunedList[].
void FinePruneLights(uint threadID, int iNrCoarseLights, uint2 viTilLL, float4 vLinDepths)
{
uint t = threadID;
uint iWidth = g_viDimensions.x;
uint iHeight = g_viDimensions.y;
uint uLightsFlags[2] = {0,0};
int l=0;
// need this outer loop even on xb1 and ps4 since direct lights and
// reflection lights are kept in separate regions.
while(l<iNrCoarseLights)
{
// fetch light
int idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uint uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
// spot
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_CONE)
{
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// TODO: Change by SebL
const bool bIsSpotDisc = true; // (lightData.flags&IS_CIRCULAR_SPOT_SHAPE) != 0;
// serially check 4 pixels
uint uVal = 0;
for(int i=0; i<4; i++)
{
int idx = t + i*NR_THREADS;
uint2 uPixLoc = min(uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1));
float3 vVPos = GetViewPosFromLinDepth(uPixLoc + float2(0.5,0.5), vLinDepths[i]);
// check pixel
float3 fromLight = vVPos-lightData.lightPos.xyz;
float distSq = dot(fromLight,fromLight);
const float fSclProj = dot(fromLight, lightData.lightAxisZ.xyz); // spotDir = lightData.lightAxisZ.xyz
float2 V = abs( float2( dot(fromLight, lightData.lightAxisX.xyz), dot(fromLight, lightData.lightAxisY.xyz) ) );
float fDist2D = bIsSpotDisc ? length(V) : max(V.x,V.y);
if( all( float2(lightData.radiusSq, fSclProj) > float2(distSq, fDist2D*lightData.cotan) ) ) uVal = 1;
}
uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
}
// sphere
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_SPHERE)
{
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// serially check 4 pixels
uint uVal = 0;
for(int i=0; i<4; i++)
{
int idx = t + i*NR_THREADS;
uint2 uPixLoc = min(uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1));
float3 vVPos = GetViewPosFromLinDepth(uPixLoc + float2(0.5,0.5), vLinDepths[i]);
// check pixel
float3 vLp = lightData.lightPos.xyz;
float3 toLight = vLp - vVPos;
float distSq = dot(toLight,toLight);
if(lightData.radiusSq>distSq) uVal = 1;
}
uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
}
// Box
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_BOX)
{
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// serially check 4 pixels
uint uVal = 0;
for(int i=0; i<4; i++)
{
int idx = t + i*NR_THREADS;
uint2 uPixLoc = min(uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1));
float3 vVPos = GetViewPosFromLinDepth(uPixLoc + float2(0.5,0.5), vLinDepths[i]);
// check pixel
float3 toLight = lightData.lightPos.xyz - vVPos;
float3 dist = float3( dot(toLight, lightData.lightAxisX), dot(toLight, lightData.lightAxisY), dot(toLight, lightData.lightAxisZ) );
dist = (abs(dist) - lightData.boxInnerDist) * lightData.boxInvRange; // not as efficient as it could be
if( max(max(dist.x, dist.y), dist.z)<1 ) uVal = 1; // but allows us to not write out OuterDists
}
uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
}
// in case we have some corrupt data make sure we terminate
if(uLightVolume >=LIGHTVOLUMETYPE_COUNT) ++l;
}
InterlockedOr(ldsDoesLightIntersect[0], uLightsFlags[0]);
InterlockedOr(ldsDoesLightIntersect[1], uLightsFlags[1]);
if(t==0) ldsNrLightsFinal = 0;
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
if(t<(uint) iNrCoarseLights && (ldsDoesLightIntersect[t<32 ? 0 : 1]&(1<<(t&31)))!=0 )
{
unsigned int uInc = 1;
unsigned int uIndex;
InterlockedAdd(ldsNrLightsFinal, uInc, uIndex);
if(uIndex<MAX_NR_COARSE_ENTRIES) prunedList[uIndex] = coarseList[t]; // we allow up to 64 pruned lights while stored in LDS.
}
}
#endif
// The implementation is based on the demo on "fine pruned tiled lighting" published in GPU Pro 7.
// https://github.com/wolfgangfengel/GPU-Pro-7
#pragma kernel TileLightListGen LIGHTLISTGEN=TileLightListGen
#pragma kernel TileLightListGen_SrcBigTile LIGHTLISTGEN=TileLightListGen_SrcBigTile USE_TWO_PASS_TILED_LIGHTING
#pragma kernel TileLightListGen_FeatureFlags LIGHTLISTGEN=TileLightListGen_FeatureFlags USE_FEATURE_FLAGS
#pragma kernel TileLightListGen_SrcBigTile_FeatureFlags LIGHTLISTGEN=TileLightListGen_SrcBigTile_FeatureFlags USE_TWO_PASS_TILED_LIGHTING USE_FEATURE_FLAGS
#pragma #pragma enable_d3d11_debug_symbols
#include "../../../../ShaderLibrary/common.hlsl"
#include "../ShaderBase.hlsl"
#include "../TilePass.cs.hlsl"
#include "../LightingConvexHullUtils.hlsl"
#include "../FeatureFlags.hlsl"
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
#include "../SortingComputeUtils.hlsl"
#endif
#define FINE_PRUNING_ENABLED
#define PERFORM_SPHERICAL_INTERSECTION_TESTS
uniform int g_iNrVisibLights;
uniform uint2 g_viDimensions;
uniform float4x4 g_mInvScrProjection;
uniform float4x4 g_mScrProjection;
uniform int _EnvLightIndexShift;
Texture2D g_depth_tex : register( t0 );
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<LightVolumeData> _LightVolumeData : register(t2);
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );
#ifdef USE_TWO_PASS_TILED_LIGHTING
StructuredBuffer<uint> g_vBigTileLightList : register( t4 ); // don't support Buffer yet in unity
#endif
#define NR_THREADS 64
// output buffer
RWStructuredBuffer<uint> g_vLightList : register( u0 ); // don't support RWBuffer yet in unity
#define MAX_NR_COARSE_ENTRIES 64
#define MAX_NR_PRUNED_ENTRIES 24
groupshared unsigned int coarseList[MAX_NR_COARSE_ENTRIES];
groupshared unsigned int prunedList[MAX_NR_COARSE_ENTRIES]; // temporarily support room for all 64 while in LDS
groupshared uint ldsZMin;
groupshared uint ldsZMax;
groupshared uint lightOffs;
#ifdef FINE_PRUNING_ENABLED
groupshared uint ldsDoesLightIntersect[2];
#endif
groupshared int ldsNrLightsFinal;
groupshared int ldsCategoryListCount[LIGHTCATEGORY_COUNT]; // since LIGHTCATEGORY_COUNT is 3
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
groupshared uint lightOffsSph;
#endif
uniform uint g_BaseFeatureFlags;
#ifdef USE_FEATURE_FLAGS
groupshared uint ldsFeatureFlags;
RWBuffer<uint> g_DispatchIndirectBuffer;
RWStructuredBuffer<uint> g_TileList;
#endif
//float GetLinearDepth(float3 vP)
//{
// float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
// return v4Pres.z / v4Pres.w;
//}
float GetLinearDepth(float zDptBufSpace) // 0 is near 1 is far
{
float3 vP = float3(0.0f,0.0f,zDptBufSpace);
float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
return v4Pres.z / v4Pres.w;
}
float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
float fSx = g_mScrProjection[0].x;
float fCx = g_mScrProjection[0].z;
float fSy = g_mScrProjection[1].y;
float fCy = g_mScrProjection[1].z;
#if USE_LEFTHAND_CAMERASPACE
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
#else
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
#endif
}
float GetOnePixDiagWorldDistAtDepthOne()
{
float fSx = g_mScrProjection[0].x;
float fSy = g_mScrProjection[1].y;
return length( float2(1.0/fSx,1.0/fSy) );
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate);
#endif
#ifdef FINE_PRUNING_ENABLED
void FinePruneLights(uint threadID, int iNrCoarseLights, uint2 viTilLL, float4 vLinDepths);
#endif
[numthreads(NR_THREADS, 1, 1)]
void LIGHTLISTGEN(uint threadID : SV_GroupIndex, uint3 u3GroupID : SV_GroupID)
{
uint2 tileIDX = u3GroupID.xy;
uint t=threadID;
if(t<MAX_NR_COARSE_ENTRIES)
prunedList[t]=0;
uint iWidth = g_viDimensions.x;
uint iHeight = g_viDimensions.y;
uint nrTilesX = (iWidth+15)/16;
uint nrTilesY = (iHeight+15)/16;
uint nrTiles = nrTilesX * nrTilesY; // Precompute?
// build tile scr boundary
const uint uFltMax = 0x7f7fffff; // FLT_MAX as a uint
if(t==0)
{
ldsZMin = uFltMax;
ldsZMax = 0;
lightOffs = 0;
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
uint2 viTilLL = 16*tileIDX;
// establish min and max depth first
float dpt_mi=asfloat(uFltMax), dpt_ma=0.0;
float4 vLinDepths;
{
// Fetch depths and calculate min/max
[unroll]
for(int i = 0; i < 4; i++)
{
int idx = i * NR_THREADS + t;
uint2 uCrd = min( uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1) );
const float fDepth = FetchDepth(g_depth_tex, uCrd);
vLinDepths[i] = GetLinearDepth(fDepth);
if(fDepth<VIEWPORT_SCALE_Z) // if not skydome
{
dpt_mi = min(fDepth, dpt_mi);
dpt_ma = max(fDepth, dpt_ma);
}
}
InterlockedMax(ldsZMax, asuint(dpt_ma));
InterlockedMin(ldsZMin, asuint(dpt_mi));
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
}
float3 vTileLL = float3(viTilLL.x/(float) iWidth, viTilLL.y/(float) iHeight, asfloat(ldsZMin));
float3 vTileUR = float3((viTilLL.x+16)/(float) iWidth, (viTilLL.y+16)/(float) iHeight, asfloat(ldsZMax));
vTileUR.xy = min(vTileUR.xy,float2(1.0,1.0)).xy;
// build coarse list using AABB
#ifdef USE_TWO_PASS_TILED_LIGHTING
int NrBigTilesX = (nrTilesX+3)>>2;
const int bigTileIdx = (tileIDX.y>>2)*NrBigTilesX + (tileIDX.x>>2); // map the idx to 64x64 tiles
int nrBigTileLights = g_vBigTileLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*bigTileIdx+0];
for(int l0=(int) t; l0<(int) nrBigTileLights; l0 += NR_THREADS)
{
int l = g_vBigTileLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*bigTileIdx+l0+1];
#else
for(int l=(int) t; l<(int) g_iNrVisibLights; l += NR_THREADS)
{
#endif
const float3 vMi = g_vBoundsBuffer[l];
const float3 vMa = g_vBoundsBuffer[l+g_iNrVisibLights];
if( all(vMa>vTileLL) && all(vMi<vTileUR))
{
unsigned int uInc = 1;
unsigned int uIndex;
InterlockedAdd(lightOffs, uInc, uIndex);
if(uIndex<MAX_NR_COARSE_ENTRIES) coarseList[uIndex] = l; // add to light list
}
}
#ifdef FINE_PRUNING_ENABLED
if(t<2) ldsDoesLightIntersect[t] = 0;
#endif
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
int iNrCoarseLights = min(lightOffs,MAX_NR_COARSE_ENTRIES);
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
iNrCoarseLights = SphericalIntersectionTests( t, iNrCoarseLights, float2(min(viTilLL.xy+uint2(16/2,16/2), uint2(iWidth-1, iHeight-1))) );
#endif
#ifndef FINE_PRUNING_ENABLED
{
if((int)t<iNrCoarseLights) prunedList[t] = coarseList[t];
if(t==0) ldsNrLightsFinal=iNrCoarseLights;
}
#else
{
// initializes ldsNrLightsFinal with the number of accepted lights.
// all accepted entries delivered in prunedList[].
FinePruneLights(t, iNrCoarseLights, viTilLL, vLinDepths);
}
#endif
//
if(t<LIGHTCATEGORY_COUNT) ldsCategoryListCount[t]=0;
#ifdef USE_FEATURE_FLAGS
if(t==0) ldsFeatureFlags=0;
#endif
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
int nrLightsCombinedList = min(ldsNrLightsFinal,MAX_NR_COARSE_ENTRIES);
for(int i=t; i<nrLightsCombinedList; i+=NR_THREADS)
{
InterlockedAdd(ldsCategoryListCount[_LightVolumeData[prunedList[i]].lightCategory], 1);
#ifdef USE_FEATURE_FLAGS
InterlockedOr(ldsFeatureFlags, _LightVolumeData[prunedList[i]].featureFlags);
#endif
}
// sort lights (gives a more efficient execution in both deferred and tiled forward lighting).
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
SORTLIST(prunedList, nrLightsCombinedList, MAX_NR_COARSE_ENTRIES, t, NR_THREADS);
//MERGESORTLIST(prunedList, coarseList, nrLightsCombinedList, t, NR_THREADS);
#endif
#ifdef USE_FEATURE_FLAGS
if(t == 0)
{
uint featureFlags = g_BaseFeatureFlags | ldsFeatureFlags;
if(ldsZMax < ldsZMin) // is background pixel
{
featureFlags &= ~(FEATURE_FLAG_PUNCTUAL_LIGHT | FEATURE_FLAG_AREA_LIGHT | FEATURE_FLAG_DIRECTIONAL_LIGHT | FEATURE_FLAG_ENV_LIGHT); // list of features that are not enabled on background
}
uint variant = FeatureFlagsToTileVariant(featureFlags);
uint offset;
InterlockedAdd(g_DispatchIndirectBuffer[variant * 3 + 0], 1, offset);
g_TileList[variant*nrTiles + offset] = (tileIDX.y << 16) + tileIDX.x;
}
#endif
// write lights to global buffers
int localOffs=0;
int offs = tileIDX.y*nrTilesX + tileIDX.x;
// All our cull data are in the same list, but at render time envLights are separated so we need to shit the index
// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT] = {0, 0, _EnvLightIndexShift}; // 3 for now, will throw an error if we change LIGHTCATEGORY_COUNT
for(int category=0; category<LIGHTCATEGORY_COUNT; category++)
{
int nrLightsFinal = ldsCategoryListCount[category];
int nrLightsFinalClamped = nrLightsFinal<MAX_NR_PRUNED_ENTRIES ? nrLightsFinal : MAX_NR_PRUNED_ENTRIES;
const int nrDWords = ((nrLightsFinalClamped+1)+1)>>1;
for(int l=(int) t; l<(int) nrDWords; l += NR_THREADS)
{
// We remap the prunedList index to the original LightData / EnvLightData indices
uint uLow = l==0 ? nrLightsFinalClamped : prunedList[2 * l - 1 + localOffs] - shiftIndex[category];
uint uHigh = prunedList[2 * l + 0 + localOffs] - shiftIndex[category];
g_vLightList[16*offs + l] = (uLow&0xffff) | (uHigh<<16);
}
localOffs += nrLightsFinal;
offs += (nrTilesX*nrTilesY);
}
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate)
{
if(threadID==0) lightOffsSph = 0;
// make a copy of coarseList in prunedList.
int l;
for(l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
prunedList[l]=coarseList[l];
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
#if USE_LEFTHAND_CAMERASPACE
float3 V = GetViewPosFromLinDepth( screenCoordinate, 1.0);
#else
float3 V = GetViewPosFromLinDepth( screenCoordinate, -1.0);
#endif
float onePixDiagDist = GetOnePixDiagWorldDistAtDepthOne();
float halfTileSizeAtZDistOne = 8*onePixDiagDist; // scale by half a tile
for(l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
{
SFiniteLightBound lightData = g_data[prunedList[l]];
if( DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lightData.center.xyz, lightData.radius) )
{
unsigned int uIndex;
InterlockedAdd(lightOffsSph, 1, uIndex);
coarseList[uIndex]=prunedList[l]; // read from the original copy of coarseList which is backed up in prunedList
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
return lightOffsSph;
}
#endif
#ifdef FINE_PRUNING_ENABLED
// initializes ldsNrLightsFinal with the number of accepted lights.
// all accepted entries delivered in prunedList[].
void FinePruneLights(uint threadID, int iNrCoarseLights, uint2 viTilLL, float4 vLinDepths)
{
uint t = threadID;
uint iWidth = g_viDimensions.x;
uint iHeight = g_viDimensions.y;
uint uLightsFlags[2] = {0,0};
int l=0;
// need this outer loop even on xb1 and ps4 since direct lights and
// reflection lights are kept in separate regions.
while(l<iNrCoarseLights)
{
// fetch light
int idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uint uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
// spot
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_CONE)
{
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// TODO: Change by SebL
const bool bIsSpotDisc = true; // (lightData.flags&IS_CIRCULAR_SPOT_SHAPE) != 0;
// serially check 4 pixels
uint uVal = 0;
for(int i=0; i<4; i++)
{
int idx = t + i*NR_THREADS;
uint2 uPixLoc = min(uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1));
float3 vVPos = GetViewPosFromLinDepth(uPixLoc + float2(0.5,0.5), vLinDepths[i]);
// check pixel
float3 fromLight = vVPos-lightData.lightPos.xyz;
float distSq = dot(fromLight,fromLight);
const float fSclProj = dot(fromLight, lightData.lightAxisZ.xyz); // spotDir = lightData.lightAxisZ.xyz
float2 V = abs( float2( dot(fromLight, lightData.lightAxisX.xyz), dot(fromLight, lightData.lightAxisY.xyz) ) );
float fDist2D = bIsSpotDisc ? length(V) : max(V.x,V.y);
if( all( float2(lightData.radiusSq, fSclProj) > float2(distSq, fDist2D*lightData.cotan) ) ) uVal = 1;
}
uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
}
// sphere
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_SPHERE)
{
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// serially check 4 pixels
uint uVal = 0;
for(int i=0; i<4; i++)
{
int idx = t + i*NR_THREADS;
uint2 uPixLoc = min(uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1));
float3 vVPos = GetViewPosFromLinDepth(uPixLoc + float2(0.5,0.5), vLinDepths[i]);
// check pixel
float3 vLp = lightData.lightPos.xyz;
float3 toLight = vLp - vVPos;
float distSq = dot(toLight,toLight);
if(lightData.radiusSq>distSq) uVal = 1;
}
uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
}
// Box
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_BOX)
{
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// serially check 4 pixels
uint uVal = 0;
for(int i=0; i<4; i++)
{
int idx = t + i*NR_THREADS;
uint2 uPixLoc = min(uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1));
float3 vVPos = GetViewPosFromLinDepth(uPixLoc + float2(0.5,0.5), vLinDepths[i]);
// check pixel
float3 toLight = lightData.lightPos.xyz - vVPos;
float3 dist = float3( dot(toLight, lightData.lightAxisX), dot(toLight, lightData.lightAxisY), dot(toLight, lightData.lightAxisZ) );
dist = (abs(dist) - lightData.boxInnerDist) * lightData.boxInvRange; // not as efficient as it could be
if( max(max(dist.x, dist.y), dist.z)<1 ) uVal = 1; // but allows us to not write out OuterDists
}
uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
}
// in case we have some corrupt data make sure we terminate
if(uLightVolume >=LIGHTVOLUMETYPE_COUNT) ++l;
}
InterlockedOr(ldsDoesLightIntersect[0], uLightsFlags[0]);
InterlockedOr(ldsDoesLightIntersect[1], uLightsFlags[1]);
if(t==0) ldsNrLightsFinal = 0;
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
if(t<(uint) iNrCoarseLights && (ldsDoesLightIntersect[t<32 ? 0 : 1]&(1<<(t&31)))!=0 )
{
unsigned int uInc = 1;
unsigned int uIndex;
InterlockedAdd(ldsNrLightsFinal, uInc, uIndex);
if(uIndex<MAX_NR_COARSE_ENTRIES) prunedList[uIndex] = coarseList[t]; // we allow up to 64 pruned lights while stored in LDS.
}
}
#endif

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/scrbound.compute


#pragma kernel ScreenBoundsAABB
#include "ShaderLibrary/common.hlsl"
#include "../../../../ShaderLibrary/common.hlsl"
#include "../TilePass.cs.hlsl"
uniform int g_iNrVisibLights;

#define NR_THREADS 64

185
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Resources/shadeopaque.compute


#pragma kernel ShadeOpaque_Fptl SHADE_OPAQUE_ENTRY=ShadeOpaque_Fptl USE_FPTL_LIGHTLIST
#pragma kernel ShadeOpaque_Fptl_DebugLighting SHADE_OPAQUE_ENTRY=ShadeOpaque_Fptl_DebugLighting USE_FPTL_LIGHTLIST LIGHTING_DEBUG
#pragma kernel ShadeOpaque_Clustered SHADE_OPAQUE_ENTRY=ShadeOpaque_Clustered USE_CLUSTERED_LIGHTLIST
#pragma kernel ShadeOpaque_Clustered_DebugLighting SHADE_OPAQUE_ENTRY=ShadeOpaque_Clustered_DebugLighting USE_CLUSTERED_LIGHTLIST LIGHTING_DEBUG
// Split lighting is required for the SSS pass.
// Not currently possible since we need to access the stencil buffer from the compute shader.
// #pragma multi_compile _ OUTPUT_SPLIT_LIGHTING
#define LIGHTLOOP_TILE_PASS 1
#define LIGHTLOOP_TILE_DIRECT 1
#define LIGHTLOOP_TILE_INDIRECT 1
#define LIGHTLOOP_TILE_ALL 1
#define USE_FPTL_LIGHTLIST 1
//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------
#include "ShaderLibrary/Common.hlsl"
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
// Note: We have fix as guidelines that we have only one deferred material (with control of GBuffer enabled). Mean a users that add a new
// deferred material must replace the old one here. If in the future we want to support multiple layout (cause a lot of consistency problem),
// the deferred shader will require to use multicompile.
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/Lighting/Lighting.hlsl" // This include Material.hlsl
//-------------------------------------------------------------------------------------
// variable declaration
//-------------------------------------------------------------------------------------
DECLARE_GBUFFER_TEXTURE(_GBufferTexture);
TEXTURE2D_FLOAT(_CameraDepthTexture);
SAMPLER2D(sampler_CameraDepthTexture);
#ifdef OUTPUT_SPLIT_LIGHTING
RWTexture2D<float4> specularLightingUAV;
RWTexture2D<float3> diffuseLightingUAV;
#else
RWTexture2D<float4> combinedLightingUAV;
#endif
[numthreads(TILE_SIZE, TILE_SIZE, 1)]
void SHADE_OPAQUE_ENTRY(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupId : SV_GroupID)
{
// input.positionCS is SV_Position
uint2 pixelCoord = dispatchThreadId;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).x;
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
FETCH_GBUFFER(gbuffer, _GBufferTexture, posInput.unPositionSS);
BSDFData bsdfData;
float3 bakeDiffuseLighting;
DECODE_FROM_GBUFFER(gbuffer, bsdfData, bakeDiffuseLighting);
PreLightData preLightData = GetPreLightData(V, posInput, bsdfData);
float3 diffuseLighting;
float3 specularLighting;
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, diffuseLighting, specularLighting);
#ifdef OUTPUT_SPLIT_LIGHTING
specularLightingUAV[pixelCoord] = float4(specularLighting, 1.0);
diffuseLightingUAV[pixelCoord] = diffuseLighting;
#else
combinedLightingUAV[pixelCoord] = float4(diffuseLighting + specularLighting, 1.0);
#endif
}
#pragma kernel ShadeOpaque_Direct_Fptl SHADE_OPAQUE_ENTRY=ShadeOpaque_Direct_Fptl USE_FPTL_LIGHTLIST
#pragma kernel ShadeOpaque_Direct_Fptl_DebugLighting SHADE_OPAQUE_ENTRY=ShadeOpaque_Direct_Fptl_DebugLighting USE_FPTL_LIGHTLIST LIGHTING_DEBUG
#pragma kernel ShadeOpaque_Direct_Clustered SHADE_OPAQUE_ENTRY=ShadeOpaque_Direct_Clustered USE_CLUSTERED_LIGHTLIST
#pragma kernel ShadeOpaque_Direct_Clustered_DebugLighting SHADE_OPAQUE_ENTRY=ShadeOpaque_Direct_Clustered_DebugLighting USE_CLUSTERED_LIGHTLIST LIGHTING_DEBUG
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant0 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant0 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=0
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant1 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant1 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=1
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant2 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant2 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=2
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant3 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant3 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=3
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant4 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant4 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=4
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant5 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant5 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=5
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant6 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant6 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=6
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant7 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant7 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=7
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant0 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant0 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=0
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant1 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant1 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=1
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant2 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant2 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=2
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant3 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant3 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=3
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant4 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant4 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=4
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant5 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant5 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=5
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant6 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant6 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=6
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant7 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant7 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=7
#pragma #pragma enable_d3d11_debug_symbols
// Split lighting is required for the SSS pass.
// Not currently possible since we need to access the stencil buffer from the compute shader.
// #pragma multi_compile _ OUTPUT_SPLIT_LIGHTING
#define LIGHTLOOP_TILE_PASS 1
#define LIGHTLOOP_TILE_DIRECT 1
#define LIGHTLOOP_TILE_INDIRECT 1
#define LIGHTLOOP_TILE_ALL 1
//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------
#include "../../../../ShaderLibrary/Common.hlsl"
#include "../../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../../Debug/DebugLighting.hlsl"
// Note: We have fix as guidelines that we have only one deferred material (with control of GBuffer enabled). Mean a users that add a new
// deferred material must replace the old one here. If in the future we want to support multiple layout (cause a lot of consistency problem),
// the deferred shader will require to use multicompile.
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#include "../../../ShaderConfig.cs.hlsl"
#include "../../../ShaderVariables.hlsl"
#include "../../../Lighting/Lighting.hlsl" // This include Material.hlsl
#include "../../../Lighting/TilePass/FeatureFlags.hlsl"
//-------------------------------------------------------------------------------------
// variable declaration
//-------------------------------------------------------------------------------------
DECLARE_GBUFFER_TEXTURE(_GBufferTexture);
#ifdef OUTPUT_SPLIT_LIGHTING
RWTexture2D<float4> specularLightingUAV;
RWTexture2D<float3> diffuseLightingUAV;
#else
RWTexture2D<float4> combinedLightingUAV;
#endif
#if USE_INDIRECT
uint g_TileListOffset;
StructuredBuffer<uint> g_TileList;
// Indirect
[numthreads(16, 16, 1)]
void SHADE_OPAQUE_ENTRY(uint2 groupThreadId : SV_GroupThreadID, uint groupId : SV_GroupID)
{
uint tileIndex = g_TileList[g_TileListOffset + groupId];
uint2 tileCoord = uint2(tileIndex & 0xFFFF, tileIndex >> 16);
uint2 pixelCoord = tileCoord * GetTileSize() + groupThreadId;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, tileCoord);
uint featureFlags = TileVariantToFeatureFlags(VARIANT);
#else
// Direct
[numthreads(16, 16, 1)]
void SHADE_OPAQUE_ENTRY(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupId : SV_GroupID)
{
uint2 pixelCoord = dispatchThreadId;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, groupId);
uint featureFlags = 0xFFFFFFFF;
#endif
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).x;
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
FETCH_GBUFFER(gbuffer, _GBufferTexture, posInput.unPositionSS);
BSDFData bsdfData;
float3 bakeDiffuseLighting;
DECODE_FROM_GBUFFER(gbuffer, bsdfData, bakeDiffuseLighting);
PreLightData preLightData = GetPreLightData(V, posInput, bsdfData);
float3 diffuseLighting;
float3 specularLighting;
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, featureFlags, diffuseLighting, specularLighting);
#ifdef OUTPUT_SPLIT_LIGHTING
specularLightingUAV[pixelCoord] = float4(specularLighting, 1.0);
diffuseLightingUAV[pixelCoord] = diffuseLighting;
#else
combinedLightingUAV[pixelCoord] = float4(diffuseLighting + specularLighting, 1.0);
#endif
}

1001
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
文件差异内容过多而无法显示
查看文件

14
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl


#define MAX_NR_BIGTILE_LIGHTS_PLUSONE (512)
#define VIEWPORT_SCALE_Z (1)
#define USE_LEFTHAND_CAMERASPACE (1)
#define TILE_SIZE_FPTL (16)
#define TILE_SIZE_CLUSTERED (32)
#define FEATURE_FLAG_PUNCTUAL_LIGHT (1)
#define FEATURE_FLAG_AREA_LIGHT (2)
#define FEATURE_FLAG_DIRECTIONAL_LIGHT (4)
#define FEATURE_FLAG_ENV_LIGHT (8)
#define FEATURE_FLAG_SKY_LIGHT (16)
#define NUM_FEATURE_VARIANTS (8)
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.TilePass.SFiniteLightBound
// PackingRules = Exact

float3 lightAxisZ;
float cotan;
float3 boxInnerDist;
float unused;
uint featureFlags;
float3 boxInvRange;
float unused2;
};

{
return value.boxInnerDist;
}
float GetUnused(LightVolumeData value)
uint GetFeatureFlags(LightVolumeData value)
return value.unused;
return value.featureFlags;
}
float3 GetBoxInvRange(LightVolumeData value)
{

62
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl


#if defined (LIGHTLOOP_TILE_DIRECT) || defined(LIGHTLOOP_TILE_ALL)
#if defined (LIGHTLOOP_TILE_DIRECT) || defined(LIGHTLOOP_TILE_ALL)
#define PROCESS_DIRECTIONAL_LIGHT
#define PROCESS_PUNCTUAL_LIGHT
#define PROCESS_AREA_LIGHT

#include "TilePass.cs.hlsl"
uint _NumTileX;
uint _NumTileY;
// For FPTL
uint _NumTileFtplX;
uint _NumTileFtplY;
#define TILE_SIZE 16 // This is fixed
#ifdef USE_FPTL_LIGHTLIST
#define TILE_SIZE TILE_SIZE_FPTL
#endif
// Don't do a "#else" so we can catch error if including call don't setup thing correctly
#ifdef USE_CLUSTERED_LIGHTLIST
#define TILE_SIZE TILE_SIZE_CLUSTERED
#endif
#define DWORD_PER_TILE 16 // See dwordsPerTile in TilePass.cs, we have roomm for 31 lights and a number of light value all store on 16 bit (ushort)
// these uniforms are only needed for when OPAQUES_ONLY is NOT defined

//#endif
//#ifdef USE_CLUSTERED_LIGHTLIST
uint _NumTileClusteredX;
uint _NumTileClusteredY;
StructuredBuffer<DirectionalLightData> _DirectionalLightDatas;
StructuredBuffer<LightData> _LightDatas;
StructuredBuffer<EnvLightData> _EnvLightDatas;
StructuredBuffer<ShadowData> _ShadowDatas;
StructuredBuffer<DirectionalLightData> _DirectionalLightDatas;
StructuredBuffer<LightData> _LightDatas;
StructuredBuffer<EnvLightData> _EnvLightDatas;
StructuredBuffer<ShadowData> _ShadowDatas;
// Use texture atlas for shadow map
//TEXTURE2D(_ShadowAtlas);

SAMPLER2D(sampler_CookieTextures);
// Used by point lights
TEXTURECUBE_ARRAY(_CookieCubeTextures);
SAMPLERCUBE(sampler_CookieCubeTextures);
TEXTURECUBE_ARRAY_ABSTRACT(_CookieCubeTextures);
SAMPLERCUBE_ABSTRACT(sampler_CookieCubeTextures);
#ifdef CUBE_ARRAY_NOT_SUPPORTED
TEXTURE2D_ARRAY(_EnvTextures);
SAMPLER2D(sampler_EnvTextures);
#else
TEXTURECUBE_ARRAY(_EnvTextures);
SAMPLERCUBE(sampler_EnvTextures);
#endif
TEXTURECUBE_ARRAY_ABSTRACT(_EnvTextures);
SAMPLERCUBE_ABSTRACT(sampler_EnvTextures);
TEXTURECUBE(_SkyTexture);
SAMPLERCUBE(sampler_SkyTexture); // NOTE: Sampler could be share here with _EnvTextures. Don't know if the shader compiler will complain...

{
int sampleShadow;
int sampleReflection;
#ifdef SHADOWS_USE_SHADOWCTXT
ShadowContext shadowContext;
#endif
#ifndef SHADOWS_USE_SHADOWCTXT
//-----------------------------------------------------------------------------
// Shadow sampling function

// Note: scale and bias of shadow atlas are included in ShadowTransform but could be apply here.
float4 positionTXS = mul(float4(positionWS, 1.0), shadowData.worldToShadow);
positionTXS.xyz /= positionTXS.w;
// positionTXS.z -= shadowData.bias; // Apply a linear bias
positionTXS.z -= 0.001;
// positionTXS.z -= shadowData.bias;
positionTXS.z -= 0.001; // Apply a linear bias
#if UNITY_REVERSED_Z
positionTXS.z = 1.0 - positionTXS.z;

return int(4.0 - dot(weights, float4(4.0, 3.0, 2.0, 1.0)));
}
float GetDirectionalShadowAttenuation(LightLoopContext lightLoopContext, float3 positionWS, int index, float3 L, float2 unPositionSS)
{
// Note Index is 0 for now, but else we need to provide the correct index in _DirShadowSplitSpheres and _ShadowDatas

// Note: scale and bias of shadow atlas are included in ShadowTransform but could be apply here.
float4 positionTXS = mul(float4(positionWS, 1.0), shadowData.worldToShadow);
positionTXS.xyz /= positionTXS.w;
// positionTXS.z -= shadowData.bias; // Apply a linear bias
positionTXS.z -= 0.003;
// positionTXS.z -= shadowData.bias;
positionTXS.z -= 0.003; // Apply a linear bias
#if UNITY_REVERSED_Z
positionTXS.z = 1.0 - positionTXS.z;

return flSum;
}
#endif
//-----------------------------------------------------------------------------
// Cookie sampling functions

// Returns the color in the RGB components, and the transparency (lack of occlusion) in A.
float4 SampleCookieCube(LightLoopContext lightLoopContext, float3 coord, int index)
{
return SAMPLE_TEXTURECUBE_ARRAY_LOD(_CookieCubeTextures, sampler_CookieCubeTextures, coord, index, 0);
return SAMPLE_TEXTURECUBE_ARRAY_LOD_ABSTRACT(_CookieCubeTextures, sampler_CookieCubeTextures, coord, index, 0);
}
//-----------------------------------------------------------------------------

// This code will be inlined as lightLoopContext is hardcoded in the light loop
if (lightLoopContext.sampleReflection == SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES)
{
#ifdef CUBE_ARRAY_NOT_SUPPORTED
return SAMPLE_TEXTURE2D_ARRAY_LOD(_EnvTextures, sampler_EnvTextures, DirectionToLatLongCoordinate(texCoord), index, lod);
#else
return SAMPLE_TEXTURECUBE_ARRAY_LOD(_EnvTextures, sampler_EnvTextures, texCoord, index, lod);
#endif
return SAMPLE_TEXTURECUBE_ARRAY_LOD_ABSTRACT(_EnvTextures, sampler_EnvTextures, texCoord, index, lod);
}
else // SINGLE_PASS_SAMPLE_SKY
{

700
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


//-----------------------------------------------------------------------------
// LightLoop
// ----------------------------------------------------------------------------
void ApplyDebug(inout float3 diffuseLighting, inout float3 specularLighting)
{
#ifdef LIGHTING_DEBUG
int lightDebugMode = (int)_DebugLightModeAndAlbedo.x;
if (lightDebugMode == LIGHTINGDEBUGMODE_DIFFUSE_LIGHTING)
{
specularLighting = float3(0.0, 0.0, 0.0);
}
else if (lightDebugMode == LIGHTINGDEBUGMODE_SPECULAR_LIGHTING)
{
diffuseLighting = float3(0.0, 0.0, 0.0);
}
#endif
}
#ifdef LIGHTLOOP_TILE_PASS
// Calculate the offset in global light index light for current light category
int GetTileOffset(PositionInputs posInput, uint lightCategory)
{
uint2 tileIndex = posInput.unPositionSS / TILE_SIZE;
return (tileIndex.y + lightCategory * _NumTileY) * _NumTileX + tileIndex.x;
}
void GetCountAndStartTile(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
const int tileOffset = GetTileOffset(posInput, lightCategory);
// The first entry inside a tile is the number of light for lightCategory (thus the +0)
lightCount = g_vLightListGlobal[DWORD_PER_TILE * tileOffset + 0] & 0xffff;
start = tileOffset;
}
uint FetchIndexTile(uint tileOffset, uint lightIndex)
{
const uint lightIndexPlusOne = lightIndex + 1; // Add +1 as first slot is reserved to store number of light
// Light index are store on 16bit
return (g_vLightListGlobal[DWORD_PER_TILE * tileOffset + (lightIndexPlusOne >> 1)] >> ((lightIndexPlusOne & 1) * DWORD_PER_TILE)) & 0xffff;
}
#ifdef USE_FPTL_LIGHTLIST
void GetCountAndStart(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
GetCountAndStartTile(posInput, lightCategory, start, lightCount);
}
uint FetchIndex(uint tileOffset, uint lightIndex)
{
return FetchIndexTile(tileOffset, lightIndex);
}
#elif defined(USE_CLUSTERED_LIGHTLIST)
#include "ClusteredUtils.hlsl"
void GetCountAndStartCluster(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
uint2 tileIndex = posInput.unPositionSS / TILE_SIZE;
float logBase = g_fClustBase;
if (g_isLogBaseBufferEnabled)
{
logBase = g_logBaseBuffer[tileIndex.y * _NumTileX + tileIndex.x];
}
int clustIdx = SnapToClusterIdxFlex(posInput.depthVS, logBase, g_isLogBaseBufferEnabled != 0);
int nrClusters = (1 << g_iLog2NumClusters);
const int idx = ((lightCategory * nrClusters + clustIdx) * _NumTileY + tileIndex.y) * _NumTileX + tileIndex.x;
uint dataPair = g_vLayeredOffsetsBuffer[idx];
start = dataPair & 0x7ffffff;
lightCount = (dataPair >> 27) & 31;
}
uint FetchIndexCluster(uint tileOffset, uint lightIndex)
{
return g_vLightListGlobal[tileOffset + lightIndex];
}
void GetCountAndStart(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
if (_UseTileLightList)
GetCountAndStartTile(posInput, lightCategory, start, lightCount);
else
GetCountAndStartCluster(posInput, lightCategory, start, lightCount);
}
uint FetchIndex(uint tileOffset, uint lightIndex)
{
if (_UseTileLightList)
return FetchIndexTile(tileOffset, lightIndex);
else
return FetchIndexCluster(tileOffset, lightIndex);
}
#endif
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
void LightLoop( float3 V, PositionInputs posInput, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
out float3 diffuseLighting,
out float3 specularLighting)
{
LightLoopContext context;
ZERO_INITIALIZE(LightLoopContext, context);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
#ifdef PROCESS_DIRECTIONAL_LIGHT
for (i = 0; i < _DirectionalLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional( context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
#endif
#ifdef PROCESS_PUNCTUAL_LIGHT
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
uint punctualLightStart;
uint punctualLightCount;
GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, punctualLightStart, punctualLightCount);
for (i = 0; i < punctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Punctual( context, V, posInput, prelightData, _LightDatas[FetchIndex(punctualLightStart, i)], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
#endif
#ifdef PROCESS_AREA_LIGHT
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
uint areaLightStart;
uint areaLightCount;
GetCountAndStart(posInput, LIGHTCATEGORY_AREA, areaLightStart, areaLightCount);
for (i = 0; i < areaLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
uint areaIndex = FetchIndex(areaLightStart, i);
if(_LightDatas[areaIndex].lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
else
{
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
#endif
#ifdef PROCESS_ENV_LIGHT
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
// Only apply sky IBL if the sky texture is available.
if (_EnvLightSkyEnabled)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
EvaluateBSDF_Env(context, V, posInput, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
uint envLightStart;
uint envLightCount;
GetCountAndStart(posInput, LIGHTCATEGORY_ENV, envLightStart, envLightCount);
for (i = 0; i < envLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
EvaluateBSDF_Env(context, V, posInput, prelightData, _EnvLightDatas[FetchIndex(envLightStart, i)], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
diffuseLighting += iblDiffuseLighting;
specularLighting += iblSpecularLighting;
#endif
// TODO: currently apply GI at the same time as reflection
#ifdef PROCESS_ENV_LIGHT
// Add indirect diffuse + emissive (if any)
diffuseLighting += bakeDiffuseLighting;
#endif
ApplyDebug(diffuseLighting, specularLighting);
}
#else // LIGHTLOOP_SINGLE_PASS
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
void LightLoop( float3 V, PositionInputs posInput, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
out float3 diffuseLighting,
out float3 specularLighting)
{
LightLoopContext context;
ZERO_INITIALIZE(LightLoopContext, context);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
for (i = 0; i < _DirectionalLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional( context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
for (i = 0; i < _PunctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Punctual( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
// Area are store with punctual, just offset the index
for (i = _PunctualLightCount; i < _AreaLightCount + _PunctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
if (_LightDatas[i].lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
else
{
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
// TODO: Check the reflection hierarchy, for the current system (matching legacy unity) we must sort from bigger solid angle to lower (lower override bigger). So begging by sky
// TODO: Change the way it is done by reversing the order, from smaller solid angle to bigger, so we can early out when the weight is 1.
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
// Only apply sky IBL if the sky texture is available.
if (_EnvLightSkyEnabled)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
EvaluateBSDF_Env(context, V, posInput, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
for (i = 0; i < _EnvLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
EvaluateBSDF_Env(context, V, posInput, prelightData, _EnvLightDatas[i], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
diffuseLighting += iblDiffuseLighting;
specularLighting += iblSpecularLighting;
// Add indirect diffuse + emissive (if any)
diffuseLighting += bakeDiffuseLighting;
ApplyDebug(diffuseLighting, specularLighting);
}
#endif
//-----------------------------------------------------------------------------
// LightLoop
// ----------------------------------------------------------------------------
void ApplyDebug(LightLoopContext lightLoopContext, float3 positionWS, inout float3 diffuseLighting, inout float3 specularLighting)
{
#ifdef LIGHTING_DEBUG
int lightDebugMode = (int)_DebugLightModeAndAlbedo.x;
if (lightDebugMode == LIGHTINGDEBUGMODE_DIFFUSE_LIGHTING)
{
specularLighting = float3(0.0, 0.0, 0.0);
}
else if (lightDebugMode == LIGHTINGDEBUGMODE_SPECULAR_LIGHTING)
{
diffuseLighting = float3(0.0, 0.0, 0.0);
}
else if (lightDebugMode == LIGHTINGDEBUGMODE_VISUALIZE_CASCADE)
{
specularLighting = float3(0.0, 0.0, 0.0);
const float3 s_CascadeColors[] = {
float3(1.0, 0.0, 0.0),
float3(0.0, 1.0, 0.0),
float3(0.0, 0.0, 1.0),
float3(1.0, 1.0, 0.0)
};
#ifdef SHADOWS_USE_SHADOWCTXT
float shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, 0, float3(0.0, 0.0, 0.0), float2(0.0, 0.0));
#else
float shadow = GetDirectionalShadowAttenuation(lightLoopContext, positionWS, 0, float3(0.0, 0.0, 0.0), float2(0.0, 0.0));
#endif
int shadowSplitIndex = GetSplitSphereIndexForDirshadows(positionWS, _DirShadowSplitSpheres);
if (shadowSplitIndex == -1)
diffuseLighting = float3(0.0, 0.0, 0.0);
else
{
diffuseLighting = s_CascadeColors[shadowSplitIndex] * shadow;
}
}
#endif
}
#ifdef LIGHTLOOP_TILE_PASS
// Calculate the offset in global light index light for current light category
int GetTileOffset(PositionInputs posInput, uint lightCategory)
{
uint2 tileIndex = posInput.unTileCoord;
return (tileIndex.y + lightCategory * _NumTileFtplY) * _NumTileFtplX + tileIndex.x;
}
void GetCountAndStartTile(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
const int tileOffset = GetTileOffset(posInput, lightCategory);
// The first entry inside a tile is the number of light for lightCategory (thus the +0)
lightCount = g_vLightListGlobal[DWORD_PER_TILE * tileOffset + 0] & 0xffff;
start = tileOffset;
}
uint FetchIndexTile(uint tileOffset, uint lightIndex)
{
const uint lightIndexPlusOne = lightIndex + 1; // Add +1 as first slot is reserved to store number of light
// Light index are store on 16bit
return (g_vLightListGlobal[DWORD_PER_TILE * tileOffset + (lightIndexPlusOne >> 1)] >> ((lightIndexPlusOne & 1) * DWORD_PER_TILE)) & 0xffff;
}
#ifdef USE_FPTL_LIGHTLIST
uint GetTileSize()
{
return TILE_SIZE_FPTL;
}
void GetCountAndStart(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
GetCountAndStartTile(posInput, lightCategory, start, lightCount);
}
uint FetchIndex(uint tileOffset, uint lightIndex)
{
return FetchIndexTile(tileOffset, lightIndex);
}
#elif defined(USE_CLUSTERED_LIGHTLIST)
#include "ClusteredUtils.hlsl"
uint GetTileSize()
{
return TILE_SIZE_CLUSTERED;
}
void GetCountAndStartCluster(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
uint2 tileIndex = posInput.unTileCoord;
float logBase = g_fClustBase;
if (g_isLogBaseBufferEnabled)
{
logBase = g_logBaseBuffer[tileIndex.y * _NumTileClusteredX + tileIndex.x];
}
int clustIdx = SnapToClusterIdxFlex(posInput.depthVS, logBase, g_isLogBaseBufferEnabled != 0);
int nrClusters = (1 << g_iLog2NumClusters);
const int idx = ((lightCategory * nrClusters + clustIdx) * _NumTileClusteredY + tileIndex.y) * _NumTileClusteredX + tileIndex.x;
uint dataPair = g_vLayeredOffsetsBuffer[idx];
start = dataPair & 0x7ffffff;
lightCount = (dataPair >> 27) & 31;
}
uint FetchIndexCluster(uint tileOffset, uint lightIndex)
{
return g_vLightListGlobal[tileOffset + lightIndex];
}
void GetCountAndStart(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
{
if (_UseTileLightList)
GetCountAndStartTile(posInput, lightCategory, start, lightCount);
else
GetCountAndStartCluster(posInput, lightCategory, start, lightCount);
}
uint FetchIndex(uint tileOffset, uint lightIndex)
{
if (_UseTileLightList)
return FetchIndexTile(tileOffset, lightIndex);
else
return FetchIndexCluster(tileOffset, lightIndex);
}
#endif
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
void LightLoop( float3 V, PositionInputs posInput, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting, uint featureFlags,
out float3 diffuseLighting,
out float3 specularLighting)
{
LightLoopContext context;
#ifndef SHADOWS_USE_SHADOWCTXT
ZERO_INITIALIZE(LightLoopContext, context);
#else
context.sampleShadow = 0;
context.sampleReflection = 0;
context.shadowContext = InitShadowContext();
#endif
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
#ifdef PROCESS_DIRECTIONAL_LIGHT
if(featureFlags & FEATURE_FLAG_DIRECTIONAL_LIGHT)
{
for(i = 0; i < _DirectionalLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional(context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
}
#endif
#ifdef PROCESS_PUNCTUAL_LIGHT
if(featureFlags & FEATURE_FLAG_PUNCTUAL_LIGHT)
{
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
uint punctualLightStart;
uint punctualLightCount;
GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, punctualLightStart, punctualLightCount);
for(i = 0; i < punctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Punctual(context, V, posInput, prelightData, _LightDatas[FetchIndex(punctualLightStart, i)], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
}
#endif
#ifdef PROCESS_AREA_LIGHT
if(featureFlags & FEATURE_FLAG_AREA_LIGHT)
{
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
uint areaLightStart;
uint areaLightCount;
GetCountAndStart(posInput, LIGHTCATEGORY_AREA, areaLightStart, areaLightCount);
for(i = 0; i < areaLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
uint areaIndex = FetchIndex(areaLightStart, i);
if(_LightDatas[areaIndex].lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line(context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
else
{
EvaluateBSDF_Area(context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
}
#endif
#ifdef PROCESS_ENV_LIGHT
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
// Only apply sky IBL if the sky texture is available.
if(featureFlags & FEATURE_FLAG_SKY_LIGHT)
{
if(_EnvLightSkyEnabled)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
EvaluateBSDF_Env(context, V, posInput, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
}
if(featureFlags & FEATURE_FLAG_ENV_LIGHT)
{
uint envLightStart;
uint envLightCount;
GetCountAndStart(posInput, LIGHTCATEGORY_ENV, envLightStart, envLightCount);
for(i = 0; i < envLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
EvaluateBSDF_Env(context, V, posInput, prelightData, _EnvLightDatas[FetchIndex(envLightStart, i)], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
}
diffuseLighting += iblDiffuseLighting;
specularLighting += iblSpecularLighting;
#endif
// TODO: currently apply GI at the same time as reflection
#ifdef PROCESS_ENV_LIGHT
// Add indirect diffuse + emissive (if any)
diffuseLighting += bakeDiffuseLighting;
#endif
ApplyDebug(context, posInput.positionWS, diffuseLighting, specularLighting);
}
#else // LIGHTLOOP_SINGLE_PASS
uint GetTileSize()
{
return 1;
}
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
void LightLoop( float3 V, PositionInputs posInput, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting, uint featureFlag,
out float3 diffuseLighting,
out float3 specularLighting)
{
LightLoopContext context;
#ifndef SHADOWS_USE_SHADOWCTXT
ZERO_INITIALIZE(LightLoopContext, context);
#else
context.sampleShadow = 0;
context.sampleReflection = 0;
context.shadowContext = InitShadowContext();
#endif
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
for (i = 0; i < _DirectionalLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional( context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
for (i = 0; i < _PunctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Punctual( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
// Area are store with punctual, just offset the index
for (i = _PunctualLightCount; i < _AreaLightCount + _PunctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
if (_LightDatas[i].lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
else
{
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
// TODO: Check the reflection hierarchy, for the current system (matching legacy unity) we must sort from bigger solid angle to lower (lower override bigger). So begging by sky
// TODO: Change the way it is done by reversing the order, from smaller solid angle to bigger, so we can early out when the weight is 1.
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
// Only apply sky IBL if the sky texture is available.
if (_EnvLightSkyEnabled)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
EvaluateBSDF_Env(context, V, posInput, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
for (i = 0; i < _EnvLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
EvaluateBSDF_Env(context, V, posInput, prelightData, _EnvLightDatas[i], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
diffuseLighting += iblDiffuseLighting;
specularLighting += iblSpecularLighting;
// Add indirect diffuse + emissive (if any)
diffuseLighting += bakeDiffuseLighting;
ApplyDebug(context, posInput.positionWS, diffuseLighting, specularLighting);
}
#endif

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassProducer.asset


m_Name: TilePassProducer
m_EditorClassIdentifier:
m_TileSettings:
enableDrawLightBoundsDebug: 0
disableTileAndCluster: 0
disableDeferredShadingInCompute: 1
enableTileAndCluster: 1
disableFptlWhenClustered: 0
enableFptlForOpaqueWhenClustered: 1
diffuseGlobalDimmer: 1
specularGlobalDimmer: 1
m_PassResources: {fileID: 11400000, guid: 7f2998544b2ac3848822b80ec3e6c446, type: 2}

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassProducer.asset.meta


fileFormatVersion: 2
guid: bf8cd9ae03ff7d54c89603e67be0bfc5
timeCreated: 1485857933
timeCreated: 1486997442
licenseType: Pro
NativeFormatImporter:
mainObjectFileID: 11400000

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassResources.asset


type: 3}
buildPerVoxelLightListShader: {fileID: 7200000, guid: 0bb1b7e0ddcd5c44baf3ddc7456eb196,
type: 3}
clearDispatchIndirectShader: {fileID: 7200000, guid: fc1f553acb80a6446a32d33e403d0656,
type: 3}
shadeOpaqueShader: {fileID: 7200000, guid: 0b64f79746d2daf4198eaf6eab9af259, type: 3}
m_DebugViewMaterialGBuffer: {fileID: 4800000, guid: 439949ea1bfa91b4ba0d04269fcde33d,
type: 3}

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassResources.cs


public ComputeShader buildPerTileLightListShader = null; // FPTL
public ComputeShader buildPerBigTileLightListShader = null;
public ComputeShader buildPerVoxelLightListShader = null; // clustered
public ComputeShader clearDispatchIndirectShader = null;
public ComputeShader shadeOpaqueShader = null;
// Various set of material use in render loop

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material.meta


fileFormatVersion: 2
guid: 96af336cb096f854ea18990a1c0a4e19
guid: 49844bc6823848a4087668ebd3367436
folderAsset: yes
timeCreated: 1474297943
licenseType: Pro

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Builtin/BuiltinData.hlsl


//TODO: return this original relative path include after fixing a bug in Unity side
//#include "BuiltinData.cs.hlsl"
#include "HDRenderPipeline/Material/Builtin/BuiltinData.cs.hlsl"
#include "../../Material/Builtin/BuiltinData.cs.hlsl"
//-----------------------------------------------------------------------------
// common Encode/Decode functions

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit.meta


fileFormatVersion: 2
guid: e173dfe6cd75d954b95306237244f6de
guid: c526d3e6d7f3ce1408308bb431089d2d
folderAsset: yes
timeCreated: 1476653183
licenseType: Pro

296
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs


Material[] m_MaterialLayers = new Material[kMaxLayerCount];
// Layer options
MaterialProperty layerCount = null;
const string kLayerCount = "_LayerCount";
MaterialProperty layerCount = null;
const string kLayerCount = "_LayerCount";
MaterialProperty[] layerTexWorldScale = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVBase = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVMappingMask = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVMappingPlanar = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVDetail = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVDetailsMappingMask = new MaterialProperty[kMaxLayerCount];
MaterialProperty objectScaleAffectTile = null;
MaterialProperty objectScaleAffectTile = null;
MaterialProperty UVBlendMask = null;
MaterialProperty UVBlendMask = null;
const string kUVMappingPlanarBlendMask = "_UVMappingPlanarBlendMask";
MaterialProperty UVMappingPlanarBlendMask = null;
MaterialProperty layerTilingBlendMask = null;
MaterialProperty layerTilingBlendMask = null;
MaterialProperty texWorldScaleBlendMask = null;
MaterialProperty texWorldScaleBlendMask = null;
const string kLayerTiling = "_LayerTiling";
MaterialProperty[] layerTiling = new MaterialProperty[kMaxLayerCount];
MaterialProperty useMainLayerInfluence = null;
MaterialProperty useMainLayerInfluence = null;
const string kUseHeightBasedBlend = "_UseHeightBasedBlend";
const string kUseHeightBasedBlend = "_UseHeightBasedBlend";
const string kUseDensityMode = "_UseDensityMode";
MaterialProperty useDensityMode = null;
// Properties for multiple layers inherit from referenced lit materials
MaterialProperty[] layerTexWorldScale = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVBase = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVMappingMask = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVDetail = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVDetailsMappingMask = new MaterialProperty[kMaxLayerCount];
// This one is specific to layer lit
MaterialProperty[] layerTiling = new MaterialProperty[kMaxLayerCount];
const string kLayerTiling = "_LayerTiling";
const string kOpacityAsDensity = "_OpacityAsDensity";
// Density/opacity mode
MaterialProperty useDensityMode = null;
const string kUseDensityMode = "_UseDensityMode";
const string kOpacityAsDensity = "_OpacityAsDensity";
MaterialProperty[] minimumOpacity = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] minimumOpacity = new MaterialProperty[kMaxLayerCount];
// HeightmapMode control
MaterialProperty[] heightFactor = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] heightFactor = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] heightCenterOffset = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] heightCenterOffset = new MaterialProperty[kMaxLayerCount];
const string kLayerHeightAmplitude = "_LayerHeightAmplitude";
const string kLayerHeightAmplitude = "_LayerHeightAmplitude";
MaterialProperty[] layerCenterOffset = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerCenterOffset = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] blendUsingHeight = new MaterialProperty[kMaxLayerCount - 1]; // Only in case of influence mode
MaterialProperty[] blendUsingHeight = new MaterialProperty[kMaxLayerCount - 1];
// influence
// Influence
MaterialProperty[] inheritBaseNormal = new MaterialProperty[kMaxLayerCount - 1];
MaterialProperty[] inheritBaseNormal = new MaterialProperty[kMaxLayerCount - 1];
const string kInheritBaseHeight = "_InheritBaseHeight";
const string kInheritBaseColor = "_InheritBaseColor";
const string kInheritBaseHeight = "_InheritBaseHeight";
const string kInheritBaseColorThreshold = "_InheritBaseColorThreshold";
const string kInheritBaseColor = "_InheritBaseColor";
const string kInheritBaseColorThreshold = "_InheritBaseColorThreshold";
MaterialProperty layerEmissiveColor = null;
MaterialProperty layerEmissiveColorMap = null;
MaterialProperty layerEmissiveIntensity = null;
override protected void FindMaterialProperties(MaterialProperty[] props)
protected override void FindMaterialProperties(MaterialProperty[] props)
layerMaskMap = FindProperty(kLayerMaskMap, props);
// Inherit from LitUI
horizonFade = FindProperty(kHorizonFade, props);
layerMaskMap = FindProperty(kLayerMaskMap, props);
objectScaleAffectTile = FindProperty(kObjectScaleAffectTile, props);
UVBlendMask = FindProperty(kUVBlendMask, props);
layerTilingBlendMask = FindProperty(kLayerTilingBlendMask, props);
texWorldScaleBlendMask = FindProperty(kTexWorldScaleBlendMask, props);
objectScaleAffectTile = FindProperty(kObjectScaleAffectTile, props);
UVBlendMask = FindProperty(kUVBlendMask, props);
UVMappingPlanarBlendMask = FindProperty(kUVMappingPlanarBlendMask, props);
layerTilingBlendMask = FindProperty(kLayerTilingBlendMask, props);
texWorldScaleBlendMask = FindProperty(kTexWorldScaleBlendMask, props);
layerUVMappingPlanar[i] = FindProperty(string.Format("{0}{1}", kUVMappingPlanar, i), props);
// Density/opacity mode
opacityAsDensity[i] = FindProperty(string.Format("{0}{1}", kOpacityAsDensity, i), props);
opacityAsDensity[i] = FindProperty(string.Format("{0}{1}", kOpacityAsDensity, i), props);
// HeightmapMode control
heightFactor[i] = FindProperty(string.Format("{0}{1}", kHeightFactor, i), props);
heightCenterOffset[i] = FindProperty(string.Format("{0}{1}", kHeightCenterOffset, i), props);
layerHeightAmplitude[i] = FindProperty(string.Format("{0}{1}", kLayerHeightAmplitude, i), props);

{
blendUsingHeight[i - 1] = FindProperty(string.Format("{0}{1}", kBlendUsingHeight, i), props);
// Influence
inheritBaseNormal[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseNormal, i), props);
inheritBaseHeight[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseHeight, i), props);
inheritBaseColor[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseColor, i), props);

layerEmissiveColor = FindProperty(kEmissiveColor, props);
layerEmissiveColorMap = FindProperty(kEmissiveColorMap, props);
layerEmissiveIntensity = FindProperty(kEmissiveIntensity, props);
// Reuse property from LitUI.cs
emissiveColor = FindProperty(kEmissiveColor, props);
emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty(kEmissiveIntensity, props);
}
int numLayer

}
// This function is call by a script to help artists to ahve up to date material
// that why it is static
int layerCount = (int)material.GetFloat("_LayerCount");
int layerCount = (int)material.GetFloat(kLayerCount);
for (int i = 0 ; i < layerCount ; ++i)
// We could have no userData in the assets, so test if we have load something
if (layers != null)
SynchronizeLayerProperties(material, layers, i);
for (int i = 0; i < layerCount; ++i)
{
SynchronizeLayerProperties(material, layers, i);
}
}
}

// put the name in the exclusionList below
static void SynchronizeLayerProperties(Material material, Material[] layers, int layerIndex)
{
string[] exclusionList = { kTexWorldScale, kUVBase, kUVMappingMask, kUVMappingPlanar, kUVDetail, kUVDetailsMappingMask };
string[] exclusionList = { kTexWorldScale, kUVBase, kUVMappingMask, kUVDetail, kUVDetailsMappingMask };
Material layerMaterial = layers[layerIndex];

}
}
// We setup the masking map based on the enum for each layer.
// using mapping mask allow to reduce the number of generated combination for a very small increase in ALU
LayerUVBaseMapping layerUVBaseMapping = (LayerUVBaseMapping)layerUVBase[layerIndex].floatValue;
float X, Y, Z, W;
X = (layerUVBaseMapping == LayerUVBaseMapping.UV0) ? 1.0f : 0.0f;
Y = (layerUVBaseMapping == LayerUVBaseMapping.UV1) ? 1.0f : 0.0f;
Z = (layerUVBaseMapping == LayerUVBaseMapping.UV2) ? 1.0f : 0.0f;
W = (layerUVBaseMapping == LayerUVBaseMapping.UV3) ? 1.0f : 0.0f;
layerUVMappingMask[layerIndex].colorValue = (layerIndex == 0) ? new Color(1.0f, 0.0f, 0.0f, 0.0f) : new Color(X, Y, Z, W); // Special case for Main Layer and Blend Mask, only UV0. As Layer0 is share by both here, need to force X to 1.0 in all case
UVDetailMapping layerUVDetailMapping = (UVDetailMapping)layerUVDetail[layerIndex].floatValue;
X = (layerUVDetailMapping == UVDetailMapping.UV0) ? 1.0f : 0.0f;
Y = (layerUVDetailMapping == UVDetailMapping.UV1) ? 1.0f : 0.0f;
Z = (layerUVDetailMapping == UVDetailMapping.UV2) ? 1.0f : 0.0f;
W = (layerUVDetailMapping == UVDetailMapping.UV3) ? 1.0f : 0.0f;
layerUVDetailsMappingMask[layerIndex].colorValue = new Color(X, Y, Z, W);
bool useDensityModeEnable = useDensityMode.floatValue != 0.0f;
if (useDensityModeEnable)
{

useHeightBasedBlend.floatValue = enabled ? 1.0f : 0.0f;
}
m_MaterialEditor.ShaderProperty(objectScaleAffectTile, mainLayerModeInfluenceEnable ? styles.objectScaleAffectTileText2 : styles.objectScaleAffectTileText);
m_MaterialEditor.ShaderProperty(objectScaleAffectTile, mainLayerModeInfluenceEnable ? styles.objectScaleAffectTileText2 : styles.objectScaleAffectTileText);
m_MaterialEditor.ShaderProperty(horizonFade, Styles.horizonFadeText);
EditorGUILayout.Space();

return layerChanged;
}
protected override void SetupMaterialKeywords(Material material)
protected override bool ShouldEmissionBeEnabled(Material mat)
SetupCommonOptionsKeywords(material);
SetupLayersMappingKeywords(material);
for (int i = 0; i < kMaxLayerCount; ++i)
{
SetKeyword(material, "_NORMALMAP_TANGENT_SPACE" + i, ((NormalMapSpace)material.GetFloat(kNormalMapSpace + i)) == NormalMapSpace.TangentSpace);
SetKeyword(material, "_NORMALMAP" + i, material.GetTexture(kNormalMap + i));
SetKeyword(material, "_MASKMAP" + i, material.GetTexture(kMaskMap + i));
SetKeyword(material, "_SPECULAROCCLUSIONMAP" + i, material.GetTexture(kSpecularOcclusionMap + i));
SetKeyword(material, "_DETAIL_MAP" + i, material.GetTexture(kDetailMap + i));
SetKeyword(material, "_HEIGHTMAP0" + i, material.GetTexture(kHeightMap + i));
}
bool perPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) == 1.0;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", perPixelDisplacement);
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_MAIN_LAYER_INFLUENCE_MODE", material.GetFloat(kkUseMainLayerInfluence) != 0.0f);
VertexColorMode VCMode = (VertexColorMode)vertexColorMode.floatValue;
if (VCMode == VertexColorMode.Multiply)
{
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", true);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", false);
}
else if (VCMode == VertexColorMode.Add)
{
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", false);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", true);
}
else
{
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", false);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", false);
}
return mat.GetFloat(kEmissiveIntensity) > 0.0f;
}
bool useHeightBasedBlend = material.GetFloat(kUseHeightBasedBlend) != 0.0f;
SetKeyword(material, "_HEIGHT_BASED_BLEND", useHeightBasedBlend);
bool useDensityModeEnable = material.GetFloat(kUseDensityMode) != 0.0f;
SetKeyword(material, "_DENSITY_MODE", useDensityModeEnable);
protected override void SetupMaterialKeywordsAndPassInternal(Material material)
{
SetupMaterialKeywordsAndPass(material);
void SetupLayersMappingKeywords(Material material)
static public void SetupLayersMappingKeywords(Material material)
SetKeyword(material, "_LAYER_TILING_UNIFORM_SCALE", material.GetFloat(kObjectScaleAffectTile) > 0.0f);
SetKeyword(material, "_LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE", material.GetFloat(kObjectScaleAffectTile) > 0.0f);
UVMappingPlanarBlendMask.floatValue = (UVBlendMaskMapping == LayerUVBaseMapping.Planar) ? 1.0f : 0.0f;
SetKeyword(material, "_LAYER_MAPPING_PLANAR_BLENDMASK", UVBlendMaskMapping == LayerUVBaseMapping.Planar);
int numLayer = (int)material.GetFloat(kLayerCount);
// Layer
if (numLayer == 4)
{

SetKeyword(material, "_LAYEREDLIT_3_LAYERS", false);
}
const string kLayerMappingPlanar = "_LAYER_MAPPING_PLANAR";
const string kLayerMappingTriplanar = "_LAYER_MAPPING_TRIPLANAR";
// We have to check for each layer if the UV2 or UV3 is needed.

for (int i = 0 ; i < numLayer; ++i)
{
// We setup the masking map based on the enum for each layer.
// using mapping mask allow to reduce the number of generated combination for a very small increase in ALU
string layerUVDetailParam = string.Format("{0}{1}", kUVDetail, i);
UVDetailMapping layerUVDetailMapping = (UVDetailMapping)material.GetFloat(layerUVDetailParam);
string currentLayerMappingPlanar = string.Format("{0}{1}", kLayerMappingPlanar, i);
SetKeyword(material, currentLayerMappingPlanar, layerUVBaseMapping == LayerUVBaseMapping.Planar);
float X, Y, Z, W;
X = (layerUVBaseMapping == LayerUVBaseMapping.UV0) ? 1.0f : 0.0f;
Y = (layerUVBaseMapping == LayerUVBaseMapping.UV1) ? 1.0f : 0.0f;
Z = (layerUVBaseMapping == LayerUVBaseMapping.UV2) ? 1.0f : 0.0f;
W = (layerUVBaseMapping == LayerUVBaseMapping.UV3) ? 1.0f : 0.0f;
layerUVMappingMask[i].colorValue = (i == 0) ? new Color(1.0f, 0.0f, 0.0f, 0.0f) : new Color(X, Y, Z, W); // Special case for Main Layer and Blend Mask, only UV0. As Layer0 is share by both here, need to force X to 1.0 in all case
layerUVMappingPlanar[i].floatValue = (layerUVBaseMapping == LayerUVBaseMapping.Planar) ? 1.0f : 0.0f; // Planar have priority on UV0
X = (layerUVDetailMapping == UVDetailMapping.UV0) ? 1.0f : 0.0f;
Y = (layerUVDetailMapping == UVDetailMapping.UV1) ? 1.0f : 0.0f;
Z = (layerUVDetailMapping == UVDetailMapping.UV2) ? 1.0f : 0.0f;
W = (layerUVDetailMapping == UVDetailMapping.UV3) ? 1.0f : 0.0f;
layerUVDetailsMappingMask[i].colorValue = new Color(X, Y, Z, W);
string uvBase = string.Format("{0}{1}", kUVBase, i);
string uvDetail = string.Format("{0}{1}", kUVDetail, i);

}
}
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change
static new public void SetupMaterialKeywordsAndPass(Material material)
{
SetupBaseLitKeywords(material);
SetupBaseLitMaterialPass(material);
SetupLayersMappingKeywords(material);
for (int i = 0; i < kMaxLayerCount; ++i)
{
SetKeyword(material, "_NORMALMAP_TANGENT_SPACE" + i, ((NormalMapSpace)material.GetFloat(kNormalMapSpace + i)) == NormalMapSpace.TangentSpace);
SetKeyword(material, "_NORMALMAP" + i, material.GetTexture(kNormalMap + i));
SetKeyword(material, "_MASKMAP" + i, material.GetTexture(kMaskMap + i));
SetKeyword(material, "_SPECULAROCCLUSIONMAP" + i, material.GetTexture(kSpecularOcclusionMap + i));
SetKeyword(material, "_DETAIL_MAP" + i, material.GetTexture(kDetailMap + i));
SetKeyword(material, "_HEIGHTMAP" + i, material.GetTexture(kHeightMap + i));
}
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_MAIN_LAYER_INFLUENCE_MODE", material.GetFloat(kkUseMainLayerInfluence) != 0.0f);
VertexColorMode VCMode = (VertexColorMode)material.GetFloat(kVertexColorMode);
if (VCMode == VertexColorMode.Multiply)
{
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", true);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", false);
}
else if (VCMode == VertexColorMode.Add)
{
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", false);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", true);
}
else
{
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", false);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", false);
}
bool useHeightBasedBlend = material.GetFloat(kUseHeightBasedBlend) != 0.0f;
SetKeyword(material, "_HEIGHT_BASED_BLEND", useHeightBasedBlend);
bool useDensityModeEnable = material.GetFloat(kUseDensityMode) != 0.0f;
SetKeyword(material, "_DENSITY_MODE", useDensityModeEnable);
}
FindCommonOptionProperties(props);
FindBaseMaterialProperties(props);
// We should always do this call at the beginning
m_MaterialEditor.serializedObject.Update();
Material material = m_MaterialEditor.target as Material;

bool optionsChanged = false;
EditorGUI.BeginChangeCheck();
{
ShaderOptionsGUI();
BaseMaterialPropertiesGUI();
EditorGUILayout.Space();
}
if (EditorGUI.EndChangeCheck())

EditorGUILayout.Space();
GUILayout.Label(Styles.lightingText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, layerEmissiveColorMap, layerEmissiveColor);
m_MaterialEditor.ShaderProperty(layerEmissiveIntensity, Styles.emissiveIntensityText);
m_MaterialEditor.LightmapEmissionProperty(1);
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
DoEmissionArea(material);
m_MaterialEditor.EnableInstancingField();
SetupMaterialKeywords((Material)obj);
SetupMaterialKeywordsAndPassInternal((Material)obj);
// SaveAssetsProcessor the referenced material in the users data
// We should always do this call at the end
m_MaterialEditor.serializedObject.ApplyModifiedProperties();
}
}

79
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader


[ToggleOff] _ObjectScaleAffectTile("_ObjectScaleAffectTile", Float) = 0.0
[Enum(UV0, 0, Planar, 4, Triplanar, 5)] _UVBlendMask("UV Set for blendMask", Float) = 0
[HideInInspector] _UVMappingPlanarBlendMask("_UVMappingPlanarBlendMask", Float) = 0.0
_TexWorldScaleBlendMask("Tiling", Float) = 1.0
// Following are builtin properties

_HorizonFade("Horizon fade", Range(0.0, 5.0)) = 1.0
// Stencil state
[HideInInspector] _StencilRef("_StencilRef", Int) = 2 // StencilBits.Standard
// Blending state
[HideInInspector] _SurfaceType("__surfacetype", Float) = 0.0
[HideInInspector] _BlendMode ("__blendmode", Float) = 0.0

[HideInInspector] _ZTestMode("_ZTestMode", Int) = 8
[ToggleOff] _DoubleSidedEnable("Double sided enable", Float) = 0.0
[ToggleOff] _DoubleSidedMirrorEnable("Double sided mirror enable", Float) = 1.0
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5

// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.
// 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
_EmissionColor("Color", Color) = (1, 1, 1)
// WARNING
// All the following properties that concern the UV mapping are the same as in the Lit shader.
// This means that they will get overridden when synchronizing the various layers.

[HideInInspector] _UVMappingMask0("_UVMappingMask0", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingMask1("_UVMappingMask1", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingMask2("_UVMappingMask2", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingMask3("_UVMappingMask3", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingPlanar0("_UVMappingPlanar0", Float) = 0.0
[HideInInspector] _UVMappingPlanar1("_UVMappingPlanar1", Float) = 0.0
[HideInInspector] _UVMappingPlanar2("_UVMappingPlanar2", Float) = 0.0
[HideInInspector] _UVMappingPlanar3("_UVMappingPlanar3", Float) = 0.0
[HideInInspector] _UVMappingMask3("_UVMappingMask3", Color) = (1, 0, 0, 0)
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail0("UV Set for detail0", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail1("UV Set for detail1", Float) = 0

#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _LAYER_TILING_UNIFORM_SCALE
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR_BLENDMASK
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR0
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR1
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR2
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR3
#pragma shader_feature _LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE
#pragma shader_feature _ _LAYER_MAPPING_PLANAR_BLENDMASK _LAYER_MAPPING_TRIPLANAR_BLENDMASK
#pragma shader_feature _ _LAYER_MAPPING_PLANAR0 _LAYER_MAPPING_TRIPLANAR0
#pragma shader_feature _ _LAYER_MAPPING_PLANAR1 _LAYER_MAPPING_TRIPLANAR1
#pragma shader_feature _ _LAYER_MAPPING_PLANAR2 _LAYER_MAPPING_TRIPLANAR2
#pragma shader_feature _ _LAYER_MAPPING_PLANAR3 _LAYER_MAPPING_TRIPLANAR3
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
#pragma shader_feature _EMISSIVE_COLOR

#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE
// TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ?
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON

#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
// Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet
#define SURFACE_GRADIENT
#include "ShaderLibrary/common.hlsl"
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
#include "../../../ShaderLibrary/common.hlsl"
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../ShaderPass/FragInputs.hlsl"
#include "../../ShaderPass/ShaderPass.cs.hlsl"
//-------------------------------------------------------------------------------------
// variable declaration

// variable declaration
//-------------------------------------------------------------------------------------
#include "HDRenderPipeline/Material/Lit/LitProperties.hlsl"
#include "../../Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert

Name "GBuffer" // Name is not used
Tags { "LightMode" = "GBuffer" } // This will be only for opaque object based on the RenderQueue index
Cull [_CullMode]
Cull [_CullMode]
Stencil
{
Ref [_StencilRef]
Comp Always
Pass Replace
}
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassGBuffer.hlsl"

Name "GBufferDebugLighting" // Name is not used
Tags{ "LightMode" = "GBufferDebugLighting" } // This will be only for opaque object based on the RenderQueue index
Cull[_CullMode]
Cull [_CullMode]
Stencil
{
Ref [_StencilRef]
Comp Always
Pass Replace
}
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitData.hlsl"

#define LIGHTING_DEBUG
#define SHADERPASS SHADERPASS_FORWARD
#include "../../Lighting/Forward.hlsl"
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
// TEMP until pragma work in include
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS

118
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader


[HideInInspector] _LayerCount("_LayerCount", Float) = 2.0
[Enum(None, 0, Multiply, 1, Add, 2)] _VertexColorMode("Vertex color mode", Float) = 0
[HideInInspector] _UVMappingPlanarBlendMask("_UVMappingPlanarBlendMask", Float) = 0.0
_TexWorldScaleBlendMask("Tiling", Float) = 1.0
// Following are builtin properties

_HorizonFade("Horizon fade", Range(0.0, 5.0)) = 1.0
// Stencil state
[HideInInspector] _StencilRef("_StencilRef", Int) = 2 // StencilBits.Standard
// Blending state
[HideInInspector] _SurfaceType("__surfacetype", Float) = 0.0
[HideInInspector] _BlendMode ("__blendmode", Float) = 0.0

[HideInInspector] _ZTestMode("_ZTestMode", Int) = 8
[ToggleOff] _DoubleSidedEnable("Double sided enable", Float) = 0.0
[ToggleOff] _DoubleSidedMirrorEnable("Double sided mirror enable", Float) = 1.0
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5

// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.
// 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
_EmissionColor("Color", Color) = (1, 1, 1)
// WARNING
// All the following properties that concern the UV mapping are the same as in the Lit shader.
// This means that they will get overridden when synchronizing the various layers.

[HideInInspector] _UVMappingMask2("_UVMappingMask2", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingMask3("_UVMappingMask3", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingPlanar0("_UVMappingPlanar0", Float) = 0.0
[HideInInspector] _UVMappingPlanar1("_UVMappingPlanar1", Float) = 0.0
[HideInInspector] _UVMappingPlanar2("_UVMappingPlanar2", Float) = 0.0
[HideInInspector] _UVMappingPlanar3("_UVMappingPlanar3", Float) = 0.0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail0("UV Set for detail0", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail1("UV Set for detail1", Float) = 0
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail2("UV Set for detail2", Float) = 0

[HideInInspector] _UVDetailsMappingMask1("_UVDetailsMappingMask1", Color) = (1, 0, 0, 0)
[HideInInspector] _UVDetailsMappingMask2("_UVDetailsMappingMask2", Color) = (1, 0, 0, 0)
[HideInInspector] _UVDetailsMappingMask3("_UVDetailsMappingMask3", Color) = (1, 0, 0, 0)
_TessellationFactorTriangleSize("Tessellation triangle size", Float) = 100.0
_TessellationFactorTriangleSize("Tessellation triangle size", Float) = 100.0
[ToggleOff] _TessellationTilingScale("Tessellation tiling scale", Float) = 1.0
// TODO: Handle culling mode for backface culling
}

#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _TESSELLATION_TILING_SCALE
#pragma shader_feature _LAYER_TILING_UNIFORM_SCALE
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR_BLENDMASK
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR0
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR1
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR2
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR3
#pragma shader_feature _LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE
#pragma shader_feature _ _LAYER_MAPPING_PLANAR_BLENDMASK _LAYER_MAPPING_TRIPLANAR_BLENDMASK
#pragma shader_feature _ _LAYER_MAPPING_PLANAR0 _LAYER_MAPPING_TRIPLANAR0
#pragma shader_feature _ _LAYER_MAPPING_PLANAR1 _LAYER_MAPPING_TRIPLANAR1
#pragma shader_feature _ _LAYER_MAPPING_PLANAR2 _LAYER_MAPPING_TRIPLANAR2
#pragma shader_feature _ _LAYER_MAPPING_PLANAR3 _LAYER_MAPPING_TRIPLANAR3
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
#pragma shader_feature _EMISSIVE_COLOR

#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
// Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet
#define SURFACE_GRADIENT
#include "ShaderLibrary/common.hlsl"
#include "ShaderLibrary/tessellation.hlsl"
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
#include "../../../ShaderLibrary/common.hlsl"
#include "../../../ShaderLibrary/tessellation.hlsl"
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../ShaderPass/FragInputs.hlsl"
#include "../../ShaderPass/ShaderPass.cs.hlsl"
//-------------------------------------------------------------------------------------
// variable declaration

// variable declaration
//-------------------------------------------------------------------------------------
#include "HDRenderPipeline/Material/Lit/LitProperties.hlsl"
#include "../../Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert

Name "GBuffer" // Name is not used
Tags { "LightMode" = "GBuffer" } // This will be only for opaque object based on the RenderQueue index
Cull [_CullMode]
Cull [_CullMode]
Stencil
{
Ref [_StencilRef]
Comp Always
Pass Replace
}
HLSLPROGRAM

#define SHADERPASS SHADERPASS_GBUFFER
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassGBuffer.hlsl"

Name "GBufferDebugLighting" // Name is not used
Tags{ "LightMode" = "GBufferDebugLighting" } // This will be only for opaque object based on the RenderQueue index
Cull[_CullMode]
Cull [_CullMode]
Stencil
{
Ref [_StencilRef]
Comp Always
Pass Replace
}
HLSLPROGRAM

#define LIGHTING_DEBUG
#define SHADERPASS SHADERPASS_GBUFFER
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassGBuffer.hlsl"

#define SHADERPASS SHADERPASS_DEBUG_VIEW_MATERIAL
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassDebugViewMaterial.hlsl"

HLSLPROGRAM
// Lightmap memo
// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light,
// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light,
// both direct and indirect lighting) will hand up in the "regular" lightmap->LIGHTMAP_ON.
// No tessellation for Meta pass

#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitMetaPass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassLightTransport.hlsl"

HLSLPROGRAM
// TODO: Tesselation can't work with velocity for now...
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitVelocityPass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassVelocity.hlsl"

Cull[_CullMode]
ZWrite On
ZWrite On
ZTest LEqual
HLSLPROGRAM

#define SHADERPASS SHADERPASS_DEPTH_ONLY
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDepthPass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"

Cull[_CullMode]
ZWrite On
ZWrite On
HLSLPROGRAM

#define SHADERPASS SHADERPASS_DEPTH_ONLY
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDepthPass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"

#pragma domain Domain
#define SHADERPASS SHADERPASS_DISTORTION
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDistortionPass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassDistortion.hlsl"

// TEMP until pragma work in include
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS
#include "../../Lighting/Lighting.hlsl"
#include "../../Lighting/Lighting.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassForward.hlsl"

#define LIGHTING_DEBUG
#define SHADERPASS SHADERPASS_FORWARD
#include "../../Lighting/Forward.hlsl"
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
#include "../../Lighting/Lighting.hlsl"
#include "../../Lighting/Lighting.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitData.hlsl"
#include "../../ShaderPass/ShaderPassForward.hlsl"

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit.meta


fileFormatVersion: 2
guid: d6cadd3aaf3ad6641b86e85a0929b245
guid: 0d05f89ce69203543914d745c388e6bb
folderAsset: yes
timeCreated: 1476653183
licenseType: Pro

558
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public abstract class BaseLitGUI : ShaderGUI
// A Material can be authored from the shader graph or by hand. When written by hand we need to provide an inspector.
// Such a Material will share some properties between it various variant (shader graph variant or hand authored variant).
// This is the purpose of BaseLitGUI. It contain all properties that are common to all Material based on Lit template.
// For the default hand written Lit material see LitUI.cs that contain specific properties for our default implementation.
public abstract class BaseLitGUI : BaseUnlitGUI
protected static class Styles
protected static class StylesBaseLit
public static string optionText = "Surface options";
public static string surfaceTypeText = "Surface Type";
public static string blendModeText = "Blend Mode";
public static string detailText = "Inputs Detail";
public static string textureControlText = "Input textures control";
public static string lightingText = "Inputs Lighting";
public static GUIContent alphaCutoffEnableText = new GUIContent("Alpha Cutoff Enable", "Threshold for alpha cutoff");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent doubleSidedEnableText = new GUIContent("Double Sided", "This will render the two face of the objects (disable backface culling) and mirror normal");
public static GUIContent distortionEnableText = new GUIContent("Distortion", "Enable distortion on this shader");
public static GUIContent distortionOnlyText = new GUIContent("Distortion Only", "This shader will only be use to render distortion");
public static GUIContent distortionDepthTestText = new GUIContent("Distortion Depth Test", "Enable the depth test for distortion");
public static GUIContent doubleSidedMirrorEnableText = new GUIContent("Mirror normal", "This will mirror the normal with vertex normal plane if enabled, else flip the normal");
public static GUIContent horizonFadeText = new GUIContent("Horizon Fade (Spec occlusion)", "horizon fade is use to control specular occlusion");
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
// Material ID
public static GUIContent materialIDText = new GUIContent("Material type", "Subsurface Scattering: enable for translucent materials such as skin, vegetation, fruit, marble, wax and milk.");
public static GUIContent smoothnessMapChannelText = new GUIContent("Smoothness Source", "Smoothness texture and channel");
public static GUIContent UVBaseMappingText = new GUIContent("Base UV mapping", "");
public static GUIContent texWorldScaleText = new GUIContent("World scale", "Tiling factor applied to Planar/Trilinear mapping");
public static GUIContent normalMapSpaceText = new GUIContent("Normal/Tangent Map space", "");
// Per pixel displacement
public static GUIContent ppdMinSamplesText = new GUIContent("Minimum samples", "Minimun samples to use with per pixel displacement mapping");
public static GUIContent ppdMaxSamplesText = new GUIContent("Maximum samples", "Maximum samples to use with per pxiel displacement mapping");
public static GUIContent ppdMinSamplesText = new GUIContent("Minimum samples", "Minimum samples to use with per pixel displacement mapping");
public static GUIContent ppdMaxSamplesText = new GUIContent("Maximum samples", "Maximum samples to use with per pixel displacement mapping");
public static GUIContent detailMapModeText = new GUIContent("Detail Map with Normal", "Detail Map with AO / Height");
public static GUIContent UVDetailMappingText = new GUIContent("Detail UV mapping", "");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");
public static string InputsText = "Inputs";
public static string InputsMapText = "";
public static GUIContent baseColorText = new GUIContent("Base Color + Opacity", "Albedo (RGB) and Opacity (A)");
public static GUIContent baseColorSmoothnessText = new GUIContent("Base Color + Smoothness", "Albedo (RGB) and Smoothness (A)");
public static GUIContent metallicText = new GUIContent("Metallic", "Metallic scale factor");
public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness scale factor");
public static GUIContent maskMapESText = new GUIContent("Mask Map - M(R), AO(G), E(B), S(A)", "Mask map");
public static GUIContent maskMapSText = new GUIContent("Mask Map - M(R), AO(G), S(A)", "Mask map");
public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (DXT5) - Need to implement BC5");
public static GUIContent heightMapText = new GUIContent("Height Map (R)", "Height Map");
public static GUIContent heightMapAmplitudeText = new GUIContent("Height Map Amplitude", "Height Map amplitude in world units.");
public static GUIContent heightMapCenterText = new GUIContent("Height Map Center", "Center of the heightmap in the texture (between 0 and 1)");
public static GUIContent tangentMapText = new GUIContent("Tangent Map", "Tangent Map (BC5) - DXT5 for test");
public static GUIContent anisotropyText = new GUIContent("Anisotropy", "Anisotropy scale factor");
public static GUIContent anisotropyMapText = new GUIContent("Anisotropy Map (B)", "Anisotropy");
public static GUIContent detailMapNormalText = new GUIContent("Detail Map A(R) Ny(G) S(B) Nx(A)", "Detail Map");
public static GUIContent detailMaskText = new GUIContent("Detail Mask (G)", "Mask for detailMap");
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 detailHeightScaleText = new GUIContent("Detail HeightScale", "Height Scale factor");
public static GUIContent detailAOScaleText = new GUIContent("Detail AOScale", "AO Scale factor");
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");
public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
public static GUIContent emissiveColorWarning = new GUIContent("Ensure emissive color is non-black for emission to have effect.");
// Tessellation
public static string tessellationModeText = "Tessellation Mode";
public static readonly string[] tessellationModeNames = Enum.GetNames(typeof(TessellationMode));

public static GUIContent tessellationFactorTriangleSizeText = new GUIContent("Triangle size", "Desired screen space sized of triangle (in pixel). Smaller value mean smaller triangle.");
public static GUIContent tessellationShapeFactorText = new GUIContent("Shape factor", "Strength of Phong tessellation shape (lerp factor)");
public static GUIContent tessellationBackFaceCullEpsilonText = new GUIContent("Triangle culling Epsilon", "If -1.0 back face culling is enabled for tessellation, higher number mean more aggressive culling and better performance");
public static GUIContent tessellationObjectScaleText = new GUIContent("Enable object scale", "Tesselation displacement will take into account the object scale - Only work with uniform positive scale");
public static GUIContent perPixelDisplacementText = new GUIContent("Per pixel displacement", "Per pixel displacement options");
public static GUIContent materialIDText = new GUIContent("Material type", "Subsurface Scattering: enable for translucent materials such as skin, vegetation, fruit, marble, wax and milk.");
public static GUIContent subsurfaceProfileText = new GUIContent("Subsurface profile", "A profile determines the shape of the blur filter.");
public static GUIContent subsurfaceRadiusText = new GUIContent("Subsurface radius", "Determines the range of the blur.");
public static GUIContent subsurfaceRadiusMapText = new GUIContent("Subsurface radius map", "Determines the range of the blur.");
public static GUIContent thicknessText = new GUIContent("Thickness", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
public static GUIContent thicknessMapText = new GUIContent("Thickness map", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
}
public enum SurfaceType
{
Opaque,
Transparent
}
public enum BlendMode
{
Lerp,
Add,
SoftAdd,
Multiply,
Premultiply
public static GUIContent tessellationObjectScaleText = new GUIContent("Enable object scale", "Tessellation displacement will take into account the object scale - Only work with uniform positive scale");
public static GUIContent tessellationTilingScaleText = new GUIContent("Enable tiling scale", "Tessellation displacement will take into account the tiling scale - Only work with uniform positive scale");
}
public enum TessellationMode

DisplacementPhong,
}
void SurfaceTypePopup()
{
EditorGUI.showMixedValue = surfaceType.hasMixedValue;
var mode = (SurfaceType)surfaceType.floatValue;
protected MaterialProperty doubleSidedMirrorEnable = null;
protected const string kDoubleSidedMirrorEnable = "_DoubleSidedMirrorEnable";
protected MaterialProperty depthOffsetEnable = null;
protected const string kDepthOffsetEnable = "_DepthOffsetEnable";
EditorGUI.BeginChangeCheck();
mode = (SurfaceType)EditorGUILayout.Popup(Styles.surfaceTypeText, (int)mode, Styles.surfaceTypeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Surface Type");
surfaceType.floatValue = (float)mode;
}
// Properties
// Material ID
protected MaterialProperty materialID = null;
protected const string kMaterialID = "_MaterialID";
// Per pixel displacement params
protected MaterialProperty enablePerPixelDisplacement = null;
protected const string kEnablePerPixelDisplacement = "_EnablePerPixelDisplacement";
protected MaterialProperty ppdMinSamples = null;
protected const string kPpdMinSamples = "_PPDMinSamples";
protected MaterialProperty ppdMaxSamples = null;
protected const string kPpdMaxSamples = "_PPDMaxSamples";
protected MaterialProperty ppdLodThreshold = null;
protected const string kPpdLodThreshold = "_PPDLodThreshold";
EditorGUI.showMixedValue = false;
}
// tessellation params
protected MaterialProperty tessellationMode = null;
protected const string kTessellationMode = "_TessellationMode";
protected MaterialProperty tessellationFactor = null;
protected const string kTessellationFactor = "_TessellationFactor";
protected MaterialProperty tessellationFactorMinDistance = null;
protected const string kTessellationFactorMinDistance = "_TessellationFactorMinDistance";
protected MaterialProperty tessellationFactorMaxDistance = null;
protected const string kTessellationFactorMaxDistance = "_TessellationFactorMaxDistance";
protected MaterialProperty tessellationFactorTriangleSize = null;
protected const string kTessellationFactorTriangleSize = "_TessellationFactorTriangleSize";
protected MaterialProperty tessellationShapeFactor = null;
protected const string kTessellationShapeFactor = "_TessellationShapeFactor";
protected MaterialProperty tessellationBackFaceCullEpsilon = null;
protected const string kTessellationBackFaceCullEpsilon = "_TessellationBackFaceCullEpsilon";
protected MaterialProperty tessellationObjectScale = null;
protected const string kTessellationObjectScale = "_TessellationObjectScale";
protected MaterialProperty tessellationTilingScale = null;
protected const string kTessellationTilingScale = "_TessellationTilingScale";
private void BlendModePopup()
protected override void FindBaseMaterialProperties(MaterialProperty[] props)
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
base.FindBaseMaterialProperties(props);
doubleSidedMirrorEnable = FindProperty(kDoubleSidedMirrorEnable, props);
depthOffsetEnable = FindProperty(kDepthOffsetEnable, props);
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.blendModeText, (int)mode, Styles.blendModeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Blend Mode");
blendMode.floatValue = (float)mode;
}
// MaterialID
materialID = FindProperty(kMaterialID, props, false);
EditorGUI.showMixedValue = false;
// Per pixel displacement
enablePerPixelDisplacement = FindProperty(kEnablePerPixelDisplacement, props);
ppdMinSamples = FindProperty(kPpdMinSamples, props);
ppdMaxSamples = FindProperty(kPpdMaxSamples, props);
ppdLodThreshold = FindProperty(kPpdLodThreshold, props);
// tessellation specific, silent if not found
tessellationMode = FindProperty(kTessellationMode, props, false);
tessellationFactor = FindProperty(kTessellationFactor, props, false);
tessellationFactorMinDistance = FindProperty(kTessellationFactorMinDistance, props, false);
tessellationFactorMaxDistance = FindProperty(kTessellationFactorMaxDistance, props, false);
tessellationFactorTriangleSize = FindProperty(kTessellationFactorTriangleSize, props, false);
tessellationShapeFactor = FindProperty(kTessellationShapeFactor, props, false);
tessellationBackFaceCullEpsilon = FindProperty(kTessellationBackFaceCullEpsilon, props, false);
tessellationObjectScale = FindProperty(kTessellationObjectScale, props, false);
tessellationTilingScale = FindProperty(kTessellationTilingScale, props, false);
}
void TessellationModePopup()

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

EditorGUI.showMixedValue = false;
}
protected void ShaderOptionsGUI()
protected override void BaseMaterialPropertiesGUI()
EditorGUI.indentLevel++;
GUILayout.Label(Styles.optionText, EditorStyles.boldLabel);
SurfaceTypePopup();
if ((SurfaceType)surfaceType.floatValue == SurfaceType.Transparent)
{
BlendModePopup();
m_MaterialEditor.ShaderProperty(distortionEnable, Styles.distortionEnableText.text);
base.BaseMaterialPropertiesGUI();
if (distortionEnable.floatValue == 1.0)
{
m_MaterialEditor.ShaderProperty(distortionOnly, Styles.distortionOnlyText.text);
m_MaterialEditor.ShaderProperty(distortionDepthTest, Styles.distortionDepthTestText.text);
}
}
m_MaterialEditor.ShaderProperty(alphaCutoffEnable, Styles.alphaCutoffEnableText.text);
if (alphaCutoffEnable.floatValue == 1.0)
// This follow double sided option
if (doubleSidedEnable.floatValue > 0.0f)
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(doubleSidedMirrorEnable, StylesBaseLit.doubleSidedMirrorEnableText);
EditorGUI.indentLevel--;
m_MaterialEditor.ShaderProperty(doubleSidedEnable, Styles.doubleSidedEnableText.text);
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, Styles.enablePerPixelDisplacementText);
if (enablePerPixelDisplacement.floatValue > 0.0)
if (materialID != null)
m_MaterialEditor.ShaderProperty(materialID, StylesBaseLit.materialIDText);
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, StylesBaseLit.enablePerPixelDisplacementText);
if (enablePerPixelDisplacement.floatValue > 0.0f)
m_MaterialEditor.ShaderProperty(ppdMinSamples, Styles.ppdMinSamplesText);
m_MaterialEditor.ShaderProperty(ppdMaxSamples, Styles.ppdMaxSamplesText);
m_MaterialEditor.ShaderProperty(ppdMinSamples, StylesBaseLit.ppdMinSamplesText);
m_MaterialEditor.ShaderProperty(ppdMaxSamples, StylesBaseLit.ppdMaxSamplesText);
m_MaterialEditor.ShaderProperty(ppdLodThreshold, Styles.ppdLodThresholdText);
m_MaterialEditor.ShaderProperty(depthOffsetEnable, Styles.depthOffsetEnableText.text);
m_MaterialEditor.ShaderProperty(ppdLodThreshold, StylesBaseLit.ppdLodThresholdText);
m_MaterialEditor.ShaderProperty(depthOffsetEnable, StylesBaseLit.depthOffsetEnableText);
m_MaterialEditor.ShaderProperty(horizonFade, Styles.horizonFadeText);
// Display tessellation option if it exist
GUILayout.Label(Styles.tessellationText, EditorStyles.boldLabel);
GUILayout.Label(StylesBaseLit.tessellationText, EditorStyles.boldLabel);
m_MaterialEditor.ShaderProperty(tessellationFactor, Styles.tessellationFactorText);
m_MaterialEditor.ShaderProperty(tessellationFactorMinDistance, Styles.tessellationFactorMinDistanceText);
m_MaterialEditor.ShaderProperty(tessellationFactorMaxDistance, Styles.tessellationFactorMaxDistanceText);
m_MaterialEditor.ShaderProperty(tessellationFactor, StylesBaseLit.tessellationFactorText);
m_MaterialEditor.ShaderProperty(tessellationFactorMinDistance, StylesBaseLit.tessellationFactorMinDistanceText);
m_MaterialEditor.ShaderProperty(tessellationFactorMaxDistance, StylesBaseLit.tessellationFactorMaxDistanceText);
m_MaterialEditor.ShaderProperty(tessellationFactorTriangleSize, Styles.tessellationFactorTriangleSizeText);
m_MaterialEditor.ShaderProperty(tessellationFactorTriangleSize, StylesBaseLit.tessellationFactorTriangleSizeText);
m_MaterialEditor.ShaderProperty(tessellationShapeFactor, Styles.tessellationShapeFactorText);
m_MaterialEditor.ShaderProperty(tessellationShapeFactor, StylesBaseLit.tessellationShapeFactorText);
m_MaterialEditor.ShaderProperty(tessellationBackFaceCullEpsilon, Styles.tessellationBackFaceCullEpsilonText);
m_MaterialEditor.ShaderProperty(tessellationBackFaceCullEpsilon, StylesBaseLit.tessellationBackFaceCullEpsilonText);
m_MaterialEditor.ShaderProperty(tessellationObjectScale, Styles.tessellationObjectScaleText);
m_MaterialEditor.ShaderProperty(tessellationObjectScale, StylesBaseLit.tessellationObjectScaleText);
m_MaterialEditor.ShaderProperty(tessellationTilingScale, StylesBaseLit.tessellationTilingScaleText);
protected void FindCommonOptionProperties(MaterialProperty[] props)
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if ocde change
static public void SetupBaseLitKeywords(Material material)
surfaceType = FindProperty(kSurfaceType, props);
blendMode = FindProperty(kBlendMode, props);
alphaCutoff = FindProperty(kAlphaCutoff, props);
alphaCutoffEnable = FindProperty(kAlphaCutoffEnabled, props);
doubleSidedEnable = FindProperty(kDoubleSidedEnable, props);
distortionEnable = FindProperty(kDistortionEnable, props);
distortionOnly = FindProperty(kDistortionOnly, props);
distortionDepthTest = FindProperty(kDistortionDepthTest, props);
depthOffsetEnable = FindProperty(kDepthOffsetEnable, props);
horizonFade = FindProperty(kHorizonFade, props);
// tessellation specific, silent if not found
tessellationMode = FindProperty(kTessellationMode, props, false);
tessellationFactor = FindProperty(kTessellationFactor, props, false);
tessellationFactorMinDistance = FindProperty(kTessellationFactorMinDistance, props, false);
tessellationFactorMaxDistance = FindProperty(kTessellationFactorMaxDistance, props, false);
tessellationFactorTriangleSize = FindProperty(kTessellationFactorTriangleSize, props, false);
tessellationShapeFactor = FindProperty(kTessellationShapeFactor, props, false);
tessellationBackFaceCullEpsilon = FindProperty(kTessellationBackFaceCullEpsilon, props, false);
tessellationObjectScale = FindProperty(kTessellationObjectScale, props, false);
// Per pixel displacement
enablePerPixelDisplacement = FindProperty(kEnablePerPixelDisplacement, props);
ppdMinSamples = FindProperty(kPpdMinSamples, props);
ppdMaxSamples = FindProperty(kPpdMaxSamples, props);
ppdLodThreshold = FindProperty(kPpdLodThreshold, props);
}
SetupBaseUnlitKeywords(material);
protected void SetupCommonOptionsKeywords(Material material)
{
bool alphaTestEnable = material.GetFloat(kAlphaCutoffEnabled) > 0.0f;
SurfaceType surfaceType = (SurfaceType)material.GetFloat(kSurfaceType);
BlendMode blendMode = (BlendMode)material.GetFloat(kBlendMode);
bool doubleSidedMirrorEnable = material.GetFloat(kDoubleSidedMirrorEnable) > 0.0f;
if (surfaceType == SurfaceType.Opaque)
if (doubleSidedEnable)
material.SetOverrideTag("RenderType", alphaTestEnable ? "TransparentCutout" : "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.renderQueue = alphaTestEnable ? (int)UnityEngine.Rendering.RenderQueue.AlphaTest : -1;
if (doubleSidedMirrorEnable)
{
// Mirror mode (in tangent space)
material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f));
}
else
{
// Flip mode (in tangent space)
material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f));
}
else
{
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_ZWrite", 0);
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
switch (blendMode)
{
case BlendMode.Lerp:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
break;
bool depthOffsetEnable = material.GetFloat(kDepthOffsetEnable) > 0.0f;
SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable);
case BlendMode.Add:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
break;
int stencilRef = (int)UnityEngine.Experimental.Rendering.HDPipeline.StencilBits.Standard; // See 'StencilBits'.
if (material.HasProperty(kMaterialID))
{
int materialID = (int)material.GetFloat(kMaterialID);
case BlendMode.SoftAdd:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusDstColor);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
switch (materialID)
{
case (int)UnityEngine.Experimental.Rendering.HDPipeline.Lit.MaterialId.LitSSS:
stencilRef = (int)UnityEngine.Experimental.Rendering.HDPipeline.StencilBits.SSS;
case BlendMode.Multiply:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
case (int)UnityEngine.Experimental.Rendering.HDPipeline.Lit.MaterialId.LitStandard:
stencilRef = (int)UnityEngine.Experimental.Rendering.HDPipeline.StencilBits.Standard;
case BlendMode.Premultiply:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
default:
stencilRef = 1 + materialID;
if (doubleSidedEnable)
{
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Off);
}
else
{
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Back);
}
SetKeyword(material, "_DOUBLESIDED_ON", doubleSidedEnable);
SetKeyword(material, "_ALPHATEST_ON", alphaTestEnable);
bool distortionEnable = material.GetFloat(kDistortionEnable) == 1.0;
bool distortionOnly = material.GetFloat(kDistortionOnly) == 1.0;
bool distortionDepthTest = material.GetFloat(kDistortionDepthTest) == 1.0;
bool depthOffsetEnable = material.GetFloat(kDepthOffsetEnable) == 1.0;
if (distortionEnable)
{
material.SetShaderPassEnabled("DistortionVectors", true);
}
else
{
material.SetShaderPassEnabled("DistortionVectors", false);
}
if (distortionEnable && distortionOnly)
{
// Disable all passes except dbug material
material.SetShaderPassEnabled("GBuffer", false);
material.SetShaderPassEnabled("DebugViewMaterial", true);
material.SetShaderPassEnabled("Meta", false);
material.SetShaderPassEnabled("ShadowCaster", false);
material.SetShaderPassEnabled("DepthOnly", false);
material.SetShaderPassEnabled("MotionVectors", false);
material.SetShaderPassEnabled("Forward", false);
}
else
{
material.SetShaderPassEnabled("GBuffer", true);
material.SetShaderPassEnabled("DebugViewMaterial", true);
material.SetShaderPassEnabled("Meta", true);
material.SetShaderPassEnabled("ShadowCaster", true);
material.SetShaderPassEnabled("DepthOnly", true);
material.SetShaderPassEnabled("MotionVectors", true);
material.SetShaderPassEnabled("Forward", true);
}
material.SetInt("_StencilRef", stencilRef);
if (distortionDepthTest)
{
material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.LessEqual);
}
else
{
material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.Always);
}
bool enablePerPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) > 0.0f;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", enablePerPixelDisplacement);
SetKeyword(material, "_DISTORTION_ON", distortionEnable);
SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable);
SetupEmissionGIFlags(material);
if (tessellationMode != null)
if (material.HasProperty(kTessellationMode))
{
TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode);

material.EnableKeyword("_TESSELLATION_DISPLACEMENT_PHONG");
}
bool tessellationObjectScaleEnable = material.GetFloat(kTessellationObjectScale) == 1.0;
bool tessellationObjectScaleEnable = material.GetFloat(kTessellationObjectScale) > 0.0;
bool tessellationTilingScaleEnable = material.GetFloat(kTessellationTilingScale) > 0.0;
SetKeyword(material, "_TESSELLATION_TILING_SCALE", tessellationTilingScaleEnable);
protected void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword(keyword);
else
m.DisableKeyword(keyword);
}
public void ShaderPropertiesGUI(Material material)
static public void SetupBaseLitMaterialPass(Material material)
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
bool distortionEnable = material.GetFloat(kDistortionEnable) > 0.0f;
bool distortionOnly = material.GetFloat(kDistortionOnly) > 0.0f;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
if (distortionEnable && distortionOnly)
ShaderOptionsGUI();
EditorGUILayout.Space();
EditorGUILayout.Space();
ShaderInputGUI();
}
if (EditorGUI.EndChangeCheck())
{
foreach (var obj in m_MaterialEditor.targets)
SetupMaterialKeywords((Material)obj);
// Disable all passes except debug material
material.SetShaderPassEnabled("GBuffer", false);
material.SetShaderPassEnabled("DebugViewMaterial", true);
material.SetShaderPassEnabled("Meta", false);
material.SetShaderPassEnabled("ShadowCaster", false);
material.SetShaderPassEnabled("DepthOnly", false);
material.SetShaderPassEnabled("MotionVectors", false);
material.SetShaderPassEnabled("Forward", false);
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
FindCommonOptionProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
FindMaterialProperties(props);
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
ShaderPropertiesGUI(material);
}
// TODO: ? or remove
bool HasValidEmissiveKeyword(Material material)
{
/*
// Material animation might be out of sync with the material keyword.
// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
if (!hasEmissionKeyword && ShouldEmissionBeEnabled (material, emissionColorForRendering.colorValue))
return false;
return true;
*/
return true;
}
protected virtual void SetupEmissionGIFlags(Material material)
{
// Setup lightmap emissive flags
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
if (ShouldEmissionBeEnabled(material))
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
else
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
material.globalIlluminationFlags = flags;
material.SetShaderPassEnabled("GBuffer", true);
material.SetShaderPassEnabled("DebugViewMaterial", true);
material.SetShaderPassEnabled("Meta", true);
material.SetShaderPassEnabled("ShadowCaster", true);
material.SetShaderPassEnabled("DepthOnly", true);
material.SetShaderPassEnabled("MotionVectors", true);
material.SetShaderPassEnabled("Forward", true);
protected MaterialEditor m_MaterialEditor;
MaterialProperty surfaceType = null;
const string kSurfaceType = "_SurfaceType";
MaterialProperty alphaCutoffEnable = null;
const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
MaterialProperty blendMode = null;
const string kBlendMode = "_BlendMode";
MaterialProperty alphaCutoff = null;
const string kAlphaCutoff = "_AlphaCutoff";
MaterialProperty doubleSidedEnable = null;
const string kDoubleSidedEnable = "_DoubleSidedEnable";
MaterialProperty distortionEnable = null;
const string kDistortionEnable = "_DistortionEnable";
MaterialProperty distortionOnly = null;
const string kDistortionOnly = "_DistortionOnly";
MaterialProperty distortionDepthTest = null;
const string kDistortionDepthTest = "_DistortionDepthTest";
MaterialProperty depthOffsetEnable = null;
const string kDepthOffsetEnable = "_DepthOffsetEnable";
protected MaterialProperty horizonFade = null;
const string kHorizonFade = "_HorizonFade";
// tessellation params
protected MaterialProperty tessellationMode = null;
const string kTessellationMode = "_TessellationMode";
MaterialProperty tessellationFactor = null;
const string kTessellationFactor = "_TessellationFactor";
MaterialProperty tessellationFactorMinDistance = null;
const string kTessellationFactorMinDistance = "_TessellationFactorMinDistance";
MaterialProperty tessellationFactorMaxDistance = null;
const string kTessellationFactorMaxDistance = "_TessellationFactorMaxDistance";
MaterialProperty tessellationFactorTriangleSize = null;
const string kTessellationFactorTriangleSize = "_TessellationFactorTriangleSize";
MaterialProperty tessellationShapeFactor = null;
const string kTessellationShapeFactor = "_TessellationShapeFactor";
MaterialProperty tessellationBackFaceCullEpsilon = null;
const string kTessellationBackFaceCullEpsilon = "_TessellationBackFaceCullEpsilon";
MaterialProperty tessellationObjectScale = null;
const string kTessellationObjectScale = "_TessellationObjectScale";
// Per pixel displacement params
protected MaterialProperty enablePerPixelDisplacement = null;
protected const string kEnablePerPixelDisplacement = "_EnablePerPixelDisplacement";
protected MaterialProperty ppdMinSamples = null;
protected const string kPpdMinSamples = "_PPDMinSamples";
protected MaterialProperty ppdMaxSamples = null;
protected const string kPpdMaxSamples = "_PPDMaxSamples";
protected MaterialProperty ppdLodThreshold = null;
protected const string kPpdLodThreshold = "_PPDLodThreshold";
protected static string[] reservedProperties = new string[] { kSurfaceType, kBlendMode, kAlphaCutoff, kAlphaCutoffEnabled, kDoubleSidedEnable };
protected abstract void FindMaterialProperties(MaterialProperty[] props);
protected abstract void ShaderInputGUI();
protected abstract void SetupMaterialKeywords(Material material);
protected abstract bool ShouldEmissionBeEnabled(Material material);
}
} // namespace UnityEditor

206
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs


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

protected static class Styles
{
public static string InputsText = "Inputs";
public static GUIContent baseColorText = new GUIContent("Base Color + Opacity", "Albedo (RGB) and Opacity (A)");
public static GUIContent baseColorSmoothnessText = new GUIContent("Base Color + Smoothness", "Albedo (RGB) and Smoothness (A)");
public static GUIContent smoothnessMapChannelText = new GUIContent("Smoothness Source", "Smoothness texture and channel");
public static GUIContent metallicText = new GUIContent("Metallic", "Metallic scale factor");
public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness scale factor");
public static GUIContent maskMapESText = new GUIContent("Mask Map - M(R), AO(G), E(B), S(A)", "Mask map");
public static GUIContent maskMapSText = new GUIContent("Mask Map - M(R), AO(G), S(A)", "Mask map");
public static GUIContent normalMapSpaceText = new GUIContent("Normal/Tangent Map space", "");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (DXT5) - Need to implement BC5");
public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent horizonFadeText = new GUIContent("Horizon Fade (Spec occlusion)", "horizon fade is use to control specular occlusion");
public static GUIContent heightMapText = new GUIContent("Height Map (R)", "Height Map");
public static GUIContent heightMapAmplitudeText = new GUIContent("Height Map Amplitude", "Height Map amplitude in world units.");
public static GUIContent heightMapCenterText = new GUIContent("Height Map Center", "Center of the heightmap in the texture (between 0 and 1)");
public static GUIContent tangentMapText = new GUIContent("Tangent Map", "Tangent Map (BC5) - DXT5 for test");
public static GUIContent anisotropyText = new GUIContent("Anisotropy", "Anisotropy scale factor");
public static GUIContent anisotropyMapText = new GUIContent("Anisotropy Map (B)", "Anisotropy");
public static string textureControlText = "Input textures control";
public static GUIContent UVBaseMappingText = new GUIContent("Base UV mapping", "");
public static GUIContent texWorldScaleText = new GUIContent("World scale", "Tiling factor applied to Planar/Trilinear mapping");
// Details
public static string detailText = "Inputs Detail";
public static GUIContent detailMapModeText = new GUIContent("Detail Map with Normal", "Detail Map with AO / Height");
public static GUIContent UVDetailMappingText = new GUIContent("Detail UV mapping", "");
public static GUIContent detailMapNormalText = new GUIContent("Detail Map A(R) Ny(G) S(B) Nx(A)", "Detail Map");
public static GUIContent detailMaskText = new GUIContent("Detail Mask (G)", "Mask for detailMap");
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");
// Subsurface
public static GUIContent subsurfaceProfileText = new GUIContent("Subsurface profile", "A profile determines the shape of the blur filter.");
public static GUIContent subsurfaceRadiusText = new GUIContent("Subsurface radius", "Determines the range of the blur.");
public static GUIContent subsurfaceRadiusMapText = new GUIContent("Subsurface radius map", "Determines the range of the blur.");
public static GUIContent thicknessText = new GUIContent("Thickness", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
public static GUIContent thicknessMapText = new GUIContent("Thickness map", "If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
// Emissive
public static string lightingText = "Inputs Lighting";
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");
public static GUIContent normalMapSpaceWarning = new GUIContent("Object space normal can't be use with triplanar mapping.");
}
public enum UVBaseMapping
{
UV0,

protected const string kTexWorldScale = "_TexWorldScale";
protected MaterialProperty UVMappingMask = null;
protected const string kUVMappingMask = "_UVMappingMask";
protected MaterialProperty UVMappingPlanar = null;
protected const string kUVMappingPlanar = "_UVMappingPlanar";
protected MaterialProperty normalMapSpace = null;
protected const string kNormalMapSpace = "_NormalMapSpace";
protected MaterialProperty UVDetail = null;
protected const string kUVDetail = "_UVDetail";
protected MaterialProperty UVDetailsMappingMask = null;
protected const string kUVDetailsMappingMask = "_UVDetailsMappingMask";
protected MaterialProperty emissiveColorMode = null;
protected const string kEmissiveColorMode = "_EmissiveColorMode";
protected MaterialProperty baseColor = null;
protected const string kBaseColor = "_BaseColor";

protected const string kMaskMap = "_MaskMap";
protected MaterialProperty specularOcclusionMap = null;
protected const string kSpecularOcclusionMap = "_SpecularOcclusionMap";
protected MaterialProperty horizonFade = null;
protected const string kHorizonFade = "_HorizonFade";
protected MaterialProperty normalMapSpace = null;
protected const string kNormalMapSpace = "_NormalMapSpace";
protected MaterialProperty heightMap = null;
protected const string kHeightMap = "_HeightMap";
protected MaterialProperty heightAmplitude = null;

protected MaterialProperty anisotropyMap = null;
protected const string kAnisotropyMap = "_AnisotropyMap";
protected MaterialProperty UVDetail = null;
protected const string kUVDetail = "_UVDetail";
protected MaterialProperty UVDetailsMappingMask = null;
protected const string kUVDetailsMappingMask = "_UVDetailsMappingMask";
protected MaterialProperty detailMap = null;
protected const string kDetailMap = "_DetailMap";
protected MaterialProperty detailMask = null;

protected MaterialProperty detailSmoothnessScale = null;
protected const string kDetailSmoothnessScale = "_DetailSmoothnessScale";
protected MaterialProperty emissiveColor = null;
protected const string kEmissiveColor = "_EmissiveColor";
protected MaterialProperty emissiveColorMap = null;
protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected MaterialProperty emissiveIntensity = null;
protected const string kEmissiveIntensity = "_EmissiveIntensity";
protected MaterialProperty materialID = null;
protected const string kMaterialID = "_MaterialID";
protected MaterialProperty subsurfaceProfile = null;
protected const string kSubsurfaceProfile = "_SubsurfaceProfile";
protected SubsurfaceScatteringProfile subsurfaceProfile = null;
protected MaterialProperty subsurfaceProfileID = null;
protected const string kSubsurfaceProfileID = "_SubsurfaceProfile";
protected MaterialProperty subsurfaceRadius = null;
protected const string kSubsurfaceRadius = "_SubsurfaceRadius";
protected MaterialProperty subsurfaceRadiusMap = null;

protected MaterialProperty thicknessMap = null;
protected const string kThicknessMap = "_ThicknessMap";
override protected void FindMaterialProperties(MaterialProperty[] props)
protected MaterialProperty emissiveColorMode = null;
protected const string kEmissiveColorMode = "_EmissiveColorMode";
protected MaterialProperty emissiveColor = null;
protected const string kEmissiveColor = "_EmissiveColor";
protected MaterialProperty emissiveColorMap = null;
protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected MaterialProperty emissiveIntensity = null;
protected const string kEmissiveIntensity = "_EmissiveIntensity";
protected override void FindMaterialProperties(MaterialProperty[] props)
normalMapSpace = FindProperty(kNormalMapSpace, props);
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
UVBase = FindProperty(kUVBase, props);
TexWorldScale = FindProperty(kTexWorldScale, props);
UVMappingMask = FindProperty(kUVMappingMask, props);
baseColor = FindProperty(kBaseColor, props);
baseColorMap = FindProperty(kBaseColorMap, props);

specularOcclusionMap = FindProperty(kSpecularOcclusionMap, props);
horizonFade = FindProperty(kHorizonFade, props);
normalScale = FindProperty(kNormalScale, props);
normalScale = FindProperty(kNormalScale, props);
normalMapSpace = FindProperty(kNormalMapSpace, props);
heightMap = FindProperty(kHeightMap, props);
heightAmplitude = FindProperty(kHeightAmplitude, props);
heightCenter = FindProperty(kHeightCenter, props);

UVBase = FindProperty(kUVBase, props);
// Details
TexWorldScale = FindProperty(kTexWorldScale, props);
UVMappingMask = FindProperty(kUVMappingMask, props);
UVMappingPlanar = FindProperty(kUVMappingPlanar, props);
detailMap = FindProperty(kDetailMap, props);
detailMask = FindProperty(kDetailMask, props);
detailAlbedoScale = FindProperty(kDetailAlbedoScale, props);

// Sub surface
subsurfaceProfileID = FindProperty(kSubsurfaceProfileID, props);
subsurfaceRadius = FindProperty(kSubsurfaceRadius, props);
subsurfaceRadiusMap = FindProperty(kSubsurfaceRadiusMap, props);
thickness = FindProperty(kThickness, props);
thicknessMap = FindProperty(kThicknessMap, props);
// Emissive
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
materialID = FindProperty(kMaterialID, props);
subsurfaceProfile = FindProperty(kSubsurfaceProfile, props);
subsurfaceRadius = FindProperty(kSubsurfaceRadius, props);
subsurfaceRadiusMap = FindProperty(kSubsurfaceRadiusMap, props);
thickness = FindProperty(kThickness, props);
thicknessMap = FindProperty(kThicknessMap, props);
m_MaterialEditor.ShaderProperty(subsurfaceProfile, Styles.subsurfaceProfileText);
if (subsurfaceProfile == null)
{
int profileID = (int)subsurfaceProfileID.floatValue;
HDRenderPipelineInstance hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipelineInstance;
if (profileID >= 0 && profileID < hdPipeline.sssSettings.profiles.Length)
{
// This is a valid profile ID.
subsurfaceProfile = hdPipeline.sssSettings.profiles[profileID];
}
else
{
subsurfaceProfile = SubsurfaceScatteringProfile.defaultProfile;
}
// Refresh the ID of the profile.
hdPipeline.sssSettings.OnValidate();
}
// Extract the profile ID.
subsurfaceProfile = EditorGUILayout.ObjectField(Styles.subsurfaceProfileText, subsurfaceProfile, subsurfaceProfile.GetType(), false, null) as SubsurfaceScatteringProfile;
subsurfaceProfileID.floatValue = subsurfaceProfile.settingsIndex;
m_MaterialEditor.ShaderProperty(subsurfaceRadius, Styles.subsurfaceRadiusText);
m_MaterialEditor.TexturePropertySingleLine(Styles.subsurfaceRadiusMapText, subsurfaceRadiusMap);
m_MaterialEditor.ShaderProperty(thickness, Styles.thicknessText);

m_MaterialEditor.TexturePropertySingleLine(Styles.anisotropyMapText, anisotropyMap);
}
override protected void ShaderInputGUI()
{
protected override void MaterialPropertiesGUI()
{
m_MaterialEditor.ShaderProperty(materialID, Styles.materialIDText);
m_MaterialEditor.TexturePropertySingleLine(Styles.baseColorText, baseColorMap, baseColor);
m_MaterialEditor.ShaderProperty(metallic, Styles.metallicText);

m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapSText, maskMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.specularOcclusionMapText, specularOcclusionMap);
m_MaterialEditor.ShaderProperty(horizonFade, Styles.horizonFadeText);
// Triplanar only work with tangent space normal
if ((NormalMapSpace)normalMapSpace.floatValue == NormalMapSpace.ObjectSpace && ((UVBaseMapping)UVBase.floatValue == UVBaseMapping.Triplanar))
{
EditorGUILayout.HelpBox(Styles.normalMapSpaceWarning.text, MessageType.Error);
}
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, normalMap, normalScale);
m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap);

GUILayout.Label(" " + Styles.textureControlText, EditorStyles.label);
m_MaterialEditor.ShaderProperty(UVBase, Styles.UVBaseMappingText);
// UVSet0 is always set, planar and triplanar will override it.
UVMappingMask.colorValue = new Color(1.0f, 0.0f, 0.0f, 0.0f); // This is override in the shader anyway but just in case.
UVMappingPlanar.floatValue = ((UVBaseMapping)UVBase.floatValue == UVBaseMapping.Planar) ? 1.0f : 0.0f;
UVMappingMask.colorValue = new Color(1.0f, 0.0f, 0.0f, 0.0f); // This is override in the shader anyway but just in case.
if (((UVBaseMapping)UVBase.floatValue == UVBaseMapping.Planar) || ((UVBaseMapping)UVBase.floatValue == UVBaseMapping.Triplanar))
{
m_MaterialEditor.ShaderProperty(TexWorldScale, Styles.texWorldScaleText);

GUILayout.Label(" " + Styles.UVDetailMappingText.text + ": Triplanar");
}
// IF planar/triplanar is not chose, setup the UVSet chosen
// Setup the UVSet for detail, if planar/triplanar is use for base, it will override the mapping of detail (See shader code)
float X, Y, Z, W;
X = ((UVDetailMapping)UVDetail.floatValue == UVDetailMapping.UV0) ? 1.0f : 0.0f;
Y = ((UVDetailMapping)UVDetail.floatValue == UVDetailMapping.UV1) ? 1.0f : 0.0f;

m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);
}
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
m_MaterialEditor.LightmapEmissionProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
EditorGUI.indentLevel--;
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
EditorGUILayout.Space();
// The parent Base.ShaderPropertiesGUI will call DoEmissionArea
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
protected override bool ShouldEmissionBeEnabled(Material mat)
base.AssignNewShaderToMaterial(material, oldShader, newShader);
return mat.GetFloat(kEmissiveIntensity) > 0.0f;
protected override bool ShouldEmissionBeEnabled(Material mat)
protected override void SetupMaterialKeywordsAndPassInternal(Material material)
float emissiveIntensity = mat.GetFloat(kEmissiveIntensity);
var realtimeEmission = (mat.globalIlluminationFlags & MaterialGlobalIlluminationFlags.RealtimeEmissive) > 0;
return emissiveIntensity > 0.0f || realtimeEmission;
SetupMaterialKeywordsAndPass(material);
override protected void SetupMaterialKeywords(Material material)
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change
static public void SetupMaterialKeywordsAndPass(Material material)
SetupCommonOptionsKeywords(material);
SetupBaseLitKeywords(material);
SetupBaseLitMaterialPass(material);
SetKeyword(material, "_MAPPING_PLANAR", ((UVBaseMapping)material.GetFloat(kUVBase)) == UVBaseMapping.Planar);
bool perPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) == 1.0;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", perPixelDisplacement);
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap) || material.GetTexture(kDetailMap)); // With details map, we always use a normal map and Unity provide a default (0, 0, 1) normal map for ir
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap) || material.GetTexture(kDetailMap)); // With details map, we always use a normal map and Unity provide a default (0, 0, 1) normal map for ir
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kSpecularOcclusionMap));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));

SetKeyword(material, "_DETAIL_MAP", material.GetTexture(kDetailMap));
SetKeyword(material, "_SUBSURFACE_RADIUS_MAP", material.GetTexture(kSubsurfaceRadiusMap));
SetKeyword(material, "_THICKNESS_MAP", material.GetTexture(kThicknessMap));
bool needUV2 = (UVDetailMapping)material.GetFloat(kUVDetail) == UVDetailMapping.UV2 && (UVBaseMapping)material.GetFloat(kUVBase) == UVBaseMapping.UV0;
bool needUV3 = (UVDetailMapping)material.GetFloat(kUVDetail) == UVDetailMapping.UV3 && (UVBaseMapping)material.GetFloat(kUVBase) == UVBaseMapping.UV0;

material.DisableKeyword("_REQUIRE_UV2");
material.DisableKeyword("_REQUIRE_UV3");
}
material.SetInt("_StencilRef", (int)material.GetFloat(kMaterialID)); // See 'StencilBits'.
}
}
} // namespace UnityEditor

17
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/StandardSpecularToHDLitMaterialUpgrader.cs


{
class StandardSpecularToHDLitMaterialUpgrader : MaterialUpgrader
{
public StandardSpecularToHDLitMaterialUpgrader()
public StandardSpecularToHDLitMaterialUpgrader() : this("Standard (Specular setup)", "HDRenderPipeline/Lit", LitGUI.SetupMaterialKeywordsAndPass) {}
public StandardSpecularToHDLitMaterialUpgrader(string sourceShaderName, string destShaderName, MaterialFinalizer finalizer)
RenameShader("Standard (Specular setup)", "HDRenderPipeline/LitLegacySupport");
RenameShader(sourceShaderName, destShaderName, finalizer);
RenameTexture("_MainTex", "_BaseColorMap");
RenameColor("_Color", "_BaseColor");

RenameColor("_EmissionColor", "_EmissiveColor");
RenameFloat("_DetailNormalMapScale", "_DetailNormalScale");
RenameFloat("_Cutoff", "_AlphaCutoff");
RenameKeywordToFloat("_ALPHATEST_ON", "_AlphaCutoffEnable", 1f, 0f);
// the HD renderloop packs detail albedo and detail normals into a single texture.
// mapping the detail normal map, if any, to the detail map, should do the right thing if
// there is no detail albedo.
RenameTexture("_DetailNormalMap", "_DetailMap");
// Anything reasonable that can be done here?

[Test]
public void UpgradeMaterial()
{
var newShader = Shader.Find("HDRenderPipeline/LitLegacySupport");
var newShader = Shader.Find("HDRenderPipeline/Lit");
var mat = new Material(Shader.Find("Standard (Specular setup)"));
var albedo = new Texture2D(1, 1);
var normals = new Texture2D(1, 1);

mat.color = color;
mat.SetTextureScale("_MainTex", baseScale);
MaterialUpgrader.Upgrade(mat, new StandardSpecularToHDLitMaterialUpgrader(), MaterialUpgrader.UpgradeFlags.CleanupNonUpgradedProperties);
MaterialUpgrader.Upgrade(mat, this, MaterialUpgrader.UpgradeFlags.CleanupNonUpgradedProperties);
Assert.AreEqual(newShader, mat.shader);
Assert.AreEqual(albedo, mat.GetTexture("_BaseColorMap"));

Assert.IsTrue(mat.IsKeywordEnabled("_NORMALMAP"));
}
}
}

17
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/StandardToHDLitMaterialUpgrader.cs


using UnityEngine;
namespace UnityEditor.Experimental.Rendering.HDPipeline
class StandardToHDLitMaterialUpgrader : MaterialUpgrader
class StandardToHDLitMaterialUpgrader : MaterialUpgrader
public StandardToHDLitMaterialUpgrader()
public StandardToHDLitMaterialUpgrader() : this("Standard", "HDRenderPipeline/Lit", LitGUI.SetupMaterialKeywordsAndPass) { }
public StandardToHDLitMaterialUpgrader(string sourceShaderName, string destShaderName, MaterialFinalizer finalizer)
RenameShader("Standard", "HDRenderPipeline/LitLegacySupport");
RenameShader(sourceShaderName, destShaderName, finalizer);
RenameTexture("_MainTex", "_BaseColorMap");
RenameColor("_Color", "_BaseColor");

RenameColor("_EmissionColor", "_EmissiveColor");
RenameFloat("_DetailNormalMapScale", "_DetailNormalScale");
RenameFloat("_Cutoff", "_AlphaCutoff");
RenameKeywordToFloat("_ALPHATEST_ON", "_AlphaCutoffEnable", 1f, 0f);
// the HD renderloop packs detail albedo and detail normals into a single texture.
// mapping the detail normal map, if any, to the detail map, should do the right thing if

[Test]
public void UpgradeMaterial()
{
var newShader = Shader.Find("HDRenderPipeline/LitLegacySupport");
var newShader = Shader.Find("HDRenderPipeline/Lit");
var mat = new Material(Shader.Find("Standard"));
var albedo = new Texture2D(1, 1);
var normals = new Texture2D(1, 1);

mat.color = color;
mat.SetTextureScale("_MainTex", baseScale);
MaterialUpgrader.Upgrade(mat, new StandardToHDLitMaterialUpgrader(), MaterialUpgrader.UpgradeFlags.CleanupNonUpgradedProperties);
MaterialUpgrader.Upgrade(mat, this, MaterialUpgrader.UpgradeFlags.CleanupNonUpgradedProperties);
Assert.AreEqual(newShader, mat.shader);
Assert.AreEqual(albedo, mat.GetTexture("_BaseColorMap"));

Assert.IsTrue(mat.IsKeywordEnabled("_NORMALMAP"));
}
}
}

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


// fold into fresnel0
// SSS
public float subsurfaceRadius;
public float thickness;
public int subsurfaceProfile;
public float subsurfaceRadius;
public float thickness;
public int subsurfaceProfile;
public bool enableTransmission; // Read from the SSS profile
public Vector3 transmittance;
// Clearcoat
public Vector3 coatNormalWS;

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl


#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_RADIUS (1042)
#define DEBUGVIEW_LIT_BSDFDATA_THICKNESS (1043)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_PROFILE (1044)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_NORMAL_WS (1045)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS (1046)
#define DEBUGVIEW_LIT_BSDFDATA_ENABLE_TRANSMISSION (1045)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE (1046)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_NORMAL_WS (1047)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS (1048)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit.GBufferMaterial: static fields

float subsurfaceRadius;
float thickness;
int subsurfaceProfile;
bool enableTransmission;
float3 transmittance;
float3 coatNormalWS;
float coatRoughness;
};

238
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


//-----------------------------------------------------------------------------
// SurfaceData is define in Lit.cs which generate Lit.cs.hlsl
//TODO: return this original relative path include after fixing a bug in Unity side
//#include "Lit.cs.hlsl"
#include "HDRenderPipeline/Material/Lit/Lit.cs.hlsl"
#include "Lit.cs.hlsl"
// In case we pack data uint16 buffer we need to change the output render target format to uint16
// TODO: Is there a way to automate these output type based on the format declare in lit.cs ?

// Reference Lambert diffuse / GGX Specular for IBL and area lights
#ifdef HAS_LIGHTLOOP // Both reference define below need to be define only if LightLoop is present, else we get a compile error
// #define LIT_DISPLAY_REFERENCE_AREA
// #define LIT_DISPLAY_REFERENCE_IBL
//#define LIT_DISPLAY_REFERENCE_AREA
//#define LIT_DISPLAY_REFERENCE_IBL
#endif
// Use Lambert diffuse instead of Disney diffuse
// #define LIT_DIFFUSE_LAMBERT_BRDF

// TODO: Check if anisotropy with a dynamic if on anisotropy > 0 is performant. Because it may mean we always calculate both isotropy and anisotropy case.
// Maybe we should always calculate anisotropy in case of standard ? Don't think the compile can optimize correctly.
SamplerState ltc_linear_clamp_sampler;
// TODO: we can share the sampler here and name it SRL_BilinearSampler. However Unity currently doesn't support to set sampler in C#
// + to avoid the message Fragment program 'Frag' : sampler 'sampler_PreIntegratedFGD' has no matching texture and will be undefined.
SAMPLER2D(sampler_PreIntegratedFGD);
SAMPLER2D(sampler_LtcData);
// SSS parameters
#define SSS_N_PROFILES 8
#define SSS_UNIT_CONVERSION (1.0 / 300.0) // From meters to 1/3 centimeters
uint _TransmissionFlags; // One bit per profile; 1 = enabled
float _ThicknessRemaps[SSS_N_PROFILES][2]; // Remap: 0 = start, 1 = end - start
float4 _HalfRcpVariancesAndLerpWeights[SSS_N_PROFILES][2]; // 2x Gaussians per color channel, A is the the associated interpolation weight
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material
//-----------------------------------------------------------------------------

// _PreIntegratedFGD.y = Gv * Fc
// Pre integrate DisneyDiffuse FGD:
// _PreIntegratedFGD.z = DisneyDiffuse
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, sampler_PreIntegratedFGD, float2(NdotV, perceptualRoughness), 0).xyz;
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, ltc_linear_clamp_sampler, float2(NdotV, perceptualRoughness), 0).xyz;
// f0 * Gv * (1 - Fc) + Gv * Fc
specularFGD = fresnel0 * preFGD.x + preFGD.y;

#endif
}
void ConfigureTexturingForSSS(inout BSDFData bsdfData)
{
#ifdef SSS_PRE_SCATTER_TEXTURING
bsdfData.diffuseColor = bsdfData.diffuseColor;
#elif SSS_POST_SCATTER_TEXTURING
bsdfData.diffuseColor = float3(1, 1, 1);
#else // combine pre-scatter and post-scatter texturing
bsdfData.diffuseColor = sqrt(bsdfData.diffuseColor);
#endif
}
// Evaluates transmittance for a linear combination of two normalized 2D Gaussians.
// Computes results for each color channel separately.
// Ref: Real-Time Realistic Skin Translucency (2010), equation 9 (modified).
float3 ComputeTransmittance(float3 halfRcpVariance1, float lerpWeight1,
float3 halfRcpVariance2, float lerpWeight2,
float thickness, float radiusScale)
{
// Thickness and SSS radius are decoupled for artists.
// In theory, we should modify the thickness by the inverse of the radius scale of the profile.
// thickness /= radiusScale;
thickness /= SSS_UNIT_CONVERSION;
float t2 = thickness * thickness;
// TODO: 6 exponentials is kind of expensive... Should we use a LUT instead?
// lerp(exp(-t2 * halfRcpVariance1), exp(-t2 * halfRcpVariance2), lerpWeight2)
return exp(-t2 * halfRcpVariance1) * lerpWeight1 + exp(-t2 * halfRcpVariance2) * lerpWeight2;
}
//-----------------------------------------------------------------------------
// conversion function for forward
//-----------------------------------------------------------------------------

{
bsdfData.diffuseColor = surfaceData.baseColor;
bsdfData.fresnel0 = 0.028; // TODO take from subsurfaceProfile
bsdfData.subsurfaceRadius = surfaceData.subsurfaceRadius;
bsdfData.thickness = surfaceData.thickness;
// Make the Std. Dev. of 1 correspond to the effective radius of 1 cm (three-sigma rule).
bsdfData.subsurfaceRadius = SSS_UNIT_CONVERSION * surfaceData.subsurfaceRadius;
bsdfData.thickness = SSS_UNIT_CONVERSION * (_ThicknessRemaps[bsdfData.subsurfaceProfile][0] +
_ThicknessRemaps[bsdfData.subsurfaceProfile][1] * surfaceData.thickness);
bsdfData.enableTransmission = (1 << bsdfData.subsurfaceProfile) & _TransmissionFlags;
if (bsdfData.enableTransmission)
{
bsdfData.transmittance = ComputeTransmittance(_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][0].xyz,
_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][0].w,
_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][1].xyz,
_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][1].w,
bsdfData.thickness, bsdfData.subsurfaceRadius);
}
}
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT)
{

bsdfData.fresnel0 = surfaceData.specularColor;
}
#ifdef OUTPUT_SPLIT_LIGHTING
ConfigureTexturingForSSS(bsdfData);
#endif
return bsdfData;
}

}
else if (surfaceData.materialId == MATERIALID_LIT_SSS)
{
outGBuffer2 = float4(surfaceData.subsurfaceRadius, surfaceData.thickness, 0.0, surfaceData.subsurfaceProfile / 8.0); // Number of profile not define yet
outGBuffer2 = float4(surfaceData.subsurfaceRadius, surfaceData.thickness, 0.0, surfaceData.subsurfaceProfile * rcp(SSS_N_PROFILES));
}
else if (surfaceData.materialId == MATERIALID_LIT_CLEAR_COAT)
{

#endif
}
void DecodeFromGBuffer(
float4 DecodeGBuffer0(GBufferType0 encodedGBuffer0)
{
float4 decodedGBuffer0;
#if SHADEROPTIONS_PACK_GBUFFER_IN_U16
decodedGBuffer0.x = UnpackUIntToFloat(encodedGBuffer0.x, 8, 0);
decodedGBuffer0.y = UnpackUIntToFloat(encodedGBuffer0.x, 8, 8);
decodedGBuffer0.z = UnpackUIntToFloat(encodedGBuffer0.y, 8, 0);
decodedGBuffer0.w = UnpackUIntToFloat(encodedGBuffer0.y, 8, 8);
decodedGBuffer0.xyz = Gamma20ToLinear(encodedGBuffer0.xyz);
#else
decodedGBuffer0 = encodedGBuffer0;
#endif
return decodedGBuffer0;
}
void DecodeFromGBuffer(
#if SHADEROPTIONS_PACK_GBUFFER_IN_U16
GBufferType0 inGBufferU0,
GBufferType1 inGBufferU1,

#if SHADEROPTIONS_PACK_GBUFFER_IN_U16
float4 inGBuffer0, inGBuffer1, inGBuffer2, inGBuffer3;
inGBuffer0.x = UnpackUIntToFloat(inGBufferU0.x, 8, 0);
inGBuffer0.y = UnpackUIntToFloat(inGBufferU0.x, 8, 8);
inGBuffer0.z = UnpackUIntToFloat(inGBufferU0.y, 8, 0);
inGBuffer0.w = UnpackUIntToFloat(inGBufferU0.y, 8, 8);
inGBuffer0.xyz = Gamma20ToLinear(inGBuffer0.xyz);
inGBuffer0 = DecodeGBuffer0(inGBufferU0);
inGBuffer2.x = UnpackUIntToFloat(inGBufferU1.x, 8, 0);
inGBuffer2.y = UnpackUIntToFloat(inGBufferU1.x, 8, 8);
inGBuffer2.z = UnpackUIntToFloat(inGBufferU1.y, 8, 0);

{
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = 0.028; // TODO take from subsurfaceProfile
bsdfData.subsurfaceRadius = inGBuffer2.r;
bsdfData.thickness = inGBuffer2.g;
bsdfData.subsurfaceProfile = inGBuffer2.a * 8.0;
bsdfData.subsurfaceProfile = SSS_N_PROFILES * inGBuffer2.a;
// Make the Std. Dev. of 1 correspond to the effective radius of 1 cm (three-sigma rule).
bsdfData.subsurfaceRadius = SSS_UNIT_CONVERSION * inGBuffer2.r;
bsdfData.thickness = SSS_UNIT_CONVERSION * (_ThicknessRemaps[bsdfData.subsurfaceProfile][0] +
_ThicknessRemaps[bsdfData.subsurfaceProfile][1] * inGBuffer2.g);
bsdfData.enableTransmission = (1 << bsdfData.subsurfaceProfile) & _TransmissionFlags;
if (bsdfData.enableTransmission)
{
bsdfData.transmittance = ComputeTransmittance(_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][0].xyz,
_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][0].w,
_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][1].xyz,
_HalfRcpVariancesAndLerpWeights[bsdfData.subsurfaceProfile][1].w,
bsdfData.thickness, bsdfData.subsurfaceRadius);
}
}
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT)
{

bakeDiffuseLighting = inGBuffer3.rgb;
#ifdef OUTPUT_SPLIT_LIGHTING
ConfigureTexturingForSSS(bsdfData);
#endif
ApplyDebugToBSDFData(bsdfData);
}

// Note we load the matrix transpose (avoid to have to transpose it in shader)
preLightData.ltcXformGGX = 0.0;
preLightData.ltcXformGGX._m22 = 1.0;
preLightData.ltcXformGGX._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, sampler_LtcData, uv, LTC_GGX_MATRIX_INDEX, 0);
preLightData.ltcXformGGX._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0);
preLightData.ltcXformDisneyDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, sampler_LtcData, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0);
preLightData.ltcXformDisneyDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0);
float3 ltcMagnitude = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, sampler_LtcData, uv, LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX, 0).rgb;
float3 ltcMagnitude = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX, 0).rgb;
preLightData.ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r;
preLightData.ltcGGXFresnelMagnitude = ltcMagnitude.g;
preLightData.ltcDisneyDiffuseMagnitude = ltcMagnitude.b;

#ifdef HAS_LIGHTLOOP
//-----------------------------------------------------------------------------
// BSDF share between directional light, punctual light and area light (reference)
// BSDF share between directional light, punctual light and area light (reference)
//-----------------------------------------------------------------------------
void BSDF( float3 V, float3 L, float3 positionWS, PreLightData preLightData, BSDFData bsdfData,

float3 L = -lightData.forward; // Lights are pointing backward in Unity
float illuminance = saturate(dot(bsdfData.normalWS, L));
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float3 cookieColor = float3(1.0, 1.0, 1.0);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float4 cookie = float4(1.0, 1.0, 1.0, 1.0);
float shadowAttenuation = GetDirectionalShadowAttenuation(lightLoopContext, positionWS, lightData.shadowIndex, L, posInput.unPositionSS);
#ifdef SHADOWS_USE_SHADOWCTXT
float shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, lightData.shadowIndex, L, posInput.unPositionSS);
#else
float shadow = GetDirectionalShadowAttenuation(lightLoopContext, positionWS, lightData.shadowIndex, L, posInput.unPositionSS);
#endif
illuminance *= shadowAttenuation;
illuminance *= shadow;
}
[branch] if (lightData.cookieIndex >= 0 && illuminance > 0.0)

coord = coord * 0.5 + 0.5;
// Tile the texture if the 'repeat' wrap mode is enabled.
if (lightData.tileCookie)
if (lightData.tileCookie)
float4 cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
cookieColor = cookie.rgb;
illuminance *= cookie.a;
}

diffuseLighting *= (cookieColor * lightData.color) * (illuminance * lightData.diffuseScale);
specularLighting *= (cookieColor * lightData.color) * (illuminance * lightData.specularScale);
diffuseLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale);
specularLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.specularScale);
}
[branch] if (bsdfData.enableTransmission)
{
// Reverse the normal.
illuminance = saturate(dot(-bsdfData.normalWS, L));
[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0)
{
// TODO: factor out the biased position?
float3 biasedPositionWS = positionWS + bsdfData.normalWS * bsdfData.thickness;
#ifdef SHADOWS_USE_SHADOWCTXT
float shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, biasedPositionWS, lightData.shadowIndex, L, posInput.unPositionSS);
#else
float shadow = GetDirectionalShadowAttenuation(lightLoopContext, biasedPositionWS, lightData.shadowIndex, L, posInput.unPositionSS);
#endif
illuminance *= shadow;
}
illuminance *= cookie.a;
// The difference between the Disney Diffuse and the Lambertian BRDF for transmittance is negligible.
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale * Lambert());
// TODO: multiplication by 'diffuseColor' and 'transmittance' is the same for each light.
float3 transmittedLight = backLight * bsdfData.diffuseColor * bsdfData.transmittance;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += transmittedLight;
}
}

attenuation *= GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
float illuminance = saturate(dot(bsdfData.normalWS, L)) * attenuation;
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float3 cookieColor = float3(1.0, 1.0, 1.0);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float4 cookie = float4(1.0, 1.0, 1.0, 1.0);
// TODO: measure impact of having all these dynamic branch here and the gain (or not) of testing illuminace > 0

[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0)
{
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
float shadowAttenuation = GetPunctualShadowAttenuation(lightLoopContext, lightData.lightType, positionWS + offset, lightData.shadowIndex, L, posInput.unPositionSS);
shadowAttenuation = lerp(1.0, shadowAttenuation, lightData.shadowDimmer);
#ifdef SHADOWS_USE_SHADOWCTXT
float shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, lightData.shadowIndex, L, posInput.unPositionSS);
#else
float shadow = GetPunctualShadowAttenuation(lightLoopContext, lightData.lightType, positionWS + offset, lightData.shadowIndex, L, posInput.unPositionSS);
#endif
shadow = lerp(1.0, shadow, lightData.shadowDimmer);
illuminance *= shadowAttenuation;
illuminance *= shadow;
}
[branch] if (lightData.cookieIndex >= 0 && illuminance > 0.0)

// Rotate 'L' into the light space.
// We perform the negation because lights are oriented backwards (-Z).
float3 coord = mul(-L, transpose(lightToWorld));
float4 cookie;
[branch] if (lightData.lightType == GPULIGHTTYPE_SPOT)
{

cookie = SampleCookieCube(lightLoopContext, coord, lightData.cookieIndex);
}
cookieColor = cookie.rgb;
illuminance *= cookie.a;
}

diffuseLighting *= (cookieColor * lightData.color) * (illuminance * lightData.diffuseScale);
specularLighting *= (cookieColor * lightData.color) * (illuminance * lightData.specularScale);
diffuseLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale);
specularLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.specularScale);
}
[branch] if (bsdfData.enableTransmission)
{
// Reverse the normal.
illuminance = saturate(dot(-bsdfData.normalWS, L)) * attenuation;
[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0)
{
// TODO: factor out the common biased position?
float3 biasedPositionWS = positionWS + bsdfData.normalWS * bsdfData.thickness;
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
#ifdef SHADOWS_USE_SHADOWCTXT
float shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, biasedPositionWS + offset, lightData.shadowIndex, L, posInput.unPositionSS);
#else
float shadow = GetPunctualShadowAttenuation(lightLoopContext, lightData.lightType, biasedPositionWS + offset, lightData.shadowIndex, L, posInput.unPositionSS);
#endif
shadow = lerp(1.0, shadow, lightData.shadowDimmer);
illuminance *= shadow;
}
illuminance *= cookie.a;
// The difference between the Disney Diffuse and the Lambertian BRDF for transmittance is negligible.
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale * Lambert());
// TODO: multiplication by 'diffuseColor' and 'transmittance' is the same for each light.
float3 transmittedLight = backLight * bsdfData.diffuseColor * bsdfData.transmittance;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += transmittedLight;
}
}

62
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader


_Anisotropy("Anisotropy", Range(0.0, 1.0)) = 0
_AnisotropyMap("AnisotropyMap", 2D) = "white" {}
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2, Specular Color, 3)] _MaterialID("MaterialId", Int) = 0
_SubsurfaceProfile("Subsurface Profile", Int) = 0
_SubsurfaceProfile("Subsurface Profile", Float) = 0
_Thickness("Thickness", Range(0.004, 1.0)) = 0.5
_Thickness("Thickness", Range(0.004, 1.0)) = 1.0
_ThicknessMap("Thickness Map", 2D) = "white" {}
//_CoatCoverage("CoatCoverage", Range(0.0, 1.0)) = 0

_HorizonFade("Horizon fade", Range(0.0, 5.0)) = 1.0
// Stencil state
[HideInInspector] _StencilRef("_StencilRef", Int) = 0
[HideInInspector] _StencilRef("_StencilRef", Int) = 1
// Blending state
[HideInInspector] _SurfaceType("__surfacetype", Float) = 0.0

[HideInInspector] _CullMode("__cullmode", Float) = 2.0
[HideInInspector] _ZTestMode("_ZTestMode", Int) = 8
// Material Id
[HideInInspector] _MaterialId("_MaterialId", FLoat) = 0
[ToggleOff] _DoubleSidedMirrorEnable("Double sided mirror enable", Float) = 1.0
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[HideInInspector] _UVMappingPlanar("_UVMappingPlanar", Float) = 0
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2, Specular Color, 3)] _MaterialID("MaterialId", Int) = 0
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15

[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1
[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1
// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.
// 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
_EmissionColor("Color", Color) = (1, 1, 1)
}
HLSLINCLUDE

// #pragma enable_d3d11_debug_symbols
//-------------------------------------------------------------------------------------
// Variant

#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _MAPPING_TRIPLANAR
#pragma shader_feature _ _MAPPING_PLANAR _MAPPING_TRIPLANAR
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
#pragma shader_feature _EMISSIVE_COLOR

#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _SUBSURFACE_RADIUS_MAP
#pragma shader_feature _THICKNESS_MAP
#pragma shader_feature _SUBSURFACE_SCATTERING
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE
// TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ?
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON

#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
// Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet
#define SURFACE_GRADIENT
#include "ShaderLibrary/common.hlsl"
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
#include "../../../ShaderLibrary/common.hlsl"
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../ShaderPass/FragInputs.hlsl"
#include "../../ShaderPass/ShaderPass.cs.hlsl"
#include "HDRenderPipeline/Material/Lit/LitProperties.hlsl"
#include "../../Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert

Name "GBuffer" // Name is not used
Tags { "LightMode" = "GBuffer" } // This will be only for opaque object based on the RenderQueue index
Cull [_CullMode]
Cull [_CullMode]
Stencil
{

Name "GBufferDebugLighting" // Name is not used
Tags{ "LightMode" = "GBufferDebugLighting" } // This will be only for opaque object based on the RenderQueue index
Cull[_CullMode]
Cull [_CullMode]
Stencil
Stencil
Ref[_StencilRef]
Ref [_StencilRef]
Comp Always
Pass Replace
}

#define LIGHTING_DEBUG
#define SHADERPASS SHADERPASS_GBUFFER
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitSharePass.hlsl"
#include "LitData.hlsl"

#define LIGHTING_DEBUG
#define SHADERPASS SHADERPASS_FORWARD
#include "../../Lighting/Forward.hlsl"
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
// TEMP until pragma work in include
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS

466
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl


//-------------------------------------------------------------------------------------
// Fill SurfaceData/Builtin data function
//-------------------------------------------------------------------------------------
#include "ShaderLibrary/SampleUVMapping.hlsl"
#include "../SampleLayer.hlsl"
void GetBuiltinData(FragInputs input, SurfaceData surfaceData, float alpha, float depthOffset, out BuiltinData builtinData)
{

builtinData.depthOffset = depthOffset;
}
// Struct that gather UVMapping info of all layers + common calculation
// This is use to abstract the mapping that can differ on layers
LayerUV base;
LayerUV details;
UVMapping base;
UVMapping details;
LayerUV base0;
LayerUV base1;
LayerUV base2;
LayerUV base3;
UVMapping base0;
UVMapping base1;
UVMapping base2;
UVMapping base3;
LayerUV details0;
LayerUV details1;
LayerUV details2;
LayerUV details3;
UVMapping details0;
UVMapping details1;
UVMapping details2;
UVMapping details3;
LayerUV blendMask;
UVMapping blendMask;
// triplanar weight
float3 triplanarWeights;
// Store information that will be share by all UVMapping
float3 vertexNormalWS; // TODO: store also object normal map for object triplanar
float3 triplanarWeights;
#ifdef SURFACE_GRADIENT
// tangent basis for each UVSet - up to 4 for now
float3 vertexTangentWS0, vertexBitangentWS0;
float3 vertexTangentWS1, vertexBitangentWS1;
float3 vertexTangentWS2, vertexBitangentWS2;
float3 vertexTangentWS3, vertexBitangentWS3;
#endif
#ifdef SURFACE_GRADIENT
void GenerateLayerTexCoordBasisTB(FragInputs input, inout LayerTexCoord layerTexCoord)
{
float3 vertexNormalWS = input.worldToTangent[2];
layerTexCoord.vertexTangentWS0 = input.worldToTangent[0];
layerTexCoord.vertexBitangentWS0 = input.worldToTangent[1];
// TODO: We should use relative camera position here - This will be automatic when we will move to camera relative space.
float3 dPdx = ddx_fine(input.positionWS);
float3 dPdy = ddy_fine(input.positionWS);
float3 sigmaX = dPdx - dot(dPdx, vertexNormalWS) * vertexNormalWS;
float3 sigmaY = dPdy - dot(dPdy, vertexNormalWS) * vertexNormalWS;
//float flipSign = dot(sigmaY, cross(nrmVertexNormal, sigmaX) ) ? -1.0 : 1.0;
float flipSign = dot(dPdy, cross(vertexNormalWS, dPdx)) < 0.0 ? -1.0 : 1.0; // gives same as the commented out line above
// TODO: Optimize! The compiler will not be able to remove the tangent space that are not use because it can't know due to our UVMapping constant we use for both base and details
// To solve this we should track which UVSet is use for normal mapping... Maybe not as simple as it sounds
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord1, layerTexCoord.vertexTangentWS1, layerTexCoord.vertexBitangentWS1);
#if defined(_REQUIRE_UV2) || defined(_REQUIRE_UV3)
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord2, layerTexCoord.vertexTangentWS2, layerTexCoord.vertexBitangentWS2);
#endif
#if defined(_REQUIRE_UV3)
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord3, layerTexCoord.vertexTangentWS3, layerTexCoord.vertexBitangentWS3);
#endif
}
#endif
#ifndef LAYERED_LIT_SHADER
#define SAMPLER_NORMALMAP_IDX sampler_NormalMap

#endif
#include "LitDataInternal.hlsl"
// This maybe call directly by tessellation (domain) shader, thus all part regarding surface gradient must be done
// in function with FragInputs input as parameters
// layerTexCoord must have been initialize to 0 outside of this function
float3 positionWS, float3 normalWS, out LayerTexCoord layerTexCoord)
float3 positionWS, float3 vertexNormalWS, inout LayerTexCoord layerTexCoord)
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
layerTexCoord.vertexNormalWS = vertexNormalWS;
layerTexCoord.triplanarWeights = ComputeTriplanarWeights(vertexNormalWS);
bool isTriplanar = false;
#ifdef _MAPPING_TRIPLANAR
// one weight for each direction XYZ - Use vertex normal for triplanar
layerTexCoord.triplanarWeights = ComputeTriplanarWeights(normalWS);
isTriplanar = true;
int mappingType = UV_MAPPING_UVSET;
#if defined(_MAPPING_PLANAR)
mappingType = UV_MAPPING_PLANAR;
#elif defined(_MAPPING_TRIPLANAR)
mappingType = UV_MAPPING_TRIPLANAR;
// Be sure that the compiler is aware that we don't touch UV1 to UV3 for main layer so it can optimize code
// Also we have always UVset to 1, if planar/triplanar is enable, it will override it.
// Be sure that the compiler is aware that we don't use UV1 to UV3 for main layer so it can optimize code
positionWS, normalWS, _UVMappingPlanar > 0.0, isTriplanar, _TexWorldScale, layerTexCoord);
positionWS, mappingType, _TexWorldScale, layerTexCoord);
}
// This is call only in this file
// layerTexCoord must have been initialize to 0 outside of this function
void GetLayerTexCoord(FragInputs input, inout LayerTexCoord layerTexCoord)
{
#ifdef SURFACE_GRADIENT
GenerateLayerTexCoordBasisTB(input, layerTexCoord);
#endif
GetLayerTexCoord( input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.worldToTangent[2].xyz, layerTexCoord);
// Note: This function is call by both Per vertex and Per pixel displacement
float GetMaxDisplacement()
{
float maxDisplacement = 0.0;

float2 minUvSize = float2(FLT_MAX, FLT_MAX);
#if defined(_HEIGHTMAP)
if (layerTexCoord.base.isTriplanar)
if (layerTexCoord.base.mappingType == UV_MAPPING_TRIPLANAR)
{
minUvSize = min(layerTexCoord.base.uvZY * _HeightMap_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base.uvXZ * _HeightMap_TexelSize.zw, minUvSize);

#include "ShaderLibrary/PerPixelDisplacement.hlsl"
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
float ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
bool ppdEnable = false;
bool isPlanar = false;

// All variable are compile time value
isPlanar = layerTexCoord.base.isPlanar;
isTriplanar = layerTexCoord.base.isTriplanar;
isPlanar = layerTexCoord.base.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base.mappingType == UV_MAPPING_TRIPLANAR;
#endif
if (ppdEnable)

PerPixelHeightDisplacementParam ppdParam;
float height; // final height processed
float NdotV;
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
// TODO: support object space planar/triplanar ?
// TODO: implement. Require 3 call to POM + dedicated viewDirTS based on triplanar convention
// apply the 3 offset on all layers
/*
float3 viewDirTS;
float planeHeight;
int numSteps;
ppdParam.uv = layerTexCoord.base0.uvZY;
// 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);
float3 viewDirTS = ;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, abs(viewDirTS.z));
ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
// Apply offset to all triplanar UVSet
layerTexCoord.base.uvZY += offsetZY;
layerTexCoord.details.uvZY += offsetZY;
height = layerTexCoord.triplanarWeights.x * planeHeight;
(...)
*/
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);
layerTexCoord.base.uvXZ += offsetXZ;
layerTexCoord.details.uvXZ += offsetXZ;
height += layerTexCoord.triplanarWeights.y * planeHeight;
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);
layerTexCoord.base.uvXY += offsetXY;
layerTexCoord.details.uvXY += offsetXY;
height += layerTexCoord.triplanarWeights.z * planeHeight;
NdotV = 1; // TODO.
ppdParam.uv = layerTexCoord.base.uv;
ppdParam.uv = layerTexCoord.base.uv; // For planar it is uv too, not uvXZ
float3x3 worldToTangent = input.worldToTangent;
#ifdef SURFACE_GRADIENT
// The TBN is not normalize, normalize it to do per pixel displacement
worldToTangent[1] = normalize(worldToTangent[1]);
worldToTangent[2] = normalize(worldToTangent[2]);
#endif
// For planar the view vector is the world view vector (unless we want to support object triplanar ? and in this case used TransformWorldToObject)
// TODO: do we support object triplanar ? See ComputeLayerTexCoord
float3 viewDirTS = isPlanar ? float3(-V.xz, V.y) : TransformWorldToTangent(V, input.tangentToWorld);
float3 viewDirTS = isPlanar ? float3(uvXZ, V.y) : TransformWorldToTangent(V, worldToTangent);
NdotV = viewDirTS.z;
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);
// Apply offset to all UVSet
// Apply offset to all UVSet0 / planar
layerTexCoord.details.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
// 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;
return 0.0;
return (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap, sampler_HeightMap, layerTexCoord.base, lod).r - _HeightCenter) * _HeightAmplitude;
float height = (SAMPLE_UVMAPPING_TEXTURE2D_LOD(_HeightMap, sampler_HeightMap, layerTexCoord.base, lod).r - _HeightCenter) * _HeightAmplitude;
#ifdef _TESSELLATION_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;
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
LODDitheringTransition(posInput.unPositionSS, unity_LODFade.y); // Note that we pass the quantized value of LOD fade
#endif
ApplyDoubleSidedFlipOrMirror(input); // Apply double sided flip on the vertex normal
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
GetLayerTexCoord(input, layerTexCoord);
ApplyPerPixelDisplacement(input, V, layerTexCoord);
float depthOffset = 0.0;
float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord);
ApplyDepthOffsetPositionInput(V, depthOffset, posInput);
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);
#endif
// We perform the conversion to world of the normalTS outside of the GetSurfaceData

GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
// Done one time for all layered - cumulate with spec occ alpha for now
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, input.tangentToWorld[2].xyz, _HorizonFade);
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, input.worldToTangent[2].xyz, _HorizonFade);
// Caution: surfaceData must be fully initialize before calling GetBuiltinData
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);

return result;
}
#define SURFACEDATA_BLEND_VECTOR3(surfaceData, name, mask) BlendLayeredVector3(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_SCALAR(surfaceData, name, mask) BlendLayeredScalar(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_VECTOR3(surfaceData, name, mask) BlendLayeredVector3(MERGE_NAME(surfaceData, 0) MERGE_NAME(., name), MERGE_NAME(surfaceData, 1) MERGE_NAME(., name), MERGE_NAME(surfaceData, 2) MERGE_NAME(., name), MERGE_NAME(surfaceData, 3) MERGE_NAME(., name), mask);
#define SURFACEDATA_BLEND_SCALAR(surfaceData, name, mask) BlendLayeredScalar(MERGE_NAME(surfaceData, 0) MERGE_NAME(., name), MERGE_NAME(surfaceData, 1) MERGE_NAME(., name), MERGE_NAME(surfaceData, 2) MERGE_NAME(., name), MERGE_NAME(surfaceData, 3) MERGE_NAME(., name), mask);
float3 positionWS, float3 normalWS, out LayerTexCoord layerTexCoord)
float3 positionWS, float3 vertexNormalWS, inout LayerTexCoord layerTexCoord)
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
layerTexCoord.vertexNormalWS = vertexNormalWS;
layerTexCoord.triplanarWeights = ComputeTriplanarWeights(vertexNormalWS);
#if defined(_LAYER_MAPPING_TRIPLANAR_BLENDMASK) || defined(_LAYER_MAPPING_TRIPLANAR0) || defined(_LAYER_MAPPING_TRIPLANAR1) || defined(_LAYER_MAPPING_TRIPLANAR2) || defined(_LAYER_MAPPING_TRIPLANAR3)
// one weight for each direction XYZ - Use vertex normal for triplanar
layerTexCoord.triplanarWeights = ComputeTriplanarWeights(normalWS);
int mappingType = UV_MAPPING_UVSET;
#if defined(_LAYER_MAPPING_PLANAR_BLENDMASK)
mappingType = UV_MAPPING_PLANAR;
#elif defined(_LAYER_MAPPING_TRIPLANAR_BLENDMASK)
mappingType = UV_MAPPING_TRIPLANAR;
bool isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR_BLENDMASK
isTriplanar = true;
#endif
// Be sure that the compiler is aware that we don't use UV1 to UV3 for main layer and blend mask so it can optimize code
// Note: Blend mask have its dedicated mapping and tiling. And as Main layer it only use UV0
_UVMappingMask0 = float4(1.0, 0.0, 0.0, 0.0);
// Be sure that the compiler is aware that we don't touch UV1 to UV3 for main layer so it can optimize code
_UVMappingMask0.yzw = float3(0.0, 0.0, 0.0);
// Note: Blend mask have its dedicated mapping adn tiling. And as Main layer it only use UV0
// To share code, we simply call the regular code from the main layer for it save the result, then do regular call for all layers.
// 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.
positionWS, normalWS, _UVMappingPlanarBlendMask > 0.0, isTriplanar, _TexWorldScaleBlendMask, layerTexCoord, _LayerTilingBlendMask);
positionWS, mappingType, _TexWorldScaleBlendMask, layerTexCoord, _LayerTilingBlendMask);
layerTexCoord.blendMask = layerTexCoord.base0;

#ifdef _LAYER_TILING_UNIFORM_SCALE
#ifdef _LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE
// Extract scaling from world transform
float4x4 worldTransform = GetObjectToWorldMatrix();
// assuming uniform scaling, take only the first column

isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR0
isTriplanar = true;
mappingType = UV_MAPPING_UVSET;
#if defined(_LAYER_MAPPING_PLANAR0)
mappingType = UV_MAPPING_PLANAR;
#elif defined(_LAYER_MAPPING_TRIPLANAR0)
mappingType = UV_MAPPING_TRIPLANAR;
positionWS, normalWS, _UVMappingPlanar0 > 0.0, isTriplanar, _TexWorldScale0, layerTexCoord, _LayerTiling0
positionWS, mappingType, _TexWorldScale0, layerTexCoord, _LayerTiling0
isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR1
isTriplanar = true;
mappingType = UV_MAPPING_UVSET;
#if defined(_LAYER_MAPPING_PLANAR1)
mappingType = UV_MAPPING_PLANAR;
#elif defined(_LAYER_MAPPING_TRIPLANAR1)
mappingType = UV_MAPPING_TRIPLANAR;
positionWS, normalWS, _UVMappingPlanar1 > 0.0, isTriplanar, _TexWorldScale1, layerTexCoord, _LayerTiling1 * tileObjectScale);
positionWS, mappingType, _TexWorldScale1, layerTexCoord, _LayerTiling1 * tileObjectScale);
isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR2
isTriplanar = true;
mappingType = UV_MAPPING_UVSET;
#if defined(_LAYER_MAPPING_PLANAR2)
mappingType = UV_MAPPING_PLANAR;
#elif defined(_LAYER_MAPPING_TRIPLANAR2)
mappingType = UV_MAPPING_TRIPLANAR;
positionWS, normalWS, _UVMappingPlanar2 > 0.0, isTriplanar, _TexWorldScale2, layerTexCoord, _LayerTiling2 * tileObjectScale);
positionWS, mappingType, _TexWorldScale2, layerTexCoord, _LayerTiling2 * tileObjectScale);
isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR3
isTriplanar = true;
mappingType = UV_MAPPING_UVSET;
#if defined(_LAYER_MAPPING_PLANAR3)
mappingType = UV_MAPPING_PLANAR;
#elif defined(_LAYER_MAPPING_TRIPLANAR3)
mappingType = UV_MAPPING_TRIPLANAR;
positionWS, normalWS, _UVMappingPlanar3 > 0.0, isTriplanar, _TexWorldScale3, layerTexCoord, _LayerTiling3 * tileObjectScale);
positionWS, mappingType, _TexWorldScale3, layerTexCoord, _LayerTiling3 * tileObjectScale);
}
// This is call only in this file
// layerTexCoord must have been initialize to 0 outside of this function
void GetLayerTexCoord(FragInputs input, inout LayerTexCoord layerTexCoord)
{
#ifdef SURFACE_GRADIENT
GenerateLayerTexCoordBasisTB(input, layerTexCoord);
#endif
GetLayerTexCoord( input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.worldToTangent[2].xyz, layerTexCoord);
}
void ApplyTessellationTileScale(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 _TESSELLATION_TILING_SCALE
float tileObjectScale = 1.0;
#ifdef _LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE
// Extract scaling from world transform
float4x4 worldTransform = GetObjectToWorldMatrix();
// assuming uniform scaling, take only the first column
tileObjectScale = length(float3(worldTransform._m00, worldTransform._m01, worldTransform._m02));
#endif
height0 /= _LayerTiling0 * max(_BaseColorMap0_ST.x, _BaseColorMap0_ST.y);
#if !defined(_MAIN_LAYER_INFLUENCE_MODE)
height0 *= tileObjectScale; // We only affect layer0 in case we are not in influence mode (i.e we should not change the base object)
#endif
height1 /= tileObjectScale * _LayerTiling1 * max(_BaseColorMap1_ST.x, _BaseColorMap1_ST.y);
height2 /= tileObjectScale * _LayerTiling2 * max(_BaseColorMap2_ST.x, _BaseColorMap2_ST.y);
height3 /= tileObjectScale * _LayerTiling3 * max(_BaseColorMap3_ST.x, _BaseColorMap3_ST.y);
#endif
}
// This function is just syntaxic sugar to nullify height not used based on heightmap avaibility and layer

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

// Return the maximun amplitude use by all enabled heightmap
// use for tessellation culling and per pixel displacement
// TODO: For vertex displacement this should take into account the modification in ApplyTessellationTileScale but it should be conservative here (as long as tiling is not negative)
float GetMaxDisplacement()
{
float maxDisplacement = 0.0;

float2 minUvSize = float2(FLT_MAX, FLT_MAX);
#if defined(_HEIGHTMAP0)
if (layerTexCoord.base0.isTriplanar)
if (layerTexCoord.base0.mappingType == UV_MAPPING_TRIPLANAR)
{
minUvSize = min(layerTexCoord.base0.uvZY * _HeightMap0_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base0.uvXZ * _HeightMap0_TexelSize.zw, minUvSize);

#endif
#if defined(_HEIGHTMAP1)
if (layerTexCoord.base1.isTriplanar)
if (layerTexCoord.base1.mappingType == UV_MAPPING_TRIPLANAR)
{
minUvSize = min(layerTexCoord.base1.uvZY * _HeightMap1_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base1.uvXZ * _HeightMap1_TexelSize.zw, minUvSize);

#if _LAYER_COUNT >= 3
#if defined(_HEIGHTMAP2)
if (layerTexCoord.base2.isTriplanar)
if (layerTexCoord.base2.mappingType == UV_MAPPING_TRIPLANAR)
{
minUvSize = min(layerTexCoord.base2.uvZY * _HeightMap2_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base2.uvXZ * _HeightMap2_TexelSize.zw, minUvSize);

#if _LAYER_COUNT >= 4
#if defined(_HEIGHTMAP3)
if (layerTexCoord.base3.isTriplanar)
if (layerTexCoord.base3.mappingType == UV_MAPPING_TRIPLANAR)
{
minUvSize = min(layerTexCoord.base3.uvZY * _HeightMap3_TexelSize.zw, minUvSize);
minUvSize = min(layerTexCoord.base3.uvXZ * _HeightMap3_TexelSize.zw, minUvSize);

// - Blend Mask use same mapping as main layer (UVO, Planar, Triplanar)
// From these rules it mean that PPD is enable only if the user 1) ask for it, 2) if there is one heightmap enabled on active layer, 3) if mapping is the same for all layer respecting 2), 4) if mapping is UV0, planar or triplanar mapping
// Most contraint are handled by the inspector (i.e the UI) like the mapping constraint and is assumed in the shader.
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
float ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
bool ppdEnable = false;
bool isPlanar = false;

// To know if we are planar or triplanar just need to check if any of the active heightmap layer is true as they are enforce to be the same mapping
#if defined(_HEIGHTMAP0)
ppdEnable = true;
isPlanar = layerTexCoord.base0.isPlanar;
isTriplanar = layerTexCoord.base0.isTriplanar;
isPlanar = layerTexCoord.base0.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base0.mappingType == UV_MAPPING_TRIPLANAR;
isPlanar = layerTexCoord.base1.isPlanar;
isTriplanar = layerTexCoord.base1.isTriplanar;
isPlanar = layerTexCoord.base1.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base1.mappingType == UV_MAPPING_TRIPLANAR;
isPlanar = layerTexCoord.base2.isPlanar;
isTriplanar = layerTexCoord.base2.isTriplanar;
isPlanar = layerTexCoord.base2.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base2.mappingType == UV_MAPPING_TRIPLANAR;
#endif
#endif

isPlanar = layerTexCoord.base3.isPlanar;
isTriplanar = layerTexCoord.base3.isTriplanar;
isPlanar = layerTexCoord.base3.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base3.mappingType == UV_MAPPING_TRIPLANAR;
#endif
#endif

ppdParam.mainHeightInfluence = 0.0;
#endif
float height; // final height processed
float NdotV;
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{

// Apply to all layer that used triplanar
*/
height = 1;
NdotV = 1;
}
else
{

ppdParam.uv[3] = layerTexCoord.base3.uv;
float3x3 worldToTangent = input.worldToTangent;
#ifdef SURFACE_GRADIENT
// The TBN is not normalize, normalize it to do per pixel displacement
worldToTangent[1] = normalize(worldToTangent[1]);
worldToTangent[2] = normalize(worldToTangent[2]);
#endif
float3 viewDirTS = isPlanar ? float3(-V.xz, V.y) : TransformWorldToTangent(V, input.tangentToWorld);
float3 viewDirTS = isPlanar ? float3(-V.xz, V.y) : TransformWorldToTangent(V, worldToTangent);
NdotV = viewDirTS.z;
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam);
// Apply offset to all planar uvset
// _UVMappingPlanar0 will be 1.0 is planar is used - _UVMappingMask0.x will be 1.0 is UVSet0 is used;
float4 offsetWeights = isPlanar ? float4(_UVMappingPlanar0, _UVMappingPlanar1, _UVMappingPlanar2, _UVMappingPlanar3) : float4(_UVMappingMask0.x, _UVMappingMask1.x, _UVMappingMask2.x, _UVMappingMask3.x);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);
// 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);
offsetWeights = isPlanar ? float4(_UVMappingPlanar0, _UVMappingPlanar1, _UVMappingPlanar2, _UVMappingPlanar3) : float4(_UVDetailsMappingMask0.x, _UVDetailsMappingMask1.x, _UVDetailsMappingMask2.x, _UVDetailsMappingMask3.x);
offsetWeights = isPlanar ? planarWeight : float4(_UVDetailsMappingMask0.x, _UVDetailsMappingMask1.x, _UVDetailsMappingMask2.x, _UVDetailsMappingMask3.x);
layerTexCoord.details0.uv += offsetWeights.x * offset;
layerTexCoord.details1.uv += offsetWeights.y * 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 / NdotV;
return 0.0;
}
// Calculate displacement for per vertex displacement mapping

ComputeMaskWeights(blendMasks, weights);
#if defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || defined(_HEIGHTMAP2) || defined(_HEIGHTMAP3)
float height0 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap0, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base0, lod).r - _LayerCenterOffset0) * _LayerHeightAmplitude0;
float height1 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap1, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base1, lod).r - _LayerCenterOffset1) * _LayerHeightAmplitude1;
float height2 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap2, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base2, lod).r - _LayerCenterOffset2) * _LayerHeightAmplitude2;
float height3 = (SAMPLE_LAYER_TEXTURE2D_LOD(_HeightMap3, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base3, lod).r - _LayerCenterOffset3) * _LayerHeightAmplitude3;
float height0 = (SAMPLE_UVMAPPING_TEXTURE2D_LOD(_HeightMap0, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base0, lod).r - _LayerCenterOffset0) * _LayerHeightAmplitude0;
float height1 = (SAMPLE_UVMAPPING_TEXTURE2D_LOD(_HeightMap1, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base1, lod).r - _LayerCenterOffset1) * _LayerHeightAmplitude1;
float height2 = (SAMPLE_UVMAPPING_TEXTURE2D_LOD(_HeightMap2, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base2, lod).r - _LayerCenterOffset2) * _LayerHeightAmplitude2;
float height3 = (SAMPLE_UVMAPPING_TEXTURE2D_LOD(_HeightMap3, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base3, lod).r - _LayerCenterOffset3) * _LayerHeightAmplitude3;
ApplyTessellationTileScale(height0, height1, height2, height3); // Only apply with per vertex displacement
SetEnabledHeightByLayer(height0, height1, height2, height3);
float heightResult = BlendLayeredScalar(height0, height1, height2, height3, weights);

#if defined(_HEIGHT_BASED_BLEND)
#if defined(_HEIGHTMAP0) || defined(_HEIGHTMAP1) || defined(_HEIGHTMAP2) || defined(_HEIGHTMAP3)
float height0 = (SAMPLE_LAYER_TEXTURE2D(_HeightMap0, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base0).r - _LayerCenterOffset0) * _LayerHeightAmplitude0;
float height1 = (SAMPLE_LAYER_TEXTURE2D(_HeightMap1, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base1).r - _LayerCenterOffset1) * _LayerHeightAmplitude1;
float height2 = (SAMPLE_LAYER_TEXTURE2D(_HeightMap2, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base2).r - _LayerCenterOffset2) * _LayerHeightAmplitude2;
float height3 = (SAMPLE_LAYER_TEXTURE2D(_HeightMap3, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base3).r - _LayerCenterOffset3) * _LayerHeightAmplitude3;
float height0 = (SAMPLE_UVMAPPING_TEXTURE2D(_HeightMap0, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base0).r - _LayerCenterOffset0) * _LayerHeightAmplitude0;
float height1 = (SAMPLE_UVMAPPING_TEXTURE2D(_HeightMap1, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base1).r - _LayerCenterOffset1) * _LayerHeightAmplitude1;
float height2 = (SAMPLE_UVMAPPING_TEXTURE2D(_HeightMap2, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base2).r - _LayerCenterOffset2) * _LayerHeightAmplitude2;
float height3 = (SAMPLE_UVMAPPING_TEXTURE2D(_HeightMap3, SAMPLER_HEIGHTMAP_IDX, layerTexCoord.base3).r - _LayerCenterOffset3) * _LayerHeightAmplitude3;
SetEnabledHeightByLayer(height0, height1, height2, height3);
float4 heights = float4(height0, height1, height2, height3);

float3 mainNormalTS = GetNormalTS0(input, layerTexCoord, float3(0.0, 0.0, 1.0), 0.0, true, maxMipBias * (1.0 - influenceFactor));
// Add on our regular normal a bit of Main Layer normal base on influence factor. Note that this affect only the "visible" normal.
#ifdef SURFACE_GRADIENT
return normalTS + influenceFactor * mainNormalTS;
#else
#endif
}
float3 ComputeMainBaseColorInfluence(float3 baseColor0, float3 baseColor1, float3 baseColor2, float3 baseColor3, float compoMask, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])

// We want to calculate the mean color of the texture. For this we will sample a low mipmap
float textureBias = 15.0; // Use maximum bias
float3 baseMeanColor0 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap0, sampler_BaseColorMap0, layerTexCoord.base0, textureBias).rgb *_BaseColor0.rgb;
float3 baseMeanColor1 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap1, sampler_BaseColorMap0, layerTexCoord.base1, textureBias).rgb *_BaseColor1.rgb;
float3 baseMeanColor2 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap2, sampler_BaseColorMap0, layerTexCoord.base2, textureBias).rgb *_BaseColor2.rgb;
float3 baseMeanColor3 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap3, sampler_BaseColorMap0, layerTexCoord.base3, textureBias).rgb *_BaseColor3.rgb;
float3 baseMeanColor0 = SAMPLE_UVMAPPING_TEXTURE2D_BIAS(_BaseColorMap0, sampler_BaseColorMap0, layerTexCoord.base0, textureBias).rgb *_BaseColor0.rgb;
float3 baseMeanColor1 = SAMPLE_UVMAPPING_TEXTURE2D_BIAS(_BaseColorMap1, sampler_BaseColorMap0, layerTexCoord.base1, textureBias).rgb *_BaseColor1.rgb;
float3 baseMeanColor2 = SAMPLE_UVMAPPING_TEXTURE2D_BIAS(_BaseColorMap2, sampler_BaseColorMap0, layerTexCoord.base2, textureBias).rgb *_BaseColor2.rgb;
float3 baseMeanColor3 = SAMPLE_UVMAPPING_TEXTURE2D_BIAS(_BaseColorMap3, sampler_BaseColorMap0, layerTexCoord.base3, textureBias).rgb *_BaseColor3.rgb;
float3 meanColor = BlendLayeredVector3(baseMeanColor0, baseMeanColor1, baseMeanColor2, baseMeanColor3, weights);

return saturate(influenceFactor * (baseColor0 - meanColor) + baseColor);
// saturate(influenceFactor * (baseColor0 - meanColor) + baseColor);
// There is a special case when baseColor < meanColor to avoid getting negative values.
float3 factor = baseColor > meanColor ? (baseColor0 - meanColor) : (baseColor0 * baseColor / meanColor - baseColor);
return influenceFactor * factor + baseColor;
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
LODDitheringTransition(posInput.unPositionSS, unity_LODFade.y); // Note that we pass the quantized value of LOD fade
#endif
ApplyDoubleSidedFlipOrMirror(input); // Apply double sided flip on the vertex normal
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
GetLayerTexCoord(input, layerTexCoord);
ApplyPerPixelDisplacement(input, V, layerTexCoord);
float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord);
float depthOffset = 0.0;
ApplyDepthOffsetPositionInput(V, depthOffset, posInput);
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);
#endif
SurfaceData surfaceData0, surfaceData1, surfaceData2, surfaceData3;

#endif
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
surfaceData.baseColor = ComputeMainBaseColorInfluence(surfaceData0.baseColor, surfaceData1.baseColor, surfaceData2.baseColor, surfaceData3.baseColor, alpha, layerTexCoord, weights);
surfaceData.baseColor = ComputeMainBaseColorInfluence(surfaceData0.baseColor, surfaceData1.baseColor, surfaceData2.baseColor, surfaceData3.baseColor, alpha0, layerTexCoord, weights);
float3 normalTS = ComputeMainNormalInfluence(input, normalTS0, normalTS1, normalTS2, normalTS3, layerTexCoord, weights);
#else
surfaceData.baseColor = SURFACEDATA_BLEND_VECTOR3(surfaceData, baseColor, weights);

surfaceData.perceptualSmoothness = SURFACEDATA_BLEND_SCALAR(surfaceData, perceptualSmoothness, weights);
surfaceData.ambientOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, ambientOcclusion, weights);
surfaceData.metallic = SURFACEDATA_BLEND_SCALAR(surfaceData, metallic, weights);
// Init other unused parameter
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
#ifdef SURFACE_GRADIENT
surfaceData.tangentWS = normalize(input.worldToTangent[0].xyz); // The tangent is not normalize in worldToTangent when using surface gradient
#else
surfaceData.tangentWS = input.worldToTangent[0].xyz;
#endif
// Init other parameters
surfaceData.materialId = 0;
surfaceData.anisotropy = 0;
surfaceData.specular = 0.04;

GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
// Done one time for all layered - cumulate with spec occ alpha for now
surfaceData.specularOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, specularOcclusion, weights);
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, input.tangentToWorld[2].xyz, _HorizonFade);
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, input.worldToTangent[2].xyz, _HorizonFade);
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);
}

153
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


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

ADD_IDX(_UVDetailsMappingMask).y * texCoord1 +
ADD_IDX(_UVDetailsMappingMask).z * texCoord2 +
ADD_IDX(_UVDetailsMappingMask).w * texCoord3;
uvDetails *= additionalTiling.xx;
ADD_IDX(layerTexCoord.base).isPlanar = isPlanar;
ADD_IDX(layerTexCoord.base).isTriplanar = isTriplanar;
ADD_IDX(layerTexCoord.details).isPlanar = isPlanar;
ADD_IDX(layerTexCoord.details).isTriplanar = isTriplanar;
ADD_IDX(layerTexCoord.details).mappingType = ADD_IDX(layerTexCoord.base).mappingType = mappingType;
ADD_IDX(layerTexCoord.details).normalWS = ADD_IDX(layerTexCoord.base).normalWS = layerTexCoord.vertexNormalWS;
// Copy data for the uvmapping
ADD_IDX(layerTexCoord.details).triplanarWeights = ADD_IDX(layerTexCoord.base).triplanarWeights = layerTexCoord.triplanarWeights;
// TODO: Currently we only handle world planar/triplanar but we may want local planar/triplanar.
// In this case both position and normal need to be convert to object space.

float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(positionWS * worldScale, vertexNormalWS, uvXZ, uvXY, uvZY);
GetTriplanarCoordinate(positionWS * worldScale, uvXZ, uvXY, uvZY);
if (isPlanar)
// Planar is just XZ of triplanar
if (mappingType == UV_MAPPING_PLANAR)
{
uvBase = uvDetails = uvXZ;
}

ADD_IDX(layerTexCoord.details).uvXZ = TRANSFORM_TEX(uvXZ, ADD_IDX(_DetailMap));
ADD_IDX(layerTexCoord.details).uvXY = TRANSFORM_TEX(uvXY, ADD_IDX(_DetailMap));
ADD_IDX(layerTexCoord.details).uvZY = TRANSFORM_TEX(uvZY, ADD_IDX(_DetailMap));
#ifdef SURFACE_GRADIENT
// This part is only relevant for normal mapping with UV_MAPPING_UVSET
// Note: This code work only in pixel shader (as we rely on ddx), it should not be use in other context
ADD_IDX(layerTexCoord.base).tangentWS = ADD_IDX(_UVMappingMask).x * layerTexCoord.vertexTangentWS0 +
ADD_IDX(_UVMappingMask).y * layerTexCoord.vertexTangentWS1 +
ADD_IDX(_UVMappingMask).z * layerTexCoord.vertexTangentWS2 +
ADD_IDX(_UVMappingMask).w * layerTexCoord.vertexTangentWS3;
ADD_IDX(layerTexCoord.base).bitangentWS = ADD_IDX(_UVMappingMask).x * layerTexCoord.vertexBitangentWS0 +
ADD_IDX(_UVMappingMask).y * layerTexCoord.vertexBitangentWS1 +
ADD_IDX(_UVMappingMask).z * layerTexCoord.vertexBitangentWS2 +
ADD_IDX(_UVMappingMask).w * layerTexCoord.vertexBitangentWS3;
ADD_IDX(layerTexCoord.details).tangentWS = ADD_IDX(_UVDetailsMappingMask).x * layerTexCoord.vertexTangentWS0 +
ADD_IDX(_UVDetailsMappingMask).y * layerTexCoord.vertexTangentWS1 +
ADD_IDX(_UVDetailsMappingMask).z * layerTexCoord.vertexTangentWS2 +
ADD_IDX(_UVDetailsMappingMask).w * layerTexCoord.vertexTangentWS3;
ADD_IDX(layerTexCoord.details).bitangentWS = ADD_IDX(_UVDetailsMappingMask).x * layerTexCoord.vertexBitangentWS0 +
ADD_IDX(_UVDetailsMappingMask).y * layerTexCoord.vertexBitangentWS1 +
ADD_IDX(_UVDetailsMappingMask).z * layerTexCoord.vertexBitangentWS2 +
ADD_IDX(_UVDetailsMappingMask).w * layerTexCoord.vertexBitangentWS3;
#endif
}
float3 ADD_IDX(GetNormalTS)(FragInputs input, LayerTexCoord layerTexCoord, float3 detailNormalTS, float detailMask, bool useBias, float bias)

#ifdef _NORMALMAP_TANGENT_SPACE_IDX
if (useBias)
{
normalTS = SAMPLE_LAYER_NORMALMAP_BIAS(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale), bias);
normalTS = SAMPLE_UVMAPPING_NORMALMAP_BIAS(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale), bias);
normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale));
normalTS = SAMPLE_UVMAPPING_NORMALMAP(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale));
// to be able to combine object space normal with detail map we transform it to tangent space (object space normal composition is complex operation).
// to be able to combine object space normal with detail map or to apply a "scale" we transform it to tangent space (object space normal composition is complex operation).
// Note: There is no such a thing like triplanar with object space normal, so we call directly 2D function
float3 normalOS = SAMPLE_LAYER_NORMALMAP_RGB_BIAS(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale), bias).rgb;
normalTS = TransformObjectToTangent(normalOS, input.tangentToWorld);
#ifdef SURFACE_GRADIENT
// /We need to decompress the normal ourselve here as UnpackNormalRGB will return a surface gradient
float3 normalOS = SAMPLE_TEXTURE2D_BIAS(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv, bias).xyz * 2.0 - 1.0;
// normalize(normalOS) // TO CHECK: SurfaceGradientFromPerturbedNormal doesn't require normalOS to be normalize, to check
normalTS = SurfaceGradientFromPerturbedNormal(input.worldToTangent[2], normalOS);
normalTS *= ADD_IDX(_NormalScale);
#else
float3 normalOS = UnpackNormalRGB(SAMPLE_TEXTURE2D_BIAS(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv, bias), 1.0);
normalTS = TransformObjectToTangent(normalOS, input.worldToTangent);
normalTS.xy *= ADD_IDX(_NormalScale); // Scale in tangent space
normalTS = (normalTS);
#endif
float3 normalOS = SAMPLE_LAYER_NORMALMAP_RGB(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base), ADD_IDX(_NormalScale)).rgb;
normalTS = TransformObjectToTangent(normalOS, input.tangentToWorld);
#ifdef SURFACE_GRADIENT
// /We need to decompress the normal ourselve here as UnpackNormalRGB will return a surface gradient
float3 normalOS = SAMPLE_TEXTURE2D(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv).xyz * 2.0 - 1.0;
// normalize(normalOS) // TO CHECK: SurfaceGradientFromPerturbedNormal doesn't require normalOS to be normalize, to check
normalTS = SurfaceGradientFromPerturbedNormal(input.worldToTangent[2], normalOS);
normalTS *= ADD_IDX(_NormalScale);
#else
float3 normalOS = UnpackNormalRGB(SAMPLE_TEXTURE2D(ADD_IDX(_NormalMap), SAMPLER_NORMALMAP_IDX, ADD_IDX(layerTexCoord.base).uv), 1.0);
normalTS = TransformObjectToTangent(normalOS, input.worldToTangent);
normalTS.xy *= ADD_IDX(_NormalScale); // Scale in tangent space
normalTS = (normalTS);
#endif
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#ifdef SURFACE_GRADIENT
normalTS += detailNormalTS;
#else
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#endif
#ifdef SURFACE_GRADIENT
normalTS = float3(0.0, 0.0, 0.0); // No gradient
#else
#endif
#ifdef _DOUBLESIDED_ON
// Mirror the normal with the plane define by vertex normal
float3 oppositeNormalTS = float3(normalTS.xy, -normalTS.z);
// TODO : Test if GetOddNegativeScale() is necessary here in case of normal map, as GetOddNegativeScale is take into account in CreateTangentToWorld();
normalTS = input.isFrontFace ? (GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS) : (-GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS);
#endif
#endif
return normalTS;

float ADD_IDX(GetSurfaceData)(FragInputs input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData, out float3 normalTS)
{
float alpha = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).a * ADD_IDX(_BaseColor).a;
float alpha = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).a * ADD_IDX(_BaseColor).a;
// Perform alha test very early to save performance (a killed pixel will not sample textures)
#if defined(_ALPHATEST_ON) && !defined(LAYERED_LIT_SHADER)

float3 detailNormalTS = float3(0.0, 0.0, 0.0);
float detailMask = 0.0;
#ifdef _DETAIL_MAP_IDX
detailMask = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_DetailMask), SAMPLER_DETAILMASK_IDX, ADD_IDX(layerTexCoord.base)).g;
float2 detailAlbedoAndSmoothness = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_DetailMap), SAMPLER_DETAILMAP_IDX, ADD_IDX(layerTexCoord.details)).rb;
detailMask = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_DetailMask), SAMPLER_DETAILMASK_IDX, ADD_IDX(layerTexCoord.base)).g;
float2 detailAlbedoAndSmoothness = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_DetailMap), SAMPLER_DETAILMAP_IDX, ADD_IDX(layerTexCoord.details)).rb;
detailNormalTS = SAMPLE_LAYER_NORMALMAP_AG(ADD_IDX(_DetailMap), SAMPLER_DETAILMAP_IDX, ADD_IDX(layerTexCoord.details), ADD_ZERO_IDX(_DetailNormalScale));
detailNormalTS = SAMPLE_UVMAPPING_NORMALMAP_AG(ADD_IDX(_DetailMap), SAMPLER_DETAILMAP_IDX, ADD_IDX(layerTexCoord.details), ADD_ZERO_IDX(_DetailNormalScale));
surfaceData.baseColor = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).rgb * ADD_IDX(_BaseColor).rgb;
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 * saturate(detailAlbedo * ADD_IDX(_DetailAlbedoScale)), detailMask);
#endif

surfaceData.specularOcclusion = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_SpecularOcclusionMap), SAMPLER_SPECULAROCCLUSIONMAP_IDX, ADD_IDX(layerTexCoord.base)).a;
surfaceData.specularOcclusion = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_SpecularOcclusionMap), SAMPLER_SPECULAROCCLUSIONMAP_IDX, ADD_IDX(layerTexCoord.base)).a;
#else
// The specular occlusion will be perform outside the internal loop
surfaceData.specularOcclusion = 1.0;

normalTS = ADD_IDX(GetNormalTS)(input, layerTexCoord, detailNormalTS, detailMask, false, 0.0);
#if defined(_MASKMAP_IDX)
surfaceData.perceptualSmoothness = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_MaskMap), SAMPLER_MASKMAP_IDX, ADD_IDX(layerTexCoord.base)).a;
surfaceData.perceptualSmoothness = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_MaskMap), SAMPLER_MASKMAP_IDX, ADD_IDX(layerTexCoord.base)).a;
#else
surfaceData.perceptualSmoothness = 1.0;
#endif

// MaskMap is RGBA: Metallic, Ambient Occlusion (Optional), emissive Mask (Optional), Smoothness
#ifdef _MASKMAP_IDX
surfaceData.metallic = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_MaskMap), SAMPLER_MASKMAP_IDX, ADD_IDX(layerTexCoord.base)).r;
surfaceData.ambientOcclusion = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_MaskMap), SAMPLER_MASKMAP_IDX, ADD_IDX(layerTexCoord.base)).g;
surfaceData.metallic = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_MaskMap), SAMPLER_MASKMAP_IDX, ADD_IDX(layerTexCoord.base)).r;
surfaceData.ambientOcclusion = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_MaskMap), SAMPLER_MASKMAP_IDX, ADD_IDX(layerTexCoord.base)).g;
#else
surfaceData.metallic = 1.0;
surfaceData.ambientOcclusion = 1.0;

// This part of the code is not used in case of layered shader but we keep the same macro system for simplicity
#if !defined(LAYERED_LIT_SHADER)
#ifdef _SUBSURFACE_SCATTERING
#else
surfaceData.materialId = (_MaterialID == MATERIALID_LIT_SSS) ? 0 : _MaterialID;
#endif
#ifdef _NORMALMAP_TANGENT_SPACE_IDX // Normal and tangent use same space
float3 tangentTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_TangentMap), ADD_ZERO_IDX(sampler_TangentMap), ADD_IDX(layerTexCoord.base), 1.0);
surfaceData.tangentWS = TransformTangentToWorld(tangentTS, input.tangentToWorld);
#else // Object space
float3 tangentOS = SAMPLE_LAYER_NORMALMAP_RGB(ADD_IDX(_TangentMap), ADD_ZERO_IDX(sampler_TangentMap), ADD_IDX(layerTexCoord.base), 1.0).rgb;
#ifdef _NORMALMAP_TANGENT_SPACE_IDX // Normal and tangent use same space
float3 tangentTS = SAMPLE_UVMAPPING_NORMALMAP(_TangentMap, sampler_TangentMap, layerTexCoord.base, 1.0);
surfaceData.tangentWS = TransformTangentToWorld(tangentTS, input.worldToTangent);
#else // Object space
// Note: There is no such a thing like triplanar with object space normal, so we call directly 2D function
float3 tangentOS = UnpackNormalRGB(SAMPLE_TEXTURE2D(_TangentMap, sampler_TangentMap, layerTexCoord.base.uv), 1.0);
#endif
#endif
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
#ifdef SURFACE_GRADIENT
surfaceData.tangentWS = normalize(input.worldToTangent[0].xyz); // The tangent is not normalize in worldToTangent when using surface gradient
#else
surfaceData.tangentWS = input.worldToTangent[0].xyz;
#endif
// TODO: Is there anything todo regarding flip normal but for the tangent ?
surfaceData.anisotropy = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_AnisotropyMap), ADD_ZERO_IDX(sampler_AnisotropyMap), ADD_IDX(layerTexCoord.base)).b;
surfaceData.anisotropy = SAMPLE_UVMAPPING_TEXTURE2D(_AnisotropyMap, sampler_AnisotropyMap, layerTexCoord.base).b;
#else
surfaceData.anisotropy = 1.0;
#endif

surfaceData.subsurfaceProfile = _SubsurfaceProfile;
#ifdef _SUBSURFACE_RADIUS_MAP
surfaceData.subsurfaceRadius = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_SubsurfaceRadiusMap), ADD_ZERO_IDX(sampler_SubsurfaceRadiusMap), ADD_IDX(layerTexCoord.base)).r * _SubsurfaceRadius;
surfaceData.subsurfaceRadius = SAMPLE_UVMAPPING_TEXTURE2D(_SubsurfaceRadiusMap, sampler_SubsurfaceRadiusMap, layerTexCoord.base).r * _SubsurfaceRadius;
surfaceData.subsurfaceProfile = 0;
surfaceData.thickness = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_ThicknessMap), ADD_ZERO_IDX(sampler_ThicknessMap), ADD_IDX(layerTexCoord.base)).r;
surfaceData.thickness = SAMPLE_UVMAPPING_TEXTURE2D(_ThicknessMap, sampler_ThicknessMap, layerTexCoord.base).r;
#else
surfaceData.thickness = _Thickness;
#endif

// Layered shader only support materialId 0
surfaceData.materialId = 0;
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
surfaceData.anisotropy = 0;
surfaceData.specular = 0.04;
// All these parameters are ignore as they are re-setup outside of the layers function
surfaceData.tangentWS = float3(0.0, 0.0, 0.0);
surfaceData.anisotropy = 0.0;
surfaceData.specular = 0.0;
surfaceData.subsurfaceRadius = 1.0;
surfaceData.subsurfaceRadius = 0.0;
surfaceData.coatPerceptualSmoothness = 1.0;
surfaceData.coatPerceptualSmoothness = 0.0;
surfaceData.specularColor = float3(0.0, 0.0, 0.0);
#endif // #if !defined(LAYERED_LIT_SHADER)

69
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl


// shared constant between lit and layered lit
float _AlphaCutoff;
float4 _DoubleSidedConstants;
float _HorizonFade;
float _PPDMaxSamples;
float _PPDMinSamples;
float _PPDLodThreshold;
TEXTURE2D(_DiffuseLightingMap);
SAMPLER2D(sampler_DiffuseLightingMap);
TEXTURE2D(_DistortionVectorMap);
SAMPLER2D(sampler_DistortionVectorMap);
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);
SAMPLER2D(sampler_EmissiveColorMap);
float _EmissiveIntensity;
// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.
// 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;
#ifndef LAYERED_LIT_SHADER
// Set of users variables

//TEXTURE2D(_CoatRoughnessMap);
//SAMPLER2D(sampler_CoatRoughnessMap);
TEXTURE2D(_DiffuseLightingMap);
SAMPLER2D(sampler_DiffuseLightingMap);
TEXTURE2D(_DistortionVectorMap);
SAMPLER2D(sampler_DistortionVectorMap);
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);
SAMPLER2D(sampler_EmissiveColorMap);
float _EmissiveIntensity;
float _AlphaCutoff;
float _HorizonFade;
float _UVMappingPlanar;
float _PPDMaxSamples;
float _PPDMinSamples;
float _PPDLodThreshold;
#else // LAYERED_LIT_SHADER

PROP_DECL(float, _HeightAmplitude);
PROP_DECL(float, _HeightCenter);
TEXTURE2D(_DiffuseLightingMap);
SAMPLER2D(sampler_DiffuseLightingMap);
TEXTURE2D(_DistortionVectorMap);
SAMPLER2D(sampler_DistortionVectorMap);
TEXTURE2D(_LayerMaskMap);
SAMPLER2D(sampler_LayerMaskMap);

float _LayerTilingBlendMask;
PROP_DECL(float, _LayerTiling);
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);
SAMPLER2D(sampler_EmissiveColorMap);
float _EmissiveIntensity;
float _UVMappingPlanarBlendMask;
PROP_DECL(float, _UVMappingPlanar);
float _AlphaCutoff;
float _HorizonFade;
float _PPDMaxSamples;
float _PPDMinSamples;
float _PPDLodThreshold;
#endif // LAYERED_LIT_SHADER
// Tessellation specific

float _TessellationShapeFactor;
float _TessellationBackFaceCullEpsilon;
float _TessellationObjectScale;
float _TessellationTilingScale;
#endif

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


bool frustumCulled = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])unity_CameraWorldClipPlanes);
bool faceCull = false;
// We use the position of the primary (scene view) camera in order
// to have identical tessellation levels for both the scene view and
// shadow views. Otherwise, depth comparisons become meaningless!
float3 camPosWS = _WorldSpaceCameraPos;
faceCull = BackFaceCullTriangle(p0, p1, p2, _TessellationBackFaceCullEpsilon, _WorldSpaceCameraPos);
faceCull = BackFaceCullTriangle(p0, p1, p2, _TessellationBackFaceCullEpsilon, camPosWS);
}
#endif

// Distance based tessellation
if (_TessellationFactorMaxDistance > 0.0)
{
float3 distFactor = GetDistanceBasedTessFactor(p0, p1, p2, _WorldSpaceCameraPos, _TessellationFactorMinDistance, _TessellationFactorMaxDistance);
float3 distFactor = GetDistanceBasedTessFactor(p0, p1, p2, camPosWS, _TessellationFactorMinDistance, _TessellationFactorMaxDistance);
// We square the disance factor as it allow a better percptual descrease of vertex density.
tessFactor *= distFactor * distFactor;
}

{
// This call will work for both LayeredLit and Lit shader
LayerTexCoord layerTexCoord;
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
GetLayerTexCoord(
#ifdef VARYINGS_DS_NEED_TEXCOORD0
input.texCoord0,

#else
float2(0.0, 0.0),
#endif
input.positionWS,
input.positionWS,
input.normalWS,
layerTexCoord);

69
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader


_Anisotropy("Anisotropy", Range(0.0, 1.0)) = 0
_AnisotropyMap("AnisotropyMap", 2D) = "white" {}
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2, Specular Color, 3)] _MaterialID("MaterialId", Int) = 0
_Thickness("Thickness", Range(0.004, 1.0)) = 0.5
_Thickness("Thickness", Range(0.004, 1.0)) = 1.0
_ThicknessMap("Thickness Map", 2D) = "white" {}
//_CoatCoverage("CoatCoverage", Range(0.0, 1.0)) = 0

_HorizonFade("Horizon fade", Range(0.0, 5.0)) = 1.0
// Stencil state
[HideInInspector] _StencilRef("_StencilRef", Int) = 0
[HideInInspector] _StencilRef("_StencilRef", Int) = 1
// Blending state
[HideInInspector] _SurfaceType("__surfacetype", Float) = 0.0

[HideInInspector] _CullMode("__cullmode", Float) = 2.0
[HideInInspector] _ZTestMode("_ZTestMode", Int) = 8
// Material Id
[HideInInspector] _MaterialId("_MaterialId", FLoat) = 0
[ToggleOff] _DoubleSidedMirrorEnable("Double sided mirror enable", Float) = 1.0
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0)
[HideInInspector] _UVMappingPlanar("_UVMappingPlanar", Float) = 0
[Enum(Standard, 0, Subsurface Scattering, 1, Clear Coat, 2, Specular Color, 3)] _MaterialID("MaterialId", Int) = 0
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15

[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1
// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.
// 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
_EmissionColor("Color", Color) = (1, 1, 1)
// Tessellation specific
[Enum(Phong, 0, Displacement, 1, DisplacementPhong, 2)] _TessellationMode("Tessellation mode", Float) = 0
_TessellationFactor("Tessellation Factor", Range(0.0, 15.0)) = 4.0

_TessellationShapeFactor("Tessellation shape factor", Range(0.0, 1.0)) = 0.75 // Only use with Phong
_TessellationBackFaceCullEpsilon("Tessellation back face epsilon", Range(-1.0, 0.0)) = -0.25
[ToggleOff] _TessellationObjectScale("Tessellation object scale", Float) = 0.0
[ToggleOff] _TessellationTilingScale("Tessellation tiling height scale", Float) = 1.0
// TODO: Handle culling mode for backface culling
}

#pragma only_renderers d3d11 ps4// TEMP: until we go futher in dev
// #pragma enable_d3d11_debug_symbols
//-------------------------------------------------------------------------------------
// Variant

#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _TESSELLATION_TILING_SCALE
#pragma shader_feature _MAPPING_TRIPLANAR
#pragma shader_feature _ _MAPPING_PLANAR _MAPPING_TRIPLANAR
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _NORMALMAP
#pragma shader_feature _NORMALMAP
#pragma shader_feature _MASKMAP
#pragma shader_feature _SPECULAROCCLUSIONMAP
#pragma shader_feature _EMISSIVE_COLOR_MAP

#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _SUBSURFACE_RADIUS_MAP
#pragma shader_feature _THICKNESS_MAP
#pragma shader_feature _SUBSURFACE_SCATTERING
// enable dithering LOD crossfade
#pragma multi_compile _ LOD_FADE_CROSSFADE
// TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ?
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON

#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#define TESSELLATION_ON
// Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet
#define SURFACE_GRADIENT
#include "ShaderLibrary/common.hlsl"
#include "ShaderLibrary/tessellation.hlsl"
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
#include "../../../ShaderLibrary/common.hlsl"
#include "../../../ShaderLibrary/tessellation.hlsl"
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../ShaderPass/FragInputs.hlsl"
#include "../../ShaderPass/ShaderPass.cs.hlsl"
#include "HDRenderPipeline/Material/Lit/LitProperties.hlsl"
#include "../../Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert

Name "GBuffer" // Name is not used
Tags { "LightMode" = "GBuffer" } // This will be only for opaque object based on the RenderQueue index
Cull [_CullMode]
Cull [_CullMode]
Stencil
{

Name "GBufferDebugLighting" // Name is not used
Tags{ "LightMode" = "GBufferDebugLighting" } // This will be only for opaque object based on the RenderQueue index
Cull[_CullMode]
Cull [_CullMode]
Stencil
Stencil
Ref[_StencilRef]
Ref [_StencilRef]
Comp Always
Pass Replace
}

#define LIGHTING_DEBUG
#define SHADERPASS SHADERPASS_GBUFFER
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitSharePass.hlsl"
#include "LitData.hlsl"

HLSLPROGRAM
// Lightmap memo
// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light,
// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light,
// both direct and indirect lighting) will hand up in the "regular" lightmap->LIGHTMAP_ON.
// No tessellation for Meta pass

HLSLPROGRAM
// TODO: Tesselation can't work with velocity for now...
#pragma hull Hull
#pragma domain Domain
#define SHADERPASS SHADERPASS_VELOCITY
#include "../../Material/Material.hlsl"

#define LIGHTING_DEBUG
#define SHADERPASS SHADERPASS_FORWARD
#include "../../Lighting/Forward.hlsl"
#include "HDRenderPipeline/Debug/HDRenderPipelineDebug.cs.hlsl"
#include "HDRenderPipeline/Debug/DebugLighting.hlsl"
#include "../../Debug/HDRenderPipelineDebug.cs.hlsl"
#include "../../Debug/DebugLighting.hlsl"
// TEMP until pragma work in include
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS

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

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LtcData.DisneyDiffuse.cs


{
public partial class RenderLoop : Object
{
static double[,] s_LtcDisneyDiffuseMatrixData = new double[k_LtcLUTResolution * k_LtcLUTResolution, k_LtcLUTMatrixDim * k_LtcLUTMatrixDim]
public static double[,] s_LtcDisneyDiffuseMatrixData = new double[k_LtcLUTResolution * k_LtcLUTResolution, k_LtcLUTMatrixDim * k_LtcLUTMatrixDim]
{
{1.018309, 0, 0.000000, 0, 1.018309, 0, 0.000000, 0, 1},
{1.018309, 0, 0.000000, 0, 1.018309, 0, 0.000000, 0, 1},

{1.106979, 0, 0.286686, 0, 1.061540, 0, -0.391058, 0, 1}
};
static float[] s_LtcDisneyDiffuseMagnitudeData = new float[k_LtcLUTResolution * k_LtcLUTResolution]
public static float[] s_LtcDisneyDiffuseMagnitudeData = new float[k_LtcLUTResolution * k_LtcLUTResolution]
{
0.978932f,
0.978932f,

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LtcData.GGX.cs


using UnityEngine;
using UnityEngine;
using UnityEngine.Rendering;
using System;

// This table is precomputed for squared roughness and normalized so that last entry
// is 1 and thus does not need to be store in a texture.
static double[,] s_LtcGGXMatrixData = new double[k_LtcLUTResolution * k_LtcLUTResolution, k_LtcLUTMatrixDim * k_LtcLUTMatrixDim]
public static double[,] s_LtcGGXMatrixData = new double[k_LtcLUTResolution * k_LtcLUTResolution, k_LtcLUTMatrixDim * k_LtcLUTMatrixDim]
{
{499.999756, 0, 0.000000, 0, 499.999756, 0, 0.000000, 0, 1},
{499.999756, 0, 0.000000, 0, 499.999756, 0, 0.000000, 0, 1},

{0.609037, 0, -0.053470, 0, 0.607151, 0, 0.031450, 0, 1}
};
static float[] s_LtcGGXMagnitudeData = new float[k_LtcLUTResolution * k_LtcLUTResolution]
public static float[] s_LtcGGXMagnitudeData = new float[k_LtcLUTResolution * k_LtcLUTResolution]
{
1.000000f,
1.000000f,

0.887423f
};
static float[] s_LtcGGXFresnelData = new float[k_LtcLUTResolution * k_LtcLUTResolution]
public static float[] s_LtcGGXFresnelData = new float[k_LtcLUTResolution * k_LtcLUTResolution]
{
0.000000f,
0.000000f,

81
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader


HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
// #pragma enable_d3d11_debug_symbols
#pragma multi_compile _ FILTER_HORIZONTAL
#pragma shader_feature _ SSS_PRE_SCATTER_TEXTURING SSS_POST_SCATTER_TEXTURING
#pragma multi_compile _ FILTER_HORIZONTAL_AND_COMBINE
#include "ShaderLibrary/Common.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "../../../../ShaderLibrary/Common.hlsl"
#include "../../../ShaderConfig.cs.hlsl"
#include "../../../ShaderVariables.hlsl"
#define UNITY_MATERIAL_LIT // Need to be defined before including Material.hlsl
#include "../../../Material/Material.hlsl"
//-------------------------------------------------------------------------------------
// Inputs & outputs

#define N_SAMPLES 7
#define N_SAMPLES 11
float4 _FilterKernels[N_PROFILES][N_SAMPLES + 1]; // RGB = weights, A = radial distance
float4x4 _InvProjMatrix;
float4 _FilterKernels[N_PROFILES][N_SAMPLES]; // RGB = weights, A = radial distance
float4 _HalfRcpWeightedVariances[N_PROFILES]; // RGB for chromatic, A for achromatic
#ifndef SSS_PRE_SCATTER_TEXTURING
TEXTURE2D(_GBufferTexture0); // RGB = baseColor, A = spec. occlusion
#endif
TEXTURE2D_FLOAT(_CameraDepthTexture);
TEXTURE2D(_GBufferTexture2);
TEXTURE2D(_IrradianceSource);
TEXTURE2D(_GBufferTexture2); // R = SSS radius, G = SSS thickness, A = SSS profile
TEXTURE2D(_IrradianceSource); // RGB = irradiance on the back side of the object
//-------------------------------------------------------------------------------------
// Implementation

float4 Frag(Varyings input) : SV_Target
{
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(0, 0));
int profileID = int(gBufferData.y * N_PROFILES);
float distScale = gBufferData.x * 0.01;
int profileID = N_PROFILES * gBufferData.y;
// Make the Std. Dev. of 1 correspond to the effective radius of 1 cm (three-sigma rule).
float distScale = (1.0 / 300.0) * gBufferData.x;
float rawDepth = LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).r;
float rawDepth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).r;
float fragWidth = ddx(centerPosVS.x);
float fragheight = ddy(centerPosVS.y);
float fragWidth = ddx_fine(centerPosVS.x);
float fragheight = ddy_fine(centerPosVS.y);
#ifdef FILTER_HORIZONTAL
#ifdef FILTER_HORIZONTAL_AND_COMBINE
float stepSize = stepSizeX;
float2 unitDirection = float2(1, 0);
#else

float2 scaledDirection = distScale * stepSize * unitDirection;
// Load (1 / (2 * Variance)) for bilateral weighting.
float2 scaledDirection = distScale * stepSize * unitDirection;
float phi = 0; // Random rotation; unused for now
float2x2 rotationMatrix = float2x2(cos(phi), -sin(phi), sin(phi), cos(phi));
float2 rotatedDirection = mul(rotationMatrix, scaledDirection);
// Load (1 / (2 * WeightedVariance)) for bilateral weighting.
float3 halfRcpVariance = _FilterKernels[profileID][N_SAMPLES].rgb;
float3 halfRcpVariance = _HalfRcpWeightedVariances[profileID].rgb;
float halfRcpVariance = _FilterKernels[profileID][N_SAMPLES].a;
float halfRcpVariance = _HalfRcpWeightedVariances[profileID].a;
// Accumulate filtered irradiance (already weighted by (albedo / Pi)).
float3 totalIrradiance = sampleIrradiance * sampleWeight;
// Accumulate filtered irradiance.
float3 totalIrradiance = sampleWeight * sampleIrradiance;
// Make sure bilateral filtering does not cause energy loss.
// TODO: ask Morten if there is a better way to do this.

for (int i = 1; i < N_SAMPLES; i++)
{
samplePosition = posInput.unPositionSS + scaledDirection * _FilterKernels[profileID][i].a;
samplePosition = posInput.unPositionSS + rotatedDirection * _FilterKernels[profileID][i].a;
rawDepth = LOAD_TEXTURE2D(_CameraDepthTexture, samplePosition).r;
sampleIrradiance = LOAD_TEXTURE2D(_IrradianceSource, samplePosition).rgb;
rawDepth = LOAD_TEXTURE2D(_MainDepthTexture, samplePosition).r;
sampleIrradiance = LOAD_TEXTURE2D(_IrradianceSource, samplePosition).rgb;
// Apply bilateral weighting.
// Ref #1: Skin Rendering by Pseudo–Separable Cross Bilateral Filtering.

sampleWeight *= exp(-zDistance * zDistance * halfRcpVariance);
totalIrradiance += sampleIrradiance * sampleWeight;
totalIrradiance += sampleWeight * sampleIrradiance;
#ifdef SSS_PRE_SCATTER_TEXTURING
float3 diffuseContrib = float3(1, 1, 1);
#elif SSS_POST_SCATTER_TEXTURING
float3 diffuseColor = DecodeGBuffer0(LOAD_TEXTURE2D(_GBufferTexture0, posInput.unPositionSS)).rgb;
float3 diffuseContrib = diffuseColor;
#else // combine pre-scatter and post-scatter texturing
float3 diffuseColor = DecodeGBuffer0(LOAD_TEXTURE2D(_GBufferTexture0, posInput.unPositionSS)).rgb;
float3 diffuseContrib = sqrt(diffuseColor);
#endif
#ifdef FILTER_HORIZONTAL_AND_COMBINE
return float4(diffuseContrib * totalIrradiance / totalWeight, 1.0);
#else
#endif
}
ENDHLSL
}

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/PreIntegratedFGD.shader


#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#include "ShaderLibrary/Common.hlsl"
#include "ShaderLibrary/ImageBasedLighting.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "../../../../ShaderLibrary/Common.hlsl"
#include "../../../../ShaderLibrary/ImageBasedLighting.hlsl"
#include "../../../ShaderVariables.hlsl"
struct Attributes

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDepthPass.hlsl


// Varying - Use for pixel shader
// This second set of define allow to say which varyings will be output in the vertex (no more tesselation)
#if REQUIRE_TANGENT_TO_WORLD
#define VARYINGS_NEED_POSITION_WS // Required to get view vector
#define VARYINGS_NEED_TANGENT_TO_WORLD
#endif

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitDistortionPass.hlsl


// Varying - Use for pixel shader
// This second set of define allow to say which varyings will be output in the vertex (no more tesselation)
#if REQUIRE_TANGENT_TO_WORLD
#define VARYINGS_NEED_POSITION_WS // Required to get view vector
#define VARYINGS_NEED_TANGENT_TO_WORLD
#endif

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/ShaderPass/LitVelocityPass.hlsl


#define VARYINGS_NEED_POSITION_WS
#if REQUIRE_TANGENT_TO_WORLD
#define VARYINGS_NEED_POSITION_WS // Required to get view vector
#define VARYINGS_NEED_TANGENT_TO_WORLD
#endif

18
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Material.hlsl


#ifndef UNITY_MATERIAL_INCLUDED
#define UNITY_MATERIAL_INCLUDED
#include "ShaderLibrary/Color.hlsl"
#include "ShaderLibrary/Packing.hlsl"
#include "ShaderLibrary/BSDF.hlsl"
#include "ShaderLibrary/Debug.hlsl"
#include "ShaderLibrary/GeometricTools.hlsl"
#include "ShaderLibrary/CommonMaterial.hlsl"
#include "ShaderLibrary/EntityLighting.hlsl"
#include "ShaderLibrary/ImageBasedLighting.hlsl"
#include "../../ShaderLibrary/Color.hlsl"
#include "../../ShaderLibrary/Packing.hlsl"
#include "../../ShaderLibrary/BSDF.hlsl"
#include "../../ShaderLibrary/Debug.hlsl"
#include "../../ShaderLibrary/GeometricTools.hlsl"
#include "../../ShaderLibrary/CommonMaterial.hlsl"
#include "../../ShaderLibrary/EntityLighting.hlsl"
#include "../../ShaderLibrary/ImageBasedLighting.hlsl"
//-----------------------------------------------------------------------------
// BuiltinData

#include "Lit/Lit.hlsl"
#elif defined(UNITY_MATERIAL_UNLIT)
#include "Unlit/Unlit.hlsl"
#elif defined(UNITY_MATERIAL_IRIDESCENCE)
//#include "Iridescence/Iridescence.hlsl"
#endif
//-----------------------------------------------------------------------------

34
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/MaterialUtilities.hlsl


#endif
}
// Flipping or mirroring a normal can be done directly on the tangent space. This has the benefit to apply to the whole process either in surface gradient or not.
// This function will modify FragInputs and this is not propagate outside of GetSurfaceAndBuiltinData(). This is ok as tangent space is not use outside of GetSurfaceAndBuiltinData().
void ApplyDoubleSidedFlipOrMirror(inout FragInputs input)
{
#ifdef _DOUBLESIDED_ON
// _DoubleSidedConstants is float3(-1, -1, -1) in flip mode and float3(1, 1, -1) in mirror mode
// To get a flipped normal with the tangent space, we must flip bitangent (because it is construct from the normal) and normal
// To get a mirror normal with the tangent space, we only need to flip the normal and not the tangent
float2 flipSign = input.isFrontFace ? float2(1.0, 1.0) : _DoubleSidedConstants.yz; // TOCHECK : GetOddNegativeScale() is not necessary here as it is apply for tangent space creation.
input.worldToTangent[1] = flipSign.x * input.worldToTangent[1]; // bitangent
input.worldToTangent[2] = flipSign.y * input.worldToTangent[2]; // normal
#ifdef SURFACE_GRADIENT
// TOCHECK: seems that we don't need to invert any genBasisTB(), sign cancel. Which is expected as we deal with surface gradient.
#endif
#endif
}
void GetNormalAndTangentWS(FragInputs input, float3 V, float3 normalTS, inout float3 normalWS, inout float3 tangentWS, bool twoSided = false)
void GetNormalAndTangentWS(FragInputs input, float3 V, float3 normalTS, inout float3 normalWS, inout float3 tangentWS, bool wantNegativeNormal = false)
normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#ifdef SURFACE_GRADIENT
normalWS = SurfaceGradientResolveNormal(input.worldToTangent[2], normalTS);
#else
normalWS = TransformTangentToWorld(normalTS, input.worldToTangent);
#endif
// NdotV should not be negative for visible pixels, but it can happen due to the
// perspective projection and the normal mapping + decals. In that case, the normal
// should be modified to become valid (i.e facing the camera) to avoid weird artifacts.
// Note: certain applications (e.g. SpeedTree) require to still have negative normal to perform their own two sided lighting
// This will potentially reduce the length of the normal at edges of geometry.
GetShiftedNdotV(normalWS, V, twoSided);
GetShiftedNdotV(normalWS, V, wantNegativeNormal);
// This is use with anisotropic material
tangentWS = normalize(tangentWS - dot(tangentWS, normalWS));
}

278
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
// A Material can be authored from the shader graph or by hand. When written by hand we need to provide an inspector.
// Such a Material will share some properties between it various variant (shader graph variant or hand authored variant).
// This is the purpose of BaseLitGUI. It contain all properties that are common to all Material based on Lit template.
// For the default hand written Lit material see LitUI.cs that contain specific properties for our default implementation.
protected static class Styles
protected static class StylesBaseUnlit
public static string optionText = "Options";
public static string optionText = "Surface options";
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
public static GUIContent doubleSidedEnableText = new GUIContent("Double Sided", "This will render the two face of the objects (disable backface culling)");
public static GUIContent doubleSidedEnableText = new GUIContent("Double Sided", "This will render the two face of the objects (disable backface culling) and flip/mirror normal");
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
public static string InputsText = "Inputs";
public static string InputsMapText = "";
public static GUIContent colorText = new GUIContent("Color + Opacity", "Albedo (RGB) and Opacity (A)");
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");
public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
public static GUIContent emissiveColorWarning = new GUIContent("Ensure emissive color is non-black for emission to have effect.");
}
public enum SurfaceType

}
public enum BlendMode
{
Lerp,

Premultiply
}
void SurfaceTypePopup()
protected MaterialEditor m_MaterialEditor;
// Properties
protected MaterialProperty surfaceType = null;
protected const string kSurfaceType = "_SurfaceType";
protected MaterialProperty alphaCutoffEnable = null;
protected const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
protected MaterialProperty alphaCutoff = null;
protected const string kAlphaCutoff = "_AlphaCutoff";
protected MaterialProperty doubleSidedEnable = null;
protected const string kDoubleSidedEnable = "_DoubleSidedEnable";
protected MaterialProperty blendMode = null;
protected const string kBlendMode = "_BlendMode";
protected MaterialProperty distortionEnable = null;
protected const string kDistortionEnable = "_DistortionEnable";
protected MaterialProperty distortionOnly = null;
protected const string kDistortionOnly = "_DistortionOnly";
protected MaterialProperty distortionDepthTest = null;
protected const string kDistortionDepthTest = "_DistortionDepthTest";
// See comment in LitProperties.hlsl
const string kEmissionColor = "_EmissionColor";
// The following set of functions are call by the ShaderGraph
// It will allow to display our common parameters + setup keyword correctly for them
protected abstract void FindMaterialProperties(MaterialProperty[] props);
protected abstract void SetupMaterialKeywordsAndPassInternal(Material material);
protected abstract void MaterialPropertiesGUI();
// This function will said if emissive is use or not regarding enlighten/PVR
protected abstract bool ShouldEmissionBeEnabled(Material material);
protected virtual void FindBaseMaterialProperties(MaterialProperty[] props)
{
surfaceType = FindProperty(kSurfaceType, props);
alphaCutoffEnable = FindProperty(kAlphaCutoffEnabled, props);
alphaCutoff = FindProperty(kAlphaCutoff, props);
doubleSidedEnable = FindProperty(kDoubleSidedEnable, props);
blendMode = FindProperty(kBlendMode, props);
distortionEnable = FindProperty(kDistortionEnable, props);
distortionOnly = FindProperty(kDistortionOnly, props);
distortionDepthTest = FindProperty(kDistortionDepthTest, props);
}
void SurfaceTypePopup()
mode = (SurfaceType)EditorGUILayout.Popup(Styles.surfaceTypeText, (int)mode, Styles.surfaceTypeNames);
mode = (SurfaceType)EditorGUILayout.Popup(StylesBaseUnlit.surfaceTypeText, (int)mode, StylesBaseUnlit.surfaceTypeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Surface Type");

EditorGUI.showMixedValue = false;
}
void BlendModePopup()
private void BlendModePopup()
mode = (BlendMode)EditorGUILayout.Popup(Styles.blendModeText, (int)mode, Styles.blendModeNames);
mode = (BlendMode)EditorGUILayout.Popup(StylesBaseUnlit.blendModeText, (int)mode, StylesBaseUnlit.blendModeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Blend Mode");

EditorGUI.showMixedValue = false;
}
protected void ShaderOptionsGUI()
protected virtual void BaseMaterialPropertiesGUI()
GUILayout.Label(Styles.optionText, EditorStyles.boldLabel);
GUILayout.Label(StylesBaseUnlit.optionText, EditorStyles.boldLabel);
m_MaterialEditor.ShaderProperty(distortionEnable, Styles.distortionEnableText.text);
m_MaterialEditor.ShaderProperty(distortionEnable, StylesBaseUnlit.distortionEnableText);
if (distortionEnable.floatValue == 1.0)
if (distortionEnable.floatValue == 1.0f)
m_MaterialEditor.ShaderProperty(distortionOnly, Styles.distortionOnlyText.text);
m_MaterialEditor.ShaderProperty(distortionDepthTest, Styles.distortionDepthTestText.text);
m_MaterialEditor.ShaderProperty(distortionOnly, StylesBaseUnlit.distortionOnlyText);
m_MaterialEditor.ShaderProperty(distortionDepthTest, StylesBaseUnlit.distortionDepthTestText);
m_MaterialEditor.ShaderProperty(alphaCutoffEnable, Styles.alphaCutoffEnableText.text);
if (alphaCutoffEnable.floatValue == 1.0)
m_MaterialEditor.ShaderProperty(alphaCutoffEnable, StylesBaseUnlit.alphaCutoffEnableText);
if (alphaCutoffEnable.floatValue == 1.0f)
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text);
m_MaterialEditor.ShaderProperty(alphaCutoff, StylesBaseUnlit.alphaCutoffText);
m_MaterialEditor.ShaderProperty(doubleSidedEnable, Styles.doubleSidedEnableText.text);
EditorGUI.indentLevel--;
// This function must finish with double sided option (see LitUI.cs)
m_MaterialEditor.ShaderProperty(doubleSidedEnable, StylesBaseUnlit.doubleSidedEnableText);
public void FindCommonOptionProperties(MaterialProperty[] props)
static public void SetKeyword(Material m, string keyword, bool state)
surfaceType = FindProperty(kSurfaceType, props);
blendMode = FindProperty(kBlendMode, props);
alphaCutoff = FindProperty(kAlphaCutoff, props);
alphaCutoffEnable = FindProperty(kAlphaCutoffEnabled, props);
doubleSidedEnable = FindProperty(kDoubleSidedEnable, props);
distortionEnable = FindProperty(kDistortionEnable, props);
distortionOnly = FindProperty(kDistortionOnly, props);
distortionDepthTest = FindProperty(kDistortionDepthTest, props);
if (state)
m.EnableKeyword(keyword);
else
m.DisableKeyword(keyword);
protected void SetupCommonOptionsKeywords(Material material)
{
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if ocde change
static public void SetupBaseUnlitKeywords(Material material)
{
bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f;
if (surfaceType == SurfaceType.Opaque)
{

}
}
bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f;
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Off);
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Off);
}
else
{

SetKeyword(material, "_DOUBLESIDED_ON", doubleSidedEnable);
bool distortionEnable = material.GetFloat(kDistortionEnable) == 1.0;
bool distortionOnly = material.GetFloat(kDistortionOnly) == 1.0;
bool distortionDepthTest = material.GetFloat(kDistortionDepthTest) == 1.0;
bool distortionEnable = material.GetFloat(kDistortionEnable) > 0.0f;
if (distortionEnable)
{
material.SetShaderPassEnabled("DistortionVectors", true);

material.SetShaderPassEnabled("DistortionVectors", false);
}
bool distortionDepthTest = material.GetFloat(kDistortionDepthTest) > 0.0f;
if (distortionDepthTest)
{
material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.LessEqual);
}
else
{
material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.Always);
}
SetKeyword(material, "_DISTORTION_ON", distortionEnable);
// A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect
// or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.
// The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.
MaterialEditor.FixupEmissiveFlag(material);
}
static public void SetupBaseUnlitMaterialPass(Material material)
{
bool distortionEnable = material.GetFloat(kDistortionEnable) > 0.0f;
bool distortionOnly = material.GetFloat(kDistortionOnly) > 0.0f;
// Disable all passes except dbug material
// Disable all passes except debug material
material.SetShaderPassEnabled("GBuffer", false);
material.SetShaderPassEnabled("ShadowCaster", false);
material.SetShaderPassEnabled("DepthOnly", false);
material.SetShaderPassEnabled("MotionVectors", false);
material.SetShaderPassEnabled("ForwardOnlyOpaque", false);
material.SetShaderPassEnabled("GBuffer", true);
material.SetShaderPassEnabled("ShadowCaster", true);
material.SetShaderPassEnabled("DepthOnly", true);
material.SetShaderPassEnabled("MotionVectors", true);
material.SetShaderPassEnabled("ForwardOnlyOpaque", true);
}
if (distortionDepthTest)
{
material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.LessEqual);
}
else
// Dedicated to emissive - for emissive Enlighten/PVR
protected void DoEmissionArea(Material material)
{
// Emission for GI?
if (ShouldEmissionBeEnabled(material))
material.SetInt("_ZTestMode", (int)UnityEngine.Rendering.CompareFunction.Always);
if (m_MaterialEditor.EmissionEnabledProperty())
{
// change the GI flag and fix it up with emissive as black if necessary
m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);
}
SetKeyword(material, "_DISTORTION_ON", distortionEnable);
SetupEmissionGIFlags(material);
}
protected void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword(keyword);
else
m.DisableKeyword(keyword);
}
public void ShaderPropertiesGUI(Material material)

// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
ShaderOptionsGUI();
BaseMaterialPropertiesGUI();
ShaderInputGUI();
MaterialPropertiesGUI();
DoEmissionArea(material);
m_MaterialEditor.EnableInstancingField();
SetupMaterialKeywords((Material)obj);
SetupMaterialKeywordsAndPassInternal((Material)obj);
// This is call by the inspector
FindCommonOptionProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
m_MaterialEditor = materialEditor;
// We should always do this call at the beginning
m_MaterialEditor.serializedObject.Update();
// MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
FindBaseMaterialProperties(props);
m_MaterialEditor = materialEditor;
}
// TODO: ? or remove
bool HasValidEmissiveKeyword(Material material)
{
/*
// Material animation might be out of sync with the material keyword.
// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
if (!hasEmissionKeyword && ShouldEmissionBeEnabled (material, emissionColorForRendering.colorValue))
return false;
else
return true;
*/
return true;
// We should always do this call at the end
m_MaterialEditor.serializedObject.ApplyModifiedProperties();
protected virtual void SetupEmissionGIFlags(Material material)
{
// Setup lightmap emissive flags
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{
if (ShouldEmissionBeEnabled(material))
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
else
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
material.globalIlluminationFlags = flags;
}
}
protected MaterialEditor m_MaterialEditor;
MaterialProperty surfaceType = null;
protected const string kSurfaceType = "_SurfaceType";
MaterialProperty blendMode = null;
protected const string kBlendMode = "_BlendMode";
MaterialProperty alphaCutoff = null;
protected const string kAlphaCutoff = "_AlphaCutoff";
MaterialProperty alphaCutoffEnable = null;
protected const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
MaterialProperty doubleSidedEnable = null;
protected const string kDoubleSidedEnable = "_DoubleSidedEnable";
MaterialProperty distortionEnable = null;
const string kDistortionEnable = "_DistortionEnable";
MaterialProperty distortionOnly = null;
const string kDistortionOnly = "_DistortionOnly";
MaterialProperty distortionDepthTest = null;
const string kDistortionDepthTest = "_DistortionDepthTest";
protected static string[] reservedProperties = new string[] { kSurfaceType, kBlendMode, kAlphaCutoff, kAlphaCutoffEnabled, kDoubleSidedEnable };
protected abstract void FindMaterialProperties(MaterialProperty[] props);
protected abstract void ShaderInputGUI();
protected abstract void SetupMaterialKeywords(Material material);
protected abstract bool ShouldEmissionBeEnabled(Material material);
}

58
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/UnlitUI.cs


{
class UnlitGUI : BaseUnlitGUI
{
MaterialProperty color = null;
MaterialProperty colorMap = null;
MaterialProperty emissiveColor = null;
MaterialProperty emissiveColorMap = null;
MaterialProperty emissiveIntensity = null;
protected static class Styles
{
public static string InputsText = "Inputs";
public static GUIContent colorText = new GUIContent("Color", "Color");
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");
}
protected MaterialProperty color = null;
protected const string kColor = "_Color";
protected MaterialProperty colorMap = null;
protected const string kColorMap = "_ColorMap";
protected MaterialProperty emissiveColor = null;
protected const string kEmissiveColor = "_EmissiveColor";
protected MaterialProperty emissiveColorMap = null;
protected MaterialProperty emissiveIntensity = null;
color = FindProperty("_Color", props);
colorMap = FindProperty("_ColorMap", props);
emissiveColor = FindProperty("_EmissiveColor", props);
color = FindProperty(kColor, props);
colorMap = FindProperty(kColorMap, props);
emissiveColor = FindProperty(kEmissiveColor, props);
emissiveIntensity = FindProperty("_EmissiveIntensity", props);
emissiveIntensity = FindProperty(kEmissiveIntensity, props);
override protected void ShaderInputGUI()
protected override void MaterialPropertiesGUI()
EditorGUI.indentLevel++;
GUILayout.Label(Styles.InputsText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(Styles.colorText, colorMap, color);

m_MaterialEditor.LightmapEmissionProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
}
EditorGUI.indentLevel--;
protected override bool ShouldEmissionBeEnabled(Material mat)
{
return mat.GetFloat(kEmissiveIntensity) > 0.0f;
protected override void SetupMaterialKeywords(Material material)
protected override void SetupMaterialKeywordsAndPassInternal(Material material)
SetupCommonOptionsKeywords(material);
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetupMaterialKeywordsAndPass(material);
protected override bool ShouldEmissionBeEnabled(Material mat)
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change
static public void SetupMaterialKeywordsAndPass(Material material)
float emissiveIntensity = mat.GetFloat(kEmissiveIntensity);
var realtimeEmission = (mat.globalIlluminationFlags & MaterialGlobalIlluminationFlags.RealtimeEmissive) > 0;
return emissiveIntensity > 0.0f || realtimeEmission;
SetupBaseUnlitKeywords(material);
SetupBaseUnlitMaterialPass(material);
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
}
} // namespace UnityEditor

18
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Unlit.shader


[HideInInspector] _ZTestMode("_ZTestMode", Int) = 8
[ToggleOff] _DoubleSidedEnable("Double sided enable", Float) = 0.0
// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.
// 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
_EmissionColor("Color", Color) = (1, 1, 1)
}
HLSLINCLUDE

// Include
//-------------------------------------------------------------------------------------
#include "ShaderLibrary/common.hlsl"
#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
#include "../../../ShaderLibrary/common.hlsl"
#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../ShaderPass/FragInputs.hlsl"
#include "../../ShaderPass/ShaderPass.cs.hlsl"
#include "HDRenderPipeline/Material/Unlit/UnlitProperties.hlsl"
#include "../../Material/Unlit/UnlitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/UnlitProperties.hlsl


float _EmissiveIntensity;
float _AlphaCutoff;
// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.
// 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;

68
Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Editor/PostProcessingSRPEditor.cs


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
using GradingType = PostProcessing.ColorGradingSettings.GradingType;
using EyeAdaptationType = PostProcessing.EyeAdaptationSettings.EyeAdaptationType;
using GradingType = PostProcessingSRP.ColorGradingSettings.GradingType;
using EyeAdaptationType = PostProcessingSRP.EyeAdaptationSettings.EyeAdaptationType;
[CustomEditor(typeof(PostProcessing))]
[CustomEditor(typeof(PostProcessingSRP))]
public class PostProcessingEditor : Editor
{
#region Serialized settings

public SerializedProperty center;
public SerializedProperty intensity;
public SerializedProperty smoothness;
}
public class BloomSettings
{
public SerializedProperty enabled;
public SerializedProperty intensity;
public SerializedProperty threshold;
public SerializedProperty softKnee;
public SerializedProperty radius;
public SerializedProperty lensTexture;
public SerializedProperty lensIntensity;
}
#endregion

public VignetteSettings vignetteSettings;
public BloomSettings bloomSettings;
SerializedProperty FindProperty<TValue>(Expression<Func<PostProcessing, TValue>> expr)
SerializedProperty FindProperty<TValue>(Expression<Func<PostProcessingSRP, TValue>> expr)
{
var path = Utilities.GetFieldPath(expr);
return serializedObject.FindProperty(path);

center = FindProperty(x => x.vignetteSettings.center),
intensity = FindProperty(x => x.vignetteSettings.intensity),
smoothness = FindProperty(x => x.vignetteSettings.smoothness)
};
bloomSettings = new BloomSettings
{
enabled = FindProperty(x => x.bloomSettings.enabled),
intensity = FindProperty(x => x.bloomSettings.intensity),
threshold = FindProperty(x => x.bloomSettings.threshold),
softKnee = FindProperty(x => x.bloomSettings.softKnee),
radius = FindProperty(x => x.bloomSettings.radius),
lensTexture = FindProperty(x => x.bloomSettings.lensTexture),
lensIntensity = FindProperty(x => x.bloomSettings.lensIntensity)
};
globalDithering = FindProperty(x => x.globalDithering);

Do("Color Grading", ColorGradingUI);
Do("Eye Adaptation", EyeAdaptationUI);
Do("Bloom", BloomUI);
Do("Chromatic Aberration", ChromaticAberrationUI);
Do("Vignette", VignetteUI);

void ColorGradingUI()
{
var camera = (target as PostProcessing).GetComponent<Camera>();
var camera = (target as PostProcessingSRP).GetComponent<Camera>();
if (camera != null)
{
using (new EditorGUILayout.HorizontalScope())

}
}
void BloomUI()
{
EditorGUILayout.PropertyField(bloomSettings.enabled);
if (bloomSettings.enabled.boolValue)
{
EditorGUILayout.PropertyField(bloomSettings.intensity);
EditorGUILayout.PropertyField(bloomSettings.threshold);
EditorGUILayout.PropertyField(bloomSettings.softKnee);
EditorGUILayout.PropertyField(bloomSettings.radius);
EditorGUILayout.PropertyField(bloomSettings.lensTexture);
EditorGUILayout.PropertyField(bloomSettings.lensIntensity);
bloomSettings.intensity.floatValue = Mathf.Max(0f, bloomSettings.intensity.floatValue);
bloomSettings.threshold.floatValue = Mathf.Max(0f, bloomSettings.threshold.floatValue);
bloomSettings.lensIntensity.floatValue = Mathf.Max(0f, bloomSettings.lensIntensity.floatValue);
}
}
void ChromaticAberrationUI()
{
EditorGUILayout.PropertyField(chromaSettings.enabled);

#region Color grading stuff
void SetLUTImportSettings()
{
var lut = (target as PostProcessing).colorGrading.logLut;
var lut = (target as PostProcessingSRP).colorGrading.logLut;
var importer = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(lut));
importer.textureType = TextureImporterType.Default;
importer.filterMode = FilterMode.Bilinear;

bool ValidateLutImportSettings()
{
var lut = (target as PostProcessing).colorGrading.logLut;
var lut = (target as PostProcessingSRP).colorGrading.logLut;
if (lut == null)
return true;

var targetRt = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
// Render the current frame without post processing
var oldPPState = (target as PostProcessing).enabled;
(target as PostProcessing).enabled = false;
var oldPPState = (target as PostProcessingSRP).enabled;
(target as PostProcessingSRP).enabled = false;
var oldTarget = camera.targetTexture;
var oldActive = RenderTexture.active;
camera.targetTexture = targetRt;

texture.ReadPixels(new Rect(0, 0, targetRt.width, targetRt.height), 0, 0);
camera.targetTexture = oldTarget;
RenderTexture.active = oldActive;
(target as PostProcessing).enabled = oldPPState;
(target as PostProcessingSRP).enabled = oldPPState;
// Cleanup
RenderTexture.ReleaseTemporary(stampRt);

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.shader


HLSLINCLUDE
#pragma target 4.5
#include "ShaderLibrary/Common.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
#include "../../ShaderVariables.hlsl"
#include "EyeAdaptation.hlsl"
TEXTURE2D(_MainTex);

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/EyeHistogram.compute


// Put the following line to 0 or comment it to disable vignette weighting
#define USE_VIGNETTE_WEIGHTING 1
#include "ShaderLibrary/Common.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
#include "EyeAdaptation.hlsl"
RWStructuredBuffer<uint> _Histogram;

32
Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/FinalPass.shader


HLSLINCLUDE
#pragma target 4.5
#include "ShaderLibrary/Color.hlsl"
#include "ShaderLibrary/Common.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "../../../ShaderLibrary/Color.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
#include "../../ShaderVariables.hlsl"
#include "Bloom.hlsl"
TEXTURE2D(_MainTex);
SAMPLER2D(sampler_MainTex);

float4 _LogLut_Params;
float _Exposure;
TEXTURE2D(_BloomTex);
SAMPLER2D(sampler_BloomTex);
float4 _BloomTex_TexelSize;
float2 _Bloom_Settings; // x: sampleScale, y: bloom.intensity
TEXTURE2D(_Bloom_DirtTex);
SAMPLER2D(sampler_Bloom_DirtTex);
float _Bloom_DirtIntensity;
float4 _NeutralTonemapperParams1;
float4 _NeutralTonemapperParams2;

}
#endif
#if BLOOM
{
float3 bloom = UpsampleFilter(TEXTURE2D_PARAM(_BloomTex, sampler_BloomTex), uv, _BloomTex_TexelSize.xy, _Bloom_Settings.x) * _Bloom_Settings.y; // Flipped
color += bloom;
#if BLOOM_LENS_DIRT
{
float3 dirt = SAMPLE_TEXTURE2D(_Bloom_DirtTex, sampler_Bloom_DirtTex, uv).rgb * _Bloom_DirtIntensity; // Flipped
color += bloom * dirt;
}
#endif
}
#endif
#if VIGNETTE
{
float2 d = abs(uv - _Vignette_Settings.zw) * _Vignette_Settings.x;

#pragma fragment Frag
#pragma multi_compile __ NEUTRAL_GRADING CUSTOM_GRADING
#pragma multi_compile __ EYE_ADAPTATION
#pragma multi_compile __ BLOOM
#pragma multi_compile __ BLOOM_LENS_DIRT
#pragma multi_compile __ CHROMATIC_ABERRATION
#pragma multi_compile __ VIGNETTE
#pragma multi_compile __ DITHERING

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/Resources/LutGen.shader


Shader "Hidden/HDRenderPipeline/LutGen"
Shader "Hidden/HDRenderPipeline/LutGen"
#include "ShaderLibrary/Common.hlsl"
#include "HDRenderPipeline/ShaderVariables.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
#include "../../ShaderVariables.hlsl"
#include "ColorGrading.hlsl"
float4 _LutParams;

157
Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/PostProcessingSRP.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
using GradingType = PostProcessing.ColorGradingSettings.GradingType;
using EyeAdaptationType = PostProcessing.EyeAdaptationSettings.EyeAdaptationType;
using GradingType = PostProcessingSRP.ColorGradingSettings.GradingType;
using EyeAdaptationType = PostProcessingSRP.EyeAdaptationSettings.EyeAdaptationType;
public sealed partial class PostProcessing : MonoBehaviour
public sealed partial class PostProcessingSRP : MonoBehaviour
// Quick & very dirty temporary wrapper used for bloom (easy porting from old school render
// texture blitting to command buffers)
struct RenderTextureWrapper
{
static int s_Counter = 0;
public int id;
public RenderTargetIdentifier identifier;
public int width;
public int height;
public int depth;
public FilterMode filter;
public RenderTextureFormat format;
internal void Release(CommandBuffer cmd)
{
cmd.ReleaseTemporaryRT(id);
id = 0;
}
internal static RenderTextureWrapper Create(CommandBuffer cmd, int width, int height, int depth = 0, FilterMode filter = FilterMode.Bilinear, RenderTextureFormat format = RenderTextureFormat.DefaultHDR)
{
s_Counter++;
int id = Shader.PropertyToID("_TempRenderTexture_" + s_Counter);
cmd.GetTemporaryRT(id, width, height, depth, filter, format);
return new RenderTextureWrapper
{
id = id,
identifier = new RenderTargetIdentifier(id),
width = width,
height = height,
depth = depth,
filter = filter,
format = format
};
}
}
public BloomSettings bloomSettings = new BloomSettings();
Material m_BloomMaterial;
Material m_FinalPassMaterial;
ComputeShader m_EyeCompute;

static uint[] s_EmptyHistogramBuffer = new uint[k_HistogramBins];
const int k_MaxPyramidBlurLevel = 16;
readonly RenderTextureWrapper[] m_BlurBuffer1 = new RenderTextureWrapper[k_MaxPyramidBlurLevel];
readonly RenderTextureWrapper[] m_BlurBuffer2 = new RenderTextureWrapper[k_MaxPyramidBlurLevel];
RenderTextureWrapper m_BloomTex;
bool m_FirstFrame = true;
// Don't forget to update 'EyeAdaptation.cginc' if you change these values !

void OnEnable()
{
m_EyeAdaptationMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/EyeAdaptation");
m_BloomMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/Bloom");
m_FinalPassMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/FinalPass");
m_EyeCompute = Resources.Load<ComputeShader>("EyeHistogram");

void OnDisable()
{
Utilities.Destroy(m_EyeAdaptationMaterial);
Utilities.Destroy(m_BloomMaterial);
Utilities.Destroy(m_FinalPassMaterial);
foreach (var rt in m_AutoExposurePool)

Utilities.SafeRelease(m_HistogramBuffer);
m_EyeAdaptationMaterial = null;
m_BloomMaterial = null;
m_FinalPassMaterial = null;
}

if (eyeAdaptation.enabled)
DoEyeAdaptation(camera, cmd, source);
if (bloomSettings.enabled)
DoBloom(camera, cmd, source);
if (chromaSettings.enabled)
DoChromaticAberration();

cmd.Blit(source, destination, m_FinalPassMaterial, 0);
if (bloomSettings.enabled)
m_BloomTex.Release(cmd);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}

m_FirstFrame = false;
}
void DoBloom(Camera camera, CommandBuffer cmd, RenderTargetIdentifier source)
{
m_BloomMaterial.shaderKeywords = null;
// Apply auto exposure before the prefiltering pass if needed
if (eyeAdaptation.enabled)
{
m_BloomMaterial.EnableKeyword("EYE_ADAPTATION");
m_BloomMaterial.SetTexture(Uniforms._AutoExposure, m_CurrentAutoExposure);
}
// Do bloom on a half-res buffer, full-res doesn't bring much and kills performances on
// fillrate limited platforms
int tw = camera.pixelWidth / 2;
int th = camera.pixelHeight / 2;
// Determine the iteration count
float logh = Mathf.Log(th, 2f) + bloomSettings.radius - 8f;
int logh_i = (int)logh;
int iterations = Mathf.Clamp(logh_i, 1, k_MaxPyramidBlurLevel);
// Uupdate the shader properties
float lthresh = Mathf.GammaToLinearSpace(bloomSettings.threshold);;
m_BloomMaterial.SetFloat(Uniforms._Threshold, lthresh);
float knee = lthresh * bloomSettings.softKnee + 1e-5f;
var curve = new Vector3(lthresh - knee, knee * 2f, 0.25f / knee);
m_BloomMaterial.SetVector(Uniforms._Curve, curve);
float sampleScale = 0.5f + logh - logh_i;
m_BloomMaterial.SetFloat(Uniforms._SampleScale, sampleScale);
// Prefilter pass
var prefiltered = RenderTextureWrapper.Create(cmd, tw, th, 0, FilterMode.Point);
cmd.Blit(source, prefiltered.identifier, m_BloomMaterial, 0);
var last = prefiltered;
// Construct a mip pyramid
for (int level = 0; level < iterations; level++)
{
m_BlurBuffer1[level] = RenderTextureWrapper.Create(cmd, last.width / 2, last.height / 2);
cmd.Blit(last.identifier, m_BlurBuffer1[level].identifier, m_BloomMaterial, level == 0 ? 1 : 2);
last = m_BlurBuffer1[level];
}
// Upsample and combine loop
for (int level = iterations - 2; level >= 0; level--)
{
var baseTex = m_BlurBuffer1[level];
cmd.SetGlobalTexture(Uniforms._BaseTex, baseTex.identifier); // Boooo
m_BlurBuffer2[level] = RenderTextureWrapper.Create(cmd, baseTex.width, baseTex.height);
cmd.Blit(last.identifier, m_BlurBuffer2[level].identifier, m_BloomMaterial, 3);
last = m_BlurBuffer2[level];
}
m_BloomTex = last;
// Release the temporary buffers
for (int i = 0; i < k_MaxPyramidBlurLevel; i++)
{
if (m_BlurBuffer1[i].id != 0)
m_BlurBuffer1[i].Release(cmd);
if (m_BlurBuffer2[i].id != 0 && m_BlurBuffer2[i].id != m_BloomTex.id)
m_BlurBuffer2[i].Release(cmd);
}
prefiltered.Release(cmd);
// Push everything to the uber material
m_FinalPassMaterial.EnableKeyword("BLOOM");
cmd.SetGlobalTexture(Uniforms._BloomTex, m_BloomTex.identifier);
cmd.SetGlobalVector(Uniforms._Bloom_Settings, new Vector2(sampleScale, bloomSettings.intensity));
if (bloomSettings.lensIntensity > 0f && bloomSettings.lensTexture != null)
{
m_FinalPassMaterial.EnableKeyword("BLOOM_LENS_DIRT");
cmd.SetGlobalTexture(Uniforms._Bloom_DirtTex, bloomSettings.lensTexture);
cmd.SetGlobalFloat(Uniforms._Bloom_DirtIntensity, bloomSettings.lensIntensity);
}
}
void DoChromaticAberration()
{
var spectralLut = chromaSettings.spectralTexture == null

internal static readonly int _AutoExposure = Shader.PropertyToID("_AutoExposure");
internal static readonly int _DebugWidth = Shader.PropertyToID("_DebugWidth");
internal static readonly int _Threshold = Shader.PropertyToID("_Threshold");
internal static readonly int _Curve = Shader.PropertyToID("_Curve");
internal static readonly int _SampleScale = Shader.PropertyToID("_SampleScale");
internal static readonly int _BaseTex = Shader.PropertyToID("_BaseTex");
internal static readonly int _BloomTex = Shader.PropertyToID("_BloomTex");
internal static readonly int _Bloom_Settings = Shader.PropertyToID("_Bloom_Settings");
internal static readonly int _Bloom_DirtTex = Shader.PropertyToID("_Bloom_DirtTex");
internal static readonly int _Bloom_DirtIntensity = Shader.PropertyToID("_Bloom_DirtIntensity");
internal static readonly int _ChromaticAberration_Amount = Shader.PropertyToID("_ChromaticAberration_Amount");
internal static readonly int _ChromaticAberration_Lut = Shader.PropertyToID("_ChromaticAberration_Lut");

19
Assets/ScriptableRenderPipeline/HDRenderPipeline/PostProcess/PostProcessingSRP.Settings.cs


using System;
using System;
partial class PostProcessing
partial class PostProcessingSRP
{
[Serializable]
public sealed class ColorGradingSettings

[Range(0f, 1f)] public float intensity = 0.3f;
[Range(0f, 1f)] public float smoothness = 0.3f;
}
[Serializable]
public sealed class BloomSettings
{
public bool enabled = false;
public float intensity = 0.5f;
public float threshold = 1.1f;
[Range(0f, 1f)] public float softKnee = 0.5f;
[Range(1f, 7f)] public float radius = 5f;
public Texture lensTexture;
public float lensIntensity = 3f;
}
}
}

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass.meta


fileFormatVersion: 2
guid: e3b3ad4462341ec4b86566ec1fd82c7c
guid: 057d8506536500045b3047320a4d6122
folderAsset: yes
timeCreated: 1476885561
licenseType: Pro

22
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/FragInputs.hlsl


// This structure gather all possible varying/interpolator for this shader.
//-------------------------------------------------------------------------------------
#include "HDRenderPipeline/Debug/DebugViewMaterial.cs.hlsl"
#include "../Debug/DebugViewMaterial.cs.hlsl"
struct FragInputs
{

float2 texCoord1;
float2 texCoord2;
float2 texCoord3;
float3 tangentToWorld[3]; // These 3 vectors are normalized (no need for the material to normalize) and these are only for UVSet 0
// TODO: confirm with Morten following statement
// Our TBN is orthogonal but is maybe not orthonormal in order to be compliant with external bakers (Like xnormal that use mikktspace).
// (xnormal for example take into account the interpolation when baking the normal and normalizing the tangent basis could cause distortion).
// When using worldToTangent with surface gradient, it doesn't normalize the tangent/bitangent vector (We instead use exact same scale as applied to interpolated vertex normal to avoid breaking compliance).
// this mean that any usage of worldToTangent[1] or worldToTangent[2] outside of the context of normal map (like for POM) must normalize the TBN (TCHECK if this make any difference ?)
// When not using surface gradient, each vector of worldToTangent are normalize (TODO: Maybe they should not even in case of no surface gradient ? Ask Morten)
float3x3 worldToTangent;
// For two sided lighting
bool isFrontFace;

FragInputs output;
ZERO_INITIALIZE(FragInputs, output);
output.tangentToWorld[0] = float3(0.0, 0.0, 1.0);
output.tangentToWorld[2] = float3(0.0, 0.0, 1.0);
// Init to some default value to make the computer quiet (else it output "divide by zero" warning even if value is not used).
output.worldToTangent[0] = float3(0.0, 0.0, 1.0);
output.worldToTangent[2] = float3(0.0, 0.0, 1.0);
return output;
}

result = float3(input.texCoord3, 0.0);
break;
case DEBUGVIEWVARYING_VERTEX_TANGENT_WS:
result = input.tangentToWorld[0].xyz * 0.5 + 0.5;
result = input.worldToTangent[0].xyz * 0.5 + 0.5;
result = input.tangentToWorld[1].xyz * 0.5 + 0.5;
result = input.worldToTangent[1].xyz * 0.5 + 0.5;
result = input.tangentToWorld[2].xyz * 0.5 + 0.5;
result = input.worldToTangent[2].xyz * 0.5 + 0.5;
break;
case DEBUGVIEWVARYING_VERTEX_COLOR:
result = input.color.rgb; needLinearToSRGB = true;

15
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDebugViewMaterial.hlsl


#endif // TESSELLATION_ON
float4 Frag(PackedVaryingsToPS packedInput) : SV_Target
void Frag( PackedVaryingsToPS packedInput
, out float4 outColor : SV_Target
#ifdef _DEPTHOFFSET_ON
, out float outputDepth : SV_Depth
#endif
)
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(0, 0));
UpdatePositionInput(input.unPositionSS.z, input.unPositionSS.w, input.positionWS, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

if (!needLinearToSRGB)
result = SRGBToLinear(max(0, result));
return float4(result, 0.0);
#ifdef _DEPTHOFFSET_ON
outputDepth = posInput.depthRaw;
#endif
outColor = float4(result, 1.0);
}

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(0, 0));
UpdatePositionInput(input.unPositionSS.z, input.unPositionSS.w, input.positionWS, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDistortion.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(0, 0));
UpdatePositionInput(input.unPositionSS.z, input.unPositionSS.w, input.positionWS, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

5
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(input.unPositionSS.xy) / GetTileSize());
UpdatePositionInput(input.unPositionSS.z, input.unPositionSS.w, input.positionWS, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

PreLightData preLightData = GetPreLightData(V, posInput, bsdfData);
uint featureFlags = 0xFFFFFFFF;
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, diffuseLighting, specularLighting);
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, featureFlags, diffuseLighting, specularLighting);
outColor = float4(diffuseLighting + specularLighting, builtinData.opacity);

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(0, 0));
UpdatePositionInput(input.unPositionSS.z, input.unPositionSS.w, input.positionWS, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(0, 0));
UpdatePositionInput(input.unPositionSS.z, input.unPositionSS.w, input.positionWS, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(0, 0));
// No position and depth in case of light transport
float3 V = float3(0, 0, 1); // No vector view in case of light transport

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw, uint2(0, 0));
UpdatePositionInput(input.unPositionSS.z, input.unPositionSS.w, input.positionWS, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

34
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl


#endif
#ifdef VARYINGS_NEED_TANGENT_TO_WORLD
// Normalize the normal/tangent after interpolation
float4 tangentWS = float4(input.interpolators2.xyz, input.interpolators2.w > 0.0 ? 1.0 : -1.0);
// TODO: We should be able to not make distinction between the two path, but it mean material need to be aware to normalize the TBN when required, like for example for POM.
// For now do some test by keeping code consistent with previous visual.
#ifdef SURFACE_GRADIENT
// Normalize normalWS vector but keep the renormFactor to apply it to bitangent and tangent
float renormFactor = 1.0 / length(input.interpolators1);
float3 normalWS = renormFactor * input.interpolators1;
// no normalizes is mandatory for tangentWS
// bitangent on the fly option in xnormal to reduce vertex shader outputs.
float3x3 worldToTangent = CreateWorldToTangent(normalWS, tangentWS.xyz, tangentWS.w);
output.worldToTangent[0] = worldToTangent[0];
// prepare for surfgrad formulation without breaking compliance (use exact same scale as applied to interpolated vertex normal to avoid breaking compliance).
output.worldToTangent[1] = worldToTangent[1] * renormFactor;
output.worldToTangent[2] = worldToTangent[2] * renormFactor;
#else
// TODO: Check if we must do like for surface gradient (i.e not normalize ?) For now, for consistency with previous code we normalize
// Normalize after the interpolation
float4 tangentWS = float4(normalize(input.interpolators2.xyz), input.interpolators2.w);
float3x3 tangentToWorld = CreateTangentToWorld(normalWS, tangentWS.xyz, tangentWS.w);
output.tangentToWorld[0] = tangentToWorld[0];
output.tangentToWorld[1] = tangentToWorld[1];
output.tangentToWorld[2] = tangentToWorld[2];
tangentWS.xyz = normalize(tangentWS.xyz);
// bitangent on the fly option in xnormal to reduce vertex shader outputs.
float3x3 worldToTangent = CreateWorldToTangent(normalWS, tangentWS.xyz, tangentWS.w);
output.worldToTangent[0] = worldToTangent[0];
output.worldToTangent[1] = worldToTangent[1];
output.worldToTangent[2] = worldToTangent[2];
#endif // VARYINGS_NEED_TANGENT_TO_WORLD
#ifdef VARYINGS_NEED_TEXCOORD0
output.texCoord0 = input.interpolators3.xy;

104
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl


float4 unity_SHC;
CBUFFER_END
// Use the regular depth camera texture sampler for sampling this: sampler_CameraDepthTexture
TEXTURE2D_FLOAT(_CameraDepthTextureCopy);
SAMPLER2D(sampler_CameraDepthTextureCopy);
TEXTURE2D_FLOAT(_MainDepthTexture);
SAMPLER2D(sampler_MainDepthTexture);
// Main lightmap
TEXTURE2D(unity_Lightmap);

// ----------------------------------------------------------------------------
// TODO: move this to constant buffer by Pass
float4x4 _InvViewProjMatrix;
float4 _ScreenSize;
float4 _ScreenSize;
float4x4 _InvViewProjMatrix;
float4x4 _InvProjMatrix;
float4 _InvProjParam;
float4x4 GetWorldToViewMatrix()
{

return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));
}
float3x3 CreateTangentToWorld(float3 normal, float3 tangent, float tangentSign)
float3 GetCurrentCameraPosition()
// For odd-negative scale transforms we need to flip the sign
float sgn = tangentSign * GetOddNegativeScale();
float3 bitangent = cross(normal, tangent) * sgn;
#if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_DEPTH_ONLY)
return _WorldSpaceCameraPos;
#else
// TEMP: this is rather expensive. Then again, we need '_WorldSpaceCameraPos'
// to represent the position of the primary (scene view) camera in order to
// have identical tessellation levels for both the scene view and shadow views.
// Otherwise, depth comparisons become meaningless!
float4x4 trViewMat = transpose(GetWorldToViewMatrix());
float3 rotCamPos = trViewMat[3].xyz;
return mul((float3x3)trViewMat, -rotCamPos);
#endif
}
return float3x3(tangent, bitangent, normal);
// Returns the forward direction of the current camera in the world space.
float3 GetCameraForwardDir()
{
float4x4 viewMat = GetWorldToViewMatrix();
return -viewMat[2].xyz;
// Computes world space view direction, from object space position
// Returns 'true' if the current camera performs a perspective projection.
bool IsPerspectiveCamera()
{
#if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_DEPTH_ONLY)
return (unity_OrthoParams.w == 0);
#else
// TODO: set 'unity_OrthoParams' during the shadow pass.
return (GetWorldToHClipMatrix()[3].x != 0 ||
GetWorldToHClipMatrix()[3].y != 0 ||
GetWorldToHClipMatrix()[3].z != 0 ||
GetWorldToHClipMatrix()[3].w != 1);
#endif
}
// Computes the world space view direction (pointing towards the camera).
float3 V = _WorldSpaceCameraPos.xyz - positionWS;
if (IsPerspectiveCamera())
{
// Perspective
float3 V = GetCurrentCameraPosition() - positionWS;
return normalize(V);
}
else
{
// Orthographic
return -GetCameraForwardDir();
}
}
// Uncomment this once the compiler bug is fixed.
// if (unity_OrthoParams.w == 1.0)
// {
// float4x4 M = GetWorldToViewMatrix();
// V = M[1].xyz;
// }
float3x3 CreateWorldToTangent(float3 normal, float3 tangent, float flipSign)
{
// For odd-negative scale transforms we need to flip the sign
float sgn = flipSign * GetOddNegativeScale();
float3 bitangent = cross(normal, tangent) * sgn;
return normalize(V);
return float3x3(tangent, bitangent, normal);
float3 TransformTangentToWorld(float3 dirTS, float3 tangentToWorld[3])
float3 TransformTangentToWorld(float3 dirTS, float3x3 worldToTangent)
// TODO check: do we need to normalize ?
return normalize(mul(dirTS, float3x3(tangentToWorld[0].xyz, tangentToWorld[1].xyz, tangentToWorld[2].xyz)));
// Use transpose transformation to go from tangent to world as the matrix is orthogonal
return mul(dirTS, worldToTangent);
// Assume TBN is orthonormal.
float3 TransformWorldToTangent(float3 dirWS, float3 tangentToWorld[3])
float3 TransformWorldToTangent(float3 dirWS, float3x3 worldToTangent)
// TODO check: do we need to normalize ?
return normalize(mul(float3x3(tangentToWorld[0].xyz, tangentToWorld[1].xyz, tangentToWorld[2].xyz), dirWS));
return mul(worldToTangent, dirWS);
float3 TransformTangentToObject(float3 dirTS, float3 worldToTangent[3])
float3 TransformTangentToObject(float3 dirTS, float3x3 worldToTangent)
// TODO check: do we need to normalize ?
// worldToTangent is orthonormal so inverse <==> transpose
float3x3 mWorldToTangent = float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz);
float3 normalWS = mul(dirTS, mWorldToTangent);
return normalize(mul((float3x3)unity_WorldToObject, normalWS));
// Use transpose transformation to go from tangent to world as the matrix is orthogonal
float3 normalWS = mul(dirTS, worldToTangent);
return mul((float3x3)unity_WorldToObject, normalWS);
// Assume TBN is orthonormal.
float3 TransformObjectToTangent(float3 dirOS, float3 worldToTangent[3])
float3 TransformObjectToTangent(float3 dirOS, float3x3 worldToTangent)
// TODO check: do we need to normalize ?
return normalize(mul(float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz), mul((float3x3)unity_ObjectToWorld, dirOS)));
return mul(worldToTangent, mul((float3x3)unity_ObjectToWorld, dirOS));
}
#endif // UNITY_SHADER_VARIABLES_INCLUDED

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow.meta


fileFormatVersion: 2
guid: 74dbe7f252951f340bb1038a738db89e
guid: f4cebcdbc19874c46ab4194e5ce59c67
folderAsset: yes
timeCreated: 1477395055
licenseType: Pro

135
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl


// TODO:
// - How to support a Gather sampling with such abstraction ?
// - What's belong to shadow and what's belong to renderloop ? (shadowmap size depends on the usage of atlas or not)
// - Is PunctualShadowData fixed or customizable ? Who is the owner ? Should it be pass to GetPunctualShadowAttenuation ? Sure it should...
// - Could be return by GetShadowTextureCoordinate() and pass to GetPunctualShadowAttenuation(). But in this case, who control the atlas application ?
// TODO:
// Caution: formula doesn't work as we are texture atlas...
// if (max3(abs(NDC.x), abs(NDC.y), 1.0 - texCoordXYZ.z) <= 1.0) return 1.0;
#ifndef SHADOW_HLSL
#define SHADOW_HLSL
//
// Shadow master include header.
//
// There are four relevant files for shadows.
// First ShadowContext.hlsl must declare the specific ShadowContext struct and the loader that goes along with it.
// ShadowContext loading and resource setup from C# must be in sync.
//
// Second there are two headers for shadow algorithms, whose signatures must match any of the Get...Attenuation function prototypes.
// The first header contains engine defaults, whereas the second header is empty by default. All project specific custom shadow algorithms should go in there or leave empty.
//
// Last there's a dispatcher include. By default the Get...Attenuation functions are rerouted to their default implementations. This can be overridden for each
// shadow type in the dispatcher source. For each overridden shadow type a specific define must be defined to prevent falling back to the default functions.
//
//#define SHADOWS_USE_SHADOWCTXT
#ifdef SHADOWS_USE_SHADOWCTXT
#define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0 // only on >= sm 5.1
// TODO: Remove this once we've moved over to the new system. Also delete the undef at the bottom again.
#define ShadowData ShadowDataExp
#include "ShadowBase.cs.hlsl" // ShadowData definition, auto generated (don't modify)
#include "ShadowTexFetch.hlsl" // Resource sampling definitions (don't modify)
#define SHADOWCONTEXT_DECLARE( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots ) \
\
struct ShadowContext \
{ \
StructuredBuffer<ShadowData> shadowDatas; \
StructuredBuffer<int4> payloads; \
Texture2DArray tex2DArray[_Tex2DArraySlots]; \
TextureCubeArray texCubeArray[_TexCubeArraySlots]; \
SamplerComparisonState compSamplers[_SamplerCompSlots]; \
SamplerState samplers[_SamplerSlots]; \
}; \
\
SHADOW_DEFINE_SAMPLING_FUNCS( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots )
// Shadow context definition and initialization, i.e. resource binding (project header, must be kept in sync with C# runtime)
#include "ShadowContext.hlsl"
// helper function to extract shadowmap data from the ShadowData struct
void unpackShadowmapId( uint shadowmapId, out uint texIdx, out uint sampIdx, out float slice )
{
texIdx = (shadowmapId >> 24) & 0xff;
sampIdx = (shadowmapId >> 16) & 0xff;
slice = (float)(shadowmapId & 0xffff);
}
void unpackShadowmapId( uint shadowmapId, out uint texIdx, out uint sampIdx )
{
texIdx = (shadowmapId >> 24) & 0xff;
sampIdx = (shadowmapId >> 16) & 0xff;
}
void unpackShadowmapId( uint shadowmapId, out float slice )
{
slice = (float)(shadowmapId & 0xffff);
}
// shadow sampling prototypes
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L, float2 unPositionSS );
// shadow sampling prototypes with screenspace info
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L );
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L, float2 unPositionSS );
// wedge in the actual shadow sampling algorithms
#include "ShadowSampling.hlsl" // sampling patterns
#include "ShadowAlgorithms.hlsl" // engine default algorithms (don't modify)
#include "ShadowAlgorithmsCustom.hlsl" // project specific custom algorithms (project can modify this)
// default dispatchers for the individual shadow types (with and without screenspace support)
// point/spot light shadows
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L )
{
return EvalShadow_PunctualDepth(shadowContext, positionWS, shadowDataIndex, L);
}
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuationDefault( shadowContext, positionWS, shadowDataIndex, L );
}
// directional light shadows
float GetDirectionalShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L )
{
return EvalShadow_CascadedDepth( shadowContext, positionWS, shadowDataIndex, L );
}
float GetDirectionalShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L, float2 unPositionSS )
{
return GetDirectionalShadowAttenuationDefault( shadowContext, positionWS, shadowDataIndex, L );
}
// include project specific shadow dispatcher. If this file is not empty, it MUST define which default shadows it's overriding
#include "ShadowDispatch.hlsl"
// if shadow dispatch is empty we'll fall back to default shadow sampling implementations
#ifndef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L )
{
return GetPunctualShadowAttenuationDefault( shadowContext, positionWS, shadowDataIndex, L );
}
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuationDefault( shadowContext, positionWS, shadowDataIndex, L, unPositionSS );
}
#endif
#ifndef SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L )
{
return GetDirectionalShadowAttenuationDefault( shadowContext, positionWS, shadowDataIndex, L );
}
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L, float2 unPositionSS )
{
return GetDirectionalShadowAttenuationDefault( shadowContext, positionWS, shadowDataIndex, L, unPositionSS );
}
#endif
#undef ShadowData // TODO: Remove this once we've moved over to the new system. Also delete the define at the top again.
#endif // SHADOWS_USE_SHADOWCTXT
#endif // SHADOW_HLSL

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky.meta


fileFormatVersion: 2
guid: 066ab4d03bd03384f81c9d82b479f8dd
guid: 99e8d5bd81663624399d10e3fc27571c
folderAsset: yes
timeCreated: 1479239906
licenseType: Pro

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/Editor/HDRISkyEditor.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[CanEditMultipleObjects]
[CustomEditor(typeof(HDRISkyParameters))]
[CustomEditor(typeof(HDRISkySettings))]
public class HDRISkyParametersEditor
: Editor
{

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/HDRISkyRenderer.cs


public class HDRISkyRenderer : SkyRenderer
{
Material m_SkyHDRIMaterial; // Renders a cubemap into a render texture (can be cube or 2D)
private HDRISkyParameters m_HdriSkyParams;
private HDRISkySettings m_HdriSkyParams;
public HDRISkyRenderer(HDRISkyParameters hdriSkyParams)
public HDRISkyRenderer(HDRISkySettings hdriSkyParams)
{
m_HdriSkyParams = hdriSkyParams;
}

}
}
public override void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters, bool renderForCubemap)
public override void RenderSky(BuiltinSkyParameters builtinParams, SkySettings skyParameters, bool renderForCubemap)
{
m_SkyHDRIMaterial.SetTexture("_Cubemap", m_HdriSkyParams.skyHDRI);
m_SkyHDRIMaterial.SetVector("_SkyParam", new Vector4(m_HdriSkyParams.exposure, m_HdriSkyParams.multiplier, m_HdriSkyParams.rotation, 0.0f));

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/Resources/SkyHDRI.shader


#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#include "ShaderLibrary/Color.hlsl"
#include "ShaderLibrary/Common.hlsl"
#include "ShaderLibrary/CommonLighting.hlsl"
#include "../../../../ShaderLibrary/Color.hlsl"
#include "../../../../ShaderLibrary/Common.hlsl"
#include "../../../../ShaderLibrary/CommonLighting.hlsl"
TEXTURECUBE(_Cubemap);
SAMPLERCUBE(sampler_Cubemap);

ZWrite Off
ZTest Always
Blend One Zero
Cull Off
HLSLPROGRAM
ENDHLSL

ZWrite Off
ZTest LEqual
Blend One Zero
Cull Off
HLSLPROGRAM
ENDHLSL

31
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkyRenderer.cs


public class ProceduralSkyRenderer : SkyRenderer
{
Material m_ProceduralSkyMaterial = null; // Renders a cubemap into a render texture (can be cube or 2D)
private ProceduralSkyParameters m_ProceduralSkyParameters;
private ProceduralSkySettings m_ProceduralSkySettings;
public ProceduralSkyRenderer(ProceduralSkyParameters proceduralSkyParameters)
public ProceduralSkyRenderer(ProceduralSkySettings proceduralSkySettings)
m_ProceduralSkyParameters = proceduralSkyParameters;
m_ProceduralSkySettings = proceduralSkySettings;
}
public override void Build()

public override bool IsSkyValid()
{
if (m_ProceduralSkyMaterial == null || m_ProceduralSkyParameters == null)
if (m_ProceduralSkyMaterial == null || m_ProceduralSkySettings == null)
return m_ProceduralSkyParameters.skyHDRI != null &&
m_ProceduralSkyParameters.worldMieColorRamp != null &&
m_ProceduralSkyParameters.worldRayleighColorRamp != null;
return m_ProceduralSkySettings.skyHDRI != null &&
m_ProceduralSkySettings.worldMieColorRamp != null &&
m_ProceduralSkySettings.worldRayleighColorRamp != null;
}
public override void SetRenderTargets(BuiltinSkyParameters builtinParams)

Utilities.SetRenderTarget(builtinParams.renderContext, builtinParams.colorBuffer);
}
void SetKeywords(BuiltinSkyParameters builtinParams, ProceduralSkyParameters param, bool renderForCubemap)
void SetKeywords(BuiltinSkyParameters builtinParams, ProceduralSkySettings param, bool renderForCubemap)
{
// Ensure that all preprocessor symbols are initially undefined.
m_ProceduralSkyMaterial.DisableKeyword("ATMOSPHERICS");

m_ProceduralSkyMaterial.EnableKeyword("PERFORM_SKY_OCCLUSION_TEST");
}
if (param.debugMode != ProceduralSkyParameters.ScatterDebugMode.None)
if (param.debugMode != ProceduralSkySettings.ScatterDebugMode.None)
void SetUniforms(BuiltinSkyParameters builtinParams, ProceduralSkyParameters param, bool renderForCubemap, ref MaterialPropertyBlock properties)
void SetUniforms(BuiltinSkyParameters builtinParams, ProceduralSkySettings param, bool renderForCubemap, ref MaterialPropertyBlock properties)
{
properties.SetTexture("_Cubemap", param.skyHDRI);
properties.SetVector("_SkyParam", new Vector4(param.exposure, param.multiplier, param.rotation, 0.0f));

properties.SetFloat("_HeightMieDensity", renderForCubemap ? -0.0f : -param.heightMieDensity / 100000f);
}
override public void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters, bool renderForCubemap)
override public void RenderSky(BuiltinSkyParameters builtinParams, SkySettings skyParameters, bool renderForCubemap)
SetKeywords(builtinParams, m_ProceduralSkyParameters, renderForCubemap);
SetKeywords(builtinParams, m_ProceduralSkySettings, renderForCubemap);
SetUniforms(builtinParams, m_ProceduralSkyParameters, renderForCubemap, ref properties);
SetUniforms(builtinParams, m_ProceduralSkySettings, renderForCubemap, ref properties);
if (!renderForCubemap)
{
cmd.SetGlobalTexture("_CameraDepthTexture", builtinParams.depthBuffer);
}
cmd.DrawMesh(builtinParams.skyMesh, Matrix4x4.identity, m_ProceduralSkyMaterial, 0, 0, properties);
builtinParams.renderContext.ExecuteCommandBuffer(cmd);

18
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/Resources/AtmosphericScattering.hlsl


uniform float _MiePhaseAnisotropy;
uniform float _MieExtinctionFactor;
SAMPLER2D(sampler_CameraDepthTexture);
#define SRL_BilinearSampler sampler_CameraDepthTexture // Used for all textures
SAMPLER2D(sampler_MainDepthTexture);
#define SRL_BilinearSampler sampler_MainDepthTexture // Used for all textures
TEXTURE2D_FLOAT(_CameraDepthTexture);
TEXTURE2D_FLOAT(_MainDepthTexture);
TEXTURE2D(_OcclusionTexture);
float HenyeyGreensteinPhase(float g, float cosTheta) {

#if defined(ATMOSPHERICS_OCCLUSION_EDGE_FIXUP)
float4 baseUV = float4(uv.x, uv.y, 0.f, 0.f);
float cDepth = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV, 0.f).r;
float cDepth = SAMPLE_TEXTURE2D_LOD(_CMainDepthTexture, SRL_BilinearSampler, baseUV, 0.f).r;
baseUV.xy = uv + _DepthTextureScaledTexelSize.zy; xDepth.x = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV);
baseUV.xy = uv + _DepthTextureScaledTexelSize.xy; xDepth.y = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV);
baseUV.xy = uv + _DepthTextureScaledTexelSize.xw; xDepth.z = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV);
baseUV.xy = uv + _DepthTextureScaledTexelSize.zw; xDepth.w = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV);
baseUV.xy = uv + _DepthTextureScaledTexelSize.zy; xDepth.x = SAMPLE_TEXTURE2D_LOD(_MainDepthTexture, SRL_BilinearSampler, baseUV);
baseUV.xy = uv + _DepthTextureScaledTexelSize.xy; xDepth.y = SAMPLE_TEXTURE2D_LOD(_MainDepthTexture, SRL_BilinearSampler, baseUV);
baseUV.xy = uv + _DepthTextureScaledTexelSize.xw; xDepth.z = SAMPLE_TEXTURE2D_LOD(_MainDepthTexture, SRL_BilinearSampler, baseUV);
baseUV.xy = uv + _DepthTextureScaledTexelSize.zw; xDepth.w = SAMPLE_TEXTURE2D_LOD(_MainDepthTexture, SRL_BilinearSampler, baseUV);
xDepth.x = LinearEyeDepth(xDepth.x, _ZBufferParams);
xDepth.y = LinearEyeDepth(xDepth.y, _ZBufferParams);

#define SURFACE_SCATTER_APPLY(i, color) color += (i.worldPos + i.scatterCoords1.xyz + i.scatterCoords2.xyz) * 0.000001f
#endif
#endif //FILE_ATMOSPHERICSCATTERING
#endif //FILE_ATMOSPHERICSCATTERING

11
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/Resources/SkyProcedural.shader


ZWrite Off
ZTest Always
Blend One OneMinusSrcAlpha, Zero One
Cull Off
HLSLPROGRAM
#pragma target 4.5

#pragma multi_compile _ ATMOSPHERICS_DEBUG
#pragma multi_compile _ PERFORM_SKY_OCCLUSION_TEST
#include "ShaderLibrary/Color.hlsl"
#include "ShaderLibrary/Common.hlsl"
#include "ShaderLibrary/CommonLighting.hlsl"
#include "../../../../ShaderLibrary/Color.hlsl"
#include "../../../../ShaderLibrary/Common.hlsl"
#include "../../../../ShaderLibrary/CommonLighting.hlsl"
TEXTURECUBE(_Cubemap);
SAMPLERCUBE(sampler_Cubemap);

float3 rotatedDir = float3(dot(rotDirX, dir), dir.y, dot(rotDirY, dir));
// input.positionCS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(0,0));
// An arbitrary value attempting to match the size of the sky mesh from the Blacksmith demo.
const float skyDepth = 0.00025;

// Do not perform blending with the environment map if the sky is occluded.
float depthRaw = max(skyDepth, LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).r);
float depthRaw = max(skyDepth, LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).r);
float skyTexWeight = (depthRaw > skyDepth) ? 0.0 : 1.0;
#else
float depthRaw = skyDepth;

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkySettings.cs


{
[ExecuteInEditMode]
[DisallowMultipleComponent]
public class ProceduralSkyParameters : SkyParameters
public class ProceduralSkySettings : SkySettings
{
public enum OcclusionDownscale { x1 = 1, x2 = 2, x4 = 4 }
public enum OcclusionSamples { x64 = 0, x164 = 1, x244 = 2 }

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/Resources.meta


fileFormatVersion: 2
guid: 4cdc45a9a65126a42aca158413a5b089
guid: 920208451db81a846ae1c2d55f7b50b4
folderAsset: yes
timeCreated: 1479239906
licenseType: Pro

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存