浏览代码

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

# Conflicts:
#	ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/RenderPipelineSettingsUI.cs
#	ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/SerializedRenderPipelineSettings.cs
#	ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
#	ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipeline/RenderPipelineSettings.cs
/main
Julien Ignace 7 年前
当前提交
19029ddd
共有 267 个文件被更改,包括 3126 次插入3831 次删除
  1. 1
      .gitignore
  2. 999
      ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2001_Dynamic_Directional.unity.png
  3. 999
      ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2003_Light_Parameters.unity.png
  4. 998
      ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2101_GI_Metapass.unity.png
  5. 999
      ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2301_Shadow_Mask.unity.png
  6. 365
      ImageTemplates/HDRenderPipeline/Scenes/3xxx_DebugView/3002_ObjectMotionVector.unity.png
  7. 24
      README.md
  8. 2
      ScriptableRenderPipeline/Core/CoreRP/MousePositionDebug.cs
  9. 10
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/API/GLCore.hlsl
  10. 10
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/API/GLES3.hlsl
  11. 2
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/API/PSSL.hlsl
  12. 2
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Color.hlsl
  13. 79
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl
  14. 9
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonLighting.hlsl
  15. 12
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Debug.hlsl
  16. 2
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/GeometricTools.hlsl
  17. 14
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/ImageBasedLighting.hlsl
  18. 52
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Packing.hlsl
  19. 11
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  20. 245
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl
  21. 13
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/UnityInstancing.hlsl
  22. 30
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/VolumeRendering.hlsl
  23. 2
      ScriptableRenderPipeline/Core/package.json
  24. 66
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDAdditionalCameraData.cs
  25. 20
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs
  26. 110
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugColorPicker.shader
  27. 47
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.hlsl
  28. 48
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugFullScreen.shader
  29. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewMaterialGBuffer.shader
  30. 12
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewTiles.shader
  31. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/MaterialDebug.cs
  32. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/MaterialDebug.cs.hlsl
  33. 24
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalProjectorComponent.cs
  34. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalProjectorComponent.cs.meta
  35. 30
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
  36. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Camera/HDCameraEditor.Handlers.cs
  37. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Camera/HDCameraEditor.cs
  38. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDAssetFactory.cs
  39. 7
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.cs
  40. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/DiffusionProfile/DiffusionProfileSettingsEditor.cs
  41. 15
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Lit/BaseLitUI.cs
  42. 20
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Unlit/BaseUnlitUI.cs
  43. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/RenderPipelineSettingsUI.cs
  44. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/SerializedRenderPipelineSettings.cs
  45. 145
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
  46. 32
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipelineAsset.cs
  47. 43
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderQueue.cs
  48. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  49. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Deferred.shader
  50. 7
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute
  51. 7
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightEvaluation.hlsl
  52. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Deferred.compute
  53. 14
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoopDef.hlsl
  54. 19
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/HomogeneousFog.cs
  55. 42
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  56. 380
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs
  57. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DBufferManager.cs
  58. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl
  59. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.shader
  60. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl
  61. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalProperties.hlsl
  62. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl
  63. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/ShaderPass/DecalSharePass.hlsl
  64. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLit.shader
  65. 36
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl
  66. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitTessellation.shader
  67. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs
  68. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.cs.hlsl
  69. 371
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl
  70. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.shader
  71. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl
  72. 12
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitDataIndividualLayer.hlsl
  73. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitTessellation.shader
  74. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.hlsl
  75. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Unlit/Unlit.shader
  76. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipeline/FrameSettings.cs
  77. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipeline/RenderPipelineSettings.cs
  78. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/CameraMotionVectors.shader
  79. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/HDRenderPipelineResources.asset
  80. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/RenderPipelineResources.cs
  81. 43
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl
  82. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDepthOnly.hlsl
  83. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDistortion.hlsl
  84. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassForward.hlsl
  85. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassForwardUnlit.hlsl
  86. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassGBuffer.hlsl
  87. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassLightTransport.hlsl
  88. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassVelocity.hlsl
  89. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/VaryingMesh.hlsl
  90. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/VertMesh.hlsl
  91. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderVariables.hlsl
  92. 21
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/OpaqueAtmosphericScattering.shader
  93. 7
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/ProceduralSky/Resources/ProceduralSky.shader
  94. 4
      ScriptableRenderPipeline/HDRenderPipeline/package.json
  95. 157
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineAsset.cs
  96. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineEditorResources.cs.meta
  97. 13
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightConstantBuffer.cs
  98. 124
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  99. 11
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl
  100. 4
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputSurface.hlsl

1
.gitignore


*.aspx
*.sdf
*.userprefs
*.npmrc

999
ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2001_Dynamic_Directional.unity.png
文件差异内容过多而无法显示
查看文件

999
ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2003_Light_Parameters.unity.png
文件差异内容过多而无法显示
查看文件

998
ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2101_GI_Metapass.unity.png
文件差异内容过多而无法显示
查看文件

999
ImageTemplates/HDRenderPipeline/Scenes/2xxx_Lighting/2301_Shadow_Mask.unity.png
文件差异内容过多而无法显示
查看文件

365
ImageTemplates/HDRenderPipeline/Scenes/3xxx_DebugView/3002_ObjectMotionVector.unity.png
文件差异内容过多而无法显示
查看文件

24
README.md


## Scriptable Render Pipeline Assets
The Scriptable Render Pipeline Asset controls the global rendering quality settings of your project and creates the rendering pipeline instance. The rendering pipeline instance contains intermediate resources and the render loop implementation.
We have provided a Scriptable Render Pipeline Asset for HDRP and the Lightweight Pipeline. This Asset must be assigned to the Scriptable Render Pipeline Asset field in the Graphics inspector window in order to use the HDRP or Lightweight Pipeline.
You can create multiple Pipeline Assets to store settings for different built platforms or for different testing environments.
Navigate to ___Edit > Project Settings > Graphics___ and add the required Asset (HDRP, Lightweight or your own custom asset) to the __Render Pipeline Settings__ field.
To create a Render Pipeline Asset:
1. In the Project window, navigate to a directory outside of the Scriptable Render Pipeline Folder, then right click in the Project window and select ___Create > Render Pipeline > High Definition or Lightweight > Render Pipeline/Pipeline Asset.___
2. Navigate to ___Edit > Project Settings > Graphics___ and add the Render Pipeline Asset you created to the __Render Pipeline Settings__ field to use it in your project.
Note: Always store your new Render Pipeline Asset outside of the Scriptable Render Pipeline folder. This ensures that your settings are not lost when merging new changes from the SRP repo.
## Using the High Definition Render Pipeline (HDRP) or the Lightweight Pipeline

1. Navigate to ___Edit > Project Settings > Player___ and set the color space of your project to Linear by selecting __Linear__ from the __Color Space__ dropdown. HDRP does not support Gamma lighting.
2. Navigate to ___Edit > Project Settings > Graphics___ and add the HDRenderPipelineAsset Asset to the __Render Pipeline Settings__ field.
Create a copy of the HDRenderPipelineAsset and store it outside of the Scriptable Render Pipeline folder. This ensures that your HDRP settings are not lost when merging new changes from the SRP repo.
2. In the Project window, navigate to a directory outside of the Scriptable Render Pipeline Folder, then right in click the Project window and select ___Create > Render Pipeline > High Definition > Render Pipeline.___
3. Navigate to ___Edit > Project Settings > Graphics___ and add the High Definition Render Pipeline Asset you created to the __Render Pipeline Settings__ field.
Note: Always store your High Definition Render Pipeline Asset outside of the Scriptable Render Pipeline folder. This ensures that your HDRP settings are not lost when merging new changes from the SRP repo.
To use the Lightweight Pipeline you must edit your project’s Graphics settings as follows:
To use the Lightweight Pipeline you must edit your project’s __Graphics__ settings as follows:
1. Navigate to ___Edit > Project Settings > Graphics___ and add the LightweightPipelineAsset Asset to the __Render Pipeline Settings__ field.
2. Create a copy of the LightweightPipelineAsset and store it outside of the Scriptable Render Pipeline folder. This ensures that your Lightweight settings are not lost when merging new changes from the SRP repo.
1. In the Project window, navigate to a directory outside of the Scriptable Render Pipeline Folder, then right click in the Project window and select ___Create > Render Pipeline > Lightweight > Pipeline Asset.___
2. Navigate to ___Edit > Project Settings > Graphics___ and add the Lightweight Render Pipeline Asset you created to the __Render Pipeline Settings__ field.
Note: Always store your new Render Pipeline Asset outside of the Scriptable Render Pipeline folder. This ensures that your Lightweight settings are not lost when merging new changes from the SRP repo.

2
ScriptableRenderPipeline/Core/CoreRP/MousePositionDebug.cs


}
}
#if UNITY_EDITOR
#if UNITY_EDITOR
private void OnSceneGUI(UnityEditor.SceneView sceneview)
{
m_mousePosition = Event.current.mousePosition;

10
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/API/GLCore.hlsl


#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3)
#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod)
#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias)
#if OPENGL4_1_SM5
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#else
#ifdef UNITY_NO_CUBEMAP_ARRAY
#else
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias)textureName.SampleBias(samplerName, float4(coord3, index), bias)
#endif
#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3)

10
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/API/GLES3.hlsl


#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod)
#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias)
#if GLES3_1_AEP
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias)textureName.SampleBias(samplerName, float4(coord3, index), bias)
#else
#ifdef UNITY_NO_CUBEMAP_ARRAY
#else
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias)textureName.SampleBias(samplerName, float4(coord3, index), bias)
#endif
#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3)

2
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/API/PSSL.hlsl


#define INTRINSIC_MINMAX3
#define Min3 min3
#define Max3 max3
//#define INTRINSIC_CUBEMAP_FACE_ID // Must investigate why AMD reference implementation is different than ours
#define INTRINSIC_CUBEMAP_FACE_ID
#define UNITY_UV_STARTS_AT_TOP 1
#define UNITY_REVERSED_Z 1

2
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Color.hlsl


real3 FastLinearToSRGB(real3 c)
{
return max(1.055 * pow(c, 0.416666667) - 0.055, 0.0);
return saturate(1.055 * pow(abs(c), 0.416666667) - 0.055);
}
real4 FastLinearToSRGB(real4 c)

79
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl


#define CUBEMAPFACE_NEGATIVE_Z 5
#ifndef INTRINSIC_CUBEMAP_FACE_ID
// TODO: implement this. Is the reference implementation of cubemapID provide by AMD the reverse of our ?
/*
float CubemapFaceID(float3 dir)
float CubeMapFaceID(float3 dir)
faceID = (dir.z < 0.0) ? 5.0 : 4.0;
faceID = (dir.z < 0.0) ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
faceID = (dir.y < 0.0) ? 3.0 : 2.0;
faceID = (dir.y < 0.0) ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
faceID = (dir.x < 0.0) ? 1.0 : 0.0;
faceID = (dir.x < 0.0) ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
*/
#endif // INTRINSIC_CUBEMAP_FACE_ID
// Intrinsic isnan can't be used because it require /Gic to be enabled on fxc that we can't do. So use IsNAN instead
bool IsNAN(float n)
{
return (n < 0.0 || n > 0.0 || n == 0.0) ? false : true;
}
void GetCubeFaceID(float3 dir, out int faceIndex)
bool IsNAN(float2 v)
// TODO: Use faceID intrinsic on console
float3 adir = abs(dir);
return (IsNAN(v.x) || IsNAN(v.y)) ? true : false;
}
// +Z -Z
faceIndex = dir.z > 0.0 ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
// +X -X
if (adir.x > adir.y && adir.x > adir.z)
{
faceIndex = dir.x > 0.0 ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
}
// +Y -Y
else if (adir.y > adir.x && adir.y > adir.z)
{
faceIndex = dir.y > 0.0 ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
bool IsNAN(float3 v)
{
return (IsNAN(v.x) || IsNAN(v.y) || IsNAN(v.z)) ? true : false;
#endif // INTRINSIC_CUBEMAP_FACE_ID
bool IsNAN(float4 v)
{
return (IsNAN(v.x) || IsNAN(v.y) || IsNAN(v.z) || IsNAN(v.w)) ? true : false;
}
// ----------------------------------------------------------------------------
// Common math functions

// PositivePow remove this warning when you know the value is positive and avoid inf/NAN.
TEMPLATE_2_REAL(PositivePow, base, power, return pow(max(abs(base), FLT_EPS), power))
// Computes (FastSign(s) * x) using 2x VALU.
// Composes a floating point value with the magnitude of 'x' and the sign of 's'.
float FastMulBySignOf(float s, float x, bool ignoreNegZero = true)
float CopySign(float x, float s, bool ignoreNegZero = true)
return (s >= 0) ? x : -x;
return (s >= 0) ? abs(x) : -abs(x);
return asfloat(signBit ^ asuint(x));
return asfloat(BitFieldInsert(negZero, signBit, asuint(x)));
return (s >= 0) ? x : -x;
return (s >= 0) ? abs(x) : -abs(x);
#endif
}

// Note that the sign() function in HLSL implements signum, which returns 0 for 0.
float FastSign(float s, bool ignoreNegZero = true)
{
return FastMulBySignOf(s, 1.0, ignoreNegZero);
return CopySign(1.0, s, ignoreNegZero);
}
// Orthonormalizes the tangent frame using the Gram-Schmidt process.

// From forward
// deviceDepth and linearDepth come directly from .zw of SV_Position
void UpdatePositionInput(float deviceDepth, float linearDepth, float3 positionWS, inout PositionInputs posInput)
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float linearDepth, float3 positionWS, uint2 tileCoord)
PositionInputs posInput = GetPositionInput(positionSS, invScreenSize, tileCoord);
return posInput;
}
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float linearDepth, float3 positionWS)
{
return GetPositionInput(positionSS, invScreenSize, deviceDepth, linearDepth, positionWS, uint2(0, 0));
void UpdatePositionInput(float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, inout PositionInputs posInput)
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, uint2 tileCoord)
PositionInputs posInput = GetPositionInput(positionSS, invScreenSize, tileCoord);
return posInput;
}
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix)
{
return GetPositionInput(positionSS, invScreenSize, deviceDepth, invViewProjMatrix, viewProjMatrix, uint2(0, 0));
}
// The view direction 'V' points towards the camera.

9
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonLighting.hlsl


return N;
}
// Generates an orthonormal right-handed basis from a unit vector.
// Ref: http://marc-b-reynolds.github.io/quaternions/2016/07/06/Orthonormal.html
// Generates an orthonormal (row-major) basis from a unit vector. TODO: make it column-major.
// The resulting rotation matrix has the determinant of +1.
// Ref: 'ortho_basis_pixar_r2' from http://marc-b-reynolds.github.io/quaternions/2016/07/06/Orthonormal.html
real3x3 GetLocalFrame(real3 localZ)
{
real x = localZ.x;

real3 localX = real3(c * x * a - 1, sz * b, c);
real3 localY = real3(b, y * ya - sz, y);
// Note: due to the quaternion formulation, the generated frame is rotated by 180 degrees,
// s.t. if localZ = {0, 0, 1}, then localX = {-1, 0, 0} and localY = {0, -1, 0}.
// Generates an orthonormal (row-major) basis from a unit vector. TODO: make it column-major.
// The resulting rotation matrix has the determinant of +1.
real3x3 GetLocalFrame(real3 localZ, real3 localX)
{
real3 localY = cross(localZ, localX);

12
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Debug.hlsl


outColor = real3(0.75, 1.0, 0.25);
else if (index == 9)
outColor = real3(0.75, 0.25, 1.0);
else if (index == 10)
outColor = real3(0.25, 1.0, 0.75);
else if (index == 11)
outColor = real3(0.75, 0.75, 0.25);
else if (index == 12)
outColor = real3(0.75, 0.25, 0.75);
else if (index == 13)
outColor = real3(0.25, 0.75, 0.75);
else if (index == 14)
outColor = real3(0.25, 0.25, 0.75);
else if (index == 15)
outColor = real3(0.75, 0.25, 0.25);
return outColor;
}

2
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/GeometricTools.hlsl


bool SolveQuadraticEquation(float a, float b, float c, out float2 roots)
{
float d = b * b - 4 * a * c;
float q = -0.5 * (b + FastMulBySignOf(b, sqrt(d)));
float q = -0.5 * (b + CopySign(sqrt(d), b));
roots = float2(q / a, c / q);
return (d >= 0);

14
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/ImageBasedLighting.hlsl


}
// Ref: "Moving Frostbite to PBR", p. 69.
real3 GetSpecularDominantDir(real3 N, real3 R, real roughness, real NdotV)
real3 GetSpecularDominantDir(real3 N, real3 R, real perceptualRoughness, real NdotV)
real a = 1.0 - roughness;
real p = perceptualRoughness;
real a = 1.0 - p * p;
real lerpFactor = (s + roughness) * a;
real lerpFactor = (s + p * p) * a;
real lerpFactor = (s + roughness) * saturate(a * a + lerp(0.0, a, NdotV * NdotV));
real lerpFactor = (s + p * p) * saturate(a * a + lerp(0.0, a, NdotV * NdotV));
#endif
// The result is not normalized as we fetch in a cubemap

// To simulate the streching of highlight at grazing angle for IBL we shrink the roughness
// which allow to fake an anisotropic specular lobe.
// Ref: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/ - slide 84
real AnisotropicStrechAtGrazingAngle(real roughness, real perceptualRoughness, real NdotV)
real AnisotropicStrechAtGrazingAngle(real perceptualRoughness, real NdotV)
return roughness * lerp(saturate(NdotV * 2.0), 1.0, perceptualRoughness);
real p = perceptualRoughness;
return p * lerp(saturate(NdotV * 2.0) * p, p, p);
}
// ----------------------------------------------------------------------------

52
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Packing.hlsl


return normalize(n * 2.0 - 1.0);
}
// Ref: http://www.vis.uni-stuttgart.de/~engelhts/paper/vmvOctaMaps.pdf
// Encode with Oct, this function work with any size of output
// return real between [-1, 1]
real2 PackNormalOctRectEncode(real3 n)
{
// Perform planar projection.
real3 p = n * rcp(dot(abs(n), 1.0));
real x = p.x, y = p.y, z = p.z;
// Unfold the octahedron.
// Also correct the aspect ratio from 2:1 to 1:1.
real r = saturate(0.5 - 0.5 * x + 0.5 * y);
real g = x + y;
// Negative hemisphere on the left, positive on the right.
return real2(CopySign(r, z), g);
}
real3 UnpackNormalOctRectEncode(real2 f)
{
real r = f.r, g = f.g;
// Solve for {x, y, z} given {r, g}.
real x = 0.5 + 0.5 * g - abs(r);
real y = g - x;
real z = max(1.0 - abs(x) - abs(y), FLT_EPS); // EPS is absolutely crucial for anisotropy
real3 p = real3(x, y, CopySign(z, r));
return normalize(p);
}
real2 PackNormalOctEncode(real3 n)
real2 PackNormalOctQuadEncode(real3 n)
{
//real l1norm = dot(abs(n), 1.0);
//real2 res0 = n.xy * (1.0 / l1norm);

return n.xy + (n.xy >= 0.0 ? t : -t);
}
real3 UnpackNormalOctEncode(real2 f)
real3 UnpackNormalOctQuadEncode(real2 f)
{
real3 n = real3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y));

// ...
// Example: precision is 1024.0, maxi is 8, i is [0..7] encode on 3 bit. f is [0..1] encode on 7 bit.
//...
real PackFloatInt(real f, int i, real maxi, real precision)
real PackFloatInt(real f, uint i, real maxi, real precision)
{
// Constant
real precisionMinusOne = precision - 1.0;

return t1 * f + t2 * real(i);
}
void UnpackFloatInt(real val, real maxi, real precision, out real f, out int i)
void UnpackFloatInt(real val, real maxi, real precision, out real f, out uint i)
{
// Constant
real precisionMinusOne = precision - 1.0;

}
// Define various variante for ease of read
real PackFloatInt8bit(real f, int i, real maxi)
real PackFloatInt8bit(real f, uint i, real maxi)
void UnpackFloatInt8bit(real val, real maxi, out real f, out int i)
void UnpackFloatInt8bit(real val, real maxi, out real f, out uint i)
real PackFloatInt10bit(real f, int i, real maxi)
real PackFloatInt10bit(real f, uint i, real maxi)
void UnpackFloatInt10bit(real val, real maxi, out real f, out int i)
void UnpackFloatInt10bit(real val, real maxi, out real f, out uint i)
real PackFloatInt16bit(real f, int i, real maxi)
real PackFloatInt16bit(real f, uint i, real maxi)
void UnpackFloatInt16bit(real val, real maxi, out real f, out int i)
void UnpackFloatInt16bit(real val, real maxi, out real f, out uint i)
{
UnpackFloatInt(val, maxi, 65536.0, f, i);
}

11
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl


return uint2( (posTC * sd.scaleOffset.xy + sd.scaleOffset.zw) * sd.textureSize.xy );
}
int EvalShadow_GetCubeFaceID( real3 dir )
int EvalShadow_GetCubeFaceID( real3 sampleToLight )
// TODO: Use faceID intrinsic on console
real3 lightToSample = -sampleToLight; // TODO: pass the correct (flipped) direction
#ifdef INTRINSIC_CUBEMAP_FACE_ID
return (int)CubeMapFaceID(lightToSample);
#else
// TODO: use CubeMapFaceID() defined in Common.hlsl for all pipelines on all platforms.
real3 dir = sampleToLight;
real3 adir = abs(dir);
// +Z -Z

faceIndex = dir.y > 0.0 ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
return faceIndex;
#endif
}

245
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl


