runes 7 年前
当前提交
da8acc5e
共有 90 个文件被更改,包括 2687 次插入440 次删除
  1. 88
      ScriptableRenderPipeline/Core/Editor/CoreEditorUtils.cs
  2. 69
      ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl
  3. 7
      ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl
  4. 39
      ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl
  5. 2
      ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
  6. 3
      ScriptableRenderPipeline/Core/ShaderLibrary/Macros.hlsl
  7. 50
      ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs.hlsl
  8. 2
      ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.hlsl
  9. 8
      ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs
  10. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDCustomSamplerId.cs
  11. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  12. 2
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader
  13. 1
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop/Deferred.compute
  14. 1
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  15. 41
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl
  16. 188
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  17. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl
  18. 17
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/FragInputs.hlsl
  19. 5
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl
  20. 5
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDistortion.hlsl
  21. 5
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl
  22. 5
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl
  23. 5
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl
  24. 8
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl
  25. 5
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl
  26. 8
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl
  27. 7
      ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs
  28. 4
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute
  29. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute
  30. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader
  31. 42
      ScriptableRenderPipeline/Core/Editor/CoreEditorStyles.cs
  32. 11
      ScriptableRenderPipeline/Core/Editor/CoreEditorStyles.cs.meta
  33. 8
      ScriptableRenderPipeline/Core/Volume.meta
  34. 20
      ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebug.cs.hlsl
  35. 9
      ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebug.cs.hlsl.meta
  36. 46
      ScriptableRenderPipeline/HDRenderPipeline/Debug/MaterialDebug.cs.hlsl
  37. 9
      ScriptableRenderPipeline/HDRenderPipeline/Debug/MaterialDebug.cs.hlsl.meta
  38. 8
      ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution.meta
  39. 8
      ScriptableRenderPipeline/Core/Volume/Editor.meta
  40. 8
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers.meta
  41. 77
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedFloatParameterDrawer.cs
  42. 11
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedFloatParameterDrawer.cs.meta
  43. 77
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedIntParameterDrawer.cs
  44. 11
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedIntParameterDrawer.cs.meta
  45. 21
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ColorParameterDrawer.cs
  46. 11
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ColorParameterDrawer.cs.meta
  47. 42
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/RangeParameterDrawer.cs
  48. 11
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/RangeParameterDrawer.cs.meta
  49. 20
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/Vector4ParameterDrawer.cs
  50. 11
      ScriptableRenderPipeline/Core/Volume/Editor/Drawers/Vector4ParameterDrawer.cs.meta
  51. 57
      ScriptableRenderPipeline/Core/Volume/Editor/SerializedDataParameter.cs
  52. 11
      ScriptableRenderPipeline/Core/Volume/Editor/SerializedDataParameter.cs.meta
  53. 266
      ScriptableRenderPipeline/Core/Volume/Editor/VolumeComponentEditor.cs
  54. 11
      ScriptableRenderPipeline/Core/Volume/Editor/VolumeComponentEditor.cs.meta
  55. 388
      ScriptableRenderPipeline/Core/Volume/Editor/VolumeEditor.cs
  56. 11
      ScriptableRenderPipeline/Core/Volume/Editor/VolumeEditor.cs.meta
  57. 31
      ScriptableRenderPipeline/Core/Volume/Editor/VolumeParameterDrawer.cs
  58. 11
      ScriptableRenderPipeline/Core/Volume/Editor/VolumeParameterDrawer.cs.meta
  59. 11
      ScriptableRenderPipeline/Core/Volume/Volume.cs.meta
  60. 73
      ScriptableRenderPipeline/Core/Volume/VolumeComponent.cs
  61. 11
      ScriptableRenderPipeline/Core/Volume/VolumeComponent.cs.meta
  62. 336
      ScriptableRenderPipeline/Core/Volume/VolumeManager.cs
  63. 11
      ScriptableRenderPipeline/Core/Volume/VolumeManager.cs.meta
  64. 424
      ScriptableRenderPipeline/Core/Volume/VolumeParameter.cs
  65. 11
      ScriptableRenderPipeline/Core/Volume/VolumeParameter.cs.meta
  66. 212
      ScriptableRenderPipeline/Core/Volume/Volume.cs
  67. 14
      ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs
  68. 14
      ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.hlsl
  69. 9
      ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.hlsl.meta
  70. 11
      ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.meta
  71. 113
      ScriptableRenderPipeline/HDRenderPipeline/Sky/README.txt
  72. 8
      ScriptableRenderPipeline/HDRenderPipeline/Sky/README.txt.meta
  73. 9
      ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs.hlsl.meta
  74. 14
      ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs.hlsl
  75. 9
      ScriptableRenderPipeline/HDRenderPipeline/Sky/BlacksmithlSky.meta
  76. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute
  77. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute.meta
  78. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/RuntimeFilterIBL.cs.meta
  79. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader.meta
  80. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/ComputeGgxIblSampleData.compute.meta
  81. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute.meta
  82. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute
  83. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/RuntimeFilterIBL.cs
  84. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader
  85. 0
      /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/ComputeGgxIblSampleData.compute

88
ScriptableRenderPipeline/Core/Editor/CoreEditorUtils.cs


{
public static class CoreEditorUtils
{
// GUIContent cache utilities
static Dictionary<string, GUIContent> s_GUIContentCache = new Dictionary<string, GUIContent>();
public static GUIContent GetContent(string textAndTooltip)
{
if (string.IsNullOrEmpty(textAndTooltip))
return GUIContent.none;
GUIContent content;
if (!s_GUIContentCache.TryGetValue(textAndTooltip, out content))
{
var s = textAndTooltip.Split('|');
content = new GUIContent(s[0]);
if (s.Length > 1 && !string.IsNullOrEmpty(s[1]))
content.tooltip = s[1];
s_GUIContentCache.Add(textAndTooltip, content);
}
return content;
}
// Serialization helpers
public static string FindProperty<T, TValue>(Expression<Func<T, TValue>> expr)
{

}
return state;
}
public static bool DrawHeaderToggle(string title, SerializedProperty group, SerializedProperty activeField, Action<Vector2> contextAction = null)
{
var backgroundRect = GUILayoutUtility.GetRect(1f, 17f);
var labelRect = backgroundRect;
labelRect.xMin += 16f;
labelRect.xMax -= 20f;
var toggleRect = backgroundRect;
toggleRect.y += 2f;
toggleRect.width = 13f;
toggleRect.height = 13f;
// Background rect should be full-width
backgroundRect.xMin = 0f;
backgroundRect.width += 4f;
// Background
float backgroundTint = EditorGUIUtility.isProSkin ? 0.1f : 1f;
EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f));
// Title
using (new EditorGUI.DisabledScope(!activeField.boolValue))
EditorGUI.LabelField(labelRect, GetContent(title), EditorStyles.boldLabel);
// Active checkbox
activeField.serializedObject.Update();
activeField.boolValue = GUI.Toggle(toggleRect, activeField.boolValue, GUIContent.none, CoreEditorStyles.smallTickbox);
activeField.serializedObject.ApplyModifiedProperties();
// Context menu
var menuIcon = EditorGUIUtility.isProSkin
? CoreEditorStyles.paneOptionsIconDark
: CoreEditorStyles.paneOptionsIconLight;
var menuRect = new Rect(labelRect.xMax + 4f, labelRect.y + 4f, menuIcon.width, menuIcon.height);
if (contextAction != null)
GUI.DrawTexture(menuRect, menuIcon);
// Handle events
var e = Event.current;
if (e.type == EventType.MouseDown)
{
if (contextAction != null && menuRect.Contains(e.mousePosition))
{
contextAction(new Vector2(menuRect.x, menuRect.yMax));
e.Use();
}
else if (labelRect.Contains(e.mousePosition))
{
if (e.button == 0)
group.isExpanded = !group.isExpanded;
else if (contextAction != null)
contextAction(e.mousePosition);
e.Use();
}
}
return group.isExpanded;
}
public static void RemoveMaterialKeywords(Material material)

69
ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl


// Specular BRDF
//-----------------------------------------------------------------------------
// With analytical light (not image based light) we clamp the minimun roughness in the NDF to avoid numerical instability.
#define UNITY_MIN_ROUGHNESS 0.002
float ClampRoughnessForAnalyticalLights(float roughness)
{
return max(roughness, UNITY_MIN_ROUGHNESS);
}
float a2 = roughness * roughness;
float f = (NdotH * a2 - NdotH) * NdotH + 1.0;
return a2 / (f * f);
float a2 = Sq(roughness);
float s = (NdotH * a2 - NdotH) * NdotH + 1.0;
return a2 / (s * s);
}
float D_GGX(float NdotH, float roughness)

// tan²(theta) = (1 - cos²(theta)) / cos²(theta) = 1 / cos²(theta) - 1.
// Assume that (VdotH > 0), e.i. (acos(LdotV) < Pi).
float a2 = roughness * roughness;
float z2 = NdotV * NdotV;
return 1 / (0.5 + 0.5 * sqrt(1.0 + a2 * (1.0 / z2 - 1.0)));
return 1.0 / (0.5 + 0.5 * sqrt(1.0 + Sq(roughness) * (1.0 / Sq(NdotV) - 1.0)));
}
// Ref: Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, p. 12.

// Precompute part of lambdaV
float GetSmithJointGGXPartLambdaV(float NdotV, float roughness)
{
float a2 = roughness * roughness;
float a2 = Sq(roughness);
return sqrt((-NdotV * a2 + NdotV) * NdotV + a2);
}

{
float a2 = roughness * roughness;
float a2 = Sq(roughness);
// Original formulation:
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5

// Inline D_GGX() * V_SmithJointGGX() together for better code generation.
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness, float partLambdaV)
{
float a2 = roughness * roughness;
float f = (NdotH * a2 - NdotH) * NdotH + 1.0;
float2 D = float2(a2, f * f); // Fraction without the constant (1/Pi)
float a2 = Sq(roughness);
float s = (NdotH * a2 - NdotH) * NdotH + 1.0;
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5)
float2 D = float2(a2, s * s); // Fraction without the multiplier (1/Pi)
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the multiplier (1/2)
return (INV_PI * 0.5) * (D.x * G.x) / (D.y * G.y);
}

// roughnessB -> roughness in bitangent direction
float D_GGXAnisoNoPI(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
{
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;
float a2 = roughnessT * roughnessB;
float3 v = float3(roughnessB * TdotH, roughnessT * BdotH, a2 * NdotH);
float s = dot(v, v);
float f = TdotH * TdotH / aT2 + BdotH * BdotH / aB2 + NdotH * NdotH;
return 1.0 / (roughnessT * roughnessB * f * f);
return a2 * Sq(a2 / s);
}
float D_GGXAniso(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)

float GetSmithJointGGXAnisoPartLambdaV(float TdotV, float BdotV, float NdotV, float roughnessT, float roughnessB)
{
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;
return sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV);
return length(float3(roughnessT * TdotV, roughnessB * BdotV, NdotV));
}
// Note: V = G / (4 * NdotL * NdotV)

float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;
float lambdaL = NdotV * sqrt(aT2 * TdotL * TdotL + aB2 * BdotL * BdotL + NdotL * NdotL);
float lambdaL = NdotV * length(float3(roughnessT * TdotL, roughnessB * BdotL, NdotL));
return 0.5 / (lambdaV + lambdaL);
}

}
// Inline D_GGXAniso() * V_SmithJointGGXAniso() together for better code generation.
float DV_SmithJointGGXAniso(float TdotH, float BdotH, float NdotH,
float TdotV, float BdotV, float NdotV,
float DV_SmithJointGGXAniso(float TdotH, float BdotH, float NdotH, float NdotV,
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;
float f = TdotH * TdotH / aT2 + BdotH * BdotH / aB2 + NdotH * NdotH;
float2 D = float2(1, roughnessT * roughnessB * f * f); // Fraction without the constant (1/Pi)
float a2 = roughnessT * roughnessB;
float3 v = float3(roughnessB * TdotH, roughnessT * BdotH, a2 * NdotH);
float s = dot(v, v);
float lambdaL = NdotV * sqrt(aT2 * TdotL * TdotL + aB2 * BdotL * BdotL + NdotL * NdotL);
float lambdaL = NdotV * length(float3(roughnessT * TdotL, roughnessB * BdotL, NdotL));
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5)
float2 D = float2(a2 * a2 * a2, s * s); // Fraction without the multiplier (1/Pi)
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the multiplier (1/2)
return (INV_PI * 0.5) * (D.x * G.x) / (D.y * G.y);
}