// Various shadow sampling logic.
// Again two versions, one for dynamic resource indexing, one for static resource access.
// ------------------------------------------------------------------
// PCF Filtering helpers
// ------------------------------------------------------------------
// Assuming a isoceles right angled triangle of height "triangleHeight" (as drawn below).
// This function return the area of the triangle above the first texel.
//
// |\ <-- 45 degree slop isosceles right angled triangle
// | \
// ---- <-- length of this side is "triangleHeight"
// _ _ _ _ <-- texels
real SampleShadow_GetTriangleTexelArea(real triangleHeight)
{
return triangleHeight - 0.5;
}
// Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
// This function return the area of the triangle above each of those texels.
// | <-- offset from -0.5 to 0.5, 0 meaning triangle is exactly in the center
// / \ <-- 45 degree slop isosceles triangle (ie tent projected in 2D)
// / \
// _ _ _ _ <-- texels
// X Y Z W <-- result indices (in computedArea.xyzw and computedAreaUncut.xyzw)
void SampleShadow_GetTexelAreas_Tent_3x3(real offset, out real4 computedArea, out real4 computedAreaUncut)
{
// Compute the exterior areas
real offset01SquaredHalved = (offset + 0.5) * (offset + 0.5) * 0.5;
computedAreaUncut.x = computedArea.x = offset01SquaredHalved - offset;
computedAreaUncut.w = computedArea.w = offset01SquaredHalved;
// Compute the middle areas
// For Y : We find the area in Y of as if the left section of the isoceles triangle would
// intersect the axis between Y and Z (ie where offset = 0).
computedAreaUncut.y = SampleShadow_GetTriangleTexelArea(1.5 - offset);
// This area is superior to the one we are looking for if (offset < 0) thus we need to
// subtract the area of the triangle defined by (0,1.5-offset), (0,1.5+offset), (-offset,1.5).
real clampedOffsetLeft = min(offset,0);
real areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft;
computedArea.y = computedAreaUncut.y - areaOfSmallLeftTriangle;
// We do the same for the Z but with the right part of the isoceles triangle
computedAreaUncut.z = SampleShadow_GetTriangleTexelArea(1.5 + offset);
real clampedOffsetRight = max(offset,0);
real areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight;
computedArea.z = computedAreaUncut.z - areaOfSmallRightTriangle;
}
// Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
// This function return the weight of each texels area relative to the full triangle area.
void SampleShadow_GetTexelWeights_Tent_3x3(real offset, out real4 computedWeight)
{
real4 dummy;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedWeight, dummy);
computedWeight *= 0.44444;//0.44 == 1/(the triangle area)
}
// Assuming a isoceles triangle of 2.5 texel height and 5 texels wide lying on 6 texels.
// This function return the weight of each texels area relative to the full triangle area.
// / \
// _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_5x5(real offset, out real3 texelsWeightsA, out real3 texelsWeightsB)
{
// See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
// the 5 texel wide triangle can be seen as the 3 texel wide one but shifted up by one unit/texel.
// 0.16 is 1/(the triangle area)
texelsWeightsA.x = 0.16 * (computedArea_From3texelTriangle.x);
texelsWeightsA.y = 0.16 * (computedAreaUncut_From3texelTriangle.y);
texelsWeightsA.z = 0.16 * (computedArea_From3texelTriangle.y + 1);
texelsWeightsB.x = 0.16 * (computedArea_From3texelTriangle.z + 1);
texelsWeightsB.y = 0.16 * (computedAreaUncut_From3texelTriangle.z);
texelsWeightsB.z = 0.16 * (computedArea_From3texelTriangle.w);
}
// Assuming a isoceles triangle of 3.5 texel height and 7 texels wide lying on 8 texels.
// This function return the weight of each texels area relative to the full triangle area.
// / \
// _ _ _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 6 7 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_7x7(real offset, out real4 texelsWeightsA, out real4 texelsWeightsB)
{
// See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
// the 7 texel wide triangle can be seen as the 3 texel wide one but shifted up by two unit/texel.
// 0.081632 is 1/(the triangle area)
texelsWeightsA.x = 0.081632 * (computedArea_From3texelTriangle.x);
texelsWeightsA.y = 0.081632 * (computedAreaUncut_From3texelTriangle.y);
texelsWeightsA.z = 0.081632 * (computedAreaUncut_From3texelTriangle.y + 1);
texelsWeightsA.w = 0.081632 * (computedArea_From3texelTriangle.y + 2);
texelsWeightsB.x = 0.081632 * (computedArea_From3texelTriangle.z + 2);
texelsWeightsB.y = 0.081632 * (computedAreaUncut_From3texelTriangle.z + 1);
texelsWeightsB.z = 0.081632 * (computedAreaUncut_From3texelTriangle.z);
texelsWeightsB.w = 0.081632 * (computedArea_From3texelTriangle.w);
}
// 3x3 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_3x3(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[4], out real2 fetchesUV[4])
{
// tent base is 3x3 base thus covering from 9 to 12 texels, thus we need 4 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based
real4 texelsWeightsU, texelsWeightsV;
SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU);
SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real2 fetchesWeightsU = texelsWeightsU.xz + texelsWeightsU.yw;
real2 fetchesWeightsV = texelsWeightsV.xz + texelsWeightsV.yw;
// move the PCF bilinear fetches to respect texels weights
real2 fetchesOffsetsU = texelsWeightsU.yw / fetchesWeightsU.xy + real2(-1.5,0.5);
real2 fetchesOffsetsV = texelsWeightsV.yw / fetchesWeightsV.xy + real2(-1.5,0.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[3] = fetchesWeightsU.y * fetchesWeightsV.y;
}
// 5x5 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_5x5(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[9], out real2 fetchesUV[9])
{
// tent base is 5x5 base thus covering from 25 to 36 texels, thus we need 9 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based on the area of a 45 degree slop tent above each of them.
real3 texelsWeightsU_A, texelsWeightsU_B;
real3 texelsWeightsV_A, texelsWeightsV_B;
SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real3 fetchesWeightsU = real3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + real3(texelsWeightsU_A.y, texelsWeightsU_B.xz);
real3 fetchesWeightsV = real3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + real3(texelsWeightsV_A.y, texelsWeightsV_B.xz);
// move the PCF bilinear fetches to respect texels weights
real3 fetchesOffsetsU = real3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + real3(-2.5,-0.5,1.5);
real3 fetchesOffsetsV = real3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + real3(-2.5,-0.5,1.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xxx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yyy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
fetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y;
fetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y;
fetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z;
fetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z;
fetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z;
}
// 7x7 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_7x7(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[16], out real2 fetchesUV[16])
{
// tent base is 7x7 base thus covering from 49 to 64 texels, thus we need 16 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based on the area of a 45 degree slop tent above each of them.
real4 texelsWeightsU_A, texelsWeightsU_B;
real4 texelsWeightsV_A, texelsWeightsV_B;
SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real4 fetchesWeightsU = real4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw);
real4 fetchesWeightsV = real4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw);
// move the PCF bilinear fetches to respect texels weights
real4 fetchesOffsetsU = real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + real4(-3.5,-1.5,0.5,2.5);
real4 fetchesOffsetsV = real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + real4(-3.5,-1.5,0.5,2.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xxxx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yyyy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.x);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.y);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[9] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[10] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesUV[11] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.z);
fetchesUV[12] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.w);
fetchesUV[13] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.w);
fetchesUV[14] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.w);
fetchesUV[15] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.w);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
fetchesWeights[3] = fetchesWeightsU.w * fetchesWeightsV.x;
fetchesWeights[4] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[5] = fetchesWeightsU.y * fetchesWeightsV.y;
fetchesWeights[6] = fetchesWeightsU.z * fetchesWeightsV.y;
fetchesWeights[7] = fetchesWeightsU.w * fetchesWeightsV.y;
fetchesWeights[8] = fetchesWeightsU.x * fetchesWeightsV.z;
fetchesWeights[9] = fetchesWeightsU.y * fetchesWeightsV.z;
fetchesWeights[10] = fetchesWeightsU.z * fetchesWeightsV.z;
fetchesWeights[11] = fetchesWeightsU.w * fetchesWeightsV.z;
fetchesWeights[12] = fetchesWeightsU.x * fetchesWeightsV.w;
fetchesWeights[13] = fetchesWeightsU.y * fetchesWeightsV.w;
fetchesWeights[14] = fetchesWeightsU.z * fetchesWeightsV.w;
fetchesWeights[15] = fetchesWeightsU.w * fetchesWeightsV.w;
}
#include "CoreRP/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl"
// ------------------------------------------------------------------
// PCF Filtering methods

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


#endif
#if defined(UNITY_INSTANCED_SH) && !defined(LIGHTMAP_ON)
//In HDRenderpipe we only decide to look at probe data based on Lightmap flags.
#if !defined(DYNAMICLIGHTMAP_ON)
#if !defined(DYNAMICLIGHTMAP_ON)
#define UNITY_USE_SHCOEFFS_ARRAYS
#endif
#if defined(SHADOWS_SHADOWMASK)

#undef UNITY_MATRIX_I_M
#define UNITY_MATRIX_I_M UNITY_ACCESS_INSTANCED_PROP(MERGE_UNITY_BUILTINS_INDEX(UNITY_WORLDTOOBJECTARRAY_CB), unity_WorldToObjectArray)
inline float4 UnityObjectToClipPosInstanced(in float3 pos)
{
return mul(UNITY_MATRIX_VP, mul(UNITY_MATRIX_M, float4(pos, 1.0)));
}
inline float4 UnityObjectToClipPosInstanced(float4 pos)
{
return UnityObjectToClipPosInstanced(pos.xyz);
}
#define UnityObjectToClipPos UnityObjectToClipPosInstanced
#else // UNITY_INSTANCING_ENABLED

30
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/VolumeRendering.hlsl


return INV_FOUR_PI * (1 - g * g);
}
real HenyeyGreensteinPhasePartVarying(real asymmetry, real LdotD)
real HenyeyGreensteinPhasePartVarying(real asymmetry, real cosTheta)
return pow(abs(1 + g * g - 2 * g * LdotD), -1.5);
return pow(abs(1 + g * g - 2 * g * cosTheta), -1.5);
real HenyeyGreensteinPhaseFunction(real asymmetry, real LdotD)
real HenyeyGreensteinPhaseFunction(real asymmetry, real cosTheta)
HenyeyGreensteinPhasePartVarying(asymmetry, LdotD);
HenyeyGreensteinPhasePartVarying(asymmetry, cosTheta);
}
real CornetteShanksPhasePartConstant(real asymmetry)
{
real g = asymmetry;
return INV_FOUR_PI * 1.5 * (1 - g * g) / (2 + g * g);
}
real CornetteShanksPhasePartVarying(real asymmetry, real cosTheta)
{
real g = asymmetry;
return (1 + cosTheta * cosTheta) * pow(abs(1 + g * g - 2 * g * cosTheta), -1.5);
}
// A better approximation of the Mie phase function.
// Ref: Henyey–Greenstein and Mie phase functions in Monte Carlo radiative transfer computations
real CornetteShanksPhaseFunction(real asymmetry, real cosTheta)
{
return CornetteShanksPhasePartConstant(asymmetry) *
CornetteShanksPhasePartVarying(asymmetry, cosTheta);
}
// Samples the interval of homogeneous participating medium using the closed-form tracking approach

2
ScriptableRenderPipeline/Core/package.json


{
"name": "com.unity.render-pipelines.core",
"description": "Core library for Unity render pipelines.",
"version": "0.1.24",
"version": "0.1.26",
"unity": "2018.1",
"dependencies": {
"com.unity.postprocessing": "0.1.7"

66
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDAdditionalCameraData.cs


float m_Version = 1.0f;
#pragma warning restore 414
Camera m_camera;
// This struct allow to add specialized path in HDRenderPipeline (can be use to render mini map or planar reflection etc...)
// A rendering path is the list of rendering pass that will be executed at runtime and depends on the associated FrameSettings
// Default is the default rendering path define by the HDRendeRPipelineAsset FrameSettings.

[FormerlySerializedAs("serializedFrameSettings")]
FrameSettings m_FrameSettings = new FrameSettings(); // Serialize frameSettings
// Not serialized, not visible
// Not serialized, visible only in the debug windows
bool m_frameSettingsIsDirty = true;
// Use for debug windows
// When camera name change we need to update the name in DebugWindows.
// This is the purpose of this class
bool m_IsDebugRegistered = false;
string m_CameraRegisterName;
// This is the function use outside to access FrameSettings. It return the current state of FrameSettings for the camera
// taking into account the customization via the debug menu
bool m_IsDebugRegistered = false;
Camera m_camera;
string m_CameraRegisterName;
// This function is call at the beginning of camera loop in HDRenderPipeline.Render()
// It allow to correctly init the m_FrameSettingsRuntime to use.
// If the camera use defaultFrameSettings it must be copied in m_FrameSettingsRuntime
// otherwise it is the serialized m_FrameSettings that are used
// This is required so each camera have its own debug settings even if they all use the RenderingPath.Default path
// and important at Runtime as Default Camera from Scene Preview doesn't exist
// assetFrameSettingsIsDirty is the current dirty frame settings state of HDRenderPipelineAsset
// if it is dirty and camera use RenderingPath.Default, we need to update it
// defaultFrameSettings are the settings store in the HDRenderPipelineAsset
public void UpdateDirtyFrameSettings(bool assetFrameSettingsIsDirty, FrameSettings defaultFrameSettings)
{
if (m_frameSettingsIsDirty || assetFrameSettingsIsDirty)
{
// We do a copy of the settings to those effectively used
if (renderingPath == RenderingPath.Default)
{
defaultFrameSettings.CopyTo(m_FrameSettingsRuntime);
}
else
{
m_FrameSettings.CopyTo(m_FrameSettingsRuntime);
}
m_frameSettingsIsDirty = false;
}
}
FrameSettings.RegisterDebug(m_camera.name, GetFrameSettings());
// Note that we register m_FrameSettingsRuntime, so manipulating it in the Debug windows
// doesn't affect the serialized version
if (m_camera.cameraType != CameraType.Preview)
{
FrameSettings.RegisterDebug(m_camera.name, GetFrameSettings());
}
m_CameraRegisterName = m_camera.name;
m_IsDebugRegistered = true;
}

{
if (m_IsDebugRegistered)
{
FrameSettings.UnRegisterDebug(m_CameraRegisterName);
if (m_camera.cameraType != CameraType.Preview)
{
FrameSettings.UnRegisterDebug(m_CameraRegisterName);
}
m_IsDebugRegistered = false;
}
}

m_camera = GetComponent<Camera>();
m_camera.allowHDR = false;
m_FrameSettings.CopyTo(m_FrameSettingsRuntime);
// Tag as dirty so frameSettings are correctly initialize at next HDRenderPipeline.Render() call
m_frameSettingsIsDirty = true;
RegisterDebug();
}

// We need to detect name change in the editor and update debug windows accordingly
#if UNITY_EDITOR
if (m_camera.name != m_CameraRegisterName)
{

public void OnAfterDeserialize()
{
// We do a copy of the settings to those effectively used
m_FrameSettings.CopyTo(m_FrameSettingsRuntime);
// This is call on load or when this settings are change.
// When FrameSettings are manipulated or RenderPath change we reset them to reflect the change, discarding all the Debug Windows change.
// Tag as dirty so frameSettings are correctly initialize at next HDRenderPipeline.Render() call
m_frameSettingsIsDirty = true;
}
}
}

20
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs


prevViewProjMatrix *= cameraDisplacement; // Now prevViewProjMatrix correctly transforms this frame's camera-relative positionWS
}
// Warning: near and far planes appear to be broken.
// Warning: near and far planes appear to be broken (or rather far plane seems broken)
GeometryUtility.CalculateFrustumPlanes(viewProjMatrix, frustumPlanes);
for (int i = 0; i < 4; i++)

}
// Near, far.
Vector4 forward = (camera.cameraType == CameraType.Reflection) ? camera.worldToCameraMatrix.GetRow(2) : new Vector4(camera.transform.forward.x, camera.transform.forward.y, camera.transform.forward.z, 0.0f);
Vector3 forward = viewParam.x < 0.0f ? camera.transform.forward : -camera.transform.forward;
forward = viewParam.x < 0.0f ? forward : -forward;
frustumPlaneEquations[4] = new Vector4( forward.x, forward.y, forward.z, -Vector3.Dot(forward, relPos) - camera.nearClipPlane);
frustumPlaneEquations[5] = new Vector4(-forward.x, -forward.y, -forward.z, Vector3.Dot(forward, relPos) + camera.farClipPlane);

m_CameraScaleBias.x = (float)m_ActualWidth / maxWidth;
m_CameraScaleBias.y = (float)m_ActualHeight / maxHeight;
screenSize = new Vector4(m_ActualWidth, m_ActualHeight, m_CameraScaleBias.x / m_ActualWidth, m_CameraScaleBias.y / m_ActualHeight);
}
// Warning: different views can use the same camera!
public int GetViewID()
{
if (camera.cameraType == CameraType.Game)
{
int viewID = camera.GetInstanceID();
Debug.Assert(viewID > 0);
return viewID;
}
else
{
return 0;
}
}
public void Reset()

110
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugColorPicker.shader


#pragma fragment Frag
#include "CoreRP/ShaderLibrary/Common.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "../ShaderVariables.hlsl"
#include "../Debug/DebugDisplay.cs.hlsl"
#include "../Debug/DebugDisplay.hlsl"

float4 _ColorPickerParam; // 4 increasing threshold
int _ColorPickerMode;
float3 _ColorPickerFontColor;
float _ApplyLinearToSRGB;
float _RequireToFlipInputTexture;
struct Attributes
{

return output;
}
float4 DisplayPixelInformationAtMousePosition(Varyings input, float4 result, float4 mouseResult)
float4 DisplayPixelInformationAtMousePosition(Varyings input, float4 result, float4 mouseResult, float4 mousePixelCoord)
if (_MousePixelCoord.z >= 0.0 && _MousePixelCoord.z <= 1.0 && _MousePixelCoord.w >= 0 && _MousePixelCoord.w <= 1.0)
bool flipY = _RequireToFlipInputTexture > 0.0;
if (mousePixelCoord.z >= 0.0 && mousePixelCoord.z <= 1.0 && mousePixelCoord.w >= 0 && mousePixelCoord.w <= 1.0)
// As when we read with the color picker we don't go through the final blit (that current hardcode a conversion to sRGB)
// and as our material debug take it into account, we need to a transform here.
if (_ApplyLinearToSRGB > 0.0)
{
mouseResult.rgb = LinearToSRGB(mouseResult.rgb);
}
#if UNITY_UV_STARTS_AT_TOP
int displayTextOffsetY = -DEBUG_FONT_TEXT_HEIGHT;
#else
int displayTextOffsetY = DEBUG_FONT_TEXT_HEIGHT;
#endif
int displayTextOffsetY;
if (flipY)
{
displayTextOffsetY = DEBUG_FONT_TEXT_HEIGHT;
}
else
{
displayTextOffsetY = -DEBUG_FONT_TEXT_HEIGHT;
}
uint2 displayUnormCoord = uint2(_MousePixelCoord.x + displayTextOffsetX, _MousePixelCoord.y + displayTextOffsetY);
uint2 displayUnormCoord = uint2(mousePixelCoord.x + displayTextOffsetX, mousePixelCoord.y + displayTextOffsetY);
uint2 unormCoord = input.positionCS.xy;
if (_ColorPickerMode == COLORPICKERDEBUGMODE_BYTE || _ColorPickerMode == COLORPICKERDEBUGMODE_BYTE4)

DrawCharacter('R', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawInteger(mouseValue.x, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter('R', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawInteger(mouseValue.x, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
displayUnormCoord.x = _MousePixelCoord.x + displayTextOffsetX;
displayUnormCoord.x = mousePixelCoord.x + displayTextOffsetX;
DrawCharacter('G', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawInteger(mouseValue.y, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
displayUnormCoord.x = _MousePixelCoord.x + displayTextOffsetX;
DrawCharacter('G', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawInteger(mouseValue.y, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
displayUnormCoord.x = mousePixelCoord.x + displayTextOffsetX;
DrawCharacter('B', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawInteger(mouseValue.z, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
displayUnormCoord.x = _MousePixelCoord.x + displayTextOffsetX;
DrawCharacter('B', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawInteger(mouseValue.z, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
displayUnormCoord.x = mousePixelCoord.x + displayTextOffsetX;
DrawCharacter('A', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawInteger(mouseValue.w, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter('A', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawInteger(mouseValue.w, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter('X', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawFloat(mouseResult.x, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter('X', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawFloat(mouseResult.x, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
displayUnormCoord.x = _MousePixelCoord.x + displayTextOffsetX;
displayUnormCoord.x = mousePixelCoord.x + displayTextOffsetX;
DrawCharacter('Y', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawFloat(mouseResult.y, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
displayUnormCoord.x = _MousePixelCoord.x + displayTextOffsetX;
DrawCharacter('Y', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawFloat(mouseResult.y, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
displayUnormCoord.x = mousePixelCoord.x + displayTextOffsetX;
DrawCharacter('Z', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawFloat(mouseResult.z, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
displayUnormCoord.x = _MousePixelCoord.x + displayTextOffsetX;
DrawCharacter('Z', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawFloat(mouseResult.z, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
displayUnormCoord.x = mousePixelCoord.x + displayTextOffsetX;
DrawCharacter('W', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawFloat(mouseResult.w, _ColorPickerFontColor, unormCoord, displayUnormCoord, result.rgb);
DrawCharacter('W', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawCharacter(':', _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
DrawFloat(mouseResult.w, _ColorPickerFontColor, unormCoord, displayUnormCoord, flipY, result.rgb);
}
}
}

float4 Frag(Varyings input) : SV_Target
{
if (_RequireToFlipInputTexture > 0.0)
{
input.texcoord.y = 1.0 - input.texcoord.y;
}
float4 mouseResult = SAMPLE_TEXTURE2D(_DebugColorPickerTexture, sampler_DebugColorPickerTexture, _MousePixelCoord.zw);
float4 mousePixelCoord = _MousePixelCoord;
if (_RequireToFlipInputTexture > 0.0)
{
mousePixelCoord.y = _ScreenParams.y - mousePixelCoord.y;
// Note: We must not flip the mousePixelCoord.w coordinate
}
return DisplayPixelInformationAtMousePosition(input, result, mouseResult);
float4 mouseResult = SAMPLE_TEXTURE2D(_DebugColorPickerTexture, sampler_DebugColorPickerTexture, mousePixelCoord.zw);
float4 finalResult = DisplayPixelInformationAtMousePosition(input, result, mouseResult, mousePixelCoord);
return finalResult;
}
ENDHLSL

47
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.hlsl


#include "MipMapDebug.cs.hlsl"
#include "ColorPickerDebug.cs.hlsl"
CBUFFER_START(UnityDebugDisplay)
// Set of parameters available when switching to debug shader mode
int _DebugLightingMode; // Match enum DebugLightingMode
int _DebugViewMaterial; // Contain the id (define in various materialXXX.cs.hlsl) of the property to display

float4 _MousePixelCoord; // xy unorm, zw norm
CBUFFER_END
TEXTURE2D(_DebugFont); // Debug font to write string in shader

#endif
break;
case DEBUGVIEWPROPERTIES_INSTANCING:
#if defined(UNITY_INSTANCING_ENABLED)
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);
#endif
break;
}
}

// color is current screen color
// color of the font to use
// direction is 1 or -1 and indicate fixedUnormCoord block shift
void DrawCharacter(uint asciiValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, inout float3 color, int direction)
void DrawCharacter(uint asciiValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, bool flipY, inout float3 color, int direction)
#if UNITY_UV_STARTS_AT_TOP
localCharCoord.y = DEBUG_FONT_TEXT_HEIGHT - localCharCoord.y;
#endif
if (!flipY)
localCharCoord.y = DEBUG_FONT_TEXT_HEIGHT - localCharCoord.y;
asciiValue -= DEBUG_FONT_TEXT_ASCII_START; // Our font start at ASCII table 32;
uint2 asciiCoord = uint2(asciiValue % DEBUG_FONT_TEXT_COUNT_X, asciiValue / DEBUG_FONT_TEXT_COUNT_X);

}
// Shortcut to not have to file direction
void DrawCharacter(uint asciiValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, inout float3 color)
void DrawCharacter(uint asciiValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, bool flipY, inout float3 color)
DrawCharacter(asciiValue, fontColor, currentUnormCoord, fixedUnormCoord, color, 1);
DrawCharacter(asciiValue, fontColor, currentUnormCoord, fixedUnormCoord, flipY, color, 1);
void DrawInteger(int intValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, inout float3 color)
void DrawInteger(int intValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, bool flipY, inout float3 color)
{
const uint maxStringSize = 16;

for (uint i = 0; i < maxStringSize; ++i)
{
// Numeric value incurrent font start on the second row at 0
DrawCharacter((absIntValue % 10) + '0', fontColor, currentUnormCoord, fixedUnormCoord, color, -1);
DrawCharacter((absIntValue % 10) + '0', fontColor, currentUnormCoord, fixedUnormCoord, flipY, color, -1);
if (absIntValue < 10)
break;
absIntValue /= 10;

if (intValue < 0)
{
DrawCharacter('-', fontColor, currentUnormCoord, fixedUnormCoord, color, -1);
DrawCharacter('-', fontColor, currentUnormCoord, fixedUnormCoord, flipY, color, -1);
}
// 5. Reset cursor at end location

void DrawFloat(float floatValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, inout float3 color)
void DrawFloat(float floatValue, float3 fontColor, uint2 currentUnormCoord, inout uint2 fixedUnormCoord, bool flipY, inout float3 color)
int intValue = int(floatValue);
DrawInteger(intValue, fontColor, currentUnormCoord, fixedUnormCoord, color);
DrawCharacter('.', fontColor, currentUnormCoord, fixedUnormCoord, color);
int fracValue = int(frac(floatValue) * 1e6); // 6 digit
DrawInteger(fracValue, fontColor, currentUnormCoord, fixedUnormCoord, color);
if (IsNAN(floatValue))
{
DrawCharacter('N', fontColor, currentUnormCoord, fixedUnormCoord, flipY, color);
DrawCharacter('a', fontColor, currentUnormCoord, fixedUnormCoord, flipY, color);
DrawCharacter('N', fontColor, currentUnormCoord, fixedUnormCoord, flipY, color);
}
else
{
int intValue = int(floatValue);
DrawInteger(intValue, fontColor, currentUnormCoord, fixedUnormCoord, flipY, color);
DrawCharacter('.', fontColor, currentUnormCoord, fixedUnormCoord, flipY, color);
int fracValue = int(frac(floatValue) * 1e6); // 6 digit
DrawInteger(fracValue, fontColor, currentUnormCoord, fixedUnormCoord, flipY, color);
}
}
#endif

48
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugFullScreen.shader


#pragma fragment Frag
#include "CoreRP/ShaderLibrary/Common.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "../ShaderVariables.hlsl"
#include "../Debug/DebugDisplay.cs.hlsl"

float _RequireToFlipInputTexture;
struct Attributes
{

}
// Motion vector debug utilities
// >>>
float DistanceToLine(float2 p, float2 p1, float2 p2)
{
float2 center = (p1 + p2) * 0.5;

float2 SampleMotionVectors(float2 coords)
{
#if UNITY_UV_STARTS_AT_TOP
coords.y = 1.0 - coords.y;
#endif
float2 mv = SAMPLE_TEXTURE2D(_DebugFullScreenTexture, sampler_DebugFullScreenTexture, coords).xy;
#if UNITY_UV_STARTS_AT_TOP
mv.y *= -1.0;
#endif
return mv;
return SAMPLE_TEXTURE2D(_DebugFullScreenTexture, sampler_DebugFullScreenTexture, coords).xy;
// <<<
// end motion vector utilties
if (_RequireToFlipInputTexture > 0.0)
{
input.texcoord.y = 1.0 - input.texcoord.y;
}
// SSAO
if (_FullScreenDebugMode == FULLSCREENDEBUGMODE_SSAO)
{

{
#if UNITY_UV_STARTS_AT_TOP
input.texcoord.y = 1.0 - input.texcoord.y;
#endif
if (any(isnan(color)) || any(isinf(color)))
if (IsNAN(color) || any(isinf(color)))
color = float4(1.0, 0.0, 1.0, 1.0);
color = float4(1.0, 0.0, 0.0, 1.0);
// Dim the color buffer so we can see NaNs & Infs better
color.rgb *= 0.25;
color.rgb = Luminance(color.rgb).xxx;
}
return color;

float rows = floor(kGrid * _ScreenParams.y / _ScreenParams.x);
float cols = kGrid;
float2 size = _ScreenParams.xy / float2(cols, rows);
float body = min(size.x, size.y) / 1.4142135623730951; // sqrt(2)
float body = min(size.x, size.y) / sqrt(2.0);
float2 texcoord = input.positionCS.xy;
float2 center = (floor(texcoord / size) + 0.5) * size;
texcoord -= center;

if (_RequireToFlipInputTexture > 0.0)
{
arrow_coord.y = 1.0 - arrow_coord.y;
}
if (_RequireToFlipInputTexture == 0.0)
{
mv_arrow.y *= -1;
}
// Skip empty motion
float d = 0.0;

5
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewMaterialGBuffer.shader


float4 Frag(Varyings input) : SV_Target
{
// input.positionCS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
BSDFData bsdfData;
BakeLightingData bakeLightingData;

12
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewTiles.shader


float4 Frag(Varyings input) : SV_Target
{
// positionCS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(input.positionCS.xy) / GetTileSize());
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, uint2(input.positionCS.xy) / GetTileSize());
int2 mouseTileCoord = _MousePixelCoord / GetTileSize();
int2 mouseTileCoord = _MousePixelCoord.xy / GetTileSize();
int2 offsetInTile = pixelCoord - tileCoord * GetTileSize();
int n = 0;

int maxLights = 32;
if (tileCoord.y < LIGHTCATEGORY_COUNT && tileCoord.x < maxLights + 3)
{
PositionInputs mousePosInput = GetPositionInput(_MousePixelCoord, _ScreenSize.zw, mouseTileCoord);
float depthMouse = LOAD_TEXTURE2D(_MainDepthTexture, mousePosInput.positionSS).x;
UpdatePositionInput(depthMouse, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, mousePosInput);
float depthMouse = LOAD_TEXTURE2D(_MainDepthTexture, _MousePixelCoord.xy).x;
PositionInputs mousePosInput = GetPositionInput(_MousePixelCoord.xy, _ScreenSize.zw, depthMouse, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, mouseTileCoord);
uint category = (LIGHTCATEGORY_COUNT - 1) - tileCoord.y;
uint start;

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/MaterialDebug.cs


TessellationDisplacement,
DepthOffset,
Lightmap,
Instancing,
Last,
}
}

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/MaterialDebug.cs.hlsl


#define DEBUGVIEWPROPERTIES_TESSELLATION_DISPLACEMENT (19)
#define DEBUGVIEWPROPERTIES_DEPTH_OFFSET (20)
#define DEBUGVIEWPROPERTIES_LIGHTMAP (21)
#define DEBUGVIEWPROPERTIES_LAST (22)
#define DEBUGVIEWPROPERTIES_INSTANCING (22)
#define DEBUGVIEWPROPERTIES_LAST (23)
#endif

24
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalProjectorComponent.cs


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

public Material m_Material = null;
private Material m_OldMaterial = null;
public const int kInvalidIndex = -1;
public const int kInvalidIndex = -1;
private int m_CullIndex = kInvalidIndex;
public int CullIndex

}
}
public Material Mat
{
get { return this.m_Material; }
}
if (m_Material == null)
{
var hdrp = GraphicsSettings.renderPipelineAsset as HDRenderPipelineAsset;
m_Material = hdrp != null ? hdrp.GetDefaultDecalMaterial() : null;
}
DecalSystem.instance.AddDecal(this);
}

DecalSystem.instance.UpdateBoundingSphere(this);
}
public void OnDrawGizmos()
{
DrawGizmo(false);
}
if (!m_Material.GetTexture("_BaseColorMap") && !m_Material.GetTexture("_NormalMap") &&
!m_Material.GetTexture("_MaskMap"))
return false;
return true;
}
}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalProjectorComponent.cs.meta


serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
icon: {fileID: 2800000, guid: b057b73ec5a603e4aa80ccf4b34db0d3, type: 3}
userData:
assetBundleName:
assetBundleVariant:

30
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs


}
}
private static readonly int m_NormalToWorldID = Shader.PropertyToID("normalToWorld");
private static MaterialPropertyBlock m_PropertyBlock = new MaterialPropertyBlock();
private const int kDecalBlockSize = 128;
// to work on Vulkan Mobile?

static public Mesh m_DecalMesh = null;
static public Matrix4x4[] m_InstanceMatrices = new Matrix4x4[kDrawIndexedBatchSize];
static public Matrix4x4[] m_InstanceNormalToWorld = new Matrix4x4[kDrawIndexedBatchSize];
private Dictionary<int, DecalSet> m_DecalSets = new Dictionary<int, DecalSet>();

public void UpdateBoundingSphere(DecalProjectorComponent decal)
{
m_CachedTransforms[decal.CullIndex] = decal.transform.localToWorldMatrix;
Matrix4x4 decalRotation = Matrix4x4.Rotate(decal.transform.rotation);
// z/y axis swap for normal to decal space, Unity is column major
float y0 = decalRotation.m01;
float y1 = decalRotation.m11;
float y2 = decalRotation.m21;
decalRotation.m01 = decalRotation.m02;
decalRotation.m11 = decalRotation.m12;
decalRotation.m21 = decalRotation.m22;
decalRotation.m02 = y0;
decalRotation.m12 = y1;
decalRotation.m22 = y2;
m_CachedNormalToWorld[decal.CullIndex] = decalRotation;
m_BoundingSpheres[decal.CullIndex] = GetDecalProjectBoundingSphere(m_CachedTransforms[decal.CullIndex]);
}

DecalProjectorComponent[] newDecals = new DecalProjectorComponent[m_DecalsCount + kDecalBlockSize];
BoundingSphere[] newSpheres = new BoundingSphere[m_DecalsCount + kDecalBlockSize];
Matrix4x4[] newCachedTransforms = new Matrix4x4[m_DecalsCount + kDecalBlockSize];
Matrix4x4[] newCachedNormalToWorld = new Matrix4x4[m_DecalsCount + kDecalBlockSize];
m_CachedNormalToWorld.CopyTo(newCachedNormalToWorld, 0);
m_CachedNormalToWorld = newCachedNormalToWorld;
}
m_Decals[m_DecalsCount] = decal;

// update the bounding spheres array
m_BoundingSpheres[removeAtIndex] = m_BoundingSpheres[m_DecalsCount - 1];
m_CachedTransforms[removeAtIndex] = m_CachedTransforms[m_DecalsCount - 1];
m_CachedNormalToWorld[removeAtIndex] = m_CachedNormalToWorld[m_DecalsCount - 1];
m_DecalsCount--;
decal.CullIndex = DecalProjectorComponent.kInvalidIndex;
}

int decalIndex = m_ResultIndices[resultIndex];
m_InstanceMatrices[instanceCount] = m_CachedTransforms[decalIndex];
m_InstanceNormalToWorld[instanceCount] = m_CachedNormalToWorld[decalIndex];
cmd.DrawMeshInstanced(m_DecalMesh, 0, m_Decals[0].m_Material, 0, m_InstanceMatrices, kDrawIndexedBatchSize);
m_PropertyBlock.SetMatrixArray(m_NormalToWorldID, m_InstanceNormalToWorld);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_InstanceMatrices, kDrawIndexedBatchSize, m_PropertyBlock);
cmd.DrawMeshInstanced(m_DecalMesh, 0, m_Decals[0].m_Material, 0, m_InstanceMatrices, instanceCount);
m_PropertyBlock.SetMatrixArray(m_NormalToWorldID, m_InstanceNormalToWorld);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_InstanceMatrices, instanceCount, m_PropertyBlock);
}
}

private int m_NumResults = 0;
private int m_DecalsCount = 0;
private Matrix4x4[] m_CachedTransforms = new Matrix4x4[kDecalBlockSize];
private Matrix4x4[] m_CachedNormalToWorld = new Matrix4x4[kDecalBlockSize];
private Material m_Material;
}

11
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Camera/HDCameraEditor.Handlers.cs


{
m_PreviewCamera.CopyFrom(c);
EditorUtility.CopySerialized(c, m_PreviewCamera);
EditorUtility.CopySerialized(c.GetComponent<HDAdditionalCameraData>(), m_PreviewAdditionalCameraData);
var cameraData = c.GetComponent<HDAdditionalCameraData>();
EditorUtility.CopySerialized(cameraData, m_PreviewAdditionalCameraData);
m_PreviewCamera.cameraType = CameraType.SceneView;
m_PreviewCamera.cameraType = CameraType.SceneView; // This is required else if we use Preview the image is flipped... (Unity...)
// We need to call UpdateDirtyFrameSettings to update the dirty flags that was set in the CopySerialized call
m_PreviewAdditionalCameraData.UpdateDirtyFrameSettings(true, cameraData.GetFrameSettings());
// And then to copy the runtime frame settings
// So this includes the runtime frame settings properly
cameraData.GetFrameSettings().CopyTo(m_PreviewAdditionalCameraData.GetFrameSettings());
m_PreviewHDCamera.Update(m_PreviewPostProcessLayer, m_PreviewAdditionalCameraData.GetFrameSettings());
var previewTexture = GetPreviewTextureWithSize((int)previewSize.x, (int)previewSize.y);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Camera/HDCameraEditor.cs


m_UIState.Reset(m_SerializedCamera, Repaint);
m_PreviewCamera = EditorUtility.CreateGameObjectWithHideFlags("Preview Camera", HideFlags.HideAndDontSave, typeof(Camera)).GetComponent<Camera>();
m_PreviewCamera.enabled = false;
m_PreviewCamera.cameraType = CameraType.Preview; // Must be init before adding HDAdditionalCameraData
m_PreviewCamera.enabled = false;
m_PreviewHDCamera = new HDCamera(m_PreviewCamera);
m_PreviewHDCamera.Update(m_PreviewPostProcessLayer, m_PreviewAdditionalCameraData.GetFrameSettings());
}

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


string CorePath = HDEditorUtils.GetCorePath();
newAsset.defaultDiffuseMaterial = Load<Material>(HDRenderPipelinePath + "RenderPipelineResources/DefaultHDMaterial.mat");
newAsset.defaultDecalMaterial = Load<Material>(HDRenderPipelinePath + "RenderPipelineResources/DefaultHDDecalMaterial.mat");
newAsset.defaultShader = Load<Shader>(HDRenderPipelinePath + "Material/Lit/Lit.shader");
newAsset.debugFontTexture = Load<Texture2D>(HDRenderPipelinePath + "RenderPipelineResources/DebugFont.tga");

7
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.cs


if (settings.isBakedOrMixed)
DrawBakedShadowParameters();
if (m_AdditionalLightData.showAdditionalSettings.boolValue)
// There is currently no additional settings for shadow on directional light
if (m_AdditionalLightData.showAdditionalSettings.boolValue && settings.lightType.enumValueIndex != (int)LightType.Directional)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Additional Settings", EditorStyles.boldLabel);

EditorGUILayout.PropertyField(m_AdditionalShadowData.fadeDistance, s_Styles.shadowFadeDistance);
// No shadow dimmer on directional light
if (settings.lightType.enumValueIndex != (int)LightType.Directional)
EditorGUILayout.PropertyField(m_AdditionalShadowData.dimmer, s_Styles.shadowDimmer);
EditorGUILayout.PropertyField(m_AdditionalShadowData.dimmer, s_Styles.shadowDimmer);
EditorGUI.indentLevel--;
}
}

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


EditorGUILayout.PropertyField(profile.lerpWeight, s_Styles.profileLerpWeight);
}
EditorGUILayout.Slider(profile.ior, 1.0f, 2.0f, s_Styles.profileIor);
EditorGUILayout.PropertyField(profile.worldScale, s_Styles.profileWorldScale);
EditorGUILayout.Space();

EditorGUILayout.Slider(profile.ior, 1.0f, 2.0f, s_Styles.profileIor);
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_Styles.TransmissionLabel, EditorStyles.boldLabel);

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


public static GUIContent windDragText = new GUIContent("Drag");
public static GUIContent windShiverDragText = new GUIContent("Shiver Drag");
public static GUIContent windShiverDirectionalityText = new GUIContent("Shiver Directionality");
public static GUIContent supportDBufferText = new GUIContent("Enable Decal", "Allow to specify if the material can receive decal or not");
}
public enum DoubleSidedNormalMode

protected MaterialProperty tessellationBackFaceCullEpsilon = null;
protected const string kTessellationBackFaceCullEpsilon = "_TessellationBackFaceCullEpsilon";
// Decal
protected MaterialProperty supportDBuffer = null;
protected const string kSupportDBuffer = "_SupportDBuffer";
protected override void FindBaseMaterialProperties(MaterialProperty[] props)
{
base.FindBaseMaterialProperties(props);

windDrag = FindProperty(kWindDrag, props);
windShiverDrag = FindProperty(kWindShiverDrag, props);
windShiverDirectionality = FindProperty(kWindShiverDirectionality, props);
// Decal
supportDBuffer = FindProperty(kSupportDBuffer, props);
}
void TessellationModePopup()

}
m_MaterialEditor.ShaderProperty(materialID, StylesBaseLit.materialIDText);
m_MaterialEditor.ShaderProperty(supportDBuffer, StylesBaseLit.supportDBufferText);
m_MaterialEditor.ShaderProperty(enableMotionVectorForVertexAnimation, StylesBaseLit.enableMotionVectorForVertexAnimationText);

}
SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor", material);
// Use negation so we don't create keyword by default
CoreUtils.SetKeyword(material, "_DISABLE_DBUFFER", material.GetFloat(kSupportDBuffer) == 0.0);
}
static public void SetupBaseLitMaterialPass(Material material)

20
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/Unlit/BaseUnlitUI.cs


public static GUIContent transparentDepthPrepassEnableText = new GUIContent("Enable transparent depth prepass", "It allow to to fill depth buffer to improve sorting");
public static GUIContent transparentDepthPostpassEnableText = new GUIContent("Enable transparent depth postpass", "It allow to fill depth buffer for postprocess effect like DOF");
public static GUIContent transparentBackfaceEnableText = new GUIContent("Enable back then front rendering", "It allow to better sort transparent mesh by first rendering back faces then front faces in two separate drawcall");
public static GUIContent transparentSortPriorityText = new GUIContent("Transparent Sort Priority", "Allow to define priority (from -100 to +100) to solve sorting issue with transparent");
public static GUIContent enableTransparentFogText = new GUIContent("Enable fog", "Enable fog on transparent material");
public static GUIContent enableBlendModePreserveSpecularLightingText = new GUIContent("Blend preserve specular lighting", "Blend mode will only affect diffuse lighting, allowing correct specular lighting (reflection) on transparent object");

protected const string kTransparentDepthPostpassEnable = "_TransparentDepthPostpassEnable";
protected MaterialProperty transparentBackfaceEnable = null;
protected const string kTransparentBackfaceEnable = "_TransparentBackfaceEnable";
protected MaterialProperty transparentSortPriority = null;
protected const string kTransparentSortPriority = "_TransparentSortPriority";
protected MaterialProperty doubleSidedEnable = null;
protected const string kDoubleSidedEnable = "_DoubleSidedEnable";
protected MaterialProperty blendMode = null;

transparentDepthPostpassEnable = FindProperty(kTransparentDepthPostpassEnable, props, false);
transparentBackfaceEnable = FindProperty(kTransparentBackfaceEnable, props, false);
transparentSortPriority = FindProperty(kTransparentSortPriority, props, false);
doubleSidedEnable = FindProperty(kDoubleSidedEnable, props, false);
blendMode = FindProperty(kBlendMode, props, false);

if (transparentBackfaceEnable != null && ((SurfaceType)surfaceType.floatValue == SurfaceType.Transparent))
m_MaterialEditor.ShaderProperty(transparentBackfaceEnable, StylesBaseUnlit.transparentBackfaceEnableText);
if (transparentSortPriority != null && ((SurfaceType)surfaceType.floatValue == SurfaceType.Transparent))
{
EditorGUI.BeginChangeCheck();
m_MaterialEditor.ShaderProperty(transparentSortPriority, StylesBaseUnlit.transparentSortPriorityText);
if (EditorGUI.EndChangeCheck())
{
transparentSortPriority.floatValue = Mathf.Clamp((int)transparentSortPriority.floatValue, -(int)HDRenderQueue.k_TransparentPriorityQueueRange, (int)HDRenderQueue.k_TransparentPriorityQueueRange);
}
}
// This function must finish with double sided option (see LitUI.cs)
if (doubleSidedEnable != null)
{

material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.renderQueue = alphaTestEnable ? (int)HDRenderQueue.AlphaTest : -1;
material.renderQueue = alphaTestEnable ? (int)HDRenderQueue.Priority.OpaqueAlphaTest : (int)HDRenderQueue.Priority.Opaque;
}
else
{

material.renderQueue = (int)(isPrepass ? HDRenderQueue.PreRefraction : HDRenderQueue.Transparent);
material.renderQueue = (int)(isPrepass ? HDRenderQueue.Priority.PreRefraction : HDRenderQueue.Priority.Transparent) + (int)material.GetFloat(kTransparentSortPriority);
if (material.HasProperty(kBlendMode))
{

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/RenderPipelineSettingsUI.cs


EditorGUILayout.PropertyField(d.supportDBuffer, _.GetContent("Support Decal Buffer"));
EditorGUILayout.PropertyField(d.supportMSAA, _.GetContent("Support MSAA"));
EditorGUILayout.PropertyField(d.supportSubsurfaceScattering, _.GetContent("Support Subsurface Scattering"));
EditorGUILayout.PropertyField(d.supportAsyncCompute, _.GetContent("Support AsyncCompute"));
EditorGUILayout.PropertyField(d.supportsForwardOnly, _.GetContent("Support Forward Only"));
EditorGUILayout.PropertyField(d.supportsMotionVectors, _.GetContent("Support Motion Vectors"));
EditorGUILayout.PropertyField(d.supportsStereo, _.GetContent("Support Stereo Rendering"));

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/SerializedRenderPipelineSettings.cs


public SerializedProperty supportDBuffer;
public SerializedProperty supportMSAA;
public SerializedProperty supportSubsurfaceScattering;
public SerializedProperty supportAsyncCompute;
public SerializedProperty supportsForwardOnly;
public SerializedProperty supportsMotionVectors;
public SerializedProperty supportsStereo;

supportDBuffer = root.Find((RenderPipelineSettings s) => s.supportDBuffer);
supportMSAA = root.Find((RenderPipelineSettings s) => s.supportMSAA);
supportSubsurfaceScattering = root.Find((RenderPipelineSettings s) => s.supportSubsurfaceScattering);
supportAsyncCompute = root.Find((RenderPipelineSettings s) => s.supportAsyncCompute);
supportsForwardOnly = root.Find((RenderPipelineSettings s) => s.supportsForwardOnly);
supportsMotionVectors = root.Find((RenderPipelineSettings s) => s.supportsMotionVectors);
supportsStereo = root.Find((RenderPipelineSettings s) => s.supportsStereo);

145
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public partial class HDRenderPipeline : RenderPipeline
public class HDRenderPipeline : RenderPipeline
{
enum ForwardPass
{

"Forward PreRefraction",
"Forward Transparent"
};
static readonly RenderQueueRange k_RenderQueue_PreRefraction = new RenderQueueRange { min = (int)HDRenderQueue.PreRefraction, max = (int)HDRenderQueue.Transparent - 1 };
static readonly RenderQueueRange k_RenderQueue_Transparent = new RenderQueueRange { min = (int)HDRenderQueue.Transparent, max = (int)HDRenderQueue.Overlay - 1 };
static readonly RenderQueueRange k_RenderQueue_AllTransparent = new RenderQueueRange { min = (int)HDRenderQueue.PreRefraction, max = (int)HDRenderQueue.Overlay - 1 };
readonly HDRenderPipelineAsset m_Asset;

readonly SkyManager m_SkyManager = new SkyManager();
readonly LightLoop m_LightLoop = new LightLoop();
readonly ShadowSettings m_ShadowSettings = new ShadowSettings();
readonly VolumetricLightingModule m_VolumetricLightingModule = new VolumetricLightingModule();
MaterialPropertyBlock m_SharedPropertyBlock = new MaterialPropertyBlock();
DebugDisplaySettings m_DebugDisplaySettings = new DebugDisplaySettings();
public DebugDisplaySettings debugDisplaySettings { get { return m_DebugDisplaySettings; } }
static DebugDisplaySettings s_NeutralDebugDisplaySettings = new DebugDisplaySettings();
DebugDisplaySettings m_CurrentDebugDisplaySettings;
MaterialPropertyBlock m_SharedPropertyBlock = new MaterialPropertyBlock();
DebugDisplaySettings m_DebugDisplaySettings = new DebugDisplaySettings();
public DebugDisplaySettings debugDisplaySettings { get { return m_DebugDisplaySettings; } }
static DebugDisplaySettings s_NeutralDebugDisplaySettings = new DebugDisplaySettings();
DebugDisplaySettings m_CurrentDebugDisplaySettings;
RTHandle m_DebugColorPickerBuffer;
RTHandle m_DebugFullScreenTempBuffer;
bool m_FullScreenDebugPushed;

m_LightLoop.Build(asset, m_ShadowSettings, m_IBLFilterGGX);
m_SkyManager.Build(asset, m_IBLFilterGGX);
m_VolumetricLightingModule.Build(asset);
m_DebugDisplaySettings.RegisterDebug();
FrameSettings.RegisterDebug("Default Camera", m_Asset.GetFrameSettings());

m_SSSBufferManager.Cleanup();
m_SkyManager.Cleanup();
m_VolumetricLightingModule.Cleanup();
DestroyRenderTextures();

m_LightLoop.AllocResolutionDependentBuffers(hdCamera.actualWidth, hdCamera.actualHeight);
}
int viewId = hdCamera.camera.GetInstanceID(); // Warning: different views can use the same camera
if (m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
ResizeVBuffer(viewId, hdCamera.actualWidth, hdCamera.actualHeight);
m_VolumetricLightingModule.ResizeVBuffer(hdCamera, hdCamera.actualWidth, hdCamera.actualHeight);
// update recorded window resolution
m_CurrentWidth = hdCamera.actualWidth;

m_DbufferManager.PushGlobalParams(cmd);
if (m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
{
SetVolumetricLightingData(hdCamera, cmd);
m_VolumetricLightingModule.PushGlobalParams(hdCamera, cmd);
}
bool NeedDepthBufferCopy()
{

m_FrameCount = Time.frameCount;
}
// We first update the state of asset frame settings as they can be use by various camera
// but we keep the dirty state to correctly reset other camera that use RenderingPath.Default.
bool assetFrameSettingsIsDirty = m_Asset.frameSettingsIsDirty;
m_Asset.UpdateDirtyFrameSettings();
foreach (var camera in cameras)
{
if (camera == null)

// Note: the SceneView camera will never have additionalCameraData
// Note: the scene view camera will never have additionalCameraData
var srcFrameSettings = (additionalCameraData && additionalCameraData.renderingPath != HDAdditionalCameraData.RenderingPath.Default)
? additionalCameraData.GetFrameSettings()
: m_Asset.GetFrameSettings();
// Init effective frame settings of each camera
// Each camera have its own debug frame settings control from the debug windows
// debug frame settings can't be aggregate with frame settings (i.e we can't aggregate forward only control for example)
// so debug settings (when use) are the effective frame settings
// To be able to have this behavior we init effective frame settings with serialized frame settings and copy
// debug settings change on top of it. Each time frame settings are change in the editor, we reset all debug settings
// to stay in sync. The loop below allow to update all frame settings correctly and is required because
// camera can rely on default frame settings from the HDRendeRPipelineAsset
FrameSettings srcFrameSettings;
if (additionalCameraData)
{
additionalCameraData.UpdateDirtyFrameSettings(assetFrameSettingsIsDirty, m_Asset.GetFrameSettings());
srcFrameSettings = additionalCameraData.GetFrameSettings();
}
else
{
srcFrameSettings = m_Asset.GetFrameSettings();
}
// Get the effective frame settings for this camera taking into account the global setting and camera type
FrameSettings.InitializeFrameSettings(camera, m_Asset.GetRenderPipelineSettings(), srcFrameSettings, ref m_FrameSettings);
// This is the main command buffer used for the frame.

// 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, cmd);
RenderPyramidDepth(camera, cmd, renderContext, FullScreenDebugMode.DepthPyramid);
RenderPyramidDepth(hdCamera, cmd, renderContext, FullScreenDebugMode.DepthPyramid);
if (m_CurrentDebugDisplaySettings.IsDebugMaterialDisplayEnabled())

// Render the volumetric lighting.
// The pass requires the volume properties, the light list and the shadows, and can run async.
VolumetricLightingPass(hdCamera, cmd);
m_VolumetricLightingModule.VolumetricLightingPass(hdCamera, cmd, m_FrameSettings);
RenderDeferredLighting(hdCamera, cmd);

RenderForward(m_CullResults, hdCamera, renderContext, cmd, ForwardPass.PreRefraction);
RenderForwardError(m_CullResults, hdCamera, renderContext, cmd, ForwardPass.PreRefraction);
RenderGaussianPyramidColor(camera, cmd, renderContext, true);
RenderGaussianPyramidColor(hdCamera, cmd, renderContext, true);
// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForward(m_CullResults, hdCamera, renderContext, cmd, ForwardPass.Transparent);

RenderTransparentDepthPostpass(m_CullResults, hdCamera, renderContext, cmd, ForwardPass.Transparent);
PushFullScreenDebugTexture(cmd, m_CameraColorBuffer, hdCamera, FullScreenDebugMode.NanTracker);
RenderGaussianPyramidColor(camera, cmd, renderContext, false);
RenderGaussianPyramidColor(hdCamera, cmd, renderContext, false);
PushFullScreenDebugTexture(cmd, m_CameraColorBuffer, hdCamera, FullScreenDebugMode.NanTracker);
// The final pass either postprocess of Blit will flip the screen (as it is reverse by default due to Unity openGL legacy)
// Postprocess system (that doesn't use cmd.Blit) handle it with configuration (and do not flip in SceneView) or it is automatically done in Blit
// Final blit
if (m_FrameSettings.enablePostprocess && CoreUtils.IsPostProcessingActive(postProcessLayer))
{

{
using (new ProfilingSample(cmd, "Blit to final RT", CustomSamplerId.CopyDepthForSceneView.GetSampler()))
{
// This Blit will flip the screen anything other than openGL
// Simple blit
HDUtils.BlitCameraTexture(cmd, hdCamera, m_CameraColorBuffer, BuiltinRenderTextureType.CameraTarget);
}

}
}
#endif
// Caution: RenderDebug need to take into account that we have flip the screen (so anything capture before the flip will be flipped)
RenderDebug(hdCamera, cmd);
}

var filterSettings = new FilterRenderersSettings(true)
{
renderQueueRange = inRenderQueueRange == null ? RenderQueueRange.opaque : inRenderQueueRange.Value
renderQueueRange = inRenderQueueRange == null ? HDRenderQueue.k_RenderQueue_AllOpaque : inRenderQueueRange.Value
};
if (stateBlock == null)

var filterSettings = new FilterRenderersSettings(true)
{
renderQueueRange = inRenderQueueRange == null ? k_RenderQueue_AllTransparent : inRenderQueueRange.Value
renderQueueRange = inRenderQueueRange == null ? HDRenderQueue.k_RenderQueue_AllTransparent : inRenderQueueRange.Value
};
if (stateBlock == null)

{
// We render first the opaque object as opaque alpha tested are more costly to render and could be reject by early-z (but not Hi-z as it is disable with clip instruction)
// This is handled automatically with the RenderQueue value (OpaqueAlphaTested have a different value and thus are sorted after Opaque)
RenderOpaqueRenderList(cull, camera, renderContext, cmd, m_DepthOnlyAndDepthForwardOnlyPassNames, 0, RenderQueueRange.opaque, m_DepthStateOpaque);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, m_DepthOnlyAndDepthForwardOnlyPassNames, 0, HDRenderQueue.k_RenderQueue_AllOpaque, m_DepthStateOpaque);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, m_DepthForwardOnlyPassNames, 0, RenderQueueRange.opaque, m_DepthStateOpaque);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, m_DepthForwardOnlyPassNames, 0, HDRenderQueue.k_RenderQueue_AllOpaque, m_DepthStateOpaque);
// Render Alpha test only if requested
if (addAlphaTestedOnly)

if (m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled())
{
// When doing debug display, the shader has the clip instruction regardless of the depth prepass so we can use regular depth test.
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferDebugDisplayName, m_currentRendererConfigurationBakedLighting, RenderQueueRange.opaque, m_DepthStateOpaque);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferDebugDisplayName, m_currentRendererConfigurationBakedLighting, HDRenderQueue.k_RenderQueue_AllOpaque, m_DepthStateOpaque);
var rangeOpaqueNoAlphaTest = new RenderQueueRange { min = (int)RenderQueue.Geometry, max = (int)RenderQueue.AlphaTest - 1 };
var rangeOpaqueAlphaTest = new RenderQueueRange { min = (int)RenderQueue.AlphaTest, max = (int)RenderQueue.GeometryLast - 1 };
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferName, m_currentRendererConfigurationBakedLighting, rangeOpaqueNoAlphaTest, m_FrameSettings.enableAlphaTestOnlyInDeferredPrepass ? m_DepthStateOpaque : m_DepthStateOpaqueWithPrepass);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferName, m_currentRendererConfigurationBakedLighting, HDRenderQueue.k_RenderQueue_OpaqueNoAlphaTest, m_FrameSettings.enableAlphaTestOnlyInDeferredPrepass ? m_DepthStateOpaque : m_DepthStateOpaqueWithPrepass);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferWithPrepassName, m_currentRendererConfigurationBakedLighting, rangeOpaqueAlphaTest, m_DepthStateOpaqueWithPrepass);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferWithPrepassName, m_currentRendererConfigurationBakedLighting, HDRenderQueue.k_RenderQueue_OpaqueAlphaTest, m_DepthStateOpaqueWithPrepass);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferName, m_currentRendererConfigurationBakedLighting, RenderQueueRange.opaque, m_DepthStateOpaque);
RenderOpaqueRenderList(cull, camera, renderContext, cmd, HDShaderPassNames.s_GBufferName, m_currentRendererConfigurationBakedLighting, HDRenderQueue.k_RenderQueue_AllOpaque, m_DepthStateOpaque);
}
}