float roughnessT, float roughnessB)
{
float partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
return DV_SmithJointGGXAniso(TdotH, BdotH, NdotH,
TdotV, BdotV, NdotV,
TdotL, BdotL, NdotL,
return DV_SmithJointGGXAniso(TdotH, BdotH, NdotH, NdotV, TdotL, BdotL, NdotL,
roughnessT, roughnessB, partLambdaV);
}

7
ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl


return float3x3(localX, localY, localZ);
}
float3x3 GetLocalFrame(float3 localZ, float3 localX)
{
float3 localY = cross(localZ, localX);
return float3x3(localX, localY, localZ);
}
// ior is a value between 1.0 and 2.5
float IORToFresnel0(float ior)
{

39
ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl


#define UNITY_COMMON_MATERIAL_INCLUDED
//-----------------------------------------------------------------------------
// Helper function for anisotropy
//-----------------------------------------------------------------------------
void ConvertAnisotropyToRoughness(float roughness, float anisotropy, out float roughnessT, out float roughnessB)
{
// Use the parametrization of Sony Imageworks.
// Ref: Revisiting Physically Based Shading at Imageworks, p. 15.
roughnessT = roughness * (1 + anisotropy);
roughnessB = roughness * (1 - anisotropy);
}
//-----------------------------------------------------------------------------
// Helper function for perceptual roughness
// Helper functions for roughness
//-----------------------------------------------------------------------------
float PerceptualRoughnessToRoughness(float perceptualRoughness)

float PerceptualSmoothnessToPerceptualRoughness(float perceptualSmoothness)
{
return (1.0 - perceptualSmoothness);
}
// Using roughness values of 0 leads to INFs and NANs. The only sensible place to use the roughness
// value of 0 is IBL, so we do not modify the perceptual roughness which is used to select the MIP map level.
// Note: making the constant too small results in aliasing.
float ClampRoughnessForAnalyticalLights(float roughness)
{
return max(roughness, 1.0/1024.0);
}
// 'bsdfData.roughnessT' and 'bsdfData.roughnessB' are clamped, and are meant to be used with analytical lights.
// 'bsdfData.perceptualRoughness' is not clamped, and is meant to be used for IBL.
// If IBL needs the linear roughness value for some reason, it can be computed as follows:
// float roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
void ConvertAnisotropyToRoughness(float perceptualRoughness, float anisotropy, out float roughnessT, out float roughnessB)
{
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
// Use the parametrization of Sony Imageworks.
// Ref: Revisiting Physically Based Shading at Imageworks, p. 15.
roughnessT = roughness * (1 + anisotropy);
roughnessB = roughness * (1 - anisotropy);
roughnessT = ClampRoughnessForAnalyticalLights(roughnessT);
roughnessB = ClampRoughnessForAnalyticalLights(roughnessB);
}
// ----------------------------------------------------------------------------

2
ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl


}
// Prevent NaNs arising from the division of 0 by 0.
cbsdfInt = max(cbsdfInt, FLT_MIN);
cbsdfInt = max(cbsdfInt, FLT_EPS);
return float4(lightInt / cbsdfInt, 1.0);
}

3
ScriptableRenderPipeline/Core/ShaderLibrary/Macros.hlsl


#define LOG2_E 1.44269504088896340736
#define INFINITY asfloat(0x7F800000)
#define FLT_EPS 1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPS != 1.0
#define FLT_EPS 5.960464478e-8 // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1)
#define FLT_NAN asfloat(0xFFFFFFFF)
#define HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats
#define HALF_MAX 65504.0
#define UINT_MAX 0xFFFFFFFFu

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


#ifndef DEBUGDISPLAY_CS_HLSL
#define DEBUGDISPLAY_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.DebugLightingMode: static fields
//
#define DEBUGLIGHTINGMODE_NONE (0)
#define DEBUGLIGHTINGMODE_DIFFUSE_LIGHTING (1)
#define DEBUGLIGHTINGMODE_SPECULAR_LIGHTING (2)
#define DEBUGLIGHTINGMODE_VISUALIZE_CASCADE (3)
#define DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_OCCLUSION_FROM_SSAO (4)
#define DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_GTAO_FROM_SSAO (5)
#define DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_OCCLUSION_FROM_SSAO (6)
#define DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_GTAO_FROM_SSAO (7)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewVarying: static fields
//
#define DEBUGVIEWVARYING_NONE (0)
#define DEBUGVIEWVARYING_TEXCOORD0 (1)
#define DEBUGVIEWVARYING_TEXCOORD1 (2)
#define DEBUGVIEWVARYING_TEXCOORD2 (3)
#define DEBUGVIEWVARYING_TEXCOORD3 (4)
#define DEBUGVIEWVARYING_VERTEX_TANGENT_WS (5)
#define DEBUGVIEWVARYING_VERTEX_BITANGENT_WS (6)
#define DEBUGVIEWVARYING_VERTEX_NORMAL_WS (7)
#define DEBUGVIEWVARYING_VERTEX_COLOR (8)
#define DEBUGVIEWVARYING_VERTEX_COLOR_ALPHA (9)
#define DEBUGVIEWVARYING_LAST (10)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewGbuffer: static fields
//
#define DEBUGVIEWGBUFFER_NONE (0)
#define DEBUGVIEWGBUFFER_DEPTH (10)
#define DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING_WITH_ALBEDO_PLUS_EMISSIVE (11)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK0 (12)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK1 (13)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK2 (14)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK3 (15)
#define DEBUGVIEWGBUFFER_LAST (16)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewProperties: static fields
//
#define DEBUGVIEWPROPERTIES_NONE (0)
#define DEBUGVIEWPROPERTIES_TESSELLATION (16)
#define DEBUGVIEWPROPERTIES_PIXEL_DISPLACEMENT (17)
#define DEBUGVIEWPROPERTIES_VERTEX_DISPLACEMENT (18)
#define DEBUGVIEWPROPERTIES_TESSELLATION_DISPLACEMENT (19)
#define DEBUGVIEWPROPERTIES_DEPTH_OFFSET (20)
#define DEBUGVIEWPROPERTIES_LIGHTMAP (21)
//
// UnityEngine.Experimental.Rendering.HDPipeline.FullScreenDebugMode: static fields
//
#define FULLSCREENDEBUGMODE_NONE (0)

2
ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.hlsl


#define UNITY_DEBUG_DISPLAY_INCLUDED
#include "DebugDisplay.cs.hlsl"
#include "MaterialDebug.cs.hlsl"
#include "LightingDebug.cs.hlsl"
// Set of parameters available when switching to debug shader mode
int _DebugLightingMode; // Match enum DebugLightingMode

8
ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs


class DoCreateNewAssetCommonSettings : DoCreateNewAsset<CommonSettings> {}
class DoCreateNewAssetHDRISkySettings : DoCreateNewAsset<HDRISkySettings> {}
class DoCreateNewAssetBlacksmithSkySettings : DoCreateNewAsset<BlacksmithSkySettings> {}
class DoCreateNewAssetProceduralSkySettings : DoCreateNewAsset<ProceduralSkySettings> {}
class DoCreateNewAssetSubsurfaceScatteringSettings : DoCreateNewAsset<SubsurfaceScatteringSettings> {}

{
var icon = EditorGUIUtility.FindTexture("ScriptableObject Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAssetHDRISkySettings>(), "New HDRISkySettings.asset", icon, null);
}
[MenuItem("Assets/Create/Render Pipeline/High Definition/BlacksmithSky Settings", priority = CoreUtils.assetCreateMenuPriority2)]
static void MenuCreateBlacksmithSkySettings()
{
var icon = EditorGUIUtility.FindTexture("ScriptableObject Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAssetBlacksmithSkySettings>(), "New BlacksmithSkySettings.asset", icon, null);
}
[MenuItem("Assets/Create/Render Pipeline/High Definition/ProceduralSky Settings", priority = CoreUtils.assetCreateMenuPriority2)]

3
ScriptableRenderPipeline/HDRenderPipeline/HDCustomSamplerId.cs


TPDisplayShadows,
TPRenderDeferredLighting,
// Misc
VolumeUpdate,
Max
}
}

6
ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


else
{
m_CurrentDebugDisplaySettings = m_DebugDisplaySettings;
using (new ProfilingSample(cmd, "Volume Update", GetSampler(CustomSamplerId.VolumeUpdate)))
{
// TODO: Transform & layer should be configurable per camera
VolumeManager.instance.Update(camera.transform, -1);
}
}
ApplyDebugDisplaySettings(cmd);

2
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader


Outputs outputs;
#ifdef OUTPUT_SPLIT_LIGHTING
if (_EnableSSSAndTransmission != 0)
if (_EnableSSSAndTransmission != 0 && bsdfData.materialId == MATERIALID_LIT_SSS)
{
outputs.specularLighting = float4(specularLighting, 1.0);
outputs.diffuseLighting = TagLightingForSSS(diffuseLighting);

1
ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop/Deferred.compute


#pragma kernel Deferred_Indirect_ShadowMask_Fptl_Variant25 SHADE_OPAQUE_ENTRY=Deferred_Indirect_ShadowMask_Fptl_Variant25 USE_INDIRECT SHADOWS_SHADOWMASK VARIANT=25
#pragma kernel Deferred_Indirect_ShadowMask_Fptl_Variant26 SHADE_OPAQUE_ENTRY=Deferred_Indirect_ShadowMask_Fptl_Variant26 USE_INDIRECT SHADOWS_SHADOWMASK VARIANT=26
#define LIGHTLOOP_TILE_PASS 1
// deferred opaque always use FPTL
#define USE_FPTL_LIGHTLIST 1

1
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs


[SurfaceDataAttributes("", true)]
public Vector3 normalWS;
public float perceptualRoughness;
public float roughness;
public int materialId;
// MaterialId dependent attribute

41
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl


#define DEBUGVIEW_LIT_BSDFDATA_SPECULAR_OCCLUSION (1032)
#define DEBUGVIEW_LIT_BSDFDATA_NORMAL_WS (1033)
#define DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS (1034)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS (1035)
#define DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID (1036)
#define DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS (1037)
#define DEBUGVIEW_LIT_BSDFDATA_BITANGENT_WS (1038)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_T (1039)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B (1040)
#define DEBUGVIEW_LIT_BSDFDATA_ANISOTROPY (1041)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_RADIUS (1042)
#define DEBUGVIEW_LIT_BSDFDATA_THICKNESS (1043)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_PROFILE (1044)
#define DEBUGVIEW_LIT_BSDFDATA_ENABLE_TRANSMISSION (1045)
#define DEBUGVIEW_LIT_BSDFDATA_USE_THIN_OBJECT_MODE (1046)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE (1047)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_NORMAL_WS (1048)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_COVERAGE (1049)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_IOR (1050)
#define DEBUGVIEW_LIT_BSDFDATA_IOR (1051)
#define DEBUGVIEW_LIT_BSDFDATA_ABSORPTION_COEFFICIENT (1052)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE_MASK (1053)
#define DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID (1035)
#define DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS (1036)
#define DEBUGVIEW_LIT_BSDFDATA_BITANGENT_WS (1037)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_T (1038)
#define DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B (1039)
#define DEBUGVIEW_LIT_BSDFDATA_ANISOTROPY (1040)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_RADIUS (1041)
#define DEBUGVIEW_LIT_BSDFDATA_THICKNESS (1042)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_PROFILE (1043)
#define DEBUGVIEW_LIT_BSDFDATA_ENABLE_TRANSMISSION (1044)
#define DEBUGVIEW_LIT_BSDFDATA_USE_THIN_OBJECT_MODE (1045)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE (1046)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_NORMAL_WS (1047)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_COVERAGE (1048)
#define DEBUGVIEW_LIT_BSDFDATA_COAT_IOR (1049)
#define DEBUGVIEW_LIT_BSDFDATA_IOR (1050)
#define DEBUGVIEW_LIT_BSDFDATA_ABSORPTION_COEFFICIENT (1051)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE_MASK (1052)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+GBufferMaterial: static fields

float specularOcclusion;
float3 normalWS;
float perceptualRoughness;
float roughness;
int materialId;
float3 tangentWS;
float3 bitangentWS;

break;
case DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS:
result = bsdfdata.perceptualRoughness.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS:
result = bsdfdata.roughness.xxx;
break;
case DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID:
result = GetIndexColor(bsdfdata.materialId);

188
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


#endif
// Use Lambert diffuse instead of Disney diffuse
// #define LIT_DIFFUSE_LAMBERT_BRDF
// Use optimization of Precomputing LambdaV
// TODO: Test if this is a win
// #define LIT_USE_BSDF_PRE_LAMBDAV
#define LIT_USE_GGX_ENERGY_COMPENSATION
// Sampler use by area light, gaussian pyramid, ambient occlusion etc...

bsdfData.fresnel0 = lerp(val.xxx, baseColor, metallic);
}
void FillMaterialIdAnisoData(float roughness, float3 normalWS, float3 tangentWS, float anisotropy, inout BSDFData bsdfData)
{
bsdfData.tangentWS = tangentWS;
bsdfData.bitangentWS = cross(normalWS, tangentWS);
ConvertAnisotropyToRoughness(roughness, anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
bsdfData.anisotropy = anisotropy;
}
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = SKIN_SPECULAR_VALUE; // TODO take from subsurfaceProfile instead
bsdfData.subsurfaceProfile = subsurfaceProfile;
bsdfData.subsurfaceRadius = subsurfaceRadius;
bsdfData.thickness = _ThicknessRemaps[subsurfaceProfile].x + _ThicknessRemaps[subsurfaceProfile].y * thickness;
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = SKIN_SPECULAR_VALUE; // TODO take from subsurfaceProfile instead
bsdfData.subsurfaceProfile = subsurfaceProfile;
bsdfData.subsurfaceRadius = subsurfaceRadius;
bsdfData.thickness = _ThicknessRemaps[subsurfaceProfile].x + _ThicknessRemaps[subsurfaceProfile].y * thickness;
bsdfData.enableTransmission = _EnableSSSAndTransmission != 0;
bsdfData.useThinObjectMode = true; // Do not displace the point of BSDF evaluation
bsdfData.enableTransmission = _EnableSSSAndTransmission != 0 && transmissionMode != SSS_TRSM_MODE_NONE;
if (bsdfData.enableTransmission)
if (bsdfData.enableTransmission && transmissionMode != SSS_TRSM_MODE_NONE)
{
bsdfData.useThinObjectMode = transmissionMode == SSS_TRSM_MODE_THIN;

BSDFData bsdfData;
ZERO_INITIALIZE(BSDFData, bsdfData);
bsdfData.specularOcclusion = surfaceData.specularOcclusion;
bsdfData.normalWS = surfaceData.normalWS;
bsdfData.materialId = surfaceData.materialId;
bsdfData.specularOcclusion = surfaceData.specularOcclusion;
bsdfData.normalWS = surfaceData.normalWS;
bsdfData.anisotropy = surfaceData.anisotropy;
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
bsdfData.materialId = surfaceData.materialId;
ConvertAnisotropyToRoughness(bsdfData.perceptualRoughness, bsdfData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
if (surfaceData.materialId != MATERIALID_LIT_ANISO)
{

else if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
FillMaterialIdStandardData(surfaceData.baseColor, surfaceData.metallic, bsdfData);
FillMaterialIdAnisoData(bsdfData.roughness, surfaceData.normalWS, surfaceData.tangentWS, surfaceData.anisotropy, bsdfData);
bsdfData.tangentWS = surfaceData.tangentWS;
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
}
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT)
{

bsdfData.normalWS = UnpackNormalOctEncode(float2(inGBuffer1.r, inGBuffer1.g));
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
// The material features system for material classification must allow compile time optimization (i.e everything should be static)
// Note that as we store materialId for Aniso based on content of RT2 we need to add few extra condition.
// The code is also call from MaterialFeatureFlagsFromGBuffer, so must work fully dynamic if featureFlags is UINT_MAX

// If the tile has anisotropy, all the pixels within the tile are evaluated as anisotropic.
if (HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_ANISO))
{
float anisotropy;
float3 tangentWS;
bsdfData.anisotropy = 0;
bsdfData.tangentWS = GetLocalFrame(bsdfData.normalWS)[0];
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{

tangentWS = UnpackNormalOctEncode(inGBuffer2.rg);
anisotropy = inGBuffer2.b * 2 - 1;
bsdfData.anisotropy = inGBuffer2.b * 2 - 1;
bsdfData.tangentWS = UnpackNormalOctEncode(inGBuffer2.rg);
else
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
}
ConvertAnisotropyToRoughness(bsdfData.perceptualRoughness, bsdfData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
if (HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS))
{
float subsurfaceRadius = 0;
float thickness = 0;
int subsurfaceProfile = SSS_NEUTRAL_PROFILE_ID;
if (bsdfData.materialId == MATERIALID_LIT_SSS)
anisotropy = 0;
tangentWS = GetLocalFrame(bsdfData.normalWS)[0];
subsurfaceRadius = inGBuffer2.x;
thickness = inGBuffer2.y;
subsurfaceProfile = UnpackByte(inGBuffer2.w);
FillMaterialIdAnisoData(bsdfData.roughness, bsdfData.normalWS, tangentWS, anisotropy, bsdfData);
FillMaterialIdSSSData(baseColor, subsurfaceProfile, subsurfaceRadius, thickness, bsdfData);
}
if (bsdfData.materialId == MATERIALID_LIT_STANDARD && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_STANDARD))

UnpackFloatInt8bit(inGBuffer2.a, 4.0, metallic, materialIdExtent);
if (materialIdExtent == GBUFFER_LIT_STANDARD_SPECULAR_COLOR_ID)
[flatten] if (materialIdExtent == GBUFFER_LIT_STANDARD_SPECULAR_COLOR_ID)
{
// Note: Specular is not a material id but just a way to parameterize the standard materialid, thus we reset materialId to MATERIALID_LIT_STANDARD
// For material classification it will be consider as Standard as well, thus no need to create special case

FillMaterialIdStandardData(baseColor, metallic, bsdfData);
}
}
else if (bsdfData.materialId == MATERIALID_LIT_SSS && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS))
{
float subsurfaceRadius = inGBuffer2.x;
float thickness = inGBuffer2.y;
int subsurfaceProfile = UnpackByte(inGBuffer2.w);
FillMaterialIdSSSData(baseColor, subsurfaceProfile, subsurfaceRadius, thickness, bsdfData);
}
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{
// We have swap the encoding of the normal to have more precision for coat normal as it is more smooth

// GGX
float partLambdaV;
float energyCompensation;
float TdotV;
float BdotV;
float3 coatV;
float3 refractV; // The view vector refracted through clear coat interface
// IBL

NdotV = saturate(dot(N, V));
preLightData.NdotV = NdotV;
float3 iblR;
float3 iblN, iblR;
preLightData.TdotV = dot(bsdfData.tangentWS, V);
preLightData.BdotV = dot(bsdfData.bitangentWS, V);
preLightData.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, bsdfData.roughnessT, bsdfData.roughnessB);
float TdotV = dot(bsdfData.tangentWS, V);
float BdotV = dot(bsdfData.bitangentWS, V);
preLightData.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, bsdfData.roughnessT, bsdfData.roughnessB);
// For GGX aniso and IBL we have done an empirical (eye balled) approximation compare to the reference.
// We use a single fetch, and we stretch the normal to use based on various criteria.

// NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NdotV) and use 'anisoIblNormalWS'
// into function like GetSpecularDominantDir(). However modified normal is just a hack. The goal is just to stretch a cubemap, no accuracy here.
// With this in mind and for performance reasons we chose to only use modified normal to calculate R.
float3 anisoIblNormalWS = GetAnisotropicModifiedNormal(grainDirWS, N, V, stretch);
iblR = reflect(-V, anisoIblNormalWS);
iblN = GetAnisotropicModifiedNormal(grainDirWS, N, V, stretch);
preLightData.TdotV = 0;
preLightData.BdotV = 0;
preLightData.partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, bsdfData.roughness);
iblR = reflect(-V, N);
preLightData.partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, bsdfData.roughnessT);
iblN = N;
iblR = reflect(-V, iblN);
float reflectivity;
// IBL

else
{
// Note: this is a ad-hoc tweak.
float iblRoughness, iblPerceptualRoughness;
if (bsdfData.materialId == MATERIALID_LIT_ANISO && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_ANISO))
{
// Use the min roughness, and bias it for higher values of anisotropy and roughness.
float roughnessBias = 0.075 * bsdfData.anisotropy * bsdfData.roughness;
iblRoughness = saturate(min(bsdfData.roughnessT, bsdfData.roughnessB) + roughnessBias);
iblPerceptualRoughness = RoughnessToPerceptualRoughness(iblRoughness);
}
else
{
iblRoughness = bsdfData.roughness;
iblPerceptualRoughness = bsdfData.perceptualRoughness;
}
preLightData.iblDirWS = GetSpecularDominantDir(N, iblR, iblRoughness, NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(iblPerceptualRoughness);
// TODO: we need a better hack.
float iblPerceptualRoughness = bsdfData.perceptualRoughness * saturate(1.2 - bsdfData.anisotropy);
float iblRoughness = PerceptualRoughnessToRoughness(iblPerceptualRoughness);
preLightData.iblDirWS = GetSpecularDominantDir(N, iblR, iblRoughness, NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(iblPerceptualRoughness);
}
#ifdef LIT_USE_GGX_ENERGY_COMPENSATION

// But rough metals (black diffuse) still scatter quite a lot of light around, so
// we want to take some of that into account too.
lightTransportData.diffuseColor = bsdfData.diffuseColor + bsdfData.fresnel0 * bsdfData.roughness * 0.5 * surfaceData.metallic;
float roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
lightTransportData.diffuseColor = bsdfData.diffuseColor + bsdfData.fresnel0 * roughness * 0.5 * surfaceData.metallic;
lightTransportData.emissiveColor = builtinData.emissiveColor;
return lightTransportData;

float BdotH = dot(bsdfData.bitangentWS, H);
float BdotL = dot(bsdfData.bitangentWS, L);
bsdfData.roughnessT = ClampRoughnessForAnalyticalLights(bsdfData.roughnessT);
bsdfData.roughnessB = ClampRoughnessForAnalyticalLights(bsdfData.roughnessB);
DV = DV_SmithJointGGXAniso(TdotH, BdotH, NdotH,
preLightData.TdotV, preLightData.BdotV, preLightData.NdotV,
TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData.partLambdaV);
#else
);
#endif
DV = DV_SmithJointGGXAniso(TdotH, BdotH, NdotH, NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, preLightData.partLambdaV);
bsdfData.roughness = ClampRoughnessForAnalyticalLights(bsdfData.roughness);
DV = DV_SmithJointGGX(NdotH, NdotL, NdotV, bsdfData.roughness
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData partLambdaV);
#else
);
#endif
DV = DV_SmithJointGGX(NdotH, NdotL, NdotV, bsdfData.roughnessT, preLightData.partLambdaV);
}
specularLighting += F * DV;

float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
float roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, roughness);
#else
// A note on subsurface scattering: [SSS-NOTE-TRSM]
// The correct way to handle SSS is to transmit light inside the surface, perform SSS,

float3 positionLS = mul(lighToSample, transpose(lightToWorld));
float2 positionCS = positionLS.xy;
bool isInBounds;
// Tile the texture if the 'repeat' wrap mode is enabled.
bool isInBounds = lightData.tileCookie || max(abs(positionCS.x), abs(positionCS.y)) <= 1.0;
float2 positionNDC = positionCS * 0.5 + 0.5;
float2 positionNDC = frac(positionCS * 0.5 + 0.5);
if (lightData.tileCookie)
{
// Tile the texture if the 'repeat' wrap mode is enabled.
positionNDC = frac(positionNDC);
isInBounds = true;
}
else
{
isInBounds = Max3(abs(positionCS.x), abs(positionCS.y), 1.0 - positionLS.z) <= 1.0;
}
// We let the sampler handle tiling or clamping to border.
// Note: tiling (the repeat mode) is not currently supported.
// We let the sampler handle clamping to border.
float4 cookie = SampleCookie2D(lightLoopContext, positionNDC, lightData.cookieIndex);
cookie.a = isInBounds ? cookie.a : 0;

[branch] if (intensity > 0.0)
{
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual light have a radius with this hack
// Simulate a sphere light with this hack.
bsdfData.roughnessT = max(bsdfData.roughnessT, lightData.minRoughness);
bsdfData.roughnessB = max(bsdfData.roughnessB, lightData.minRoughness);
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);
lighting.diffuse *= intensity * lightData.diffuseScale;

// TODO: factor this code in common, so other material authoring don't require to rewrite everything,
// TODO: test the strech from Tomasz
// float shrinkedRoughness = AnisotropicStrechAtGrazingAngle(bsdfData.roughness, bsdfData.perceptualRoughness, NdotV);
// float roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
// float shrunkRoughness = AnisotropicStrechAtGrazingAngle(roughness, roughness, NdotV);
// Guideline for reflection volume: In HDRenderPipeline we separate the projection volume (the proxy of the scene) from the influence volume (what pixel on the screen is affected)
// However we add the constrain that the shape of the projection and influence volume is the same (i.e if we have a sphere shape projection volume, we have a shape influence).

bakeDiffuseLighting *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), indirectAmbientOcclusion);
#endif
float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, indirectAmbientOcclusion, bsdfData.roughness);
float roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, indirectAmbientOcclusion, roughness);
// Try to mimic multibounce with specular color. Not the point of the original formula but ok result.
// Take the min of screenspace specular occlusion and visibility cone specular occlusion
#if GTAO_MULTIBOUNCE_APPROX

}
else if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_OCCLUSION_FROM_SSAO)
{
diffuseLighting = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, indirectAmbientOcclusion, bsdfData.roughness);
diffuseLighting = specularOcclusion;
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
#if GTAO_MULTIBOUNCE_APPROX

2
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl


}
else
{
ImportanceSampleGGX(u, V, localToWorld, bsdfData.roughness, NdotV, L, VdotH, NdotL, weightOverPdf);
ImportanceSampleGGX(u, V, localToWorld, bsdfData.roughnessT, NdotV, L, VdotH, NdotL, weightOverPdf);
}
if (NdotL > 0.0)

17
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/FragInputs.hlsl


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

// For two sided lighting
bool isFrontFace;
};
// FragInputs use dir vector that are normalized in the code even if not used
// so we initialize them to a valid != 0 to shutdown compiler warning
FragInputs InitializeFragInputs()
{
FragInputs output;
ZERO_INITIALIZE(FragInputs, output);
// Init to some default value to make the computer quiet (else it output "divide by zero" warning even if value is not used).
output.worldToTangent[0] = float3(1, 0, 0);
output.worldToTangent[1] = float3(0, 1, 0);
output.worldToTangent[2] = float3(0, 0, 1);
return output;
}
void GetVaryingsDataDebug(uint paramId, FragInputs input, inout float3 result, inout bool needLinearToSRGB)
{

5
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl


// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
#ifdef VARYINGS_NEED_POSITION_WS
#else
float3 V = 0; // Avoid the division by 0
#endif
SurfaceData surfaceData;
BuiltinData builtinData;

5
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDistortion.hlsl


// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
#ifdef VARYINGS_NEED_POSITION_WS
#else
float3 V = 0; // Avoid the division by 0
#endif
// Perform alpha testing + get distortion
SurfaceData surfaceData;

5
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl


// 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);
#ifdef VARYINGS_NEED_POSITION_WS
#else
float3 V = 0; // Avoid the division by 0
#endif
SurfaceData surfaceData;
BuiltinData builtinData;

5
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl


// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
#ifdef VARYINGS_NEED_POSITION_WS
#else
float3 V = 0; // Avoid the division by 0
#endif
SurfaceData surfaceData;
BuiltinData builtinData;

5
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl


// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
#ifdef VARYINGS_NEED_POSITION_WS
#else
float3 V = 0; // Avoid the division by 0
#endif
SurfaceData surfaceData;
BuiltinData builtinData;

8
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl


// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
// No position and depth in case of light transport
float3 V = float3(0.0, 0.0, 1.0); // No vector view in case of light transport
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);
#else
float3 V = 0; // Avoid the division by 0
#endif
SurfaceData surfaceData;
BuiltinData builtinData;

5
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl


// input.positionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw);
UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput);
#ifdef VARYINGS_NEED_POSITION_WS
#else
float3 V = 0; // Avoid the division by 0
#endif
// Perform alpha testing + get velocity
SurfaceData surfaceData;

8
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl


FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input)
{
FragInputs output = InitializeFragInputs();
FragInputs output;
ZERO_INITIALIZE(FragInputs, output);
// Init to some default value to make the computer quiet (else it output "divide by zero" warning even if value is not used).
// TODO: this is a really poor workaround, but the variable is used in a bunch of places
// to compute normals which are then passed on elsewhere to compute other values...
output.worldToTangent = k_identity3x3;
output.positionSS = input.positionCS; // input.positionCS is SV_Position

7
ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs


//SkyResolution4096 = 4096
}
[GenerateHLSL(PackingRules.Exact)]
public enum LightSamplingParameters
{
TextureHeight = 256,
TextureWidth = 512
}
public enum EnvironementUpdateMode
{
OnChanged = 0,

4
ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute


#pragma kernel DeferredDirectionalShadow
#include "ShaderLibrary/Common.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../Lighting/Lighting.hlsl"
#include "../ShaderVariables.hlsl"
#include "Lighting.hlsl"
RWTexture2D<float4> _DeferredShadowTextureUAV;
float _DirectionalShadowIndex;

2
ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute


GroupMemoryBarrierWithGroupSync(); \
\
/* Prevent NaNs arising from the division of 0 by 0. */ \
sum = max(temp[SHARED_MEM(n - 1)], FLT_MIN); \
sum = max(temp[SHARED_MEM(n - 1)], FLT_EPS); \
\
GroupMemoryBarrierWithGroupSync(); \
\

2
ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader


#include "ShaderLibrary/Common.hlsl"
#include "ShaderLibrary/ImageBasedLighting.hlsl"
#include "SkyManager.cs.hlsl"
#include "GGXConvolution.cs.hlsl"
TEXTURECUBE(_MainTex);
SAMPLERCUBE(sampler_MainTex);

42
ScriptableRenderPipeline/Core/Editor/CoreEditorStyles.cs


using UnityEngine;
namespace UnityEditor.Experimental.Rendering
{
public static class CoreEditorStyles
{
public static readonly GUIStyle smallTickbox;
public static readonly GUIStyle miniLabelButton;
public static readonly Texture2D paneOptionsIconDark;
public static readonly Texture2D paneOptionsIconLight;
static CoreEditorStyles()
{
smallTickbox = new GUIStyle("ShurikenCheckMark");
var transparentTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false);
transparentTexture.SetPixel(0, 0, Color.clear);
transparentTexture.Apply();
miniLabelButton = new GUIStyle(EditorStyles.miniLabel);
miniLabelButton.normal = new GUIStyleState
{
background = transparentTexture,
scaledBackgrounds = null,
textColor = Color.grey
};
var activeState = new GUIStyleState
{
background = transparentTexture,
scaledBackgrounds = null,
textColor = Color.white
};
miniLabelButton.active = activeState;
miniLabelButton.onNormal = activeState;
miniLabelButton.onActive = activeState;
paneOptionsIconDark = (Texture2D)EditorGUIUtility.Load("Builtin Skins/DarkSkin/Images/pane options.png");
paneOptionsIconLight = (Texture2D)EditorGUIUtility.Load("Builtin Skins/LightSkin/Images/pane options.png");
}
}
}

11
ScriptableRenderPipeline/Core/Editor/CoreEditorStyles.cs.meta


fileFormatVersion: 2
guid: 106fd77ef6b30234597e56c849578bad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
ScriptableRenderPipeline/Core/Volume.meta


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

20
ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebug.cs.hlsl


//
// This file was automatically generated. Please don't edit by hand.
//
#ifndef LIGHTINGDEBUG_CS_HLSL
#define LIGHTINGDEBUG_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.DebugLightingMode: static fields
//
#define DEBUGLIGHTINGMODE_NONE (0)
#define DEBUGLIGHTINGMODE_DIFFUSE_LIGHTING (1)
#define DEBUGLIGHTINGMODE_SPECULAR_LIGHTING (2)
#define DEBUGLIGHTINGMODE_VISUALIZE_CASCADE (3)
#define DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_OCCLUSION_FROM_SSAO (4)
#define DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_GTAO_FROM_SSAO (5)
#define DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_OCCLUSION_FROM_SSAO (6)
#define DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_GTAO_FROM_SSAO (7)
#endif

9
ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebug.cs.hlsl.meta


fileFormatVersion: 2
guid: ac1ebeb5a5a2fed418218ce6b347e221
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

46
ScriptableRenderPipeline/HDRenderPipeline/Debug/MaterialDebug.cs.hlsl


//
// This file was automatically generated. Please don't edit by hand.
//
#ifndef MATERIALDEBUG_CS_HLSL
#define MATERIALDEBUG_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewVarying: static fields
//
#define DEBUGVIEWVARYING_NONE (0)
#define DEBUGVIEWVARYING_TEXCOORD0 (1)
#define DEBUGVIEWVARYING_TEXCOORD1 (2)
#define DEBUGVIEWVARYING_TEXCOORD2 (3)
#define DEBUGVIEWVARYING_TEXCOORD3 (4)
#define DEBUGVIEWVARYING_VERTEX_TANGENT_WS (5)
#define DEBUGVIEWVARYING_VERTEX_BITANGENT_WS (6)
#define DEBUGVIEWVARYING_VERTEX_NORMAL_WS (7)
#define DEBUGVIEWVARYING_VERTEX_COLOR (8)
#define DEBUGVIEWVARYING_VERTEX_COLOR_ALPHA (9)
#define DEBUGVIEWVARYING_LAST (10)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewGbuffer: static fields
//
#define DEBUGVIEWGBUFFER_NONE (0)
#define DEBUGVIEWGBUFFER_DEPTH (10)
#define DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING_WITH_ALBEDO_PLUS_EMISSIVE (11)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK0 (12)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK1 (13)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK2 (14)
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK3 (15)
#define DEBUGVIEWGBUFFER_LAST (16)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewProperties: static fields
//
#define DEBUGVIEWPROPERTIES_NONE (0)
#define DEBUGVIEWPROPERTIES_TESSELLATION (16)
#define DEBUGVIEWPROPERTIES_PIXEL_DISPLACEMENT (17)
#define DEBUGVIEWPROPERTIES_VERTEX_DISPLACEMENT (18)
#define DEBUGVIEWPROPERTIES_TESSELLATION_DISPLACEMENT (19)
#define DEBUGVIEWPROPERTIES_DEPTH_OFFSET (20)
#define DEBUGVIEWPROPERTIES_LIGHTMAP (21)
#endif

9
ScriptableRenderPipeline/HDRenderPipeline/Debug/MaterialDebug.cs.hlsl.meta


fileFormatVersion: 2
guid: cce0374c3f91d32489d7ce55fcbf8d2e
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

8
ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution.meta


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

8
ScriptableRenderPipeline/Core/Volume/Editor.meta


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

8
ScriptableRenderPipeline/Core/Volume/Editor/Drawers.meta


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

77
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedFloatParameterDrawer.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering
{
[VolumeParameterDrawer(typeof(ClampedFloatParameter))]
sealed class ClampedFloatParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
if (value.propertyType != SerializedPropertyType.Float)
return false;
var o = parameter.GetObjectRef<ClampedFloatParameter>();
if (o.clampMode == ParameterClampMode.MinMax)
{
EditorGUILayout.Slider(value, o.min, o.max, title);
value.floatValue = Mathf.Clamp(value.floatValue, o.min, o.max);
}
else if (o.clampMode == ParameterClampMode.Min)
{
float v = EditorGUILayout.FloatField(title, value.floatValue);
value.floatValue = Mathf.Max(v, o.min);
}
else if (o.clampMode == ParameterClampMode.Max)
{
float v = EditorGUILayout.FloatField(title, value.floatValue);
value.floatValue = Mathf.Min(v, o.max);
}
else
{
return false;
}
return true;
}
}
[VolumeParameterDrawer(typeof(InstantClampedFloatParameter))]
sealed class InstantClampedFloatParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
if (value.propertyType != SerializedPropertyType.Float)
return false;
var o = parameter.GetObjectRef<InstantClampedFloatParameter>();
if (o.clampMode == ParameterClampMode.MinMax)
{
EditorGUILayout.Slider(value, o.min, o.max, title);
value.floatValue = Mathf.Clamp(value.floatValue, o.min, o.max);
}
else if (o.clampMode == ParameterClampMode.Min)
{
float v = EditorGUILayout.FloatField(title, value.floatValue);
value.floatValue = Mathf.Max(v, o.min);
}
else if (o.clampMode == ParameterClampMode.Max)
{
float v = EditorGUILayout.FloatField(title, value.floatValue);
value.floatValue = Mathf.Min(v, o.max);
}
else
{
return false;
}
return true;
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedFloatParameterDrawer.cs.meta


fileFormatVersion: 2
guid: f9816364c4bdf314db38db52fc67a3f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

77
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedIntParameterDrawer.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering
{
[VolumeParameterDrawer(typeof(ClampedIntParameter))]
sealed class ClampedIntParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
if (value.propertyType != SerializedPropertyType.Integer)
return false;
var o = parameter.GetObjectRef<ClampedIntParameter>();
if (o.clampMode == ParameterClampMode.MinMax)
{
EditorGUILayout.IntSlider(value, o.min, o.max, title);
value.intValue = Mathf.Clamp(value.intValue, o.min, o.max);
}
else if (o.clampMode == ParameterClampMode.Min)
{
int v = EditorGUILayout.IntField(title, value.intValue);
value.intValue = Mathf.Max(v, o.min);
}
else if (o.clampMode == ParameterClampMode.Max)
{
int v = EditorGUILayout.IntField(title, value.intValue);
value.intValue = Mathf.Min(v, o.max);
}
else
{
return false;
}
return true;
}
}
[VolumeParameterDrawer(typeof(InstantClampedIntParameter))]
sealed class InstantClampedIntParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
if (value.propertyType != SerializedPropertyType.Integer)
return false;
var o = parameter.GetObjectRef<InstantClampedIntParameter>();
if (o.clampMode == ParameterClampMode.MinMax)
{
EditorGUILayout.IntSlider(value, o.min, o.max, title);
value.intValue = Mathf.Clamp(value.intValue, o.min, o.max);
}
else if (o.clampMode == ParameterClampMode.Min)
{
int v = EditorGUILayout.IntField(title, value.intValue);
value.intValue = Mathf.Max(v, o.min);
}
else if (o.clampMode == ParameterClampMode.Max)
{
int v = EditorGUILayout.IntField(title, value.intValue);
value.intValue = Mathf.Min(v, o.max);
}
else
{
return false;
}
return true;
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedIntParameterDrawer.cs.meta


fileFormatVersion: 2
guid: 6d2f589334fbc8444b30925a405106d8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