// Depth texture is now ready, bind it.
cmd.SetGlobalTexture(HDShaderIDs._MainDepthTexture, GetDepthTexture());
HDUtils.SetRenderTarget(cmd, camera, m_DbufferManager.GetBuffersRTI(), m_CameraDepthStencilBuffer, ClearFlag.Color, CoreUtils.clearColorAllBlack);
// for alpha compositing, color is cleared to 0, alpha to 1
// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html
Color clearColor = new Color(0.0f, 0.0f, 0.0f, 1.0f);
HDUtils.SetRenderTarget(cmd, camera, m_DbufferManager.GetBuffersRTI(), m_CameraDepthStencilBuffer, ClearFlag.Color, clearColor);
// we need to do a separate clear for normals, because they are cleared to a different color
Color clearColorNormal = new Color(0.5f, 0.5f, 0.5f, 1.0f); // for normals 0.5 is neutral
m_DbufferManager.ClearNormalTarget(cmd, camera, clearColorNormal);
HDUtils.SetRenderTarget(cmd, m_DbufferManager.GetBuffersRTI(), m_CameraDepthStencilBuffer); // do not clear anymore
DecalSystem.instance.Render(renderContext, camera, cmd);
}
}

{
using (new ProfilingSample(cmd, "Blit DebugView Material Debug", CustomSamplerId.BlitDebugViewMaterialDebug.GetSampler()))
{
// This Blit will flip the screen anything other than openGL
HDUtils.BlitCameraTexture(cmd, hdCamera, m_CameraColorBuffer, BuiltinRenderTextureType.CameraTarget);
}
}

m_SkyManager.RenderSky(hdCamera, m_LightLoop.GetCurrentSunLight(), m_CameraColorBuffer, m_CameraDepthStencilBuffer, cmd);
if (visualEnv.fogType != FogType.None || m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
if (visualEnv.fogType != FogType.None || m_VolumetricLightingModule.preset != VolumetricLightingModule.VolumetricLightingPreset.Off)
m_SkyManager.RenderOpaqueAtmosphericScattering(cmd);
}

HDUtils.SetRenderTarget(cmd, hdCamera, m_CameraColorBuffer, m_CameraDepthStencilBuffer);
var passNames = m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled() ? m_AllTransparentDebugDisplayPassNames : m_AllTransparentPassNames;
RenderTransparentRenderList(cullResults, camera, renderContext, cmd, passNames, m_currentRendererConfigurationBakedLighting, pass == ForwardPass.PreRefraction ? k_RenderQueue_PreRefraction : k_RenderQueue_Transparent);
RenderTransparentRenderList(cullResults, camera, renderContext, cmd, passNames, m_currentRendererConfigurationBakedLighting, pass == ForwardPass.PreRefraction ? HDRenderQueue.k_RenderQueue_PreRefraction : HDRenderQueue.k_RenderQueue_Transparent);
}
}
}

}
else
{
RenderTransparentRenderList(cullResults, hdCamera.camera, renderContext, cmd, m_ForwardErrorPassNames, 0, pass == ForwardPass.PreRefraction ? k_RenderQueue_PreRefraction : k_RenderQueue_Transparent, null, m_ErrorMaterial);
RenderTransparentRenderList(cullResults, hdCamera, renderContext, cmd, m_ForwardErrorPassNames, 0, pass == ForwardPass.PreRefraction ? HDRenderQueue.k_RenderQueue_PreRefraction : HDRenderQueue.k_RenderQueue_Transparent, null, m_ErrorMaterial);
}
}
}

}
}
void RenderGaussianPyramidColor(Camera camera, CommandBuffer cmd, ScriptableRenderContext renderContext, bool isPreRefraction)
void RenderGaussianPyramidColor(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, bool isPreRefraction)
{
if (isPreRefraction)
{

last = dest;
}
PushFullScreenDebugTextureMip(cmd, m_GaussianPyramidColorBuffer, lodCount, isPreRefraction ? FullScreenDebugMode.PreRefractionColorPyramid : FullScreenDebugMode.FinalColorPyramid);
PushFullScreenDebugTextureMip(cmd, m_GaussianPyramidColorBuffer, lodCount, m_GaussianPyramidColorBufferDesc, hdCamera, isPreRefraction ? FullScreenDebugMode.PreRefractionColorPyramid : FullScreenDebugMode.FinalColorPyramid);
void RenderPyramidDepth(Camera camera, CommandBuffer cmd, ScriptableRenderContext renderContext, FullScreenDebugMode debugMode)
void RenderPyramidDepth(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, FullScreenDebugMode debugMode)
if (!m_FrameSettings.enableRoughRefraction)
return;
using (new ProfilingSample(cmd, "Pyramid Depth", CustomSamplerId.PyramidDepth.GetSampler()))
{
UpdatePyramidMips(m_DepthPyramidBuffer.rt.format, m_DepthPyramidMips);

cmd.CopyTexture(dest, 0, 0, m_DepthPyramidBuffer, 0, i + 1);
}
PushFullScreenDebugDepthMip(cmd, m_DepthPyramidBuffer, lodCount, debugMode);
PushFullScreenDebugDepthMip(cmd, m_DepthPyramidBuffer, lodCount, m_DepthPyramidBufferDesc, hdCamera, debugMode);
cmd.SetGlobalTexture(HDShaderIDs._DepthPyramidTexture, m_DepthPyramidBuffer);
cmd.SetGlobalTexture(HDShaderIDs._PyramidDepthTexture, m_DepthPyramidBuffer);
}
}

}
}
// allowFlip is false if we call the function after the FinalPass or cmd.Blit that flip the screen
public void PushColorPickerDebugTexture(CommandBuffer cmd, RTHandle textureID, HDCamera hdCamera)
{
if (m_CurrentDebugDisplaySettings.colorPickerDebugSettings.colorPickerMode != ColorPickerDebugMode.None)

}
}
void PushFullScreenDebugTextureMip(CommandBuffer cmd, RTHandle texture, int lodCount, FullScreenDebugMode debugMode)
void PushFullScreenDebugTextureMip(CommandBuffer cmd, RTHandle texture, int lodCount, HDCamera hdCamera, FullScreenDebugMode debugMode)
{
if (debugMode == m_CurrentDebugDisplaySettings.fullScreenDebugMode)
{

}
}
void PushFullScreenDebugDepthMip(CommandBuffer cmd, RTHandle texture, int lodCount, FullScreenDebugMode debugMode)
void PushFullScreenDebugDepthMip(CommandBuffer cmd, RTHandle texture, int lodCount, HDCamera hdCamera, FullScreenDebugMode debugMode)
{
if (debugMode == m_CurrentDebugDisplaySettings.fullScreenDebugMode)
{

cmd.SetGlobalTexture(HDShaderIDs._DebugFullScreenTexture, m_DebugFullScreenTempBuffer);
// TODO: Replace with command buffer call when available
m_DebugFullScreen.SetFloat(HDShaderIDs._FullScreenDebugMode, (float)m_CurrentDebugDisplaySettings.fullScreenDebugMode);
// Everything we have capture is flipped (as it happen before FinalPass/postprocess/Blit. So if we are not in SceneView
// (i.e. we have perform a flip, we need to flip the input texture)
m_DebugFullScreen.SetFloat(HDShaderIDs._RequireToFlipInputTexture, hdCamera.camera.cameraType != CameraType.SceneView ? 1.0f : 0.0f);
PushColorPickerDebugTexture(cmd, m_DebugFullScreenTempBuffer, hdCamera);
PushColorPickerDebugTexture(cmd, (RenderTargetIdentifier)BuiltinRenderTextureType.CameraTarget, hdCamera);
}
// Then overlays

var colorPickerParam = new Vector4(colorPickerDebugSettings.colorThreshold0, colorPickerDebugSettings.colorThreshold1, colorPickerDebugSettings.colorThreshold2, colorPickerDebugSettings.colorThreshold3);
m_DebugColorPicker.SetVector(HDShaderIDs._ColorPickerParam, colorPickerParam);
m_DebugColorPicker.SetInt(HDShaderIDs._ColorPickerMode, (int)colorPickerDebugSettings.colorPickerMode);
// The material display debug perform sRGBToLinear conversion as the final blit currently hardcode a linearToSrgb conversion. As when we read with color picker this is not done,
// we perform it inside the color picker shader. But we shouldn't do it for HDR buffer.
m_DebugColorPicker.SetFloat(HDShaderIDs._ApplyLinearToSRGB, m_CurrentDebugDisplaySettings.IsDebugMaterialDisplayEnabled() ? 1.0f : 0.0f);
// Everything we have capture is flipped (as it happen before FinalPass/postprocess/Blit. So if we are not in SceneView
// (i.e. we have perform a flip, we need to flip the input texture) + we need to handle the case were we debug a fullscreen pass that have already perform the flip
m_DebugColorPicker.SetFloat(HDShaderIDs._RequireToFlipInputTexture, hdCamera.camera.cameraType != CameraType.SceneView ? 1.0f : 0.0f);
CoreUtils.DrawFullScreen(cmd, m_DebugColorPicker, (RenderTargetIdentifier)BuiltinRenderTextureType.CameraTarget);
}
}

32
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipelineAsset.cs


FrameSettings m_FrameSettings = new FrameSettings(); // This are the defaultFrameSettings for all the camera and apply to sceneView, public to be visible in the inspector
// Not serialized, not visible, the settings effectively used
FrameSettings m_FrameSettingsRuntime = new FrameSettings();
bool m_frameSettingsIsDirty = true;
public bool frameSettingsIsDirty
{
get { return m_frameSettingsIsDirty; }
}
// See comment in FrameSettings.UpdateDirtyFrameSettings()
// for detail about this function
public void UpdateDirtyFrameSettings()
{
if (m_frameSettingsIsDirty)
{
m_FrameSettings.CopyTo(m_FrameSettingsRuntime);
m_frameSettingsIsDirty = false;
}
}
// Store the various RenderPipelineSettings for each platform (for now only one)
public RenderPipelineSettings renderPipelineSettings = new RenderPipelineSettings();

public override Material GetDefaultMaterial()
{
return m_RenderPipelineResources.defaultDiffuseMaterial;
}
// Note: This function is HD specific
public Material GetDefaultDecalMaterial()
{
return m_RenderPipelineResources.defaultDecalMaterial;
}
public override Material GetDefaultParticleMaterial()

void ISerializationCallbackReceiver.OnAfterDeserialize()
{
// Modification of defaultFrameSettings in the inspector will call OnValidate().
// We do a copy of the settings to those effectively used
m_FrameSettings.CopyTo(m_FrameSettingsRuntime);
// This is call on load or when this settings are change.
// When FrameSettings are manipulated we reset them to reflect the change, discarding all the Debug Windows change.
// Tag as dirty so frameSettings are correctly initialize at next HDRenderPipeline.Render() call
m_frameSettingsIsDirty = true;
}
}
}

43
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderQueue.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public enum HDRenderQueue
// In HD we don't expose HDRenderQueue instead we create as much value as needed in the enum for our different pass
// and use inspector to manipulate the value.
// In the case of transparent we want to use RenderQueue to help with sorting. We define a neutral value for the RenderQueue and priority going from -X to +X
// going from -X to +X instead of 0 to +X as builtin Unity is better for artists as they can decide late to sort behind or in front of the scene.
public class HDRenderQueue
Background = UnityEngine.Rendering.RenderQueue.Background,
Geometry = UnityEngine.Rendering.RenderQueue.Geometry,
AlphaTest = UnityEngine.Rendering.RenderQueue.AlphaTest,
GeometryLast = UnityEngine.Rendering.RenderQueue.GeometryLast,
PreRefraction = 2750,
Transparent = UnityEngine.Rendering.RenderQueue.Transparent,
Overlay = UnityEngine.Rendering.RenderQueue.Overlay
public const int k_TransparentPriorityQueueRange = 100;
public enum Priority
{
Background = UnityEngine.Rendering.RenderQueue.Background,
Opaque = UnityEngine.Rendering.RenderQueue.Geometry,
OpaqueAlphaTest = UnityEngine.Rendering.RenderQueue.AlphaTest,
// Warning: we must not change Geometry last value to stay compatible with occlusion
OpaqueLast = UnityEngine.Rendering.RenderQueue.GeometryLast,
// For transparent pass we define a range of 200 value to define the priority
// Warning: Be sure no range are overlapping
PreRefractionFirst = 2750 - k_TransparentPriorityQueueRange,
PreRefraction = 2750,
PreRefractionLast = 2750 + k_TransparentPriorityQueueRange,
TransparentFirst = UnityEngine.Rendering.RenderQueue.Transparent - k_TransparentPriorityQueueRange,
Transparent = UnityEngine.Rendering.RenderQueue.Transparent,
TransparentLast = UnityEngine.Rendering.RenderQueue.Transparent + k_TransparentPriorityQueueRange,
Overlay = UnityEngine.Rendering.RenderQueue.Overlay
}
public static readonly RenderQueueRange k_RenderQueue_OpaqueNoAlphaTest = new RenderQueueRange { min = (int)Priority.Opaque, max = (int)Priority.OpaqueAlphaTest - 1 };
public static readonly RenderQueueRange k_RenderQueue_OpaqueAlphaTest = new RenderQueueRange { min = (int)Priority.OpaqueAlphaTest, max = (int)Priority.OpaqueLast };
public static readonly RenderQueueRange k_RenderQueue_AllOpaque = new RenderQueueRange { min = (int)Priority.Opaque, max = (int)Priority.OpaqueLast };
public static readonly RenderQueueRange k_RenderQueue_PreRefraction = new RenderQueueRange { min = (int)Priority.PreRefractionFirst, max = (int)Priority.PreRefractionLast };
public static readonly RenderQueueRange k_RenderQueue_Transparent = new RenderQueueRange { min = (int)Priority.TransparentFirst, max = (int)Priority.TransparentLast };
public static readonly RenderQueueRange k_RenderQueue_AllTransparent = new RenderQueueRange { min = (int)Priority.PreRefractionFirst, max = (int)Priority.TransparentLast };
public static readonly RenderQueueRange k_RenderQueue_All = new RenderQueueRange { min = 0, max = 5000 };
}
}

5
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _ShadowMaskTexture = Shader.PropertyToID("_ShadowMaskTexture");
public static readonly int _DistortionTexture = Shader.PropertyToID("_DistortionTexture");
public static readonly int _GaussianPyramidColorTexture = Shader.PropertyToID("_GaussianPyramidColorTexture");
public static readonly int _DepthPyramidTexture = Shader.PropertyToID("_PyramidDepthTexture");
public static readonly int _PyramidDepthTexture = Shader.PropertyToID("_PyramidDepthTexture");
public static readonly int _GaussianPyramidColorMipSize = Shader.PropertyToID("_GaussianPyramidColorMipSize");
public static readonly int _DepthPyramidMipSize = Shader.PropertyToID("_PyramidDepthMipSize");

public static readonly int _ApplyLinearToSRGB = Shader.PropertyToID("_ApplyLinearToSRGB");
public static readonly int _RequireToFlipInputTexture = Shader.PropertyToID("_RequireToFlipInputTexture");
public static readonly int _DebugFullScreenTexture = Shader.PropertyToID("_DebugFullScreenTexture");
public static readonly int _BlitTexture = Shader.PropertyToID("_BlitTexture");

public static readonly int _GlobalFog_Extinction = Shader.PropertyToID("_GlobalFog_Extinction");
public static readonly int _GlobalFog_Scattering = Shader.PropertyToID("_GlobalFog_Scattering");
public static readonly int _GlobalFog_Asymmetry = Shader.PropertyToID("_GlobalFog_Asymmetry");
public static readonly int _VBufferResolution = Shader.PropertyToID("_VBufferResolution");
public static readonly int _VBufferScaleAndSliceCount = Shader.PropertyToID("_VBufferScaleAndSliceCount");
public static readonly int _VBufferDepthEncodingParams = Shader.PropertyToID("_VBufferDepthEncodingParams");

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


// This need to stay in sync with deferred.compute
// input.positionCS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(input.positionCS.xy) / GetTileSize());
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, uint2(input.positionCS.xy) / GetTileSize());
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
BSDFData bsdfData;

7
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute


uint2 pixelCoord = groupId * DEFERRED_SHADOW_TILE_SIZE + groupThreadId;
uint2 tileCoord = groupId;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, tileCoord);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, pixelCoord.xy).x;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, tileCoord);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
ShadowContext shadowContext = InitShadowContext();
float shadow = GetDirectionalShadowAttenuation(shadowContext, posInput.positionWS, float3(0.0, 0.0, 0.0), (uint)_DirectionalShadowIndex, float3(0.0, 0.0, 0.0));

7
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightEvaluation.hlsl


// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2.
float2 positionNDC = positionCS * 0.5 + 0.5;
// Tile the texture if the 'repeat' wrap mode is enabled.
positionNDC = lightData.tileCookie ? frac(positionNDC) : positionNDC;
return SampleCookie2D(lightLoopContext, positionNDC, lightData.cookieIndex);
return SampleCookie2D(lightLoopContext, positionNDC, lightData.cookieIndex, lightData.tileCookie);
}
// None of the outputs are premultiplied.

float2 positionNDC = positionCS * 0.5 + 0.5;
// Manually clamp to border (black).
cookie.rgb = SampleCookie2D(lightLoopContext, positionNDC, lightData.cookieIndex);
cookie.rgb = SampleCookie2D(lightLoopContext, positionNDC, lightData.cookieIndex, false);
cookie.a = isInBounds ? 1 : 0;
}

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


// This need to stay in sync with deferred.shader
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, tileCoord);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
float depth = LOAD_TEXTURE2D(_MainDepthTexture, pixelCoord.xy).x;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, tileCoord);
// For indirect case: we can still overlap inside a tile with the sky/background, reject it
// Can't rely on stencil as we are in compute shader

return;
}
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
BSDFData bsdfData;

14
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoopDef.hlsl


// ----------------------------------------------------------------------------
// Used by directional and spot lights.
float3 SampleCookie2D(LightLoopContext lightLoopContext, float2 coord, int index)
float3 SampleCookie2D(LightLoopContext lightLoopContext, float2 coord, int index, bool repeat)
// TODO: add MIP maps to combat aliasing?
return SAMPLE_TEXTURE2D_ARRAY_LOD(_CookieTextures, s_linear_clamp_sampler, coord, index, 0).rgb;
if (repeat)
{
// TODO: add MIP maps to combat aliasing?
return SAMPLE_TEXTURE2D_ARRAY_LOD(_CookieTextures, s_linear_repeat_sampler, coord, index, 0).rgb;
}
else // clamp
{
// TODO: add MIP maps to combat aliasing?
return SAMPLE_TEXTURE2D_ARRAY_LOD(_CookieTextures, s_linear_clamp_sampler, coord, index, 0).rgb;
}
}
// Used by point lights.

19
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/HomogeneousFog.cs


Gizmos.DrawWireCube(volumeParameters.bounds.center, volumeParameters.bounds.size);
}
}
// Returns NULL if a global fog component does not exist, or is not enabled.
public static HomogeneousFog GetGlobalFogComponent()
{
HomogeneousFog globalFogComponent = null;
HomogeneousFog[] fogComponents = FindObjectsOfType(typeof(HomogeneousFog)) as HomogeneousFog[];
foreach (HomogeneousFog fogComponent in fogComponents)
{
if (fogComponent.enabled && fogComponent.volumeParameters.IsVolumeUnbounded())
{
globalFogComponent = fogComponent;
break;
}
}
return globalFogComponent;
}
}
} // UnityEngine.Experimental.Rendering.HDPipeline

42
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/Resources/VolumetricLighting.compute


// Implementation
//--------------------------------------------------------------------------------------------------
#define HG 0
struct Ray
{
float3 originWS;

// Computes the light integral (in-scattered radiance) within the voxel.
// Multiplication by the scattering coefficient and the phase function is performed outside.
float3 EvaluateVoxelLighting(LightLoopContext context, uint featureFlags, PositionInputs posInput,
Ray ray, float t0, float t1, float dt, float rndVal, float extinction
Ray ray, float t0, float t1, float dt, float rndVal, float extinction, float asymmetry
#ifdef LIGHTLOOP_TILE_PASS
, uint clusterIndices[2], float clusterDepths[2])
#else

EvaluateLight_Directional(context, posInput, light, unused, 0, L,
color, attenuation);
float cosTheta = dot(L, ray.directionWS);
#if HG
float phase = HenyeyGreensteinPhasePartVarying(asymmetry, cosTheta);
#else
float phase = CornetteShanksPhasePartVarying(asymmetry, cosTheta);
#endif
float intensity = attenuation * weight;
float intensity = attenuation * (phase * weight);
// Compute the amount of in-scattered radiance.
voxelRadiance += intensity * color;

EvaluateLight_Punctual(context, posInput, light, unused, 0, L, lightToSample,
distances, color, attenuation);
float intensity = attenuation * rcpPdf;
float cosTheta = dot(L, ray.directionWS);
#if HG
float phase = HenyeyGreensteinPhasePartVarying(asymmetry, cosTheta);
#else
float phase = CornetteShanksPhasePartVarying(asymmetry, cosTheta);
#endif
float intensity = attenuation * (phase * rcpPdf);
// Compute transmittance from 't0' to 't'.
intensity *= TransmittanceHomogeneousMedium(extinction, t - t0);

EvaluateLight_Punctual(context, posInput, light, unused, 0, L, lightToSample,
distances, color, attenuation);
float cosTheta = dot(L, ray.directionWS);
#if HG
float phase = HenyeyGreensteinPhasePartVarying(asymmetry, cosTheta);
#else
float phase = CornetteShanksPhasePartVarying(asymmetry, cosTheta);
#endif
float intensity = attenuation * weight;
float intensity = attenuation * (phase * weight);
// Compute transmittance from 't0' to 'tEntr'.
intensity *= TransmittanceHomogeneousMedium(extinction, tEntr - t0);

// TODO: piecewise linear.
float3 scattering = _GlobalFog_Scattering;
float extinction = _GlobalFog_Extinction;
float asymmetry = _GlobalFog_Asymmetry;
// TODO: define a function ComputeGlobalFogCoefficients(float3 centerWS),
// which allows procedural definition of extinction and scattering.

#endif
float3 voxelRadiance = EvaluateVoxelLighting(context, featureFlags, posInput,
ray, t0, t1, dt, rndVal, extinction
ray, t0, t1, dt, rndVal, extinction, asymmetry
#ifdef LIGHTLOOP_TILE_PASS
, clusterIndices, clusterDepths);
#else

// Compute the transmittance from the camera to 't0'.
float transmittance = Transmittance(opticalDepth);
#if HG
float phase = HenyeyGreensteinPhasePartConstant(asymmetry);
#else
float phase = CornetteShanksPhasePartConstant(asymmetry);
#endif
totalRadiance += (transmittance * IsotropicPhaseFunction()) * scattering * blendedRadiance;
totalRadiance += (transmittance * phase) * scattering * blendedRadiance;
// Compute the optical depth up to the center of the interval.
opticalDepth += 0.5 * extinction * dt;

380
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs


using System;
using UnityEngine.Rendering;
using System.Collections.Generic;
[GenerateHLSL]
public struct VolumeProperties
{

public Bounds bounds; // Position and dimensions in meters
public Color albedo; // Single scattering albedo [0, 1]
public float meanFreePath; // In meters [1, inf]. Should be chromatic - this is an optimization!
public float asymmetry; // Single global parameter for all volumes. TODO: UX
public VolumeParameters()
{

asymmetry = 0.0f;
}
public bool IsVolumeUnbounded()

albedo.b = Mathf.Clamp01(albedo.b);
meanFreePath = Mathf.Max(meanFreePath, 1.0f);
asymmetry = Mathf.Clamp(asymmetry, -1.0f, 1.0f);
}
public VolumeProperties GetProperties()

}
} // class VolumeParameters
public partial class HDRenderPipeline : RenderPipeline
public class VolumetricLightingModule
{
public enum VolumetricLightingPreset
{

Count
};
}
class VBuffer
{
public int viewID = -1; // -1 is invalid; positive for Game Views, 0 otherwise
public RenderTexture[] lightingRTEX = null;
public RenderTargetIdentifier[] lightingRTID = null;
VolumetricLightingPreset m_VolumetricLightingPreset
{ get { return (VolumetricLightingPreset)Math.Min(ShaderConfig.s_VolumetricLightingPreset, (int)VolumetricLightingPreset.Count); } }
public RenderTargetIdentifier GetLightingIntegralBuffer() // Of the current frame
{
Debug.Assert(viewID >= 0);
return lightingRTID[0];
}
ComputeShader m_VolumetricLightingCS { get { return m_Asset.renderPipelineResources.volumetricLightingCS; } }
public RenderTargetIdentifier GetLightingHistoryBuffer() // From the previous frame
{
Debug.Assert(viewID > 0); // Game View only
return lightingRTID[1 + ((Time.renderedFrameCount + 0) & 1)];
}
float m_VBufferNearPlane = 0.5f; // Distance in meters; dynamic modifications not handled by reprojection
float m_VBufferFarPlane = 64.0f; // Distance in meters; dynamic modifications not handled by reprojection
const int k_VBufferCount = 3; // 0 and 1 - history (prev) and feedback (next), 2 - integral (curr)
public RenderTargetIdentifier GetLightingFeedbackBuffer() // For the next frame
{
Debug.Assert(viewID > 0); // Game View only
return lightingRTID[1 + ((Time.renderedFrameCount + 1) & 1)];
}
RenderTexture[] m_VBufferLighting = null;
RenderTargetIdentifier[] m_VBufferLightingRT = null;
public void Create(int viewID, int w, int h, int d)
{
Debug.Assert(viewID >= 0);
Debug.Assert(w > 0 && h > 0 && d > 0);
// Clean up first.
Destroy();
// The required number of buffers depends on the view type.
bool isGameView = viewID > 0;
int n = isGameView ? 3 : 1;
int m_ViewCount = 0;
int[] m_ViewIdArray = new int[8]; // TODO: account for the CameraType
this.viewID = viewID;
this.lightingRTEX = new RenderTexture[n];
this.lightingRTID = new RenderTargetIdentifier[n];
int ViewOffsetFromViewId(int viewId)
{
int viewOffset = -1;
for (int i = 0; i < n; i++)
{
this.lightingRTEX[i] = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
this.lightingRTEX[i].filterMode = FilterMode.Trilinear; // Custom
this.lightingRTEX[i].dimension = TextureDimension.Tex3D; // TODO: request the thick 3D tiling layout
this.lightingRTEX[i].volumeDepth = d;
this.lightingRTEX[i].enableRandomWrite = true;
this.lightingRTEX[i].Create();
Debug.Assert(m_ViewCount == 0 || m_ViewIdArray != null);
this.lightingRTID[i] = new RenderTargetIdentifier(this.lightingRTEX[i]);
}
}
for (int i = 0; i < m_ViewCount; i++)
public void Destroy()
if (m_ViewIdArray[i] == viewId)
if (this.lightingRTEX != null)
viewOffset = i;
for (int i = 0, n = this.lightingRTEX.Length; i < n; i++)
{
this.lightingRTEX[i].Release();
}
this.viewID = -1;
this.lightingRTEX = null;
this.lightingRTID = null;
} // class VBuffer
return viewOffset;
}
public VolumetricLightingPreset preset { get { return (VolumetricLightingPreset)Math.Min(ShaderConfig.s_VolumetricLightingPreset, (int)VolumetricLightingPreset.Count); } }
ComputeShader m_VolumetricLightingCS = null;
List<VBuffer> m_VBuffers = null;
float m_VBufferNearPlane = 0.5f; // Distance in meters; dynamic modifications not handled by reprojection
float m_VBufferFarPlane = 64.0f; // Distance in meters; dynamic modifications not handled by reprojection
public static int ComputeVBufferTileSize(VolumetricLightingPreset preset)
public void Build(HDRenderPipelineAsset asset)
switch (preset)
{
case VolumetricLightingPreset.Normal:
return 8;
case VolumetricLightingPreset.Ultra:
return 4;
case VolumetricLightingPreset.Off:
return 0;
default:
Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
return 0;
}
if (preset == VolumetricLightingPreset.Off) return;
m_VolumetricLightingCS = asset.renderPipelineResources.volumetricLightingCS;
m_VBuffers = new List<VBuffer>(1);
public static int ComputeVBufferSliceCount(VolumetricLightingPreset preset)
public void Cleanup()
switch (preset)
if (preset == VolumetricLightingPreset.Off) return;
m_VolumetricLightingCS = null;
for (int i = 0, n = m_VBuffers.Count; i < n; i++)
case VolumetricLightingPreset.Normal:
return 128;
case VolumetricLightingPreset.Ultra:
return 256;
case VolumetricLightingPreset.Off:
return 0;
default:
Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
return 0;
m_VBuffers[i].Destroy();
m_VBuffers = null;
// Since a single voxel corresponds to a tile (e.g. 8x8) of pixels,
// the VBuffer can potentially extend past the boundaries of the viewport.
// The function returns the fraction of the {width, height} of the VBuffer visible on screen.
Vector2 ComputeVBufferResolutionAndScale(float screenWidth, float screenHeight,
ref int w, ref int h, ref int d)
public void ResizeVBuffer(HDCamera camera, int screenWidth, int screenHeight)
int t = ComputeVBufferTileSize(m_VolumetricLightingPreset);
if (preset == VolumetricLightingPreset.Off) return;
// Ceil(ScreenSize / TileSize).
w = ((int)screenWidth + t - 1) / t;
h = ((int)screenHeight + t - 1) / t;
d = ComputeVBufferSliceCount(m_VolumetricLightingPreset);
int viewID = camera.GetViewID();
Debug.Assert(viewID >= 0);
return new Vector2(screenWidth / (w * t), screenHeight / (h * t));
}
int w = 0, h = 0, d = 0;
ComputeVBufferResolutionAndScale(preset, screenWidth, screenHeight, ref w, ref h, ref d);
void ResizeVBuffer(int viewId, int screenWidth, int screenHeight)
{
int viewOffset = ViewOffsetFromViewId(viewId);
VBuffer vBuffer = FindVBuffer(viewID);
if (viewOffset >= 0)
if (vBuffer != null)
// Found, check resolution.
int w = 0, h = 0, d = 0;
ComputeVBufferResolutionAndScale(screenWidth, screenHeight, ref w, ref h, ref d);
Debug.Assert(vBuffer.lightingRTEX != null);
Debug.Assert(vBuffer.lightingRTEX[0] != null);
Debug.Assert(vBuffer.lightingRTID != null);
Debug.Assert(m_VBufferLighting != null);
Debug.Assert(m_VBufferLighting.Length >= (viewOffset + 1) * k_VBufferCount);
Debug.Assert(m_VBufferLighting[viewOffset * k_VBufferCount] != null);
if (w == m_VBufferLighting[viewOffset * k_VBufferCount].width &&
h == m_VBufferLighting[viewOffset * k_VBufferCount].height &&
d == m_VBufferLighting[viewOffset * k_VBufferCount].volumeDepth)
// Found, check resolution.
if (w == vBuffer.lightingRTEX[0].width &&
h == vBuffer.lightingRTEX[0].height &&
d == vBuffer.lightingRTEX[0].volumeDepth)
else
{
// Not found - grow the array.
vBuffer = new VBuffer();
m_VBuffers.Add(vBuffer);
}
// Otherwise, we have to recreate the VBuffer.
CreateVBuffer(viewId, screenWidth, screenHeight);
vBuffer.Create(viewID, w, h, d);
void CreateVBuffer(int viewId, int screenWidth, int screenHeight)
VBuffer FindVBuffer(int viewID)
// Clean up first.
DestroyVBuffer(viewId);
Debug.Assert(viewID >= 0);
int viewOffset = ViewOffsetFromViewId(viewId);
VBuffer vBuffer = null;
if (viewOffset < 0)
if (m_VBuffers != null)
// Not found. Push back.
viewOffset = m_ViewCount++;
Debug.Assert(viewOffset < 8);
m_ViewIdArray[viewOffset] = viewId;
int n = m_VBuffers.Count;
if (m_VBufferLighting == null)
{
// Lazy initialize.
m_VBufferLighting = new RenderTexture[k_VBufferCount];
m_VBufferLightingRT = new RenderTargetIdentifier[k_VBufferCount];
}
else if (m_VBufferLighting.Length < m_ViewCount * k_VBufferCount)
for (int i = 0; i < n; i++)
// Grow by reallocation and copy.
RenderTexture[] newArray = new RenderTexture[m_ViewCount * k_VBufferCount];
RenderTargetIdentifier[] newArrayRT = new RenderTargetIdentifier[m_ViewCount * k_VBufferCount];
for (int i = 0, n = m_VBufferLighting.Length; i < n; i++)
if (viewID == m_VBuffers[i].viewID)
newArray[i] = m_VBufferLighting[i];
newArrayRT[i] = m_VBufferLightingRT[i];
vBuffer = m_VBuffers[i];
// Reassign and release memory.
m_VBufferLighting = newArray;
m_VBufferLightingRT = newArrayRT;
Debug.Assert(m_VBufferLighting != null);
int w = 0, h = 0, d = 0;
ComputeVBufferResolutionAndScale(screenWidth, screenHeight, ref w, ref h, ref d);
return vBuffer;
}
for (int i = viewOffset * k_VBufferCount,
n = viewOffset * k_VBufferCount + k_VBufferCount; i < n; i++)
static int ComputeVBufferTileSize(VolumetricLightingPreset preset)
{
switch (preset)
m_VBufferLighting[i] = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
m_VBufferLighting[i].filterMode = FilterMode.Trilinear; // Custom
m_VBufferLighting[i].dimension = TextureDimension.Tex3D; // TODO: request the thick 3D tiling layout
m_VBufferLighting[i].volumeDepth = d;
m_VBufferLighting[i].enableRandomWrite = true;
m_VBufferLighting[i].Create();
m_VBufferLightingRT[i] = new RenderTargetIdentifier(m_VBufferLighting[i]);
case VolumetricLightingPreset.Normal:
return 8;
case VolumetricLightingPreset.Ultra:
return 4;
case VolumetricLightingPreset.Off:
return 0;
default:
Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
return 0;
void DestroyVBuffer(int viewId)
static int ComputeVBufferSliceCount(VolumetricLightingPreset preset)
int viewOffset = ViewOffsetFromViewId(viewId);
if (viewOffset < 0)
switch (preset)
// Not found.
return;
case VolumetricLightingPreset.Normal:
return 128;
case VolumetricLightingPreset.Ultra:
return 256;
case VolumetricLightingPreset.Off:
return 0;
default:
Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
return 0;
}
int lastOffset = m_ViewCount - 1;
Debug.Assert(lastOffset >= 0);
if (m_VBufferLighting != null)
{
Debug.Assert(m_VBufferLighting.Length >= m_ViewCount * k_VBufferCount);
for (int i = 0; i < k_VBufferCount; i++)
{
int viewBuffer = viewOffset * k_VBufferCount + i;
int lastBuffer = lastOffset * k_VBufferCount + i;
// Release the memory.
if (m_VBufferLighting[viewBuffer] != null)
{
m_VBufferLighting[viewBuffer].Release();
}
// Since a single voxel corresponds to a tile (e.g. 8x8) of pixels,
// the VBuffer can potentially extend past the boundaries of the viewport.
// The function returns the fraction of the {width, height} of the VBuffer visible on screen.
static Vector2 ComputeVBufferResolutionAndScale(VolumetricLightingPreset preset,
int screenWidth, int screenHeight,
ref int w, ref int h, ref int d)
{
int t = ComputeVBufferTileSize(preset);
// Swap with the last element.
m_VBufferLighting[viewBuffer] = m_VBufferLighting[lastBuffer];
m_VBufferLightingRT[viewBuffer] = m_VBufferLightingRT[lastBuffer];
}
}
// Ceil(ScreenSize / TileSize).
w = (screenWidth + t - 1) / t;
h = (screenHeight + t - 1) / t;
d = ComputeVBufferSliceCount(preset);
// Swap with the last element and shrink the array.
m_ViewIdArray[viewOffset] = m_ViewIdArray[lastOffset];
m_ViewCount--;
return new Vector2((float)screenWidth / (float)(w * t), (float)screenHeight / (float)(h * t));
public static Vector4 ComputeLogarithmicDepthEncodingParams(float nearPlane, float farPlane)
static Vector4 ComputeLogarithmicDepthEncodingParams(float nearPlane, float farPlane)
{
Vector4 depthParams = new Vector4();

return depthParams;
}
// Returns NULL if a global fog component does not exist, or is not enabled.
public static HomogeneousFog GetGlobalFogComponent()
{
HomogeneousFog globalFogComponent = null;
HomogeneousFog[] fogComponents = Object.FindObjectsOfType(typeof(HomogeneousFog)) as HomogeneousFog[];
foreach (HomogeneousFog fogComponent in fogComponents)
{
if (fogComponent.enabled && fogComponent.volumeParameters.IsVolumeUnbounded())
{
globalFogComponent = fogComponent;
break;
}
}
return globalFogComponent;
}
RenderTargetIdentifier GetVBufferLightingHistory(int viewOffset) // From the previous frame
public void PushGlobalParams(HDCamera camera, CommandBuffer cmd)
return m_VBufferLightingRT[viewOffset * k_VBufferCount + ((Time.renderedFrameCount + 0) & 1)]; // Does not work in the Scene view
}
if (preset == VolumetricLightingPreset.Off) return;
RenderTargetIdentifier GetVBufferLightingFeedback(int viewOffset) // For the next frame
{
return m_VBufferLightingRT[viewOffset * k_VBufferCount + ((Time.renderedFrameCount + 1) & 1)]; // Does not work in the Scene view
}
RenderTargetIdentifier GetVBufferLightingIntegral(int viewOffset) // Of the current frame
{
return m_VBufferLightingRT[viewOffset * k_VBufferCount + 2];
}
public void SetVolumetricLightingData(HDCamera camera, CommandBuffer cmd)
{
HomogeneousFog globalFogComponent = GetGlobalFogComponent();
HomogeneousFog globalFogComponent = HomogeneousFog.GetGlobalFogComponent();
// TODO: may want to cache these results somewhere.
VolumeProperties globalFogProperties = (globalFogComponent != null) ? globalFogComponent.volumeParameters.GetProperties()

cmd.SetGlobalFloat( HDShaderIDs._GlobalFog_Extinction, globalFogProperties.extinction);
cmd.SetGlobalFloat( HDShaderIDs._GlobalFog_Asymmetry, globalFogComponent != null ? globalFogComponent.volumeParameters.asymmetry : 0);
Vector2 scale = ComputeVBufferResolutionAndScale(camera.screenSize.x, camera.screenSize.y, ref w, ref h, ref d);
int viewId = camera.camera.GetInstanceID();
int viewOffset = ViewOffsetFromViewId(viewId);
Vector2 scale = ComputeVBufferResolutionAndScale(preset, (int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
Debug.Assert(viewOffset >= 0 && viewOffset < 8);
VBuffer vBuffer = FindVBuffer(camera.GetViewID());
Debug.Assert(vBuffer != null);
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, GetVBufferLightingIntegral(viewOffset));
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, vBuffer.GetLightingIntegralBuffer());
}
// Ref: https://en.wikipedia.org/wiki/Close-packing_of_equal_spheres