21
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ColorParameterDrawer.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering
{
[VolumeParameterDrawer(typeof(ColorParameter))]
sealed class ColorParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
if (value.propertyType != SerializedPropertyType.Color)
return false;
var o = parameter.GetObjectRef<ColorParameter>();
value.colorValue = EditorGUILayout.ColorField(title, value.colorValue, o.showEyeDropper, o.showAlpha, o.showAlpha);
return true;
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ColorParameterDrawer.cs.meta


fileFormatVersion: 2
guid: 34ad702e46732ff438113b62a10ae80e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

42
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/RangeParameterDrawer.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering
{
[VolumeParameterDrawer(typeof(RangeParameter))]
sealed class RangeParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
if (value.propertyType != SerializedPropertyType.Vector2)
return false;
var o = parameter.GetObjectRef<RangeParameter>();
var v = value.vector2Value;
// The layout system breaks alignement when mixing inspector fields with custom layouted
// fields as soon as a scrollbar is needed in the inspector, so we'll do the layout
// manually instead
const int kFloatFieldWidth = 50;
const int kSeparatorWidth = 5;
float indentOffset = EditorGUI.indentLevel * 15f;
var lineRect = GUILayoutUtility.GetRect(1, EditorGUIUtility.singleLineHeight);
lineRect.xMin += 4f;
lineRect.y += 2f;
var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset, lineRect.height);
var floatFieldLeft = new Rect(labelRect.xMax, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height);
var sliderRect = new Rect(floatFieldLeft.xMax + kSeparatorWidth - indentOffset, lineRect.y, lineRect.width - labelRect.width - kFloatFieldWidth * 2 - kSeparatorWidth * 2, lineRect.height);
var floatFieldRight = new Rect(sliderRect.xMax + kSeparatorWidth - indentOffset, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height);
EditorGUI.PrefixLabel(labelRect, title);
v.x = EditorGUI.FloatField(floatFieldLeft, v.x);
EditorGUI.MinMaxSlider(sliderRect, ref v.x, ref v.y, o.min, o.max);
v.y = EditorGUI.FloatField(floatFieldRight, v.y);
value.vector2Value = v;
return true;
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/RangeParameterDrawer.cs.meta


fileFormatVersion: 2
guid: 54ad01bd6d555e0438e364d8b0f17e06
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

20
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/Vector4ParameterDrawer.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering
{
[VolumeParameterDrawer(typeof(Vector4Parameter))]
sealed class Vector4ParametrDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
if (value.propertyType != SerializedPropertyType.Vector4)
return false;
value.vector4Value = EditorGUILayout.Vector4Field(title, value.vector4Value);
return true;
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/Drawers/Vector4ParameterDrawer.cs.meta


fileFormatVersion: 2
guid: 9c51e2ea627a393478d0b5c2a086136d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

57
ScriptableRenderPipeline/Core/Volume/Editor/SerializedDataParameter.cs


using System;
using System.Linq;
using System.Reflection;
using UnityEngine.Assertions;
namespace UnityEditor.Experimental.Rendering
{
public sealed class SerializedDataParameter
{
public SerializedProperty overrideState { get; private set; }
public SerializedProperty value { get; private set; }
public Attribute[] attributes { get; private set; }
public Type referenceType { get; private set; }
SerializedProperty m_BaseProperty;
object m_ReferenceValue;
public string displayName
{
get { return m_BaseProperty.displayName; }
}
internal SerializedDataParameter(SerializedProperty property)
{
// Find the actual property type, optional attributes & reference
var path = property.propertyPath.Split('.');
object obj = property.serializedObject.targetObject;
FieldInfo field = null;
foreach (var p in path)
{
field = obj.GetType().GetField(p, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
obj = field.GetValue(obj);
}
Assert.IsNotNull(field);
m_BaseProperty = property.Copy();
overrideState = m_BaseProperty.FindPropertyRelative("m_OverrideState");
value = m_BaseProperty.FindPropertyRelative("m_Value");
attributes = field.GetCustomAttributes(false).Cast<Attribute>().ToArray();
referenceType = obj.GetType();
m_ReferenceValue = obj;
}
public T GetAttribute<T>()
where T : Attribute
{
return (T)attributes.FirstOrDefault(x => x is T);
}
public T GetObjectRef<T>()
{
return (T)m_ReferenceValue;
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/SerializedDataParameter.cs.meta


fileFormatVersion: 2
guid: abf61146103c4444290de1048016607b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

266
ScriptableRenderPipeline/Core/Volume/Editor/VolumeComponentEditor.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class VolumeComponentEditorAttribute : Attribute
{
public readonly Type componentType;
public VolumeComponentEditorAttribute(Type componentType)
{
this.componentType = componentType;
}
}
public class VolumeComponentEditor
{
internal VolumeComponent target { get; private set; }
internal SerializedObject serializedObject { get; private set; }
internal SerializedProperty baseProperty;
internal SerializedProperty activeProperty;
Editor m_Inspector;
List<SerializedDataParameter> m_Parameters;
static Dictionary<Type, VolumeParameterDrawer> s_ParameterDrawers;
static VolumeComponentEditor()
{
s_ParameterDrawers = new Dictionary<Type, VolumeParameterDrawer>();
ReloadDecoratorTypes();
}
[Callbacks.DidReloadScripts]
static void OnEditorReload()
{
ReloadDecoratorTypes();
}
static void ReloadDecoratorTypes()
{
s_ParameterDrawers.Clear();
// Look for all the valid parameter drawers
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(
a => a.GetTypes()
.Where(
t => t.IsSubclassOf(typeof(VolumeParameterDrawer))
&& t.IsDefined(typeof(VolumeParameterDrawerAttribute), false)
)
);
// Store them
foreach (var type in types)
{
var attr = (VolumeParameterDrawerAttribute)type.GetCustomAttributes(typeof(VolumeParameterDrawerAttribute), false)[0];
var decorator = (VolumeParameterDrawer)Activator.CreateInstance(type);
s_ParameterDrawers.Add(attr.parameterType, decorator);
}
}
public void Repaint()
{
m_Inspector.Repaint();
}
internal void Init(VolumeComponent target, Editor inspector)
{
this.target = target;
m_Inspector = inspector;
serializedObject = new SerializedObject(target);
activeProperty = serializedObject.FindProperty("active");
OnEnable();
}
public virtual void OnEnable()
{
m_Parameters = new List<SerializedDataParameter>();
// Grab all valid serializable field on the VolumeComponent
var fields = target.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(t => t.FieldType.IsSubclassOf(typeof(VolumeParameter)))
.Where(t =>
(t.IsPublic && t.GetCustomAttributes(typeof(NonSerializedAttribute), false).Length == 0) ||
(t.GetCustomAttributes(typeof(SerializeField), false).Length > 0)
)
.Where(t => t.GetCustomAttributes(typeof(HideInInspector), false).Length == 0)
.ToList();
// Prepare all serialized objects for this editor
foreach (var field in fields)
{
var property = serializedObject.FindProperty(field.Name);
var parameter = new SerializedDataParameter(property);
m_Parameters.Add(parameter);
}
}
public virtual void OnDisable()
{
}
internal void OnInternalInspectorGUI()
{
serializedObject.Update();
TopRowFields();
OnInspectorGUI();
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
}
public virtual void OnInspectorGUI()
{
// Display every field as-is
foreach (var parameter in m_Parameters)
PropertyField(parameter);
}
public virtual string GetDisplayTitle()
{
return ObjectNames.NicifyVariableName(target.GetType().Name);
}
void TopRowFields()
{
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button(CoreEditorUtils.GetContent("All|Toggle all overrides on. To maximize performances you should only toggle overrides that you actually need."), CoreEditorStyles.miniLabelButton, GUILayout.Width(17f), GUILayout.ExpandWidth(false)))
SetAllOverridesTo(true);
if (GUILayout.Button(CoreEditorUtils.GetContent("None|Toggle all overrides off."), CoreEditorStyles.miniLabelButton, GUILayout.Width(32f), GUILayout.ExpandWidth(false)))
SetAllOverridesTo(false);
GUILayout.FlexibleSpace();
}
}
internal void SetAllOverridesTo(bool state)
{
Undo.RecordObject(target, "Toggle All");
target.SetAllOverridesTo(state);
serializedObject.Update();
}
// Takes a serialized VolumeParameter<T> as input
protected SerializedDataParameter Unpack(SerializedProperty property)
{
Assert.IsNotNull(property);
return new SerializedDataParameter(property);
}
protected void PropertyField(SerializedDataParameter property)
{
var title = CoreEditorUtils.GetContent(property.displayName);
PropertyField(property, title);
}
protected void PropertyField(SerializedDataParameter property, GUIContent title)
{
// Handle unity built-in decorators (Space, Header, Tooltip etc)
foreach (var attr in property.attributes)
{
if (attr is PropertyAttribute)
{
if (attr is SpaceAttribute)
{
EditorGUILayout.GetControlRect(false, (attr as SpaceAttribute).height);
}
else if (attr is HeaderAttribute)
{
var rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight);
rect.y += 0f;
rect = EditorGUI.IndentedRect(rect);
EditorGUI.LabelField(rect, (attr as HeaderAttribute).header, EditorStyles.miniLabel);
}
else if (attr is TooltipAttribute)
{
if (string.IsNullOrEmpty(title.tooltip))
title.tooltip = (attr as TooltipAttribute).tooltip;
}
}
}
// Custom parameter drawer
VolumeParameterDrawer drawer;
s_ParameterDrawers.TryGetValue(property.referenceType, out drawer);
bool invalidProp = false;
if (drawer != null && !drawer.IsAutoProperty())
{
if (drawer.OnGUI(property, title))
return;
invalidProp = true;
}
// ObjectParameter<T> is a special case
if (VolumeParameter.IsObjectParameter(property.referenceType))
{
bool expanded = property.value.isExpanded;
expanded = EditorGUILayout.Foldout(expanded, title, true);
if (expanded)
{
EditorGUI.indentLevel++;
// Not the fastest way to do it but that'll do just fine for now
var it = property.value.Copy();
var end = it.GetEndProperty();
bool first = true;
while (it.Next(first) && !SerializedProperty.EqualContents(it, end))
{
PropertyField(Unpack(it));
first = false;
}
EditorGUI.indentLevel--;
}
property.value.isExpanded = expanded;
return;
}
using (new EditorGUILayout.HorizontalScope())
{
// Override checkbox
var overrideRect = GUILayoutUtility.GetRect(17f, 17f, GUILayout.ExpandWidth(false));
overrideRect.yMin += 4f;
overrideRect.xMin += EditorGUI.indentLevel * 15f;
DrawOverrideCheckbox(overrideRect, property.overrideState);
// Property
using (new EditorGUI.DisabledScope(!property.overrideState.boolValue))
{
if (drawer != null && !invalidProp)
{
if (drawer.OnGUI(property, title))
return;
}
// Default unity field
EditorGUILayout.PropertyField(property.value, title);
}
}
}
void DrawOverrideCheckbox(Rect rect, SerializedProperty property)
{
var oldColor = GUI.color;
GUI.color = new Color(0.6f, 0.6f, 0.6f, 0.75f);
property.boolValue = GUI.Toggle(rect, property.boolValue, CoreEditorUtils.GetContent("|Override this setting for this volume."), CoreEditorStyles.smallTickbox);
GUI.color = oldColor;
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/VolumeComponentEditor.cs.meta


fileFormatVersion: 2
guid: d6bb22372ebe2bc42a227c8f8c1795ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

388
ScriptableRenderPipeline/Core/Volume/Editor/VolumeEditor.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering
{
[CustomEditor(typeof(Volume))]
public sealed class VolumeEditor : Editor
{
SerializedProperty m_IsGlobal;
SerializedProperty m_BlendRadius;
SerializedProperty m_Weight;
SerializedProperty m_Priority;
SerializedProperty m_Components;
Dictionary<Type, Type> m_EditorTypes; // Component type => Editor type
List<VolumeComponentEditor> m_Editors;
static VolumeComponent s_ClipboardContent;
Volume actualTarget
{
get { return target as Volume; }
}
void OnEnable()
{
var o = new PropertyFetcher<Volume>(serializedObject);
m_IsGlobal = o.Find(x => x.isGlobal);
m_BlendRadius = o.Find(x => x.blendDistance);
m_Weight = o.Find(x => x.weight);
m_Priority = o.Find(x => x.priority);
m_Components = o.Find(x => x.components);
m_EditorTypes = new Dictionary<Type, Type>();
m_Editors = new List<VolumeComponentEditor>();
// Gets the list of all available component editors
var editorTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(
a => a.GetTypes()
.Where(
t => t.IsSubclassOf(typeof(VolumeComponentEditor))
&& t.IsDefined(typeof(VolumeComponentEditorAttribute), false)
)
).ToList();
// Map them to their corresponding component type
foreach (var editorType in editorTypes)
{
var attribute = (VolumeComponentEditorAttribute)editorType.GetCustomAttributes(typeof(VolumeComponentEditorAttribute), false)[0];
m_EditorTypes.Add(attribute.componentType, editorType);
}
// Create editors for existing components
var components = actualTarget.components;
for (int i = 0; i < components.Count; i++)
CreateEditor(components[i], m_Components.GetArrayElementAtIndex(i));
// Keep track of undo/redo to redraw the inspector when that happens
Undo.undoRedoPerformed += OnUndoRedoPerformed;
}
void OnDisable()
{
Undo.undoRedoPerformed -= OnUndoRedoPerformed;
if (m_Editors == null)
return; // Hasn't been inited yet
foreach (var editor in m_Editors)
editor.OnDisable();
m_Editors.Clear();
m_EditorTypes.Clear();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
if (actualTarget.isDirty)
{
RefreshEditors();
actualTarget.isDirty = false;
}
using (var scope = new EditorGUILayout.VerticalScope())
{
EditorGUILayout.PropertyField(m_IsGlobal);
if (!m_IsGlobal.boolValue) // Blend radius is not needed for global volumes
{
EditorGUILayout.PropertyField(m_BlendRadius);
m_BlendRadius.floatValue = Mathf.Max(m_BlendRadius.floatValue, 0f);
}
EditorGUILayout.PropertyField(m_Weight);
EditorGUILayout.PropertyField(m_Priority);
EditorGUILayout.Space();
// Component list
for (int i = 0; i < m_Editors.Count; i++)
{
var editor = m_Editors[i];
string title = editor.GetDisplayTitle();
int id = i; // Needed for closure capture below
CoreEditorUtils.DrawSplitter();
bool displayContent = CoreEditorUtils.DrawHeaderToggle(
title,
editor.baseProperty,
editor.activeProperty,
pos => OnContextClick(pos, editor.target, id)
);
if (displayContent)
{
using (new EditorGUI.DisabledScope(!editor.activeProperty.boolValue))
editor.OnInternalInspectorGUI();
}
}
if (m_Editors.Count > 0)
CoreEditorUtils.DrawSplitter();
else
EditorGUILayout.HelpBox("No override set on this volume.", MessageType.Info);
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
//if (GUILayout.Button(CoreEditorUtils.GetContent("Add Component"), GUILayout.Width(230f), GUILayout.Height(24f)))
//{
//}
GUILayout.FlexibleSpace();
}
// Handle components drag'n'drop
var e = Event.current;
if (e.type == EventType.DragUpdated)
{
if (IsDragValid(scope.rect, e.mousePosition))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Link;
e.Use();
}
else
{
DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
}
}
else if (e.type == EventType.DragPerform)
{
if (IsDragValid(scope.rect, e.mousePosition))
{
DragAndDrop.AcceptDrag();
var objs = DragAndDrop.objectReferences;
foreach (var o in objs)
{
var compType = ((MonoScript)o).GetClass();
AddComponent(compType);
}
e.Use();
}
}
}
serializedObject.ApplyModifiedProperties();
}
bool IsDragValid(Rect rect, Vector2 mousePos)
{
if (!rect.Contains(mousePos))
return false;
var objs = DragAndDrop.objectReferences;
foreach (var o in objs)
{
if (o.GetType() != typeof(MonoScript))
return false;
var script = (MonoScript)o;
var scriptType = script.GetClass();
if (!scriptType.IsSubclassOf(typeof(VolumeComponent)))
return false;
if (actualTarget.components.Exists(t => t.GetType() == scriptType))
return false;
}
return true;
}
void RefreshEditors()
{
// Disable all editors first
foreach (var editor in m_Editors)
editor.OnDisable();
// Remove them
m_Editors.Clear();
// Recreate editors for existing settings, if any
for (int i = 0; i < actualTarget.components.Count; i++)
CreateEditor(actualTarget.components[i], m_Components.GetArrayElementAtIndex(i));
}
// index is only used when we need to re-create a component in a specific spot (e.g. reset)
void CreateEditor(VolumeComponent settings, SerializedProperty property, int index = -1)
{
var settingsType = settings.GetType();
Type editorType;
if (!m_EditorTypes.TryGetValue(settingsType, out editorType))
editorType = typeof(VolumeComponentEditor);
var editor = (VolumeComponentEditor)Activator.CreateInstance(editorType);
editor.Init(settings, this);
editor.baseProperty = property.Copy();
if (index < 0)
m_Editors.Add(editor);
else
m_Editors[index] = editor;
}
void AddComponent(Type type)
{
serializedObject.Update();
var component = (VolumeComponent)CreateInstance(type);
Undo.RegisterCreatedObjectUndo(component, "Add Volume Component");
// Grow the list first, then add - that's how serialized lists work in Unity
m_Components.arraySize++;
var effectProp = m_Components.GetArrayElementAtIndex(m_Components.arraySize - 1);
effectProp.objectReferenceValue = component;
// Create & store the internal editor object for this effect
CreateEditor(component, effectProp);
serializedObject.ApplyModifiedProperties();
}
void RemoveComponent(int id)
{
// Huh. Hack to keep foldout state on the next element...
bool nextFoldoutState = false;
if (id < m_Editors.Count - 1)
nextFoldoutState = m_Editors[id + 1].baseProperty.isExpanded;
// Remove from the cached editors list
m_Editors[id].OnDisable();
m_Editors.RemoveAt(id);
serializedObject.Update();
var property = m_Components.GetArrayElementAtIndex(id);
var effect = property.objectReferenceValue;
// Unassign it (should be null already but serialization does funky things
property.objectReferenceValue = null;
// ...and remove the array index itself from the list
m_Components.DeleteArrayElementAtIndex(id);
// Finally refresh editor reference to the serialized settings list
for (int i = 0; i < m_Editors.Count; i++)
m_Editors[i].baseProperty = m_Components.GetArrayElementAtIndex(i).Copy();
// Set the proper foldout state if needed
if (id < m_Editors.Count)
m_Editors[id].baseProperty.isExpanded = nextFoldoutState;
serializedObject.ApplyModifiedProperties();
// Destroy the setting object after ApplyModifiedProperties(). If we do it before, redo
// actions will be in the wrong order and the reference to the setting object in the
// list will be lost.
Undo.DestroyObjectImmediate(effect);
}
// Reset is done by deleting and removing the object from the list and adding a new one in
// the same spot as it was before
void ResetComponent(Type type, int id)
{
// Remove from the cached editors list
m_Editors[id].OnDisable();
m_Editors[id] = null;
serializedObject.Update();
var property = m_Components.GetArrayElementAtIndex(id);
var prevSettings = property.objectReferenceValue;
// Unassign it but down remove it from the array to keep the index available
property.objectReferenceValue = null;
// Create a new object
var newEffect = (VolumeComponent)CreateInstance(type);
Undo.RegisterCreatedObjectUndo(newEffect, "Reset Volume Component");
// Put it in the reserved space
property.objectReferenceValue = newEffect;
// Create & store the internal editor object for this effect
CreateEditor(newEffect, property, id);
serializedObject.ApplyModifiedProperties();
// Same as RemoveComponent, destroy at the end so it's recreated first on Undo to make
// sure the GUID exists before undoing the list state
Undo.DestroyObjectImmediate(prevSettings);
}
void OnContextClick(Vector2 position, VolumeComponent targetComponent, int id)
{
var menu = new GenericMenu();
menu.AddItem(CoreEditorUtils.GetContent("Reset"), false, () => ResetComponent(targetComponent.GetType(), id));
menu.AddItem(CoreEditorUtils.GetContent("Remove"), false, () => RemoveComponent(id));
menu.AddSeparator(string.Empty);
menu.AddItem(CoreEditorUtils.GetContent("Copy Settings"), false, () => CopySettings(targetComponent));
if (CanPaste(targetComponent))
menu.AddItem(CoreEditorUtils.GetContent("Paste Settings"), false, () => PasteSettings(targetComponent));
else
menu.AddDisabledItem(CoreEditorUtils.GetContent("Paste Settings"));
menu.AddSeparator(string.Empty);
menu.AddItem(CoreEditorUtils.GetContent("Toggle All"), false, () => m_Editors[id].SetAllOverridesTo(true));
menu.AddItem(CoreEditorUtils.GetContent("Toggle None"), false, () => m_Editors[id].SetAllOverridesTo(false));
menu.DropDown(new Rect(position, Vector2.zero));
}
// Copy/pasting is simply done by creating an in memory copy of the selected component and
// copying over the serialized data to another; it doesn't use nor affect the OS clipboard
bool CanPaste(VolumeComponent targetComponent)
{
return s_ClipboardContent != null
&& s_ClipboardContent.GetType() == targetComponent.GetType();
}
void CopySettings(VolumeComponent targetComponent)
{
if (s_ClipboardContent != null)
{
CoreUtils.Destroy(s_ClipboardContent);
s_ClipboardContent = null;
}
s_ClipboardContent = (VolumeComponent)CreateInstance(targetComponent.GetType());
EditorUtility.CopySerializedIfDifferent(targetComponent, s_ClipboardContent);
}
void PasteSettings(VolumeComponent targetComponent)
{
Assert.IsNotNull(s_ClipboardContent);
Assert.AreEqual(s_ClipboardContent.GetType(), targetComponent.GetType());
Undo.RecordObject(targetComponent, "Paste Settings");
EditorUtility.CopySerializedIfDifferent(s_ClipboardContent, targetComponent);
}
void OnUndoRedoPerformed()
{
actualTarget.isDirty = true;
// Dumb hack to make sure the serialized object is up to date on undo
serializedObject.Update();
serializedObject.ApplyModifiedProperties();
// Seems like there's an issue with the inspector not repainting after some undo events
// This will take care of that
Repaint();
}
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/VolumeEditor.cs.meta


fileFormatVersion: 2
guid: 9a033a261241d6e48af8ca011ab7c5c1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

31
ScriptableRenderPipeline/Core/Volume/Editor/VolumeParameterDrawer.cs


using System;
using UnityEngine;
namespace UnityEditor.Experimental.Rendering
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class VolumeParameterDrawerAttribute : Attribute
{
public readonly Type parameterType;
public VolumeParameterDrawerAttribute(Type parameterType)
{
this.parameterType = parameterType;
}
}
// Default parameter drawer - simply displays the serialized property as Unity would
public abstract class VolumeParameterDrawer
{
// Override this and return false if you want to customize the override checkbox position,
// else it'll automatically draw it and put the property content in a horizontal scope.
public virtual bool IsAutoProperty()
{
return true;
}
// Return false is the input parameter is invalid - unity will display the default editor
// for this control then
public abstract bool OnGUI(SerializedDataParameter parameter, GUIContent title);
}
}

11
ScriptableRenderPipeline/Core/Volume/Editor/VolumeParameterDrawer.cs.meta


fileFormatVersion: 2
guid: d8ce10b4215bd81438b65f7e23ac0946
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
ScriptableRenderPipeline/Core/Volume/Volume.cs.meta


fileFormatVersion: 2
guid: 172515602e62fb746b5d573b38a5fe58
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

73
ScriptableRenderPipeline/Core/Volume/VolumeComponent.cs


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Linq;
namespace UnityEngine.Experimental.Rendering
{
[Serializable]
public class VolumeComponent : ScriptableObject
{
// Used to control the state of this override - handy to quickly turn a volume override
// on & off in the editor
public bool active = true;
internal ReadOnlyCollection<VolumeParameter> parameters { get; private set; }
void OnEnable()
{
// Automatically grab all fields of type VolumeParameter for this instance
parameters = this.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(t => t.FieldType.IsSubclassOf(typeof(VolumeParameter)))
.OrderBy(t => t.MetadataToken) // Guaranteed order
.Select(t => (VolumeParameter)t.GetValue(this))
.ToList()
.AsReadOnly();
}
public void SetAllOverridesTo(bool state)
{
SetAllOverridesTo(parameters, state);
}
void SetAllOverridesTo(IEnumerable<VolumeParameter> enumerable, bool state)
{
foreach (var prop in enumerable)
{
prop.overrideState = state;
var t = prop.GetType();
if (VolumeParameter.IsObjectParameter(t))
{
// This method won't be called a lot but this is sub-optimal, fix me
var innerParams = (ReadOnlyCollection<VolumeParameter>)
t.GetProperty("parameters", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(prop, null);
if (innerParams != null)
SetAllOverridesTo(innerParams, state);
}
}
}
// Custom hashing function used to compare the state of settings (it's not meant to be
// unique but to be a quick way to check if two setting sets have the same state or not).
// Hash collision rate should be pretty low.
public override int GetHashCode()
{
unchecked
{
//return parameters.Aggregate(17, (i, p) => i * 23 + p.GetHash());
int hash = 17;
foreach (var p in parameters)
hash = hash * 23 + p.GetHashCode();
return hash;
}
}
}
}

11
ScriptableRenderPipeline/Core/Volume/VolumeComponent.cs.meta


fileFormatVersion: 2
guid: 556096baecf4aeb4e9f0d3efce77e08f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

336
ScriptableRenderPipeline/Core/Volume/VolumeManager.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.Assertions;
namespace UnityEngine.Experimental.Rendering
{
public sealed class VolumeManager
{
//>>> System.Lazy<T> is broken in Unity (legacy runtime) so we'll have to do it ourselves :|
static volatile VolumeManager s_Instance;
static object s_LockObj = new Object();
public static VolumeManager instance
{
get
{
// Double-lock checking
if (s_Instance == null)
{
lock (s_LockObj) // Lock on a separate object to avoid deadlocks
{
if (s_Instance == null)
s_Instance = new VolumeManager();
}
}
return s_Instance;
}
}
//<<<
// Max amount of layers available in Unity
const int k_MaxLayerCount = 32;
// List of all volumes (sorted by priority) per layer
readonly List<Volume>[] m_Volumes;
// Keep track of sorting states for all layers
readonly bool[] m_SortNeeded;
// Internal state of all component types
readonly Dictionary<Type, VolumeComponent> m_Components;
// Internal list of default state for each component type - this is used to reset component
// states on update instead of having to implement a Reset method on all components (which
// would be error-prone)
readonly List<VolumeComponent> m_ComponentsDefaultState;
// Recycled list used for volume traversal
readonly List<Collider> m_TempColliders;
// In the editor, when entering play-mode, it will call the constructor and OnEditorReload()
// which in turn will call ReloadBaseTypes() twice, so we need to keep track of the reloads
// to avoid wasting any more CPU than required
static bool s_StopReloads = false;
VolumeManager()
{
m_Volumes = new List<Volume>[k_MaxLayerCount];
m_SortNeeded = new bool[k_MaxLayerCount];
m_TempColliders = new List<Collider>(8);
m_Components = new Dictionary<Type, VolumeComponent>();
m_ComponentsDefaultState = new List<VolumeComponent>();
ReloadBaseTypes();
}
#if UNITY_EDITOR
// Called every time Unity recompiles scripts in the editor. We need this to keep track of
// any new custom component the user might add to the project.
[UnityEditor.Callbacks.DidReloadScripts]
static void OnEditorReload()
{
if (!s_StopReloads)
instance.ReloadBaseTypes();
s_StopReloads = false;
}
#endif
// This will be called only once at runtime and everytime script reload kicks-in in the
// editor as we need to keep track of any compatible component in the project
void ReloadBaseTypes()
{
// Clean component map & default states
foreach (var component in m_Components)
CoreUtils.Destroy(component.Value);
foreach (var component in m_ComponentsDefaultState)
CoreUtils.Destroy(component);
m_Components.Clear();
m_ComponentsDefaultState.Clear();
// Rebuild it from scratch
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(
a => a.GetTypes()
.Where(
t => t.IsSubclassOf(typeof(VolumeComponent))
)
);
foreach (var type in types)
{
// We need two instances, one for global state tracking and another one to keep a
// default state that will act as the lowest priority global volume (so that we have
// a state to fallback to when exiting volumes)
var inst = (VolumeComponent)ScriptableObject.CreateInstance(type);
m_Components.Add(type, inst);
inst = (VolumeComponent)ScriptableObject.CreateInstance(type);
inst.SetAllOverridesTo(true);
m_ComponentsDefaultState.Add(inst);
}
s_StopReloads = true;
}
public T GetComponent<T>()
where T : VolumeComponent
{
var comp = GetComponent(typeof(T));
return (T)comp;
}
public VolumeComponent GetComponent(Type type)
{
VolumeComponent comp;
m_Components.TryGetValue(type, out comp);
Assert.IsNotNull(comp, "Component map is corrupted, \"" + type + "\" not found");
return comp;
}
public void Register(Volume volume, int layer)
{
var volumes = m_Volumes[layer];
if (volumes == null)
{
volumes = new List<Volume>();
m_Volumes[layer] = volumes;
}
Assert.IsFalse(volumes.Contains(volume), "Volume has already been registered");
volumes.Add(volume);
SetLayerDirty(layer);
}
public void Unregister(Volume volume, int layer)
{
var volumes = m_Volumes[layer];
if (volumes == null)
return;
volumes.Remove(volume);
}
internal void SetLayerDirty(int layer)
{
Assert.IsTrue(layer >= 0 && layer <= k_MaxLayerCount, "Invalid layer bit");
m_SortNeeded[layer] = true;
}
internal void UpdateVolumeLayer(Volume volume, int prevLayer, int newLayer)
{
Assert.IsTrue(prevLayer >= 0 && prevLayer <= k_MaxLayerCount, "Invalid layer bit");
Unregister(volume, prevLayer);
Register(volume, newLayer);
}
// Go through all listed components and lerp overriden values in the global state
void OverrideData(List<VolumeComponent> components, float interpFactor)
{
foreach (var component in components)
{
if (!component.active)
continue;
var target = GetComponent(component.GetType());
int count = component.parameters.Count;
for (int i = 0; i < count; i++)
{
var toParam = component.parameters[i];
if (toParam.overrideState)
{
var fromParam = target.parameters[i];
fromParam.Interp(fromParam, toParam, interpFactor);
}
}
}
}
// Faster version of OverrideData to force replace values in the global state
void ReplaceData(List<VolumeComponent> components)
{
foreach (var component in components)
{
var target = GetComponent(component.GetType());
int count = component.parameters.Count;
for (int i = 0; i < count; i++)
target.parameters[i].SetValue(component.parameters[i]);
}
}
// Update the global state - should be called once per frame in the update loop before
// anything else
public void Update(Transform trigger, LayerMask layerMask)
{
#if UNITY_EDITOR
// Editor specific hack to work around serialization doing funky things when exiting
// play mode -> re-create the world when bad things happen
if (m_ComponentsDefaultState == null
|| (m_ComponentsDefaultState.Count > 0 && m_ComponentsDefaultState[0] == null))
{
ReloadBaseTypes();
}
else
#endif
{
// Start by resetting the global state to default values
ReplaceData(m_ComponentsDefaultState);
}
// Do magic
bool onlyGlobal = trigger == null;
int mask = layerMask.value;
var triggerPos = onlyGlobal ? Vector3.zero : trigger.position;
for (int i = 0; i < k_MaxLayerCount; i++)
{
// Skip layers not in the mask
if ((mask & (1 << i)) == 0)
continue;
// Skip empty layers
var volumes = m_Volumes[i];
if (volumes == null)
continue;
// Sort the volume list if needed
if (m_SortNeeded[i])
{
SortByPriority(volumes);
m_SortNeeded[i] = false;
}
// Traverse all volumes
foreach (var volume in volumes)
{
// Skip disabled volumes and volumes without any data or weight
if (!volume.enabled || volume.weight <= 0f)
continue;
var components = volume.components;
// Global volumes always have influence
if (volume.isGlobal)
{
OverrideData(components, Mathf.Clamp01(volume.weight));
continue;
}
if (onlyGlobal)
continue;
// If volume isn't global and has no collider, skip it as it's useless
var colliders = m_TempColliders;
volume.GetComponents(colliders);
if (colliders.Count == 0)
continue;
// Find closest distance to volume, 0 means it's inside it
float closestDistanceSqr = float.PositiveInfinity;
foreach (var collider in colliders)
{
if (!collider.enabled)
continue;
var closestPoint = collider.ClosestPoint(triggerPos);
var d = (closestPoint - triggerPos).sqrMagnitude;
if (d < closestDistanceSqr)
closestDistanceSqr = d;
}
colliders.Clear();
float blendDistSqr = volume.blendDistance * volume.blendDistance;
// Volume has no influence, ignore it
// Note: Volume doesn't do anything when `closestDistanceSqr = blendDistSqr` but
// we can't use a >= comparison as blendDistSqr could be set to 0 in which
// case volume would have total influence
if (closestDistanceSqr > blendDistSqr)
continue;
// Volume has influence
float interpFactor = 1f;
if (blendDistSqr > 0f)
interpFactor = 1f - (closestDistanceSqr / blendDistSqr);
// No need to clamp01 the interpolation factor as it'll always be in [0;1[ range
OverrideData(components, interpFactor * Mathf.Clamp01(volume.weight));
}
}
}
// Stable insertion sort. Faster than List<T>.Sort() for our needs.
static void SortByPriority(List<Volume> volumes)
{
Assert.IsNotNull(volumes, "Trying to sort volumes of non-initialized layer");
for (int i = 1; i < volumes.Count; i++)
{
var temp = volumes[i];
int j = i - 1;
// Sort order is ascending
while (j >= 0 && volumes[j].priority > temp.priority)
{
volumes[j + 1] = volumes[j];
j--;
}
volumes[j + 1] = temp;
}
}
}
}

11
ScriptableRenderPipeline/Core/Volume/VolumeManager.cs.meta


fileFormatVersion: 2
guid: f709aacbf8d0b0048889f52315d67d58
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

424
ScriptableRenderPipeline/Core/Volume/VolumeParameter.cs


using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
namespace UnityEngine.Experimental.Rendering
{
// We need this base class to be able to store a list of VolumeParameter in collections as we
// can't store VolumeParameter<T> with variable T types in the same collection. As a result some
// of the following is a bit hacky...
public abstract class VolumeParameter
{
[SerializeField]
protected bool m_OverrideState;
public virtual bool overrideState
{
get { return m_OverrideState; }
set { m_OverrideState = value; }
}
internal abstract void Interp(VolumeParameter from, VolumeParameter to, float t);
public T GetValue<T>()
{
return ((VolumeParameter<T>)this).value;
}
internal abstract void SetValue(VolumeParameter parameter);
public static bool IsObjectParameter(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ObjectParameter<>))
return true;
return type.BaseType != null
&& IsObjectParameter(type.BaseType);
}
}
[Serializable]
public class VolumeParameter<T> : VolumeParameter
{
[SerializeField]
protected T m_Value;
public virtual T value
{
get { return m_Value; }
set { m_Value = value; }
}
public VolumeParameter()
: this(default(T), false)
{
}
protected VolumeParameter(T value, bool overrideState)
{
m_Value = value;
this.overrideState = overrideState;
}
internal override void Interp(VolumeParameter from, VolumeParameter to, float t)
{
// Note: this is relatively unsafe (assumes that from and to are both holding type T)
Interp(from.GetValue<T>(), to.GetValue<T>(), t);
}
public virtual void Interp(T from, T to, float t)
{
// Returns `b` if `dt > 0` by default so we don't have to write overrides for bools and
// enumerations.
m_Value = t > 0f ? to : from;
}
public void Override(T x)
{
overrideState = true;
m_Value = x;
}
internal override void SetValue(VolumeParameter parameter)
{
m_Value = parameter.GetValue<T>();
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + overrideState.GetHashCode();
hash = hash * 23 + value.GetHashCode();
return hash;
}
}
//
// Implicit conversion; assuming the following:
//
// var myFloatProperty = new ParameterOverride<float> { value = 42f; };
//
// It allows for implicit casts:
//
// float myFloat = myFloatProperty.value; // No implicit cast
// float myFloat = myFloatProperty; // Implicit cast
//
// For safety reason this is one-way only.
//
public static implicit operator T(VolumeParameter<T> prop)
{
return prop.m_Value;
}
}
public enum ParameterClampMode
{
Min,
Max,
MinMax
}
//
// The serialization system in Unity can't serialize generic types, the workaround is to extend
// and flatten pre-defined generic types.
// For enums it's recommended to make your own types on the spot, like so:
//
// [Serializable]
// public sealed class MyEnumParameter : VolumeParameter<MyEnum> { }
// public enum MyEnum { One, Two }
//
[Serializable]
public sealed class BoolParameter : VolumeParameter<bool> { }
[Serializable]
public sealed class IntParameter : VolumeParameter<int>
{
public override void Interp(int from, int to, float t)
{
// Int snapping interpolation. Don't use this for enums as they don't necessarily have
// contiguous values. Use the default interpolator instead (same as bool).
m_Value = (int)(from + (to - from) * t);
}
}
[Serializable]
public sealed class InstantIntParameter : VolumeParameter<int> { }
[Serializable]
public sealed class ClampedIntParameter : VolumeParameter<int>
{
public ParameterClampMode clampMode = ParameterClampMode.MinMax;
public int min = 0;
public int max = 10;
public override int value
{
get { return m_Value; }
set
{
switch (clampMode)
{
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break;
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break;
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break;
}
}
}
public override void Interp(int from, int to, float t)
{
m_Value = (int)(from + (to - from) * t);
}
}
[Serializable]
public sealed class InstantClampedIntParameter : VolumeParameter<int>
{
public ParameterClampMode clampMode = ParameterClampMode.MinMax;
public int min = 0;
public int max = 10;
public override int value
{
get { return m_Value; }
set
{
switch (clampMode)
{
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break;
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break;
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break;
}
}
}
}
[Serializable]
public sealed class FloatParameter : VolumeParameter<float>
{
public override void Interp(float from, float to, float t)
{
m_Value = from + (to - from) * t;
}
}
[Serializable]
public sealed class InstantFloatParameter : VolumeParameter<float> { }
[Serializable]
public sealed class ClampedFloatParameter : VolumeParameter<float>
{
public ParameterClampMode clampMode = ParameterClampMode.MinMax;
public float min = 0f;
public float max = 1f;
public override float value
{
get { return m_Value; }
set
{
switch (clampMode)
{
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break;
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break;
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break;
}
}
}
// We could override FloatParameter here but that would require making it not-sealed which
// will stop the compiler from doing specific optimizations on virtual methods - considering
// how often float is used, duplicating the code in this case is a definite win
public override void Interp(float from, float to, float t)
{
m_Value = from + (to - from) * t;
}
}
[Serializable]
public sealed class InstantClampedFloatParameter : VolumeParameter<float>
{
public ParameterClampMode clampMode = ParameterClampMode.MinMax;
public float min = 0f;
public float max = 1f;
public override float value
{
get { return m_Value; }
set
{
switch (clampMode)
{
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break;
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break;
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break;
}
}
}
}
// Holds a min & a max values clamped in a range (MinMaxSlider in the editor)
[Serializable]
public sealed class RangeParameter : VolumeParameter<Vector2>
{
public float min = 0;
public float max = 1;
public override Vector2 value
{
get { return m_Value; }
set
{
m_Value.x = Mathf.Max(value.x, min);
m_Value.y = Mathf.Min(value.y, max);
}
}
public override void Interp(Vector2 from, Vector2 to, float t)
{
m_Value.x = from.x + (to.x - from.x) * t;
m_Value.y = from.y + (to.y - from.y) * t;
}
}
[Serializable]
public sealed class InstantRangeParameter : VolumeParameter<Vector2>
{
public float min = 0;
public float max = 1;
public override Vector2 value
{
get { return m_Value; }
set
{
m_Value.x = Mathf.Max(value.x, min);
m_Value.y = Mathf.Min(value.y, max);
}
}
}
// 32-bit RGBA
[Serializable]
public sealed class ColorParameter : VolumeParameter<Color>
{
public bool hdr = false;
public bool showAlpha = true;
public bool showEyeDropper = true;
public override void Interp(Color from, Color to, float t)
{
// Lerping color values is a sensitive subject... We looked into lerping colors using
// HSV and LCH but they have some downsides that make them not work correctly in all
// situations, so we stick with RGB lerping for now, at least its behavior is
// predictable despite looking desaturated when `t ~= 0.5` and it's faster anyway.
m_Value.r = from.r + (to.r - from.r) * t;
m_Value.g = from.g + (to.g - from.g) * t;
m_Value.b = from.b + (to.b - from.b) * t;
m_Value.a = from.a + (to.a - from.a) * t;
}
}
[Serializable]
public sealed class InstantColorParameter : VolumeParameter<Color> { }
[Serializable]
public sealed class Vector2Parameter : VolumeParameter<Vector2>
{
public override void Interp(Vector2 from, Vector2 to, float t)
{
m_Value.x = from.x + (to.x - from.x) * t;
m_Value.y = from.y + (to.y - from.y) * t;
}
}
[Serializable]
public sealed class InstantVector2Parameter : VolumeParameter<Vector2> { }
[Serializable]
public sealed class Vector3Parameter : VolumeParameter<Vector3>
{
public override void Interp(Vector3 from, Vector3 to, float t)
{
m_Value.x = from.x + (to.x - from.x) * t;
m_Value.y = from.y + (to.y - from.y) * t;
m_Value.z = from.z + (to.z - from.z) * t;
}
}
[Serializable]
public sealed class InstantVector3Parameter : VolumeParameter<Vector3> { }
[Serializable]
public sealed class Vector4Parameter : VolumeParameter<Vector4>
{
public override void Interp(Vector4 from, Vector4 to, float t)
{
m_Value.x = from.x + (to.x - from.x) * t;
m_Value.y = from.y + (to.y - from.y) * t;
m_Value.z = from.z + (to.z - from.z) * t;
m_Value.w = from.w + (to.w - from.w) * t;
}
}
[Serializable]
public sealed class InstantVector4Parameter : VolumeParameter<Vector4> { }
// Used as a container to store custom serialized classes/structs inside volume components
[Serializable]
public class ObjectParameter<T> : VolumeParameter<T>
{
internal ReadOnlyCollection<VolumeParameter> parameters { get; private set; }
// Force override state to true for container objects
public override bool overrideState
{
get { return true; }
set { m_OverrideState = true; }
}
public override T value
{
get { return m_Value; }
set
{
m_Value = value;
if (m_Value == null)
{
parameters = null;
return;
}
// Automatically grab all fields of type VolumeParameter contained in this instance
parameters = m_Value.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(t => t.FieldType.IsSubclassOf(typeof(VolumeParameter)))
.OrderBy(t => t.MetadataToken) // Guaranteed order
.Select(t => (VolumeParameter)t.GetValue(m_Value))
.ToList()
.AsReadOnly();
}
}
internal override void Interp(VolumeParameter from, VolumeParameter to, float t)
{
if (m_Value == null)
return;
var paramOrigin = parameters;
var paramFrom = ((ObjectParameter<T>)from).parameters;
var paramTo = ((ObjectParameter<T>)to).parameters;
for (int i = 0; i < paramFrom.Count; i++)
{
if (paramOrigin[i].overrideState)
paramOrigin[i].Interp(paramFrom[i], paramTo[i], t);
}
}
}
}

11
ScriptableRenderPipeline/Core/Volume/VolumeParameter.cs.meta


fileFormatVersion: 2
guid: d53242bc2649d524aa42f2a84eb077b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

212
ScriptableRenderPipeline/Core/Volume/Volume.cs


using System;
using System.Collections.Generic;
namespace UnityEngine.Experimental.Rendering
{
[ExecuteInEditMode]
public class Volume : MonoBehaviour
{
[Tooltip("A global volume is applied to the whole scene.")]
public bool isGlobal = false;
[Tooltip("Volume priority in the stack. Higher number means higher priority. Negative values are supported.")]
public float priority = 0f;
[Tooltip("Outer distance to start blending from. A value of 0 means no blending and the volume overrides will be applied immediatly upon entry.")]
public float blendDistance = 0f;
[Range(0f, 1f), Tooltip("Total weight of this volume in the scene. 0 means it won't do anything, 1 means full effect.")]
public float weight = 1f;
public List<VolumeComponent> components = new List<VolumeComponent>();
// Editor-only
[NonSerialized]
public bool isDirty;
// Needed for state tracking (see the comments in Update)
int m_PreviousLayer;
float m_PreviousPriority;
void OnEnable()
{
// Make sure every setting is valid. If a profile holds a script that doesn't exist
// anymore, nuke it to keep the volume clean. Note that if you delete a script that is
// currently in use in a volume you'll still get a one-time error in the console, it's
// harmless and happens because Unity does a redraw of the editor (and thus the current
// frame) before the recompilation step.
components.RemoveAll(x => x == null);
m_PreviousLayer = gameObject.layer;
VolumeManager.instance.Register(this, m_PreviousLayer);
}
void OnDisable()
{
VolumeManager.instance.Unregister(this, gameObject.layer);
}
void Reset()
{
isDirty = true;
}
void Update()
{
// Unfortunately we need to track the current layer to update the volume manager in
// real-time as the user could change it at any time in the editor or at runtime.
// Because no event is raised when the layer changes, we have to track it on every
// frame :/
int layer = gameObject.layer;
if (layer != m_PreviousLayer)
{
VolumeManager.instance.UpdateVolumeLayer(this, m_PreviousLayer, layer);
m_PreviousLayer = layer;
}
// Same for priority. We could use a property instead, but it doesn't play nice with the
// serialization system. Using a custom Attribute/PropertyDrawer for a property is
// possible but it doesn't work with Undo/Redo in the editor, which makes it useless for
// our case.
if (priority != m_PreviousPriority)
{
VolumeManager.instance.SetLayerDirty(layer);
m_PreviousPriority = priority;
}
}
public T Add<T>(bool overrides = false)
where T : VolumeComponent
{
if (Has<T>())
throw new InvalidOperationException("Component already exists in the volume");
var component = ScriptableObject.CreateInstance<T>();
component.SetAllOverridesTo(overrides);
isDirty = true;
return component;
}
public void Remove<T>()
where T : VolumeComponent
{
int toRemove = -1;
var type = typeof(T);
for (int i = 0; i < components.Count; i++)
{
if (components[i].GetType() == type)
{
toRemove = i;
break;
}
}
if (toRemove >= 0)
{
components.RemoveAt(toRemove);
isDirty = true;
}
}
public bool Has<T>()
where T : VolumeComponent
{
var type = typeof(T);
foreach (var component in components)
{
if (component.GetType() == type)
return true;
}
return false;
}
public bool TryGet<T>(out T component)
where T : VolumeComponent
{
var type = typeof(T);
component = null;
foreach (var comp in components)
{
if (comp.GetType() == type)
{
component = (T)comp;
return true;
}
}
return false;
}
#if UNITY_EDITOR
// TODO: Look into a better volume previsualization system
List<Collider> m_TempColliders;
void OnDrawGizmos()
{
if (m_TempColliders == null)
m_TempColliders = new List<Collider>();
var colliders = m_TempColliders;
GetComponents(colliders);
if (isGlobal || colliders == null)
return;
var scale = transform.localScale;
var invScale = new Vector3(1f / scale.x, 1f / scale.y, 1f / scale.z);
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, scale);
Gizmos.color = new Color(0f, 1f, 0.1f, 0.6f);
// Draw a separate gizmo for each collider
foreach (var collider in colliders)
{
if (!collider.enabled)
continue;
// We'll just use scaling as an approximation for volume skin. It's far from being
// correct (and is completely wrong in some cases). Ultimately we'd use a distance
// field or at least a tesselate + push modifier on the collider's mesh to get a
// better approximation, but the current Gizmo system is a bit limited and because
// everything is dynamic in Unity and can be changed at anytime, it's hard to keep
// track of changes in an elegant way (which we'd need to implement a nice cache
// system for generated volume meshes).
var type = collider.GetType();
if (type == typeof(BoxCollider))
{
var c = (BoxCollider)collider;
Gizmos.DrawCube(c.center, c.size);
Gizmos.DrawWireCube(c.center, c.size + invScale * blendDistance * 2f);
}
else if (type == typeof(SphereCollider))
{
var c = (SphereCollider)collider;
Gizmos.DrawSphere(c.center, c.radius);
Gizmos.DrawWireSphere(c.center, c.radius + invScale.x * blendDistance);
}
else if (type == typeof(MeshCollider))
{
var c = (MeshCollider)collider;
// Only convex mesh colliders are allowed
if (!c.convex)
c.convex = true;
// Mesh pivot should be centered or this won't work
Gizmos.DrawMesh(c.sharedMesh);
Gizmos.DrawWireMesh(c.sharedMesh, Vector3.zero, Quaternion.identity, Vector3.one + invScale * blendDistance * 2f);
}
// Nothing for capsule (DrawCapsule isn't exposed in Gizmo), terrain, wheel and
// other colliders...
}
colliders.Clear();
}
#endif
}
}

14
ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs


using UnityEngine.Rendering;
using System;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
// For multiple importance sampling
// TODO: not working currently, will be updated later
[GenerateHLSL(PackingRules.Exact)]
public enum LightSamplingParameters
{
TextureHeight = 256,
TextureWidth = 512
}
}