Vector2[] GetHexagonalClosePackedSpheres7()
static Vector2[] GetHexagonalClosePackedSpheres7()
{
Vector2[] coords = new Vector2[7];

return coords;
}
void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd)
public void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd, FrameSettings frameSettings)
if (m_VolumetricLightingPreset == VolumetricLightingPreset.Off) return;
if (preset == VolumetricLightingPreset.Off) return;
int viewId = camera.camera.GetInstanceID(); // Warning: different views can use the same camera
int viewOffset = ViewOffsetFromViewId(viewId);
Debug.Assert(viewOffset >= 0 && viewOffset < 8);
VBuffer vBuffer = FindVBuffer(camera.GetViewID());
Debug.Assert(vBuffer != null);
if (GetGlobalFogComponent() == null)
if (HomogeneousFog.GetGlobalFogComponent() == null)
{
// Clear the render target instead of running the shader.
// CoreUtils.SetRenderTarget(cmd, GetVBufferLightingIntegral(viewOffset), ClearFlag.Color, CoreUtils.clearColorAllBlack);

// Use the workaround by running the full shader with no volume.
}
bool enableClustered = m_FrameSettings.lightLoopSettings.enableTileAndCluster;
bool enableClustered = frameSettings.lightLoopSettings.enableTileAndCluster;
bool enableReprojection = Application.isPlaying && camera.camera.cameraType == CameraType.Game;
int kernel;

}
int w = 0, h = 0, d = 0;
Vector2 scale = ComputeVBufferResolutionAndScale(camera.screenSize.x, camera.screenSize.y, ref w, ref h, ref d);
Vector2 scale = ComputeVBufferResolutionAndScale(preset, (int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
float vFoV = camera.camera.fieldOfView * Mathf.Deg2Rad;
// Compose the matrix which allows us to compute the world space view direction.

// TODO: set 'm_VolumetricLightingPreset'.
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._VBufferSampleOffset, offset);
cmd.SetComputeMatrixParam( m_VolumetricLightingCS, HDShaderIDs._VBufferCoordToViewDirWS, transform);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingHistory, GetVBufferLightingHistory(viewOffset)); // Read
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingFeedback, GetVBufferLightingFeedback(viewOffset)); // Write
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingIntegral, GetVBufferLightingIntegral(viewOffset)); // Write
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingIntegral, vBuffer.GetLightingIntegralBuffer()); // Write
if (enableReprojection)
{
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingFeedback, vBuffer.GetLightingFeedbackBuffer()); // Write
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingHistory, vBuffer.GetLightingHistoryBuffer()); // Read
}
} // class HDRenderPipeline
} // class VolumetricLightingModule
} // namespace UnityEngine.Experimental.Rendering.HDPipeline

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DBufferManager.cs


m_TextureShaderIDs[dbufferIndex] = HDShaderIDs._DBufferTexture[dbufferIndex];
}
}
public void ClearNormalTarget(CommandBuffer cmd, HDCamera camera, Color clearColor)
{
// index 1 is normals
HDUtils.SetRenderTarget(cmd, m_ColorMRTs[1], ClearFlag.Color, clearColor);
}
public void PushGlobalParams(CommandBuffer cmd)
{

5
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl


uint _EnableDBuffer;
CBUFFER_END
UNITY_INSTANCING_BUFFER_START(Decal)
UNITY_DEFINE_INSTANCED_PROP(float4x4, normalToWorld)
UNITY_INSTANCING_BUFFER_END(matrix)
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild
void EncodeIntoDBuffer( DecalSurfaceData surfaceData,
out DBufferType0 outDBuffer0,

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


Name "DBuffer" // Name is not used
Tags { "LightMode" = "DBuffer" } // This will be only for opaque object based on the RenderQueue index
// need to optimize this and use proper Cull and ZTest modes for cases when decal geometry is clipped by camera
Cull Off
// back faces with zfail, for cases when camera is inside the decal volume
Cull Front
ZTest Always
ZTest Greater
// using alpha compositing https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html
Blend SrcAlpha OneMinusSrcAlpha, Zero OneMinusSrcAlpha
HLSLPROGRAM

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl


#endif
#if _MASKMAP
surfaceData.mask = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, texCoordDS.xy);
surfaceData.mask.z = totalBlend;
surfaceData.mask.z = surfaceData.mask.w;
surfaceData.mask.w = totalBlend;
#endif
}

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalProperties.hlsl


#ifndef UNITY_DECALPROPERTIES_INCLUDED
#define UNITY_DECALPROPERTIES_INCLUDED
TEXTURE2D(_BaseColorMap);
SAMPLER(sampler_BaseColorMap);
TEXTURE2D(_NormalMap);

float _DecalBlend;
CBUFFER_START(Decal)
float4x4 _WorldToDecal;
float4x4 _DecalToWorldR;
CBUFFER_END
#endif

11
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl


DecalSurfaceData decalSurfaceData;
DECODE_FROM_DBUFFER(DBuffer, decalSurfaceData);
surfaceData.baseColor.xyz = lerp(surfaceData.baseColor.xyz, decalSurfaceData.baseColor.xyz, decalSurfaceData.baseColor.w);
surfaceData.normalWS.xyz = normalize(lerp(surfaceData.normalWS.xyz, decalSurfaceData.normalWS.xyz, decalSurfaceData.normalWS.w));
surfaceData.metallic = lerp(surfaceData.metallic, decalSurfaceData.mask.x, decalSurfaceData.mask.z);
surfaceData.ambientOcclusion = lerp(surfaceData.ambientOcclusion, decalSurfaceData.mask.y, decalSurfaceData.mask.z);
surfaceData.perceptualSmoothness = lerp(surfaceData.perceptualSmoothness, decalSurfaceData.mask.w, decalSurfaceData.mask.z);
// using alpha compositing https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html
surfaceData.baseColor.xyz = surfaceData.baseColor.xyz * decalSurfaceData.baseColor.w + decalSurfaceData.baseColor.xyz;
surfaceData.normalWS.xyz = normalize(surfaceData.normalWS.xyz * decalSurfaceData.normalWS.w + decalSurfaceData.normalWS.xyz);
surfaceData.metallic = surfaceData.metallic * decalSurfaceData.mask.w + decalSurfaceData.mask.x;
surfaceData.ambientOcclusion = surfaceData.ambientOcclusion * decalSurfaceData.mask.w + decalSurfaceData.mask.y;
surfaceData.perceptualSmoothness = surfaceData.perceptualSmoothness * decalSurfaceData.mask.w + decalSurfaceData.mask.z;
}
}

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/ShaderPass/DecalSharePass.hlsl


#error Undefine_SHADERPASS
#endif
// need 3 x float3 interpolators...
#define VARYINGS_NEED_POSITION_WS
#define VARYINGS_NEED_TANGENT_TO_WORLD
// This include will define the various Attributes/Varyings structure
#include "../../ShaderPass/VaryingMesh.hlsl"

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


[ToggleUI] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_TransparentSortPriority("_TransparentSortPriority", Float) = 0
// Stencil state
[HideInInspector] _StencilRef("_StencilRef", Int) = 2 // StencilLightingUsage.RegularLighting

_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
[ToggleUI] _SupportDBuffer("Support DBuffer", Float) = 1.0
}
HLSLINCLUDE

#pragma shader_feature _DENSITY_MODE
#pragma shader_feature _HEIGHT_BASED_BLEND
#pragma shader_feature _ _LAYEREDLIT_3_LAYERS _LAYEREDLIT_4_LAYERS
#pragma shader_feature _DISABLE_DBUFFER
// Keyword for transparent
#pragma shader_feature _SURFACE_TYPE_TRANSPARENT

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


// In the case of subsurface profile index, the goal is to take the index with the hights weights.
// Or the last found in case of equality.
float BlendLayeredSSSprofile(float x0, float x1, float x2, float x3, float weight[4])
float BlendLayeredDiffusionProfile(float x0, float x1, float x2, float x3, float weight[4])
int sssProfileIndex = x0;
int diffusionProfileId = x0;
sssProfileIndex = currentMax < weight[1] ? x1 : sssProfileIndex;
diffusionProfileId = currentMax < weight[1] ? x1 : diffusionProfileId;
sssProfileIndex = currentMax < weight[2] ? x2 : sssProfileIndex;
diffusionProfileId = currentMax < weight[2] ? x2 : diffusionProfileId;
sssProfileIndex = currentMax < weight[3] ? x3 : sssProfileIndex;
diffusionProfileId = currentMax < weight[3] ? x3 : diffusionProfileId;
return sssProfileIndex;
return diffusionProfileId;
#define SURFACEDATA_BLEND_SSS_PROFILE(surfaceData, name, mask) BlendLayeredSSSprofile(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_DIFFUSION_PROFILE(surfaceData, name, mask) BlendLayeredDiffusionProfile(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 PROP_BLEND_SCALAR(name, mask) BlendLayeredScalar(name##0, name##1, name##2, name##3, mask);
void GetLayerTexCoord(float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3,

surfaceData.tangentWS = normalize(input.worldToTangent[0].xyz); // The tangent is not normalize in worldToTangent for mikkt. Tag: SURFACE_GRADIENT
surfaceData.subsurfaceMask = SURFACEDATA_BLEND_SCALAR(surfaceData, subsurfaceMask, weights);
surfaceData.thickness = SURFACEDATA_BLEND_SCALAR(surfaceData, thickness, weights);
surfaceData.diffusionProfile = SURFACEDATA_BLEND_SSS_PROFILE(surfaceData, diffusionProfile, weights);
surfaceData.diffusionProfile = SURFACEDATA_BLEND_DIFFUSION_PROFILE(surfaceData, diffusionProfile, weights);
surfaceData.materialFeatures = 0;
surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD;
#ifdef _MATERIALFEATURE_SUBSURFACE_SCATTERING
#ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION;
// TEMP: The UI must control if we have transmission or not.
// Currently until we update the UI, this is control in the diffusion profile
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * surfaceData.diffusionProfile, 2u);
// Caution: Because of this dynamic test we don't know anymore statically if we have transmission, which mess with performance.
// in deferred case as we still have both sss and transmission until we update the UI it should be the same perf
if (transmissionMode != TRANSMISSION_MODE_NONE)
{
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION;
}
#endif
// Init other parameters

#else
surfaceData.specularOcclusion = 1.0;
#endif
AddDecalContribution(posInput.positionSS, surfaceData);
#ifndef _DISABLE_DBUFFER
AddDecalContribution(posInput.positionSS, surfaceData);
#endif
#if defined(DEBUG_DISPLAY)
if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE)

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


[ToggleUI] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_TransparentSortPriority("_TransparentSortPriority", Float) = 0
// Stencil state
[HideInInspector] _StencilRef("_StencilRef", Int) = 2 // StencilLightingUsage.RegularLighting

_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
[ToggleUI] _SupportDBuffer("Support DBuffer", Float) = 1.0
}
HLSLINCLUDE

#pragma shader_feature _DENSITY_MODE
#pragma shader_feature _HEIGHT_BASED_BLEND
#pragma shader_feature _ _LAYEREDLIT_3_LAYERS _LAYEREDLIT_4_LAYERS
#pragma shader_feature _DISABLE_DBUFFER
// Keyword for transparent
#pragma shader_feature _SURFACE_TYPE_TRANSPARENT

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


// SSS
[SurfaceDataAttributes("Diffusion Profile")]
public int diffusionProfile;
public uint diffusionProfile;
[SurfaceDataAttributes("Subsurface Mask")]
public float subsurfaceMask;

// SpecularColor fold into fresnel0
// SSS
public int diffusionProfile;
public uint diffusionProfile;
public float subsurfaceMask;
// Transmission

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


float metallic;
float coatMask;
float3 specularColor;
int diffusionProfile;
uint diffusionProfile;
float subsurfaceMask;
float thickness;
float3 tangentWS;

float3 normalWS;
float perceptualRoughness;
float coatMask;
int diffusionProfile;
uint diffusionProfile;
float subsurfaceMask;
float thickness;
bool useThickObjectMode;

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


#define DEFAULT_SPECULAR_VALUE 0.04
#define GBUFFER_LIT_SPECULAR_COLOR 15
#define GBUFFER_LIT_SSS_OR_TRANSMISSION 14
#define GBUFFER_LIT_IRIDESCENCE 13
#define GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND 12
// Enum for materialFeatureId (only use for encode/decode GBuffer)
#define GBUFFER_LIT_STANDARD 0
// we have not enough space (3bit) to store mat feature to have SSS and Transmission as bitmask, such why we have all variant
#define GBUFFER_LIT_SSS 1
#define GBUFFER_LIT_TRANSMISSION 2
#define GBUFFER_LIT_TRANSMISSION_SSS 3
#define GBUFFER_LIT_ANISOTROPIC 4
#define GBUFFER_LIT_IRIDESCENCE 5 // TODO
#define CLEAR_COAT_IOR 1.5
#define CLEAR_COAT_IETA (1.0 / CLEAR_COAT_IOR) // IETA is the inverse eta which is the ratio of IOR of two interface

return ((featureFlags & flag) != 0);
}
float3 ComputeDiffuseColor(float3 baseColor, float metallic)
{
return baseColor * (1.0 - metallic);

}
// Assume that bsdfData.diffusionProfile is init
void FillMaterialSSS(float subsurfaceMask, inout BSDFData bsdfData)
void FillMaterialSSS(uint diffusionProfile, float subsurfaceMask, inout BSDFData bsdfData)
bsdfData.fresnel0 = _TransmissionTintsAndFresnel0[bsdfData.diffusionProfile].a;
bsdfData.diffusionProfile = diffusionProfile;
bsdfData.fresnel0 = _TransmissionTintsAndFresnel0[diffusionProfile].a;
void FillMaterialTransmission(float thickness, inout BSDFData bsdfData)
void FillMaterialTransmission(uint diffusionProfile, float thickness, inout BSDFData bsdfData)
int diffusionProfile = bsdfData.diffusionProfile;
bsdfData.diffusionProfile = diffusionProfile;
bsdfData.fresnel0 = _TransmissionTintsAndFresnel0[diffusionProfile].a;
bsdfData.thickness = _ThicknessRemaps[diffusionProfile].x + _ThicknessRemaps[diffusionProfile].y * thickness;
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * diffusionProfile, 2u);

}
// Assume bsdfData.normalWS is init
void FillMaterialAnisotropy(float anisotropy, float3 tangentWS, inout BSDFData bsdfData)
void FillMaterialAnisotropy(float anisotropy, float3 tangentWS, float3 bitangentWS, inout BSDFData bsdfData)
bsdfData.anisotropy = anisotropy;
bsdfData.tangentWS = tangentWS;
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
bsdfData.anisotropy = anisotropy;
bsdfData.tangentWS = tangentWS;
bsdfData.bitangentWS = bitangentWS;
}
void FillMaterialIridescence(float thicknessIrid, inout BSDFData bsdfData)

ZERO_INITIALIZE(BSDFData, bsdfData);
// IMPORTANT: In case of foward or gbuffer pass all enable flags are statically know at compile time, so the compiler can do compile time optimization
bsdfData.materialFeatures = surfaceData.materialFeatures | MATERIALFEATUREFLAGS_LIT_STANDARD; // Not really needed but for consistency with deferred path
bsdfData.materialFeatures = surfaceData.materialFeatures;
// Standard material
bsdfData.specularOcclusion = surfaceData.specularOcclusion;

// There is no mettalic with SSS and specular color mode
// There is no metallic with SSS and specular color mode
// Always assign even if not used, DIFFUSION_PROFILE_NEUTRAL_ID is 0
bsdfData.diffusionProfile = surfaceData.diffusionProfile;
// Note: DIFFUSION_PROFILE_NEUTRAL_ID is 0
// However in practice we keep parity between deferred and forward, so we should contrain the various features.
// The UI is in charge of setuping the constrain not the code, so if users is forward only and want full power, it is easy to unleash by some UI change
// However in practice we keep parity between deferred and forward, so we should constrain the various features.
// The UI is in charge of setuping the constrain, not the code. So if users is forward only and want unleash power, it is easy to unleash by some UI change
// Modify fresnel0
FillMaterialSSS(surfaceData.subsurfaceMask, bsdfData);
// Assign profile id and overwrite fresnel0
FillMaterialSSS(surfaceData.diffusionProfile, surfaceData.subsurfaceMask, bsdfData);
FillMaterialTransmission(surfaceData.thickness, bsdfData);
// Assign profile id and overwrite fresnel0
FillMaterialTransmission(surfaceData.diffusionProfile, surfaceData.thickness, bsdfData);
FillMaterialAnisotropy(surfaceData.anisotropy, surfaceData.tangentWS, bsdfData);
FillMaterialAnisotropy(surfaceData.anisotropy, surfaceData.tangentWS, cross(surfaceData.normalWS, surfaceData.tangentWS), bsdfData);
}
if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE))

// conversion function for deferred
//-----------------------------------------------------------------------------
// GBuffer layout.
// GBuffer2 and GBuffer0.a interpretation depends on material feature enabled
//GBuffer0 RGBA8 sRGB Gbuffer0 encode baseColor and so is sRGB to save precision. Alpha is not affected.
//GBuffer1 R10B10G10A2
//GBuffer2 RGBA8
//GBuffer3 RGBA8
//FeatureName Standard
//GBuffer0 baseColor.r, baseColor.g, baseColor.b, specularOcclusion
//GBuffer1 perceptualRoughness, normal.x, normal.y, normal.sign
//GBuffer2 f0.r, f0.g, f0.b, featureID(3) / coatMask(5)
//GBuffer3 bakedDiffuseLighting.rgb
//FeatureName Subsurface Scattering + Transmission
//GBuffer0 baseColor.r, baseColor.g, baseColor.b, diffusionProfile(4) / subsurfaceMask(4)
//GBuffer1 perceptualRoughness, normal.x, normal.y, normal.sign
//GBuffer2 specularOcclusion, thickness, diffusionProfile(4) / subsurfaceMask(4), featureID(3) / coatMask(5)
//GBuffer3 bakedDiffuseLighting.rgb
//FeatureName Anisotropic
//GBuffer0 baseColor.r, baseColor.g, baseColor.b, specularOcclusion
//GBuffer1 perceptualRoughness, normal.x, normal.y, normal.sign
//GBuffer2 anisotropy, tangent.x, tangent.y(3) / metallic(5), featureID(3) / coatMask(5)
//GBuffer3 bakedDiffuseLighting.rgb
//FeatureName Irridescence
//GBuffer0 baseColor.r, baseColor.g, baseColor.b, specularOcclusion
//GBuffer1 perceptualRoughness, normal.x, normal.y, normal.sign
//GBuffer2 IOR, thickness, unused(3bit) / metallic(5), featureID(3) / coatMask(5)
//GBuffer3 bakedDiffuseLighting.rgb
// Note:
// For standard we have chose to always encode fresnel0. Even when we use metal/baseColor parametrization. This avoid
// compiler optimization problem that was using VGPR to deal with the various combination of metal non metal.
// For SSS, we move diffusionProfile(4) / subsurfaceMask(4) in GBuffer0.a so the forward SSS code only need to write into one RT
// and the SSS postprocess only need to read one RT
// We duplicate diffusionProfile / subsurfaceMask in GBuffer2.b so the compiler don't need to read the GBuffer0 before PostEvaluateBSDF
// The lighting code have been adapted to only apply diffuseColor at the end.
// This save VGPR as we don' need to keep the GBuffer0 value in register.
// The layout is also design to only require one RT for the material classification. All the material feature flags are deduced from GBuffer2.
// Encode SurfaceData (BSDF parameters) into GBuffer
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild
void EncodeIntoGBuffer( SurfaceData surfaceData,

ApplyDebugToSurfaceData(surfaceData);
// RT0 - 8:8:8:8 sRGB
// Warning: the contents are later overwritten for Standard and SSS!
// We store perceptualRoughness instead of roughness because it save a sqrt ALU when decoding
// (as we want both perceptualRoughness and roughness for the lighting due to Disney Diffuse model)
// Encode normal on 20bit with oct compression + 2bit of sign
float2 octNormalWS = PackNormalOctEncode(surfaceData.normalWS);
// To have more precision encode the sign of xy in a separate uint
float2 octNormalWS = PackNormalOctRectEncode(surfaceData.normalWS);
// To have better precision encode the sign of XY separately.
// Store octNormalSign on two bits with perceptualRoughness
outGBuffer1 = float4(abs(octNormalWS), PackFloatInt10bit(PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness), octNormalSign, 4.0), 0.0);
// We store perceptualRoughness instead of roughness because it is perceptually linear.
outGBuffer1 = float4(PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness), abs(octNormalWS), PackInt(octNormalSign, 2));
// mettalic will be store on 4 bit and store special value when not used
int metallic15 = int(surfaceData.metallic * (GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND + 0.5)); // Remap to [0..12] range. 13, 14, 15 are special value
// IMPORTANT: In case of foward or gbuffer pass materialFeatures is statically know at compile time, so the compiler can do compile time optimization
// Currently material features SpecularColor, Iridescence, SubsurfaceScattering/Transmission, Anisotropy are mutually exclusive due to Gbuffer constrain
// The priority of feature is handled in the code here and reflect in the UI (see LitUI.cs)
uint materialFeatureId;
// Process SSS and Transmission together as they encode almost the same data, negligible cost
metallic15 = GBUFFER_LIT_SSS_OR_TRANSMISSION;
// Special case: For SSS we will store the profile id and the subsurface radius at the location of the specular occlusion (in alpha channel of GBuffer0)
// and we will move the specular occlusion in GBuffer2. This is an optimization for SSSSS and have no other side effect as specular occlusion is always used
// during lighting pass when other buffer (Gbuffer0, 1, 2) and read anyway.
// Reminder that during GBuffer pass we know statically material materialFeatures
if ((surfaceData.materialFeatures & (MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION)) == (MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
materialFeatureId = GBUFFER_LIT_TRANSMISSION_SSS;
else if ((surfaceData.materialFeatures & MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING) == MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING)
materialFeatureId = GBUFFER_LIT_SSS;
else
materialFeatureId = GBUFFER_LIT_TRANSMISSION;
// We perform the same encoding for SSS and transmission even if not used as it is the same cost
// Note that regarding EncodeIntoSSSBuffer, as the lit.shader IS the deferred shader (and the SSS fullscreen pass is based on deferred encoding),
// it know the details of the encoding, so it is fine to assume here how SSSBuffer0 is encoded
// For the SSS feature, the alpha channel is overwritten with (diffusionProfile | subsurfaceMask).
// It is done so that the SSS pass only has to read a single G-Buffer 0.
// We move specular occlusion to the red channel of the G-Buffer 2.
outGBuffer2.rgb = float3(surfaceData.specularOcclusion, surfaceData.thickness, HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING) ? 1.0 : 0.0); // thickness for Transmission
// We duplicate the alpha channel of the G-Buffer 0 (for diffusion profile).
// It allows us to delay reading the G-Buffer 0 until the end of the deferred lighting shader.
outGBuffer2.rgb = float3(surfaceData.specularOcclusion, surfaceData.thickness, outGBuffer0.a);
}
else if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
{
materialFeatureId = GBUFFER_LIT_ANISOTROPIC;
// Reconstruct the default tangent frame.
float3x3 frame = GetLocalFrame(surfaceData.normalWS);
// Compute the rotation angle of the actual tangent frame with respect to the default one.
float sinFrame = dot(surfaceData.tangentWS, frame[1]);
float cosFrame = dot(surfaceData.tangentWS, frame[0]);
uint storeSin = abs(sinFrame) < abs(cosFrame) ? 4 : 0;
uint quadrant = ((sinFrame < 0) ? 1 : 0) | ((cosFrame < 0) ? 2 : 0);
// sin [and cos] are approximately linear up to [after] 45 degrees.
float sinOrCos = min(abs(sinFrame), abs(cosFrame)) * sqrt(2);
outGBuffer2.rgb = float3(surfaceData.anisotropy * 0.5 + 0.5,
sinOrCos,
PackFloatInt8bit(surfaceData.metallic, storeSin | quadrant, 8));
else
else if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE))
if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR))
materialFeatureId = GBUFFER_LIT_IRIDESCENCE;
outGBuffer2.rgb = float3(0.0 /* TODO: IOR */, surfaceData.thicknessIrid,
PackFloatInt8bit(surfaceData.metallic, 0, 8));
}
else // Standard
{
// In the case of standard or specular color we always convert to specular color parametrization before encoding,
// so decoding is more efficient (it allow better optimization for the compiler and save VGPR)
// This mean that on the decode side, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR doesn't exist anymore
materialFeatureId = GBUFFER_LIT_STANDARD;
float3 diffuseColor = surfaceData.baseColor;
float3 fresnel0 = surfaceData.specularColor;
if (!HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR))
metallic15 = GBUFFER_LIT_SPECULAR_COLOR;
outGBuffer2.rgb = LinearToGamma20(surfaceData.specularColor);
// Convert from the metallic parametrization.
diffuseColor = ComputeDiffuseColor(surfaceData.baseColor, surfaceData.metallic);
fresnel0 = ComputeFresnel0(surfaceData.baseColor, surfaceData.metallic, DEFAULT_SPECULAR_VALUE);
else if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_ANISOTROPY))
{
// Encode tangent on 16bit with oct compression
float2 octTangentWS = PackNormalOctEncode(surfaceData.tangentWS);
outGBuffer2.rgb = float3(octTangentWS * 0.5 + 0.5, surfaceData.anisotropy * 0.5 + 0.5);
}
else if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE))
{
metallic15 = GBUFFER_LIT_IRIDESCENCE;
outGBuffer2.rgb = float3(0.0, surfaceData.thicknessIrid, 0.0);
}
else
{
// Caution: Neutral value for anisotropy is 0.5 not 0
outGBuffer2.rgb = float3(0.0, 0.0, 0.5);
}
outGBuffer0.rgb = diffuseColor; // sRGB RT
// outGBuffer2 is not sRGB, so use a fast encode/decode sRGB to keep precision
outGBuffer2.rgb = FastLinearToSRGB(fresnel0); // TODO: optimize
// Encode coatMask (4bit) / mettalic (4bit)
outGBuffer2.a = PackFloatInt8bit(HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT) ? surfaceData.coatMask : 0.0, metallic15, 16.0);
// Ensure that surfaceData.coatMask is 0 if the feature is not enabled
float coatMask = HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT) ? surfaceData.coatMask : 0.0;
// Note: no need to store MATERIALFEATUREFLAGS_LIT_STANDARD, always present
outGBuffer2.a = PackFloatInt8bit(coatMask, materialFeatureId, 8);
// Lighting: 11:11:10f
// RT3 - 11f:11f:10f
// Note that return type is not part of the MACRO DECODE_FROM_GBUFFER, so it is safe to use return value for our need
// If you're not using the feature classification system, pass 0.
// If you're not using the feature classification system, pass UINT_MAX.
// Also, see comment in TileVariantToFeatureFlags. When we are the worse case (i.e last variant), we read the featureflags
// from the structured buffer use to generate the indirect draw call. It allow to not go through all branch and the branch is scalar (not VGPR)
// Note: we have ZERO_INITIALIZE the struct, so bsdfData.diffusionProfile == DIFFUSION_PROFILE_NEUTRAL_ID,
// bsdfData.anisotropy == 0, bsdfData.subsurfaceMask == 0, etc...
ZERO_INITIALIZE(BSDFData, bsdfData);
// Isolate material features.

GBufferType2 inGBuffer2 = LOAD_TEXTURE2D(_GBufferTexture2, positionSS);
GBufferType3 inGBuffer3 = LOAD_TEXTURE2D(_GBufferTexture3, positionSS);
// Init all material flags from Gbuffer2
// Material classification only uses the G-Buffer 2.
int metallic15;
UnpackFloatInt8bit(inGBuffer2.a, 16.0, coatMask, metallic15);
uint materialFeatureId;
UnpackFloatInt8bit(inGBuffer2.a, 8, coatMask, materialFeatureId);
uint pixelFeatureFlags = MATERIALFEATUREFLAGS_LIT_STANDARD; // Only sky/background do not have the Standard material flag
bool pixelHasSpecularColor = (metallic15 == GBUFFER_LIT_SPECULAR_COLOR); // This is always a dynamic test as it is very cheap
bool pixelHasTransmission = (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && inGBuffer2.g > 0); // Thickness > 0
bool pixelHasSubsurface = (metallic15 == GBUFFER_LIT_SSS_OR_TRANSMISSION && inGBuffer2.b > 0); // TagSSS > 0
bool pixelHasAnisotropy = (metallic15 <= GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND && abs(inGBuffer2.b - 0.5) >= 1.0/255.0); // Anisotropy > 0
bool pixelHasIridescence = (metallic15 == GBUFFER_LIT_IRIDESCENCE);
bool pixelHasClearCoat = (coatMask > 0);
uint pixelFeatureFlags = MATERIALFEATUREFLAGS_LIT_STANDARD; // Only sky/background do not have the Standard flag.
bool pixelHasSubsurface = materialFeatureId == GBUFFER_LIT_TRANSMISSION_SSS || materialFeatureId == GBUFFER_LIT_SSS;
bool pixelHasTransmission = materialFeatureId == GBUFFER_LIT_TRANSMISSION_SSS || materialFeatureId == GBUFFER_LIT_TRANSMISSION;
bool pixelHasAnisotropy = materialFeatureId == GBUFFER_LIT_ANISOTROPIC;
bool pixelHasIridescence = materialFeatureId == GBUFFER_LIT_IRIDESCENCE;
bool pixelHasClearCoat = coatMask > 0;
pixelFeatureFlags |= tileFeatureFlags & (pixelHasSpecularColor ? MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasTransmission ? MATERIALFEATUREFLAGS_LIT_TRANSMISSION : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasSubsurface ? MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasAnisotropy ? MATERIALFEATUREFLAGS_LIT_ANISOTROPY : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasIridescence ? MATERIALFEATUREFLAGS_LIT_IRIDESCENCE : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasClearCoat ? MATERIALFEATUREFLAGS_LIT_CLEAR_COAT : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasSubsurface ? MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasTransmission ? MATERIALFEATUREFLAGS_LIT_TRANSMISSION : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasAnisotropy ? MATERIALFEATUREFLAGS_LIT_ANISOTROPY : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasIridescence ? MATERIALFEATUREFLAGS_LIT_IRIDESCENCE : 0);
pixelFeatureFlags |= tileFeatureFlags & (pixelHasClearCoat ? MATERIALFEATUREFLAGS_LIT_CLEAR_COAT : 0);
// Start decompressing GBuffer
// Decompress feature-agnostic data from the G-Buffer.
bsdfData.specularOcclusion = inGBuffer0.a;
int octNormalSign;
UnpackFloatInt10bit(inGBuffer1.b, 4.0, bsdfData.perceptualRoughness, octNormalSign);
inGBuffer1.r = (octNormalSign & 1) ? -inGBuffer1.r : inGBuffer1.r;
inGBuffer1.g = (octNormalSign & 2) ? -inGBuffer1.g : inGBuffer1.g;
bsdfData.specularOcclusion = inGBuffer0.a; // Later possibly overwritten by SSS
bsdfData.perceptualRoughness = inGBuffer1.r;
float2 octNormalWS = inGBuffer1.gb;
uint octNormalSign = UnpackInt(inGBuffer1.a, 2);
octNormalWS.x = (octNormalSign & 1) ? -octNormalWS.x : octNormalWS.x;
octNormalWS.y = (octNormalSign & 2) ? -octNormalWS.y : octNormalWS.y;
bsdfData.normalWS = UnpackNormalOctRectEncode(octNormalWS);
bakeDiffuseLighting = inGBuffer3.rgb;
bsdfData.normalWS = UnpackNormalOctEncode(float2(inGBuffer1.r, inGBuffer1.g));
// Decompress feature-specific data from the G-Buffer.
bool pixelHasMetallic = HasFeatureFlag(pixelFeatureFlags, MATERIALFEATUREFLAGS_LIT_ANISOTROPY | MATERIALFEATUREFLAGS_LIT_IRIDESCENCE);
// metallic15 is range [0..12] if metallic data is needed
bool pixelHasNoMetallic = HasFeatureFlag(pixelFeatureFlags, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR | MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION);
float metallic = pixelHasNoMetallic ? 0 : metallic15 * (1.0 / GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND);
bsdfData.diffuseColor = ComputeDiffuseColor(baseColor, metallic);
bsdfData.fresnel0 = HasFeatureFlag(pixelFeatureFlags, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR) ? Gamma20ToLinear(inGBuffer2.rgb) : ComputeFresnel0(baseColor, metallic, DEFAULT_SPECULAR_VALUE);
if (pixelHasMetallic)
{
float metallic;
uint unused;
UnpackFloatInt8bit(inGBuffer2.b, 8, metallic, unused);
// Always assign even if not used, DIFFUSION_PROFILE_NEUTRAL_ID is 0
// Note: we have ZERO_INITIALIZE the struct, so bsdfData.diffusionProfile == DIFFUSION_PROFILE_NEUTRAL_ID, bsdfData.anisotropy == 0, bsdfData.subsurfaceMask == 0 etc...
bsdfData.diffuseColor = ComputeDiffuseColor(baseColor, metallic);
bsdfData.fresnel0 = ComputeFresnel0(baseColor, metallic, DEFAULT_SPECULAR_VALUE);
}
else
{
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = FastSRGBToLinear(inGBuffer2.rgb); // Later possibly overwritten by SSS
}
// Process SSS and Transmission together as they encode almost the same data
// First we must extract the diffusion profile
SSSData sssData;
// We don't need to do this call, see comment below
// DecodeFromSSSBuffer(inGBuffer0, positionSS, sssData);
// Overwrite the diffusion profile/subsurfaceMask extracted by DecodeFromSSSBuffer().
// We must do this so the compiler can optimize away the read from the G-Buffer 0 to the very end (in PostEvaluateBSDF)
// Note that we don't use sssData.subsurfaceMask here. But it is still assign so we can have the information in the
// material debug view + If we require it in the future.
UnpackFloatInt8bit(inGBuffer2.b, 16, sssData.subsurfaceMask, sssData.diffusionProfile);
SSSData sssData;
DecodeFromSSSBuffer(inGBuffer0, positionSS, sssData);
bsdfData.diffusionProfile = sssData.diffusionProfile;
// Note: both function assign profile and overwrite fresnel0 (both SSS and Transmission)
// in case one feature is enabled and not the other.
// Modify fresnel0
FillMaterialSSS(sssData.subsurfaceMask, bsdfData);
FillMaterialSSS(sssData.diffusionProfile, sssData.subsurfaceMask, bsdfData);
FillMaterialTransmission(inGBuffer2.g, bsdfData);
FillMaterialTransmission(sssData.diffusionProfile, inGBuffer2.g, bsdfData);
}
}

{
float anisotropy;
float3 tangentWS;
float anisotropy = 0;
float3x3 frame = GetLocalFrame(bsdfData.normalWS);
anisotropy = inGBuffer2.b * 2.0 - 1.0;
tangentWS = UnpackNormalOctEncode(inGBuffer2.rg * 2.0 - 1.0);
}
else
{
anisotropy = 0.0;
tangentWS = GetLocalFrame(bsdfData.normalWS)[0];
anisotropy = inGBuffer2.r * 2.0 - 1.0;
float unused;
uint tangentFlags;
UnpackFloatInt8bit(inGBuffer2.b, 8, unused, tangentFlags);
// Get the rotation angle of the actual tangent frame with respect to the default one.
uint quadrant = tangentFlags;
uint storeSin = tangentFlags & 4;
float sinOrCos = inGBuffer2.g * rsqrt(2);
float cosOrSin = sqrt(1 - sinOrCos * sinOrCos);
float sinFrame = storeSin ? sinOrCos : cosOrSin;
float cosFrame = storeSin ? cosOrSin : sinOrCos;
sinFrame = (quadrant & 1) ? -sinFrame : sinFrame;
cosFrame = (quadrant & 2) ? -cosFrame : cosFrame;
// Rotate the reconstructed tangent around the normal.
frame[0] = sinFrame * frame[1] + cosFrame * frame[0];
frame[1] = cross(frame[2], frame[0]);
FillMaterialAnisotropy(anisotropy, tangentWS, bsdfData);
FillMaterialAnisotropy(anisotropy, frame[0], frame[1], bsdfData);
}
if (HasFeatureFlag(pixelFeatureFlags, MATERIALFEATUREFLAGS_LIT_IRIDESCENCE))

// perceptualRoughness can be modify by FillMaterialClearCoatData, so ConvertAnisotropyToClampRoughness must be call after
ConvertAnisotropyToClampRoughness(bsdfData.perceptualRoughness, bsdfData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
bakeDiffuseLighting = inGBuffer3.rgb;
return pixelFeatureFlags;
}

void GetSurfaceDataDebug(uint paramId, SurfaceData surfaceData, inout float3 result, inout bool needLinearToSRGB)
{
GetGeneratedSurfaceDataDebug(paramId, surfaceData, result, needLinearToSRGB);
// Overide debug value output to be more readable
switch (paramId)
{
case DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_FEATURES:
result = (surfaceData.materialFeatures.xxx) / 255.0; // Aloow to read with color picker debug mode
break;
}
// Overide debug value output to be more readable
switch (paramId)
{
case DEBUGVIEW_LIT_BSDFDATA_MATERIAL_FEATURES:
result = (bsdfData.materialFeatures.xxx) / 255.0; // Aloow to read with color picker debug mode
break;
}
}
//-----------------------------------------------------------------------------

// This is a ad-hoc tweak to better match reference of anisotropic GGX.
// TODO: We need a better hack.
preLightData.iblPerceptualRoughness *= saturate(1.2 - abs(bsdfData.anisotropy));
float iblRoughness = PerceptualRoughnessToRoughness(preLightData.iblPerceptualRoughness);
preLightData.iblR = GetSpecularDominantDir(N, iblR, iblRoughness, NdotV);
preLightData.iblR = GetSpecularDominantDir(N, iblR, preLightData.iblPerceptualRoughness, NdotV);
#ifdef LIT_USE_GGX_ENERGY_COMPENSATION
// Ref: Practical multiple scattering compensation for microfacet models.

bool PixelHasSubsurfaceScattering(BSDFData bsdfData)
{
return bsdfData.subsurfaceMask != 0 && HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING);
return bsdfData.diffusionProfile != DIFFUSION_PROFILE_NEUTRAL_ID && bsdfData.subsurfaceMask != 0 && HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING);
}
//-----------------------------------------------------------------------------

// We define the ellipsoid s.t. r1 = (r + len / 2), r2 = r3 = r.
// TODO: This could be precomputed.
float radius = rsqrt(lightData.invSqrAttenuationRadius);
float invAspectRatio = radius / (radius + (0.5 * len));
float invAspectRatio = saturate(radius / (radius + (0.5 * len)));
// Compute the light attenuation.
float intensity = EllipsoidalDistanceAttenuation(unL, lightData.invSqrAttenuationRadius,

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


[ToggleUI] _TransparentDepthPrepassEnable("_TransparentDepthPrepassEnable", Float) = 0.0
[ToggleUI] _TransparentBackfaceEnable("_TransparentBackfaceEnable", Float) = 0.0
[ToggleUI] _TransparentDepthPostpassEnable("_TransparentDepthPostpassEnable", Float) = 0.0
_TransparentSortPriority("_TransparentSortPriority", Float) = 0
// Transparency
[Enum(None, 0, Plane, 1, Sphere, 2)]_RefractionMode("Refraction Mode", Int) = 0

_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
[ToggleUI] _SupportDBuffer("Support DBuffer", Float) = 1.0
}
HLSLINCLUDE

#pragma shader_feature _THICKNESSMAP
#pragma shader_feature _SPECULARCOLORMAP
#pragma shader_feature _TRANSMITTANCECOLORMAP
#pragma shader_feature _DISABLE_DBUFFER
// Keyword for transparent
#pragma shader_feature _SURFACE_TYPE_TRANSPARENT

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


// This is use with anisotropic material
surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS);
#ifndef _DISABLE_DBUFFER
#endif
#if defined(DEBUG_DISPLAY)
if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE)

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


#if !defined(LAYERED_LIT_SHADER)
// These static material feature allow compile time optimization
surfaceData.materialFeatures = 0;
surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD;
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION;
// TEMP: The UI must control if we have transmission or not.
// Currently until we update the UI, this is control in the diffusion profile
uint transmissionMode = BitFieldExtract(asuint(_TransmissionFlags), 2u * surfaceData.diffusionProfile, 2u);
// Caution: Because of this dynamic test we don't know anymore statically if we have transmission, which mess with performance.
// in deferred case as we still have both sss and transmission until we update the UI it should be the same perf
if (transmissionMode != TRANSMISSION_MODE_NONE)
{
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION;
}
#endif
#ifdef _MATERIAL_FEATURE_ANISOTROPY
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY;

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


[ToggleUI] _TransparentDepthPrepassEnable("_TransparentDepthPrepassEnable", Float) = 0.0
[ToggleUI] _TransparentBackfaceEnable("_TransparentBackfaceEnable", Float) = 0.0
[ToggleUI] _TransparentDepthPostpassEnable("_TransparentDepthPostpassEnable", Float) = 0.0
_TransparentSortPriority("_TransparentSortPriority", Float) = 0
// Transparency
[Enum(None, 0, Plane, 1, Sphere, 2)]_RefractionMode("Refraction Mode", Int) = 0

_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
[ToggleUI] _SupportDBuffer("Support DBuffer", Float) = 1.0
}
HLSLINCLUDE

#pragma shader_feature _THICKNESSMAP
#pragma shader_feature _SPECULARCOLORMAP
#pragma shader_feature _TRANSMITTANCECOLORMAP
#pragma shader_feature _DISABLE_DBUFFER
// Keyword for transparent
#pragma shader_feature _SURFACE_TYPE_TRANSPARENT

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


{
float3 diffuseColor;
float subsurfaceMask;
int diffusionProfile;
uint diffusionProfile;
};
#define SSSBufferType0 float4

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

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

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Unlit/Unlit.shader


[ToggleUI] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_TransparentSortPriority("_TransparentSortPriority", Float) = 0
// Blending state
[HideInInspector] _SurfaceType("__surfacetype", Float) = 0.0

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


public bool enablePostprocess = true;
public bool enableStereo = true;
public bool enableAsyncCompute = false;
public bool enableAsyncCompute = true;
public bool enableOpaqueObjects = true;
public bool enableTransparentObjects = true;

// Force forward if we request stereo. TODO: We should not enforce that, users should be able to chose deferred
aggregate.enableForwardRenderingOnly = aggregate.enableForwardRenderingOnly || aggregate.enableStereo;
aggregate.enableAsyncCompute = srcFrameSettings.enableAsyncCompute && renderPipelineSettings.supportAsyncCompute;
aggregate.enableAsyncCompute = srcFrameSettings.enableAsyncCompute && SystemInfo.supportsAsyncCompute;
aggregate.enableOpaqueObjects = srcFrameSettings.enableOpaqueObjects;
aggregate.enableTransparentObjects = srcFrameSettings.enableTransparentObjects;

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


// Engine
public bool supportDBuffer = false;
public bool supportMSAA = false;
public bool supportAsyncCompute = false;
public bool supportsMotionVectors = true;
public bool supportsStereo = false;

9
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/CameraMotionVectors.shader


float4 Frag(Varyings input) : SV_Target
{
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
float4 worldPos = float4(posInput.positionWS, 1.0);
float4 prevPos = worldPos;

float2 previousPositionCS = (prevHPos + 1.0) / 2.0;
float2 positionCS = (curHPos + 1.0) / 2.0;
#if !UNITY_UV_STARTS_AT_TOP
#if UNITY_UV_STARTS_AT_TOP
previousPositionCS.y = 1.0 - previousPositionCS.y;
positionCS.y = 1.0 - positionCS.y;
#endif

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/HDRenderPipelineResources.asset


m_EditorClassIdentifier:
defaultDiffuseMaterial: {fileID: 2100000, guid: 73c176f402d2c2f4d929aa5da7585d17,
type: 2}
defaultDecalMaterial: {fileID: 2100000, guid: 500e733574922d04ea961553b1b26a63,
type: 2}
defaultShader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
debugFontTexture: {fileID: 2800000, guid: a3ad2df0e49aaa341a3b3a80f93b3f66, type: 3}
debugDisplayLatlongShader: {fileID: 4800000, guid: c1d1d149a043a5349ba367da6c2051ba,

copyStencilBuffer: {fileID: 4800000, guid: 3d1574f1cdfa0ce4995f9bc79ed7f8ec, type: 3}
copyDepthBuffer: {fileID: 4800000, guid: 42dfcc8fe803ece4096c58630689982f, type: 3}
blit: {fileID: 4800000, guid: 370f7a9cc4e362d488af024d371091e8, type: 3}
blitFlipMip: {fileID: 4800000, guid: ef092fc4aaa1bb546a9ab4e457c4b07a, type: 3}
blitCubemap: {fileID: 4800000, guid: d05913e251bed7a4992c921c62e1b647, type: 3}
buildProbabilityTables: {fileID: 7200000, guid: b9f26cf340afe9145a699753531b2a4c,
type: 3}

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/RenderPipelineResources.cs


{
// Default Material / Shader
public Material defaultDiffuseMaterial;
public Material defaultDecalMaterial;
public Shader defaultShader;
// Debug

43
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl


#include "VertMesh.hlsl"
float3 RemoveScale(float3 val)
{
return normalize(val / length(val));
}
VaryingsMeshType Transform(AttributesMesh input)
{
VaryingsMeshType output;
UNITY_SETUP_INSTANCE_ID(input)
UNITY_TRANSFER_INSTANCE_ID(input, output);
float3 positionWS = TransformObjectToWorld(input.positionOS);
positionWS = GetCameraRelativePositionWS(positionWS);
output.positionCS = TransformWorldToHClip(positionWS);
float3x3 decalRotation;
decalRotation[0] = RemoveScale(float3(UNITY_MATRIX_M[0][0], UNITY_MATRIX_M[0][1], UNITY_MATRIX_M[0][2]));
decalRotation[2] = RemoveScale(float3(UNITY_MATRIX_M[1][0], UNITY_MATRIX_M[1][1], UNITY_MATRIX_M[1][2]));
decalRotation[1] = RemoveScale(float3(UNITY_MATRIX_M[2][0], UNITY_MATRIX_M[2][1], UNITY_MATRIX_M[2][2]));
decalRotation = transpose(decalRotation);
output.positionWS = decalRotation[0];
output.normalWS = decalRotation[1];
output.tangentWS = float4(decalRotation[2], 0.0);
return output;
}
varyingsType.vmesh = Transform(inputMesh);
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}

{
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionSS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
// Transform from world space to decal space (DS) to clip the decal.
// For this we must use absolute position.

clip(1.0 - positionDS); // Clip value above one
DecalSurfaceData surfaceData;
float3x3 decalToWorld;
// using the interpolators directly, because UnpackVaryingsMeshToFragInputs does some tangent space manipulations
decalToWorld[0] = packedInput.vmesh.interpolators0;
decalToWorld[1] = packedInput.vmesh.interpolators1;
decalToWorld[2] = packedInput.vmesh.interpolators2.xyz;
float3x3 decalToWorld = (float3x3)UNITY_ACCESS_INSTANCED_PROP(matrix, normalToWorld);
GetSurfaceData(positionDS.xz, decalToWorld, surfaceData);
ENCODE_INTO_DBUFFER(surfaceData, outDBuffer);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDepthOnly.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionWS);
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDistortion.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionWS);
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

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


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

GetVaryingsDataDebug(_DebugViewMaterial, input, result, needLinearToSRGB);
GetBuiltinDataDebug(_DebugViewMaterial, builtinData, result, needLinearToSRGB);
GetSurfaceDataDebug(_DebugViewMaterial, surfaceData, result, needLinearToSRGB);
GetBSDFDataDebug(_DebugViewMaterial, bsdfData, result, needLinearToSRGB); // TODO: This required to initialize all field from BSDFData...
GetBSDFDataDebug(_DebugViewMaterial, bsdfData, result, needLinearToSRGB);
// TEMP!
// For now, the final blit in the backbuffer performs an sRGB write

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassForwardUnlit.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionWS);
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