14
ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.hlsl


//
// This file was automatically generated. Please don't edit by hand.
//
#ifndef GGXCONVOLUTION_CS_HLSL
#define GGXCONVOLUTION_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.LightSamplingParameters: static fields
//
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_HEIGHT (256)
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_WIDTH (512)
#endif

9
ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.hlsl.meta


fileFormatVersion: 2
guid: d2c1bda84c2c45f4782732c8e3f3ba1b
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

11
ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.meta


fileFormatVersion: 2
guid: f96a85514b0168541b31f8f052d55f1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

113
ScriptableRenderPipeline/HDRenderPipeline/Sky/README.txt


# Atmospheric Scattering
Atmospheric scattering is a solution developed for nicer aerial perspective in The Blacksmith. It provides a model emulating atmospheric Rayleigh, Mie and height scattering (and also takes a lot of shortcuts in the name of performance and artistic control). Take a look at the blog post at this address http://blogs.unity3d.com/?p=27218 to get a high-level overview of the components making up the final composition.
### Options description
This component comes with quite a lot of options - but you normally don't have to tweak more than a handful of them to get good results - start with the densities and colors and that will get you started nicely.
#### World Components
**World Rayleigh Color Ramp**: The color or colors used for rayleigh scattering. It's a ramp instead of a single color because you can have different scattering colors depending on the angle to the unit being shaded. Values to the left in the ramp are mapped to angles below horizon, whereas values to the right are mapped to angles above the horizon.
**World Rayleigh Color Intensity**: An HDR color scale for the rayleigh color ramp.
**World Rayleigh Density**: The density of the rayleigh component.
**World Rayleigh Extinction Factor**: How much light is out-scattered or absorbed on its way to the eye. Basically how much to darken the shaded pixel.
**World Rayleigh Indirect Scatter**: Which percentage of the rayleigh scattering should be considered 'indirect' scattering. (relevant for occlusion only)
**World Mie Color Ramp**: The color or colors used for mie scattering. It's a ramp instead of a single color because you can have different scattering colors depending on the angle to the unit being shaded. Values to the left in the ramp are mapped to angles below horizon, whereas values to the right are mapped to angles above the horizon.
**World Mie Color Intensity**: An HDR color scale for the mie color ramp.
**World Mie Density**: The density of the mie component.
**World Mie Extinction Factor**: How much light is out-scattered or absorbed on its way to the eye. Basically how much to darken the shaded pixel.
**World Mie Phase Anisotropy**: How focused the forward directionality of the mie scattering is. Values close to 1 produce a small, very sharp mie component, whereas values below 0.5 creates a very large and unfocused mie component.
**World Near Scatter Push**: Allows the scattering to be pushed out to have no scattering directly in front of the camera, or pulled in to have more scattering close to the camera.
**World Normal Distance**: A measure of the scale of the scene. Essentially this desaturates the scattering near the camera, and interpolates into full color ramp at the edge of the specified distance.
#### Height Components
**Height Rayleigh Color**: The general global scattering color for height fog.
**Height Rayleigh Intensity**: An HDR color scale for the height global fog color.
**Height Rayleigh Density**: The density of the global height fog.
**Height Mie Density**: The density of the mie scattering being added to the global height fog.
**Height Extinction Factor**: How much light is out-scattered or absorbed on its way to the eye. Basically how much to darken the shaded pixel.
**Height Sea Level**: Sea level height offset from origin.
**Height Distance**: Falloff distance from sea level
**Height Plane Shift**: An optional plane vector for a tilted sea level.
**Height Near Scatter Push**: Allows the scattering to be pushed out to have no scattering directly in front of the camera, or pulled in to have more scattering close to the camera.
**Height Normal Distance**: A measure of the scale of the scene. Essentially this desaturates the scattering near the camera, and interpolates into full color at the edge of the specified distance.
#### Sky Dome
**Sky Dome Scale**: The scale of the skydome. We use this to virtually squash the sky sphere into behaving like a dome. The xz-dimensions affect how much scattering the horizon picks up, whereas the y-dimension dictates how far up on the sky the scattering is blended.
**Sky Dome Rotation**: An optional rotation of the skydome. Usually, only Y-rotation makes sense.
**Sky Dome Tracked Yaw Rotation**: Optionally have the skydome rotate to track a transform, typically a light source. Use in combination with rotation to perfectly align and track the sun to the skydome.
**Sky Dome Vertical Flip**: We have the option of putting two skybox textures into the same cubemap. This flags flips the UV projection to show the bottom half instead of the top half.
**Sky Dome Cube**: An HDR cubemap to use as sky dome.
**Sky Dome Exposure**: The exposure of the sky cubemap.
**Sky Dome Tint**: Tint color for the cubemap.
#### Scatter Occlusion
**Use Occlusion**: This flag enables scatter occlusion.
**Occlusion Bias**: Controls how strongly occlusion affects direct scattering.
**Occlusion BiasIndirect**: Controls how strongly occlusion affects indirect scattering.
**Occlusion BiasClouds**: Controls how strongly occlusion affects placed clouds.
**Occlusion Downscale**: Controls the downscale factor for occlusion gathering.
**Occlusion Samples**: The number of samples to use in gathering.
**Occlusion DepthFixup**: Whether to attempt to fix upsampling across depth discontinuities (currently d3d11 only).
**Occlusion DepthThreshold**: The threshold defining discontinuous depth.
**Occlusion FullSky**: Whether to gather occlusion even for skydome pixels.
**Occlusion BiasSkyRayleigh **: Controls how strongly occlusion affects rayleigh scattering on the skydome.
**Occlusion BiasSkyMie **: Controls how strongly occlusion affects mie scattering on the skydome.
#### Other
**World ScaleExponent**: An option to exponentially scale the world for scattering calculations (fake aerial perspective in small scenes).
**Force Per Pixel**: Force all scatter calculations to run at per-pixel frequency.
**Force Post Effect**: Force all scatter calculations to run in a post-process (requires the AtmosphericScatteringDeferred component on the camera, and doesn't apply to transparent object)
**Depth Texture**: Whether to enable, disable or leave alone the camera depth texture settings. (required for depth fixup and soft cloud planes)
**Debug Mode**: Various debug visualizations of the different rendering components.

8
ScriptableRenderPipeline/HDRenderPipeline/Sky/README.txt.meta


fileFormatVersion: 2
guid: 4eead1bf6efbd0a4e852367accddc070
timeCreated: 1480334378
licenseType: Pro
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

9
ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs.hlsl.meta


fileFormatVersion: 2
guid: 839dd86bae5fa4d46bf4facd02608862
timeCreated: 1483546512
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

14
ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs.hlsl


//
// This file was automatically generated. Please don't edit by hand.
//
#ifndef SKYMANAGER_CS_HLSL
#define SKYMANAGER_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.LightSamplingParameters: static fields
//
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_HEIGHT (256)
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_WIDTH (512)
#endif

9
ScriptableRenderPipeline/HDRenderPipeline/Sky/BlacksmithlSky.meta


fileFormatVersion: 2
guid: 65f9231eb40b6914eb24ea0b555778f0
folderAsset: yes
timeCreated: 1481646017
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop/DeferredDirectionalShadow.compute → /ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute

/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop/DeferredDirectionalShadow.compute.meta → /ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute.meta

/ScriptableRenderPipeline/HDRenderPipeline/Sky/RuntimeFilterIBL.cs.meta → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/RuntimeFilterIBL.cs.meta

/ScriptableRenderPipeline/HDRenderPipeline/Sky/GGXConvolve.shader.meta → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader.meta

/ScriptableRenderPipeline/HDRenderPipeline/Sky/ComputeGgxIblSampleData.compute.meta → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/ComputeGgxIblSampleData.compute.meta

/ScriptableRenderPipeline/HDRenderPipeline/Sky/BuildProbabilityTables.compute.meta → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute.meta

/ScriptableRenderPipeline/HDRenderPipeline/Sky/BuildProbabilityTables.compute → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute

/ScriptableRenderPipeline/HDRenderPipeline/Sky/RuntimeFilterIBL.cs → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/RuntimeFilterIBL.cs

/ScriptableRenderPipeline/HDRenderPipeline/Sky/GGXConvolve.shader → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader

/ScriptableRenderPipeline/HDRenderPipeline/Sky/ComputeGgxIblSampleData.compute → /ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/ComputeGgxIblSampleData.compute

正在加载...
取消
保存