GetPropertiesDataDebug(_DebugViewMaterial, result, needLinearToSRGB);
GetVaryingsDataDebug(_DebugViewMaterial, input, result, needLinearToSRGB);
GetBuiltinDataDebug(_DebugViewMaterial, builtinData, result, needLinearToSRGB);
GetBSDFDataDebug(_DebugViewMaterial, bsdfData, result, needLinearToSRGB); // TODO: This required to initialize all field from BSDFData...
GetSurfaceDataDebug(_DebugViewMaterial, surfaceData, result, needLinearToSRGB);
GetBSDFDataDebug(_DebugViewMaterial, bsdfData, result, needLinearToSRGB);
// TEMP!
// For now, the final blit in the backbuffer performs an sRGB write

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassGBuffer.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionWS);
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassLightTransport.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionWS);
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassVelocity.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionWS);
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/VaryingMesh.hlsl


float4 interpolators5 : TEXCOORD5;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID // Must be declare before FRONT_FACE_SEMANTIC
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// Functions to pack data to use as few interpolator as possible, the ShaderGraph should generate these functions

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/VertMesh.hlsl


float3 normalWS = float3(0.0, 0.0, 0.0); // We need this case to be able to compile ApplyVertexModification that doesn't use normal.
#endif
float4 tangentWS = float4(0.0, 0.0, 0.0, 0.0);
tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
float4 tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
#endif
// TODO: deal with camera center rendering and instancing (This is the reason why we always perform two steps transform to clip space + instancing matrix)

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderVariables.hlsl


float4 unity_ShadowColor;
float2 _TaaFrameRotation; // {x = sin(_TaaFrameIndex * PI/2), y = cos(_TaaFrameIndex * PI/2), z = unused}
uint _TaaFrameIndex; // [0, 7]
uint _Align128; // Pad for 128-bit alignment
// Volumetric lighting. Should be a struct in 'UnityPerFrame'.
// Unfortunately, structures inside constant buffers are not supported by Unity.
// Volumetric lighting.
float _GlobalFog_Asymmetry;
float3 _GlobalFog_Scattering;
float _GlobalFog_Extinction;
float4 _VBufferResolution; // { w, h, 1/w, 1/h }

// Avoid declaring extra samplers as they are 4x SGPR each on GCN.
SAMPLER(s_point_clamp_sampler);
SAMPLER(s_linear_clamp_sampler);
SAMPLER(s_linear_repeat_sampler);
SAMPLER(s_trilinear_clamp_sampler);
// ----------------------------------------------------------------------------

21
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/OpaqueAtmosphericScattering.shader


float4 Frag(Varyings input) : SV_Target
{
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.positionSS).x;
UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
if (depth == UNITY_RAW_FAR_CLIP_VALUE)
{
// When a pixel is at far plane, the world space coordinate reconstruction is not reliable.
// So in order to have a valid position (for example for height fog) we just consider that the sky is a sphere centered on camera with a radius of 5km (arbitrarily chosen value!)
// And recompute the position on the sphere with the current camera direction.
float3 viewDirection = -GetWorldSpaceNormalizeViewDir(posInput.positionWS) * 5000.0f;
posInput.positionWS = GetPrimaryCameraPosition() + viewDirection;
}
if (depth == UNITY_RAW_FAR_CLIP_VALUE)
{
// When a pixel is at far plane, the world space coordinate reconstruction is not reliable.
// So in order to have a valid position (for example for height fog) we just consider that the sky is a sphere centered on camera with a radius of 5km (arbitrarily chosen value!)
// And recompute the position on the sphere with the current camera direction.
float3 viewDirection = -GetWorldSpaceNormalizeViewDir(posInput.positionWS) * 5000.0f;
posInput.positionWS = GetPrimaryCameraPosition() + viewDirection;
}
return EvaluateAtmosphericScattering(posInput);
}

7
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/ProceduralSky/Resources/ProceduralSky.shader


float getMiePhase(float eyeCos, float eyeCos2)
{
float temp = 1.0 + MIE_G2 - 2.0 * MIE_G * eyeCos;
temp = pow(max(temp, 0), pow(_SunSize,0.65) * 10);
temp = PositivePow(temp, PositivePow(_SunSize, 0.65) * 10);
#if defined(UNITY_COLORSPACE_GAMMA) && SKYBOX_COLOR_IN_TARGET_COLOR_SPACE
temp = pow(temp, .454545);
#endif
return temp;
}

float3 cameraPos = float3(0,kInnerRadius + kCameraHeight,0); // The camera's current position
// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
float3 eyeRay = dir; // normalize(mul((float3x3)unity_ObjectToWorld, v.vertex.xyz));
float3 eyeRay = dir; // normalize(mul((float3x3)UNITY_MATRIX_M, v.vertex.xyz));
float far = 0.0;
float3 cIn = float3(0.0, 0.0, 0.0);

4
ScriptableRenderPipeline/HDRenderPipeline/package.json


{
"name": "com.unity.render-pipelines.high-definition",
"description": "HD Render Pipeline for Unity.",
"version": "0.1.24",
"version": "0.1.26",
"com.unity.render-pipelines.core": "0.1.24"
"com.unity.render-pipelines.core": "0.1.26"
}
}

157
ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineAsset.cs


#if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEditor.ProjectWindowCallback;
#endif

_8x = 8
}
public enum DefaultMaterialType
{
Standard = 0,
Particle,
Terrain,
UnityBuiltinDefault
}
private Shader m_DefaultShader;
[SerializeField] private float kAssetVersion = 1.0f;
[SerializeField] private int kAssetVersion = 2;
[SerializeField] private int m_MaxPixelLights = 4;
[SerializeField] private bool m_SupportsVertexLight = false;
[SerializeField] private bool m_RequireDepthTexture = false;

[SerializeField] private ShadowCascades m_ShadowCascades = ShadowCascades.FOUR_CASCADES;
[SerializeField] private float m_Cascade2Split = 0.25f;
[SerializeField] private Vector3 m_Cascade4Split = new Vector3(0.067f, 0.2f, 0.467f);
[SerializeField]
private LightweightPipelineResources m_ResourcesAsset;
// Resources
[SerializeField] private Shader m_DefaultShader;
[SerializeField] private Shader m_BlitShader;
[SerializeField] private Shader m_CopyDepthShader;
[SerializeField] private LightweightPipelineResource m_ResourceAsset;
private LightweightPipelineEditorResources m_EditorResourcesAsset;
[MenuItem("Assets/Create/Render Pipeline/Lightweight/Pipeline Asset", priority = CoreUtils.assetCreateMenuPriority1)]
static void CreateLightweightPipeline()

}
//[MenuItem("Assets/Create/Render Pipeline/Lightweight/Pipeline Resources", priority = CoreUtils.assetCreateMenuPriority1)]
static void CreateLightweightPipelineResources()
{
var instance = CreateInstance<LightweightPipelineResources>();
AssetDatabase.CreateAsset(instance, string.Format("Assets/{0}.asset", typeof(LightweightPipelineResources).Name));
}
//[MenuItem("Assets/Create/Render Pipeline/Lightweight/Pipeline Editor Resources", priority = CoreUtils.assetCreateMenuPriority1)]
static void CreateLightweightPipelineEditorResources()
{
var instance = CreateInstance<LightweightPipelineEditorResources>();
AssetDatabase.CreateAsset(instance, string.Format("Assets/{0}.asset", typeof(LightweightPipelineEditorResources).Name));
}
instance.m_EditorResourcesAsset = LoadResourceFile<LightweightPipelineEditorResources>();
instance.m_ResourcesAsset = LoadResourceFile<LightweightPipelineResources>();
AssetDatabase.CreateAsset(instance, pathName);
}
}
string[] guids = AssetDatabase.FindAssets("LightweightPipelineResource t:scriptableobject", m_SearchPaths);
LightweightPipelineResource resourceAsset = null;
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
resourceAsset = AssetDatabase.LoadAssetAtPath<LightweightPipelineResource>(path);
if (resourceAsset != null)
break;
}
private static T LoadResourceFile<T>() where T : ScriptableObject
{
T resourceAsset = null;
var guids = AssetDatabase.FindAssets(typeof(T).Name + " t:scriptableobject", m_SearchPaths);
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
resourceAsset = AssetDatabase.LoadAssetAtPath<T>(path);
if (resourceAsset != null)
break;
}
// There's currently an issue that prevents FindAssets from find resources withing the package folder.
if (resourceAsset == null)
{
string path = m_SearchPaths[PACKAGE_MANAGER_PATH_INDEX] + "/LWRP/Data/LightweightPipelineResource.asset";
resourceAsset = AssetDatabase.LoadAssetAtPath<LightweightPipelineResource>(path);
}
// There's currently an issue that prevents FindAssets from find resources withing the package folder.
if (resourceAsset == null)
{
string path = m_SearchPaths[PACKAGE_MANAGER_PATH_INDEX] + "/LWRP/Data/" + typeof(T).Name + ".asset";
resourceAsset = AssetDatabase.LoadAssetAtPath<T>(path);
}
return resourceAsset;
}
instance.m_ResourceAsset = resourceAsset;
instance.m_DefaultShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.STANDARD_PBS));
instance.m_BlitShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.HIDDEN_BLIT));
instance.m_CopyDepthShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.HIDDEN_DEPTH_COPY));
LightweightPipelineEditorResources editorResources
{
get
{
if (m_EditorResourcesAsset == null)
m_EditorResourcesAsset = LoadResourceFile<LightweightPipelineEditorResources>();
AssetDatabase.CreateAsset(instance, pathName);
return m_EditorResourcesAsset;
LightweightPipelineResources resources
{
get
{
#if UNITY_EDITOR
if (m_ResourcesAsset == null)
m_ResourcesAsset = LoadResourceFile<LightweightPipelineResources>();
#endif
return m_ResourcesAsset;
}
}
protected override IRenderPipeline InternalCreatePipeline()
{

DestroyCreatedInstances();
}
private Material GetMaterial(DefaultMaterialType materialType)
{
#if UNITY_EDITOR
switch (materialType)
{
case DefaultMaterialType.Standard:
return editorResources.DefaultMaterial;
case DefaultMaterialType.Particle:
return editorResources.DefaultParticleMaterial;
case DefaultMaterialType.Terrain:
return editorResources.DefaultTerrainMaterial;
// Unity Builtin Default
default:
return null;
}
#else
return null;
#endif
}
public bool AreShadowsEnabled()
{
return ShadowSetting != ShadowType.NO_SHADOW;

public override Material GetDefaultMaterial()
{
#if UNITY_EDITOR
if (m_ResourceAsset != null)
return m_ResourceAsset.DefaultMaterial;
#endif
return null;
return GetMaterial(DefaultMaterialType.Standard);
#if UNITY_EDITOR
if (m_ResourceAsset != null)
return m_ResourceAsset.DefaultParticleMaterial;
#endif
return null;
return GetMaterial(DefaultMaterialType.Particle);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
#if UNITY_EDITOR
if (m_ResourceAsset != null)
return m_ResourceAsset.DefaultTerrainMaterial;
#endif
return null;
return GetMaterial(DefaultMaterialType.Terrain);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
if (m_DefaultShader == null)
m_DefaultShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.STANDARD_PBS));
get { return m_BlitShader; }
get { return resources != null ? resources.BlitShader : null; }
get { return m_CopyDepthShader; }
get { return resources != null ? resources.CopyDepthShader : null; }
}
}
}

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineEditorResources.cs.meta


fileFormatVersion: 2
guid: eb91b173ce266e040aa972ca9a561308
guid: 76e49a5b88430df478c504fe5a5c1a62
MonoImporter:
externalObjects: {}
serializedVersion: 2

13
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightConstantBuffer.cs


public static int _AdditionalLightSpotDir;
public static int _AdditionalLightSpotAttenuation;
}
public static class ShadowConstantBuffer
{
public static int _WorldToShadow;
public static int _ShadowData;
public static int _DirShadowSplitSpheres;
public static int _DirShadowSplitSphereRadii;
public static int _ShadowOffset0;
public static int _ShadowOffset1;
public static int _ShadowOffset2;
public static int _ShadowOffset3;
public static int _ShadowmapSize;
}
}

124
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


private bool m_IsOffscreenCamera;
private Vector4 kDefaultLightPosition = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
private Vector4 kDefaultLightColor = Color.black;
private Vector4 kDefaultLightAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 1.0f);
private Vector4 kDefaultLightSpotDirection = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
private Vector4 kDefaultLightSpotAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
private Vector4[] m_LightPositions = new Vector4[kMaxVisibleLights];
private Vector4[] m_LightColors = new Vector4[kMaxVisibleLights];
private Vector4[] m_LightDistanceAttenuations = new Vector4[kMaxVisibleLights];

PerCameraBuffer._AdditionalLightDistanceAttenuation = Shader.PropertyToID("_AdditionalLightDistanceAttenuation");
PerCameraBuffer._AdditionalLightSpotDir = Shader.PropertyToID("_AdditionalLightSpotDir");
PerCameraBuffer._AdditionalLightSpotAttenuation = Shader.PropertyToID("_AdditionalLightSpotAttenuation");
ShadowConstantBuffer._WorldToShadow = Shader.PropertyToID("_WorldToShadow");
ShadowConstantBuffer._ShadowData = Shader.PropertyToID("_ShadowData");
ShadowConstantBuffer._DirShadowSplitSpheres = Shader.PropertyToID("_DirShadowSplitSpheres");
ShadowConstantBuffer._DirShadowSplitSphereRadii = Shader.PropertyToID("_DirShadowSplitSphereRadii");
ShadowConstantBuffer._ShadowOffset0 = Shader.PropertyToID("_ShadowOffset0");
ShadowConstantBuffer._ShadowOffset1 = Shader.PropertyToID("_ShadowOffset1");
ShadowConstantBuffer._ShadowOffset2 = Shader.PropertyToID("_ShadowOffset2");
ShadowConstantBuffer._ShadowOffset3 = Shader.PropertyToID("_ShadowOffset3");
ShadowConstantBuffer._ShadowmapSize = Shader.PropertyToID("_ShadowmapSize");
m_ShadowMapRTID = Shader.PropertyToID("_ShadowMap");

// If we have a main light we don't shade it in the per-object light loop. We also remove it from the per-object cull list
int mainLightPresent = (lightData.mainLightIndex >= 0) ? 1 : 0;
int additionalPixelLightsCount = visibleLightsCount - mainLightPresent;
int vertexLightCount = (m_Asset.SupportsVertexLight) ? Math.Min(visibleLights.Count, kMaxPerObjectLights) - additionalPixelLightsCount : 0;
int vertexLightCount = (m_Asset.SupportsVertexLight) ? Math.Min(visibleLights.Count, kMaxPerObjectLights) - additionalPixelLightsCount - mainLightPresent : 0;
vertexLightCount = Math.Min(vertexLightCount, kMaxVertexLights);
lightData.pixelAdditionalLightsCount = additionalPixelLightsCount;

private void InitializeLightConstants(List<VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
out Vector4 lightSpotAttenuation)
{
float directContributionNotBaked = 1.0f;
lightPos = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
lightColor = Color.black;
lightDistanceAttenuation = new Vector4(0.0f, 1.0f, 0.0f, directContributionNotBaked);
lightSpotDir = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
lightSpotAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
lightPos = kDefaultLightPosition;
lightColor = kDefaultLightColor;
lightDistanceAttenuation = kDefaultLightSpotAttenuation;
lightSpotDir = kDefaultLightSpotDirection;
lightSpotAttenuation = kDefaultLightAttenuation;
// When no lights are visible, main light will be set to -1.
// In this case we initialize it to default values and return

float oneOverFadeRangeSqr = 1.0f / fadeRangeSqr;
float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr;
float quadAtten = 25.0f / lightRangeSqr;
lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, directContributionNotBaked);
lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, 1.0f);
}
if (lightData.lightType == LightType.Spot)

if (lightData.shadowMapSampleType != LightShadows.None)
SetupShadowReceiverConstants(cmd, lights[lightData.mainLightIndex]);
if (lightData.totalAdditionalLightsCount > 0)
SetupAdditionalListConstants(cmd, lights, ref lightData);
SetupAdditionalListConstants(cmd, lights, ref lightData);
}
private void SetupMainLightConstants(CommandBuffer cmd, List<VisibleLight> lights, int lightIndex)

{
int additionalLightIndex = 0;
// We need to update per-object light list with the proper map to our global additional light buffer
// First we initialize all lights in the map to -1 to tell the system to discard main light index and
// remaining lights in the scene that don't fit the max additional light buffer (kMaxVisibileAdditionalLights)
int[] perObjectLightIndexMap = m_CullResults.GetLightIndexMap();
for (int i = 0; i < lights.Count; ++i)
perObjectLightIndexMap[i] = -1;
for (int i = 0; i < lights.Count && additionalLightIndex < kMaxVisibleLights; ++i)
if (lightData.totalAdditionalLightsCount > 0)
if (i != lightData.mainLightIndex)
// We need to update per-object light list with the proper map to our global additional light buffer
// First we initialize all lights in the map to -1 to tell the system to discard main light index and
// remaining lights in the scene that don't fit the max additional light buffer (kMaxVisibileAdditionalLights)
int[] perObjectLightIndexMap = m_CullResults.GetLightIndexMap();
for (int i = 0; i < lights.Count; ++i)
perObjectLightIndexMap[i] = -1;
for (int i = 0; i < lights.Count && additionalLightIndex < kMaxVisibleLights; ++i)
// The engine performs per-object light culling and initialize 8 light indices into two vec4 constants unity_4LightIndices0 and unity_4LightIndices1.
// In the shader we iterate over each visible light using the indices provided in these constants to index our global light buffer
// ex: first light position would be m_LightPosisitions[unity_4LightIndices[0]];
if (i != lightData.mainLightIndex)
{
// The engine performs per-object light culling and initialize 8 light indices into two vec4 constants unity_4LightIndices0 and unity_4LightIndices1.
// In the shader we iterate over each visible light using the indices provided in these constants to index our global light buffer
// ex: first light position would be m_LightPosisitions[unity_4LightIndices[0]];
// However since we sorted the lights we need to tell the engine how to map the original/unsorted indices to our global buffer
// We do it by settings the perObjectLightIndexMap to the appropriate additionalLightIndex.
perObjectLightIndexMap[GetLightUnsortedIndex(i)] = additionalLightIndex;
InitializeLightConstants(lights, i, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightDistanceAttenuations[additionalLightIndex],
out m_LightSpotDirections[additionalLightIndex],
out m_LightSpotAttenuations[additionalLightIndex]);
additionalLightIndex++;
// However since we sorted the lights we need to tell the engine how to map the original/unsorted indices to our global buffer
// We do it by settings the perObjectLightIndexMap to the appropriate additionalLightIndex.
perObjectLightIndexMap[GetLightUnsortedIndex(i)] = additionalLightIndex;
InitializeLightConstants(lights, i, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightDistanceAttenuations[additionalLightIndex],
out m_LightSpotDirections[additionalLightIndex],
out m_LightSpotAttenuations[additionalLightIndex]);
additionalLightIndex++;
}
m_CullResults.SetLightIndexMap(perObjectLightIndexMap);
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, new Vector4(lightData.pixelAdditionalLightsCount,
lightData.totalAdditionalLightsCount, 0.0f, 0.0f));
m_CullResults.SetLightIndexMap(perObjectLightIndexMap);
else
{
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, Vector4.zero);
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, new Vector4(lightData.pixelAdditionalLightsCount,
lightData.totalAdditionalLightsCount, 0.0f, 0.0f));
// Clear to default all light cosntant data
for (int i = 0; i < kMaxVisibleLights; ++i)
InitializeLightConstants(lights, -1, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightDistanceAttenuations[additionalLightIndex],
out m_LightSpotDirections[additionalLightIndex],
out m_LightSpotAttenuations[additionalLightIndex]);
}
cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightPosition, m_LightPositions);
cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightColor, m_LightColors);
cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightDistanceAttenuation, m_LightDistanceAttenuations);

// Scale bias by cascade's world space depth range.
// Directional shadow lights have orthogonal projection.
// proj.m22 = -2 / (far - near) since the projection's depth range is [-1.0, 1.0]
// Therefore we scale it by 0.5. We keep the negative sign and only flip it in case z is
// reversed.
// In order to be correct we should multiply bias by 0.5 but this introducing aliasing along cascades more visible.
bias = light.shadowBias * proj.m22 * 0.5f * sign;
bias = light.shadowBias * proj.m22 * sign;
// Currently only square POT cascades resolutions are used.
// We scale normalBias

private void SetupShadowReceiverConstants(CommandBuffer cmd, VisibleLight shadowLight)
{
Light light = shadowLight.light;
float shadowResolution = m_ShadowSlices[0].shadowResolution;
int cascadeCount = m_ShadowCasterCascadesCount;
for (int i = 0; i < kMaxCascades; ++i)

noOpShadowMatrix.m33 = (SystemInfo.usesReversedZBuffer) ? 1.0f : 0.0f;
m_ShadowMatrices[kMaxCascades] = noOpShadowMatrix;
float invShadowResolution = 0.5f / shadowResolution;
cmd.SetGlobalMatrixArray("_WorldToShadow", m_ShadowMatrices);
cmd.SetGlobalVector("_ShadowData", new Vector4(light.shadowStrength, 0.0f, 0.0f, 0.0f));
cmd.SetGlobalVectorArray("_DirShadowSplitSpheres", m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector("_DirShadowSplitSphereRadii", m_DirectionalShadowSplitRadii);
cmd.SetGlobalVector("_ShadowOffset0", new Vector4(-invShadowResolution, -invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset1", new Vector4(invShadowResolution, -invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset2", new Vector4(-invShadowResolution, invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset3", new Vector4(invShadowResolution, invShadowResolution, 0.0f, 0.0f));
float invShadowResolution = 1.0f / m_Asset.ShadowAtlasResolution;
float invHalfShadowResolution = 0.5f * invShadowResolution;
cmd.SetGlobalMatrixArray(ShadowConstantBuffer._WorldToShadow, m_ShadowMatrices);
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowData, new Vector4(light.shadowStrength, 0.0f, 0.0f, 0.0f));
cmd.SetGlobalVectorArray(ShadowConstantBuffer._DirShadowSplitSpheres, m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector(ShadowConstantBuffer._DirShadowSplitSphereRadii, m_DirectionalShadowSplitRadii);
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset0, new Vector4(-invHalfShadowResolution, -invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset1, new Vector4( invHalfShadowResolution, -invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset2, new Vector4(-invHalfShadowResolution, invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset3, new Vector4( invHalfShadowResolution, invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowmapSize, new Vector4(invShadowResolution, invShadowResolution, m_Asset.ShadowAtlasResolution, m_Asset.ShadowAtlasResolution));
}
private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, List<VisibleLight> visibleLights)

11
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl


#define MAX_VISIBLE_LIGHTS 16
struct InputData
{
float3 positionWS;
half3 normalWS;
half3 viewDirectionWS;
float4 shadowCoord;
half fogCoord;
half3 vertexLighting;
half3 bakedGI;
};
///////////////////////////////////////////////////////////////////////////////
// Constant Buffers //
///////////////////////////////////////////////////////////////////////////////

4
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputSurface.hlsl


half3 specular;
half metallic;
half smoothness;
half3 normal;
half3 normalTS;
half3 emission;
half occlusion;
half alpha;

#endif
outSurfaceData.smoothness = specGloss.a;
outSurfaceData.normal = Normal(uv);
outSurfaceData.normalTS = Normal(uv);
outSurfaceData.occlusion = Occlusion(uv);
outSurfaceData.emission = Emission(uv);
outSurfaceData.alpha = Alpha(albedoAlpha.a);

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

正在加载...
取消
保存