浏览代码

Merge pull request #73 from Unity-Technologies/master

Merge master
/main
GitHub 7 年前
当前提交
21a946ef
共有 818 个文件被更改,包括 3169 次插入1857 次删除
  1. 2
      .gitignore
  2. 39
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/SerializableGraph.cs
  3. 2
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/SerializableNode.cs
  4. 5
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/SerializableSlot.cs
  5. 19
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Interfaces/GraphChange.cs
  6. 1
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Interfaces/INode.cs
  7. 2
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Testing/UnitTests/SerializedGraphTests.cs
  8. 2
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/GradientField.cs
  9. 24
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/GradientNode.cs
  10. 94
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/HeightToNormalNode.cs
  11. 6
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/ParallaxNode.cs
  12. 2
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/SamplerStateNode.cs
  13. 16
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/TextureSamplerNode.cs
  14. 58
      MaterialGraphProject/Assets/NewNodes/Editor/Kill/MultiLayerParallaxNode.cs
  15. 12
      MaterialGraphProject/Assets/NewNodes/Editor/Kill/VertexNormalNode.cs
  16. 566
      MaterialGraphProject/Assets/PartyPreview.ShaderGraph
  17. 3
      MaterialGraphProject/Assets/PartyPreview.ShaderGraph.meta
  18. 4
      MaterialGraphProject/Assets/SRP.meta
  19. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline.meta
  20. 2
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Camera/CameraSwitcher.cs
  21. 82
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Camera/FreeCamera.cs
  22. 19
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/CommandBufferPool.cs
  23. 107
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugActionManager.cs
  24. 14
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugItemHandler.cs
  25. 6
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugItemUI.cs
  26. 3
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuManager.cs
  27. 56
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuState.cs
  28. 3
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuUI.cs
  29. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuUpdater.cs
  30. 14
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugPanel.cs
  31. 39
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugPanelUI.cs
  32. 1
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Debugging.cs
  33. 13
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Editor/DebugMenuEditor.cs
  34. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateBool.cs
  35. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateColor.cs
  36. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateFloat.cs
  37. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateInt.cs
  38. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateUInt.cs
  39. 2
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderGenerator/Editor/CSharpToHLSL.cs
  40. 193
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl
  41. 26
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  42. 46
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl
  43. 29
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl
  44. 13
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/EntityLighting.hlsl
  45. 8
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Fibonacci.hlsl
  46. 174
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
  47. 9
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/PerPixelDisplacement.hlsl
  48. 9
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/Shadow.hlsl
  49. 310
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  50. 46
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowSampling.hlsl
  51. 10
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
  52. 32
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Wind.hlsl
  53. 2
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Singleton.cs
  54. 90
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/TextureCache.cs
  55. 28
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LegacyShadersToLightweightPipelineUpgrader.cs
  56. 46
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightAssetInspector.cs
  57. 72
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightPipelineUpgraders.cs
  58. 3
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightUnlitGUI.cs
  59. 8
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/StandardToLightweightMaterialUpgrader.cs
  60. 1
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/UpgradeCommon.cs
  61. 888
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs
  62. 13
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset
  63. 98
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.cs
  64. 106
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineUtils.cs
  65. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-DefaultParticle.mat
  66. 2
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-StandardShader.mat
  67. 4
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-StandardSimpleLighting.mat
  68. 67
      MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightUnlit.shader
  69. 11
      MaterialGraphProject/Assets/Test.unity
  70. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/AssetCallbacks/CreateShaderGraph.cs
  71. 1
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/AssetCallbacks/CreateShaderSubGraph.cs
  72. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs.meta
  73. 321
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractMaterialGraph.cs
  74. 34
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractShaderProperty.cs
  75. 8
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialGraph.cs
  76. 665
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialSlot.cs
  77. 20
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Interfaces/MaterialGraphChange.cs
  78. 50
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Interfaces/NeededCoordinateSpace.cs
  79. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/AbstractLightweightMasterNode.cs
  80. 14
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightMetallicMasterNode.cs
  81. 14
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightSpecularMasterNode.cs
  82. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightUnlitMasterNode.cs
  83. 172
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/AbstractMaterialNode.cs
  84. 11
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Art/Adjustments/LevelsNode.cs
  85. 10
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Channel/SplitNode.cs
  86. 47
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/HLSLNode.cs
  87. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/ColorNode.cs
  88. 8
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix2Node.cs
  89. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix3Node.cs
  90. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix4Node.cs
  91. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/MatrixCommonNode.cs
  92. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/SceneData/CameraDirNode.cs
  93. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/SceneData/CameraPosNode.cs
  94. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/SceneData/ScreenPosNode.cs
  95. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Time/SinTimeNode.cs
  96. 10
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Time/TimeNode.cs
  97. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector1Node.cs
  98. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector2Node.cs
  99. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector3Node.cs
  100. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector4Node.cs

2
.gitignore


MaterialGraphProject/Library
MaterialGraphProject/obj
MaterialGraphProject/MaterialGraphProject.CSharp.csproj
MaterialGraphProject/MaterialGraphProject.sln.DotSettings.user
*.csproj
MaterialGraphProject/MaterialGraphProject.sln
MaterialGraphProject/Temp

.DS_Store
MaterialGraphProject/Assets/_MingWai/New Custom Texture.asset.meta
MaterialGraphProject/Packages/*
MaterialGraphProject/GeneratedShader.shader
!MaterialGraphProject/Packages/manifest.json

39
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/SerializableGraph.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using NUnit.Framework;

return null;
var slotEdges = GetEdges(inputSlot).ToList();
// remove any inputs that exits before adding
foreach (var edge in slotEdges)
{

Debug.LogWarning("Node does not exist");
return Enumerable.Empty<IEdge>();
}
ISlot slot = slot = node.FindSlot<ISlot>(s.slotId);
ISlot slot = node.FindSlot<ISlot>(s.slotId);
List<IEdge> candidateEdges;
if (!m_NodeEdges.TryGetValue(s.nodeGuid, out candidateEdges))

AddEdgeToNodeEdges(edge);
OnEnable();
ValidateGraph();
ValidateGraph();
}
public virtual void ValidateGraph()

//manually modifies serialized data
//of if they delete a node in the inspector
//debug view.
foreach (var edge in edges.ToArray())
//debug view.
foreach (var edge in edges.ToArray())
{
var outputNode = GetNodeFromGuid(edge.outputSlot.nodeGuid);
var inputNode = GetNodeFromGuid(edge.inputSlot.nodeGuid);

RemoveEdge(edge);
}
// Remove all nodes and re-add them.
using (var replacedNodesPooledObject = ListPool<INode>.GetDisposable())
var replacedNodes = replacedNodesPooledObject.value;
{
if (!other.ContainsNodeGuid(node.guid))
// Remove the node if it doesn't exist in the other graph.
removedNodeGuids.Add(node.guid);
else
// Replace the node with the one from the other graph otherwise.
replacedNodes.Add(node);
}
removedNodeGuids.Add(node.guid);
foreach (var node in replacedNodes)
{
var currentNode = other.GetNodeFromGuid(node.guid);
currentNode.owner = this;
m_Nodes[node.guid] = currentNode;
currentNode.onModified = node.onModified;
currentNode.onReplaced = node.onReplaced;
// Notify listeners that the reference has changed.
if (node.onReplaced != null)
node.onReplaced(node, currentNode);
if (currentNode.onModified != null)
currentNode.onModified(node, ModificationScope.Node);
node.onModified = null;
node.onReplaced = null;
}
}
// Add nodes from other graph which don't exist in this one.

2
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/SerializableNode.cs


public OnNodeModified onModified { get; set; }
public OnNodeReplaced onReplaced { get; set; }
public IEnumerable<T> GetInputSlots<T>() where T : ISlot
{
return GetSlots<T>().Where(x => x.isInputSlot);

5
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/SerializableSlot.cs


get { return m_SlotType == SlotType.Output; }
}
public SlotType slotType
{
get { return m_SlotType; }
}
// used via reflection / serialization after deserialize
// to reconstruct this slot.
public SerializableSlot()

19
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Interfaces/GraphChange.cs


public IEdge edge { get; private set; }
}
public static class GraphChangeExtensions
{
public static void Match(this GraphChange change,
Action<NodeAddedGraphChange> nodeAdded = null,
Action<NodeRemovedGraphChange> nodeRemoved = null,
Action<EdgeAddedGraphChange> edgeAdded = null,
Action<EdgeRemovedGraphChange> edgeRemoved = null)
{
if (change is NodeAddedGraphChange && nodeAdded != null)
nodeAdded((NodeAddedGraphChange)change);
else if (change is NodeRemovedGraphChange && nodeRemoved != null)
nodeRemoved((NodeRemovedGraphChange)change);
else if (change is EdgeAddedGraphChange && edgeAdded != null)
edgeAdded((EdgeAddedGraphChange)change);
else if (change is EdgeRemovedGraphChange && edgeRemoved != null)
edgeRemoved((EdgeRemovedGraphChange)change);
}
}
}

1
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Interfaces/INode.cs


public interface INode
{
OnNodeModified onModified { get; set; }
OnNodeReplaced onReplaced { get; set; }
IGraph owner { get; set; }
Guid guid { get; }
Guid RewriteGuid();

2
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Testing/UnitTests/SerializedGraphTests.cs


[TestFixture]
public class SerializableGraphTests
{
[TestFixtureSetUp]
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
Debug.unityLogger.logHandler = new ConsoleLogHandler();

2
MaterialGraphProject/Assets/NewNodes/Editor/Keep/GradientField.cs


#region Initial Setup
private static MethodInfo s_miGradientField1;
private static MethodInfo s_miGradientField2;
static GUIGradientField()
{

s_miGradientField2 = tyEditorGUILayout.GetMethod("GradientField", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { GradientWrapper.s_tyGradient, typeof(GUILayoutOption[]) }, null);
}
#endregion

24
MaterialGraphProject/Assets/NewNodes/Editor/Keep/GradientNode.cs


namespace UnityEngine.MaterialGraph
{
[Title("Procedural/Gradient Editor")]
[Title("Input/Gradient")]
Gradient m_Gradient;
Gradient m_Gradient = new Gradient();
[SerializeField]
Vector4[] m_SerializableColorKeys = { new Vector4(1f, 1f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f), };

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(TimeInputSlotId, k_TimeInputSlotName, k_TimeInputSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(RGBAOutputSlotId, k_RGBAOutputSlotName, k_RGBAOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(ROutputSlotId, k_ROutputSlotName, k_ROutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(GOutputSlotId, k_GOutputSlotName, k_GOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(BOutputSlotId, k_BOutputSlotName, k_BOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(AOutputSlotId, k_AOutputSlotName, k_AOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new Vector1MaterialSlot(TimeInputSlotId, k_TimeInputSlotName, k_TimeInputSlotName, SlotType.Input,0));
AddSlot(new Vector4MaterialSlot(RGBAOutputSlotId, k_RGBAOutputSlotName, k_RGBAOutputSlotName, SlotType.Output, Vector4.zero));
AddSlot(new Vector1MaterialSlot(ROutputSlotId, k_ROutputSlotName, k_ROutputSlotName, SlotType.Output,0));
AddSlot(new Vector1MaterialSlot(GOutputSlotId, k_GOutputSlotName, k_GOutputSlotName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(BOutputSlotId, k_BOutputSlotName, k_BOutputSlotName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(AOutputSlotId, k_AOutputSlotName, k_AOutputSlotName, SlotType.Output, 0));
}
public override void OnAfterDeserialize()
{
base.OnAfterDeserialize();
m_SerializableAlphaKeys = null;
m_SerializableColorKeys = null;
m_Gradient.SetKeys(colorKeys, alphaKeys);
}

94
MaterialGraphProject/Assets/NewNodes/Editor/Keep/HeightToNormalNode.cs


using System.Linq;
using JetBrains.Annotations;
using UnityEngine.Graphing;
public class HeightToNormalNode : CodeFunctionNode
public class HeightToNormalNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
public const int TextureInput = 0;
public const int TexCoordInput = 1;
public const int TexOffsetInput = 2;
public const int StrengthInput = 3;
public const int NormalOutput = 4;
const string TextureInputName = "Texture";
const string TexCoordInputName = "UV";
const string TexOffsetInputName = "Offset";
const string StrengthInputName = "Strength";
const string NormalOutputName = "Normal";
UpdateNodeAfterDeserialization();
protected override MethodInfo GetFunctionToConvert()
public sealed override void UpdateNodeAfterDeserialization()
return GetType().GetMethod("Unity_HeightToNormal", BindingFlags.Static | BindingFlags.NonPublic);
AddSlot(new Texture2DMaterialSlot(TextureInput, TextureInputName, TextureInputName, SlotType.Input));
AddSlot(new Vector2MaterialSlot(TexCoordInput, TexCoordInputName, TexCoordInputName, SlotType.Input, Vector2.zero));
AddSlot(new Vector1MaterialSlot(TexOffsetInput, TexOffsetInputName, TexOffsetInputName, SlotType.Input, 0.005f));
AddSlot(new Vector1MaterialSlot(StrengthInput, StrengthInputName, StrengthInputName, SlotType.Input, 8f));
AddSlot(new Vector3MaterialSlot(NormalOutput, NormalOutputName, NormalOutputName, SlotType.Output, Vector3.zero));
static string Unity_HeightToNormal(
[Slot(0, Binding.None)] Texture2D heightmap,
[Slot(1, Binding.MeshUV0)] Vector1 texCoord,
[Slot(2, Binding.None, 0.005f, 0, 0, 0)] Vector1 texOffset,
[Slot(3, Binding.None, 8f, 0, 0, 0)] Vector1 strength,
[Slot(4, Binding.None)] out Vector1 normal)
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
return
@"
{
float2 offsetU = float2(texCoord.x + texOffset, texCoord.y);
float2 offsetV = float2(texCoord.x, texCoord.y + texOffset);
var textureInput = GetSlotValue(TextureInput, generationMode);
var texCoordInput = RequiresMeshUV(UVChannel.uv0)
? string.Format("{0}.xy", UVChannel.uv0.GetUVName())
: GetSlotValue(TexCoordInput, generationMode);
var texOffsetInput = GetSlotValue(TexOffsetInput, generationMode);
var strengthInput = GetSlotValue(StrengthInput, generationMode);
var normalOutput = GetVariableNameForSlot(NormalOutput);
float normalSample = 0;
float uSample = 0;
float vSample = 0;
visitor.AddShaderChunk(string.Format("{0}3 {1};", precision, normalOutput), true);
visitor.AddShaderChunk("{", false);
visitor.Indent();
{
visitor.AddShaderChunk(string.Format("{0}2 offsetU = float2({1}.x + {2}, {1}.y);", precision, texCoordInput, texOffsetInput), true);
visitor.AddShaderChunk(string.Format("{0}2 offsetV = float2({1}.x, {1}.y + {2});", precision, texCoordInput, texOffsetInput), true);
#ifdef UNITY_COMPILER_HLSL
normalSample = heightmap.Sample(my_linear_repeat_sampler, texCoord).r;
uSample = heightmap.Sample(my_linear_repeat_sampler, offsetU).r;
vSample = heightmap.Sample(my_linear_repeat_sampler, offsetV).r;
#endif
visitor.AddShaderChunk(string.Format("{0} normalSample = UNITY_SAMPLE_TEX2D({1}, {2});", precision, textureInput, texCoordInput), true);
visitor.AddShaderChunk(string.Format("{0} uSample = UNITY_SAMPLE_TEX2D({1}, offsetU);", precision, textureInput), true);
visitor.AddShaderChunk(string.Format("{0} vSample = UNITY_SAMPLE_TEX2D({1}, offsetV);", precision, textureInput), true);
float uMinusNormal = uSample - normalSample;
float vMinusNormal = vSample - normalSample;
visitor.AddShaderChunk(string.Format("{0}3 va = float3(1, 0, (uSample - normalSample) * {1});", precision, strengthInput), true);
visitor.AddShaderChunk(string.Format("{0}3 vb = float3(0, 1, (vSample - normalSample) * {1});", precision, strengthInput), true);
visitor.AddShaderChunk(string.Format("{0} = cross(va, vb);", normalOutput), true);
}
visitor.Deindent();
visitor.AddShaderChunk("}", false);
}
public override bool hasPreview
{
get { return true; }
}
uMinusNormal = uMinusNormal * strength;
vMinusNormal = vMinusNormal * strength;
public bool RequiresMeshUV(UVChannel channel)
{
if (channel != UVChannel.uv0)
{
return false;
}
float3 va = float3(1, 0, uMinusNormal);
float3 vb = float3(0, 1, vMinusNormal);
var uvSlot = FindInputSlot<MaterialSlot>(TexCoordInput);
if (uvSlot == null)
return true;
normals = cross(va, vb);
}
";
var edges = owner.GetEdges(uvSlot.slotReference).ToList();
return edges.Count == 0;
}
}
}

6
MaterialGraphProject/Assets/NewNodes/Editor/Keep/ParallaxNode.cs


protected virtual MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector1, Vector4.zero);
return new Vector1MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, 1);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector2, Vector4.zero);
return new Vector2MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, Vector2.zero);
}
protected virtual string GetInputSlot1Name()

return GetFunctionName() + " (" +
inputValue1 + ", " +
channel.GetUVName() + ", " +
ShaderGeneratorNames.TangentSpaceViewDirection + ")";
CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent) + ")";
}
public bool RequiresMeshUV(UVChannel channel)

2
MaterialGraphProject/Assets/NewNodes/Editor/Keep/SamplerStateNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.SamplerState, Vector4.zero));
AddSlot(new SamplerStateMaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

16
MaterialGraphProject/Assets/NewNodes/Editor/Keep/TextureSamplerNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(TextureInputId, kTextureInputName, kTextureInputName, SlotType.Input, SlotValueType.Texture2D, Vector4.zero));
AddSlot(new MaterialSlot(UVInput, kUVInputName, kUVInputName, SlotType.Input, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input, SlotValueType.SamplerState, Vector4.zero));
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero));
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output,0));
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0));
AddSlot(new Texture2DMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName, SlotType.Input));
AddSlot(new Vector2MaterialSlot(UVInput, kUVInputName, kUVInputName, SlotType.Input, Vector4.zero));
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));
RemoveSlotsNameNotMatching(new[] { OutputSlotRGBAId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, TextureInputId, UVInput, SamplerInput });
}

58
MaterialGraphProject/Assets/NewNodes/Editor/Kill/MultiLayerParallaxNode.cs


protected virtual MaterialSlot GetInputDepthSlot()
{
return new MaterialSlot(InputDepthSlotId, GetInputSlot1Name(), kInputDepthShaderName, SlotType.Input, SlotValueType.Vector1, Vector4.zero);
return new Vector1MaterialSlot(InputDepthSlotId, GetInputSlot1Name(), kInputDepthShaderName, SlotType.Input,0);
return new MaterialSlot(InputFadeRateSlotId, GetInputSlot2Name(), kInputFadeRateShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
return new DynamicVectorMaterialSlot(InputFadeRateSlotId, GetInputSlot2Name(), kInputFadeRateShaderName, SlotType.Input, Vector4.zero);
return new MaterialSlot(InputLayerCountSlotId, GetInputSlot3Name(), kInputLayerCountShaderName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero);
return new DynamicVectorMaterialSlot(InputLayerCountSlotId, GetInputSlot3Name(), kInputLayerCountShaderName, SlotType.Input, Vector4.zero);
return new MaterialSlot(TextureSlotId, GetTextureSlotName(), kTextureSlotShaderName, SlotType.Input, SlotValueType.Texture2D, Vector4.zero);
return new Texture2DMaterialSlot(TextureSlotId, GetTextureSlotName(), kTextureSlotShaderName, SlotType.Input);
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Dynamic, Vector4.zero);
return new DynamicVectorMaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, Vector4.zero);
}
protected virtual string GetInputSlot1Name()

{
return kOutputSlotShaderName;
}
private string input1Dimension
{
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputDepthSlotId).concreteValueType); }
}
private string input2Dimension
{
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputFadeRateSlotId).concreteValueType); }
}
private string input3Dimension
{
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputLayerCountSlotId).concreteValueType); }
}
public string outputDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType); }
}
return "inline " + precision + outputDimension + " " + GetFunctionName() + " (" +
precision + input1Dimension + " " + depth + ", " +
precision + input2Dimension + " " + fadeRate + ", " +
precision + input3Dimension + " " + layerCount + ", " +
"sampler2D " + tex + ", " +
precision + "2 " + UVs + ", " +
precision + "3 " + viewTangentSpace + ")";
var input1 = ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputDepthSlotId).concreteValueType);
var input2 = ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputFadeRateSlotId).concreteValueType);
var input3 = ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputLayerCountSlotId).concreteValueType);
var output = ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType);
return string.Format("inline {0} {1} ({2} {3}, {4} {5}, {6} {7}, " + "sampler2D {8}, {9}2 {10}, {9}3 {11})", output, GetFunctionName(), input1, depth, input2, fadeRate, input3, layerCount, tex, precision, UVs, viewTangentSpace);
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)

string fadeRateValue = GetSlotValue(InputFadeRateSlotId, generationMode);
string layerCountValue = GetSlotValue(InputLayerCountSlotId, generationMode);
string textureValue = GetSlotValue(TextureSlotId, generationMode);
visitor.AddShaderChunk(
precision + outputDimension + " " + GetVariableNameForSlot(OutputSlotId) +
" = " + GetFunctionCallBody(depthValue, fadeRateValue, layerCountValue, textureValue) + ";", true);
var output = ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType);
visitor.AddShaderChunk(string.Format("{0} {1} = {2};", output, GetVariableNameForSlot(OutputSlotId), GetFunctionCallBody(depthValue, fadeRateValue, layerCountValue, textureValue)), true);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)

outputString.AddShaderChunk(precision + "2 texcoord = UVs;", false);
outputString.AddShaderChunk(precision + "2 offset = -viewTangentSpace.xy * depth / layerCount;", false);
outputString.AddShaderChunk(precision + outputDimension + " result = 0.0f;", false);
outputString.AddShaderChunk(precision + outputDimension + " fade = 1.0f;", false);
var output = ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType);
outputString.AddShaderChunk(output + " result = 0.0f;", false);
outputString.AddShaderChunk(output + " fade = 1.0f;", false);
outputString.AddShaderChunk(precision + " alpha = 0.0f;", false);
outputString.AddShaderChunk("for (int i = 0; i < 10; i++) {", false);

layerCountValue + ", " +
texValue + ", " +
UVChannel.uv0.GetUVName() + ", " +
ShaderGeneratorNames.TangentSpaceViewDirection + ")";
CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent) + ")";
}
public bool RequiresMeshUV(UVChannel channel)

12
MaterialGraphProject/Assets/NewNodes/Editor/Kill/VertexNormalNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdXYZ, kOutputSlotNameXYZ, kOutputSlotNameXYZ, SlotType.Output, SlotValueType.Vector3, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdX, kOutputSlotNameX, kOutputSlotNameX, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdY, kOutputSlotNameY, kOutputSlotNameY, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdZ, kOutputSlotNameZ, kOutputSlotNameZ, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdW, kOutputSlotNameW, kOutputSlotNameW, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
AddSlot(new Vector3MaterialSlot(OutputSlotIdXYZ, kOutputSlotNameXYZ, kOutputSlotNameXYZ, SlotType.Output, Vector4.zero));
AddSlot(new Vector1MaterialSlot(OutputSlotIdX, kOutputSlotNameX, kOutputSlotNameX, SlotType.Output,0));
AddSlot(new Vector1MaterialSlot(OutputSlotIdY, kOutputSlotNameY, kOutputSlotNameY, SlotType.Output,0));
AddSlot(new Vector1MaterialSlot(OutputSlotIdZ, kOutputSlotNameZ, kOutputSlotNameZ, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotIdW, kOutputSlotNameW, kOutputSlotNameW, SlotType.Output, 0));
RemoveSlotsNameNotMatching(validSlots);
}

566
MaterialGraphProject/Assets/PartyPreview.ShaderGraph
文件差异内容过多而无法显示
查看文件

3
MaterialGraphProject/Assets/PartyPreview.ShaderGraph.meta


externalObjects: {}
defaultTextures: []
nonModifiableTextures:
- Texture: {fileID: 2800000, guid: e2e7994f2c9b58f40aaebdaabbbd0ad8, type: 3}
- Texture_507A46B3: {fileID: 2800000, guid: a653bbc25cc7e4794829cf7b1184abcb, type: 3}
- Texture_E2350D28: {fileID: 2800000, guid: 7296f51323ae9485a9c834c4e3d722ed, type: 3}
userData:
assetBundleName:
assetBundleVariant:

4
MaterialGraphProject/Assets/SRP.meta


fileFormatVersion: 2
guid: c29d1b9487ffd4a729adcbe0f197a3f4
guid: 612579e2db831754e87f0b4b938dbfaf
timeCreated: 1505274236
timeCreated: 1504184175
licenseType: Pro
DefaultImporter:
externalObjects: {}

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline.meta


fileFormatVersion: 2
guid: fd470011795144262bf5aa4bf5f396a1
guid: 22c204b70537f8d46a054fa00bf16298
timeCreated: 1505274236
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:

2
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Camera/CameraSwitcher.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering

82
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Camera/FreeCamera.cs


using System.Collections.Generic;
[ExecuteInEditMode]
public float m_MoveSpeed = 50.0f;
public float m_MoveSpeed = 10.0f;
public float m_Turbo = 10.0f;
private static string kMouseX = "Mouse X";

private static string kVertical = "Vertical";
private static string kHorizontal = "Horizontal";
private string[] m_RequiredInputAxes = { kMouseX, kMouseY, kRightStickX, kRightStickY, kVertical, kHorizontal };
private bool m_Valid = true;
m_Valid = Debugging.CheckRequiredInputAxisMapping(m_RequiredInputAxes);
RegisterInputs();
}
void RegisterInputs()
{
#if UNITY_EDITOR
List <InputManagerEntry> inputEntries = new List<InputManagerEntry>();
// Add new bindings
inputEntries.Add(new InputManagerEntry { name = kRightStickX, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Fourth, sensitivity = 1.0f, gravity = 1.0f, deadZone = 0.2f });
inputEntries.Add(new InputManagerEntry { name = kRightStickY, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Fifth, sensitivity = 1.0f, gravity = 1.0f, deadZone = 0.2f, invert = true });
InputRegistering.RegisterInputs(inputEntries);
#endif
if (m_Valid)
float inputRotateAxisX = 0.0f;
float inputRotateAxisY = 0.0f;
if (Input.GetMouseButton(1))
float inputRotateAxisX = 0.0f;
float inputRotateAxisY = 0.0f;
if (Input.GetMouseButton(1))
{
inputRotateAxisX = Input.GetAxis(kMouseX) * m_LookSpeedMouse;
inputRotateAxisY = Input.GetAxis(kMouseY) * m_LookSpeedMouse;
}
inputRotateAxisX += (Input.GetAxis(kRightStickX) * m_LookSpeedController * Time.deltaTime);
inputRotateAxisY += (Input.GetAxis(kRightStickY) * m_LookSpeedController * Time.deltaTime);
inputRotateAxisX = Input.GetAxis(kMouseX) * m_LookSpeedMouse;
inputRotateAxisY = Input.GetAxis(kMouseY) * m_LookSpeedMouse;
}
inputRotateAxisX += (Input.GetAxis(kRightStickX) * m_LookSpeedController * Time.deltaTime);
inputRotateAxisY += (Input.GetAxis(kRightStickY) * m_LookSpeedController * Time.deltaTime);
float inputVertical = Input.GetAxis(kVertical);
float inputHorizontal = Input.GetAxis(kHorizontal);
float inputVertical = Input.GetAxis(kVertical);
float inputHorizontal = Input.GetAxis(kHorizontal);
bool moved = inputRotateAxisX != 0.0f || inputRotateAxisY != 0.0f || inputVertical != 0.0f || inputHorizontal != 0.0f;
if (moved)
{
float rotationX = transform.localEulerAngles.x;
float newRotationY = transform.localEulerAngles.y + inputRotateAxisX;
bool moved = inputRotateAxisX != 0.0f || inputRotateAxisY != 0.0f || inputVertical != 0.0f || inputHorizontal != 0.0f;
if (moved)
{
float rotationX = transform.localEulerAngles.x;
float newRotationY = transform.localEulerAngles.y + inputRotateAxisX;
// Weird clamping code due to weird Euler angle mapping...
float newRotationX = (rotationX - inputRotateAxisY);
if (rotationX <= 90.0f && newRotationX >= 0.0f)
newRotationX = Mathf.Clamp(newRotationX, 0.0f, 90.0f);
if (rotationX >= 270.0f)
newRotationX = Mathf.Clamp(newRotationX, 270.0f, 360.0f);
// Weird clamping code due to weird Euler angle mapping...
float newRotationX = (rotationX - inputRotateAxisY);
if (rotationX <= 90.0f && newRotationX >= 0.0f)
newRotationX = Mathf.Clamp(newRotationX, 0.0f, 90.0f);
if (rotationX >= 270.0f)
newRotationX = Mathf.Clamp(newRotationX, 270.0f, 360.0f);
transform.localRotation = Quaternion.Euler(newRotationX, newRotationY, transform.localEulerAngles.z);
transform.localRotation = Quaternion.Euler(newRotationX, newRotationY, transform.localEulerAngles.z);
float moveSpeed = Time.deltaTime * m_MoveSpeed;
if (Input.GetMouseButton(1))
moveSpeed *= Input.GetKey(KeyCode.LeftShift) ? m_Turbo : 1.0f;
else
moveSpeed *= Input.GetAxis("Fire1") > 0.0f ? m_Turbo : 1.0f;
transform.position += transform.forward * moveSpeed * inputVertical;
transform.position += transform.right * moveSpeed * inputHorizontal;
}
float moveSpeed = Time.deltaTime * m_MoveSpeed;
if (Input.GetMouseButton(1))
moveSpeed *= Input.GetKey(KeyCode.LeftShift) ? m_Turbo : 1.0f;
else
moveSpeed *= Input.GetAxis("Fire1") > 0.0f ? m_Turbo : 1.0f;
transform.position += transform.forward * moveSpeed * inputVertical;
transform.position += transform.right * moveSpeed * inputHorizontal;
}
}
}

19
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/CommandBufferPool.cs


namespace UnityEngine.Experimental.Rendering
{
internal class ObjectPool<T> where T : new()
class ObjectPool<T> where T : new()
private readonly Stack<T> m_Stack = new Stack<T>();
private readonly UnityAction<T> m_ActionOnGet;
private readonly UnityAction<T> m_ActionOnRelease;
readonly Stack<T> m_Stack = new Stack<T>();
readonly UnityAction<T> m_ActionOnGet;
readonly UnityAction<T> m_ActionOnRelease;
public int countAll { get; private set; }
public int countActive { get { return countAll - countInactive; } }

m_Stack.Push(element);
}
}
private static ObjectPool<CommandBuffer> m_BufferPool = new ObjectPool<CommandBuffer>(null, x => x.Clear());
static ObjectPool<CommandBuffer> s_BufferPool = new ObjectPool<CommandBuffer>(null, x => x.Clear());
var cmd = m_BufferPool.Get();
var cmd = s_BufferPool.Get();
var cmd = m_BufferPool.Get();
var cmd = s_BufferPool.Get();
cmd.name = name;
return cmd;
}

m_BufferPool.Release(buffer);
s_BufferPool.Release(buffer);
}
}
}

107
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugActionManager.cs


using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering

persistent.repeatMode = DebugActionRepeatMode.Never;
AddAction(DebugAction.MakePersistent, persistent);
AddAction(DebugAction.MoveVertical, new DebugActionDesc { axisTrigger = kDPadVertical, repeatMode = DebugActionRepeatMode.Delay, repeatDelay = 0.2f });
AddAction(DebugAction.MoveHorizontal, new DebugActionDesc { axisTrigger = kDPadHorizontal, repeatMode = DebugActionRepeatMode.Delay, repeatDelay = 0.2f });
AddAction(DebugAction.MoveVertical, new DebugActionDesc { axisTrigger = kDPadVertical, repeatMode = DebugActionRepeatMode.Delay, repeatDelay = 0.4f });
AddAction(DebugAction.MoveHorizontal, new DebugActionDesc { axisTrigger = kDPadHorizontal, repeatMode = DebugActionRepeatMode.Delay, repeatDelay = 0.4f });
}
DebugActionManager()

void RegisterInputs()
{
#if UNITY_EDITOR
// Grab reference to input manager
var currentSelection = UnityEditor.Selection.activeObject;
UnityEditor.EditorApplication.ExecuteMenuItem("Edit/Project Settings/Input");
var inputManager = UnityEditor.Selection.activeObject;
// Wrap in serialized object
var soInputManager = new UnityEditor.SerializedObject(inputManager);
var spAxes = soInputManager.FindProperty("m_Axes");
List <InputManagerEntry > inputEntries = new List<InputManagerEntry>();
new InputManagerEntry { name = kEnableDebugBtn1, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left ctrl", altBtnPositive = "joystick button 8" }.WriteEntry(spAxes);
new InputManagerEntry { name = kEnableDebugBtn2, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "backspace", altBtnPositive = "joystick button 9" }.WriteEntry(spAxes);
inputEntries.Add(new InputManagerEntry { name = kEnableDebugBtn1, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left ctrl", altBtnPositive = "joystick button 8" });
inputEntries.Add(new InputManagerEntry { name = kEnableDebugBtn2, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "backspace", altBtnPositive = "joystick button 9" });
inputEntries.Add(new InputManagerEntry { name = kDebugNextBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page down", altBtnPositive = "joystick button 5" });
inputEntries.Add(new InputManagerEntry { name = kDebugPreviousBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page up", altBtnPositive = "joystick button 4" });
new InputManagerEntry { name = kDebugNextBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page down", altBtnPositive = "joystick button 5" }.WriteEntry(spAxes);
new InputManagerEntry { name = kDebugPreviousBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page up", altBtnPositive = "joystick button 4" }.WriteEntry(spAxes);
new InputManagerEntry { name = kDPadHorizontal, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right", btnNegative = "left", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f }.WriteEntry(spAxes);
new InputManagerEntry { name = kDPadHorizontal, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Sixth, btnPositive = "right", btnNegative = "left", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f }.WriteEntry(spAxes);
new InputManagerEntry { name = kDPadVertical, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "up", btnNegative = "down", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f }.WriteEntry(spAxes);
new InputManagerEntry { name = kDPadVertical, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Seventh, btnPositive = "up", btnNegative = "down", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f }.WriteEntry(spAxes);
inputEntries.Add(new InputManagerEntry { name = kDPadHorizontal, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right", btnNegative = "left", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f });
inputEntries.Add(new InputManagerEntry { name = kDPadHorizontal, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Sixth, btnPositive = "right", btnNegative = "left", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f });
inputEntries.Add(new InputManagerEntry { name = kDPadVertical, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "up", btnNegative = "down", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f });
inputEntries.Add(new InputManagerEntry { name = kDPadVertical, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Seventh, btnPositive = "up", btnNegative = "down", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f });
inputEntries.Add(new InputManagerEntry { name = kValidateBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "return", altBtnPositive = "joystick button 0" });
inputEntries.Add(new InputManagerEntry { name = kPersistentBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right shift", altBtnPositive = "joystick button 2" });
new InputManagerEntry { name = kValidateBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "return", altBtnPositive = "joystick button 0" }.WriteEntry(spAxes);
new InputManagerEntry { name = kPersistentBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right shift", altBtnPositive = "joystick button 2" }.WriteEntry(spAxes);
// Commit
soInputManager.ApplyModifiedProperties();
UnityEditor.Selection.activeObject = currentSelection;
InputRegistering.RegisterInputs(inputEntries);
#if UNITY_EDITOR
class InputManagerEntry
{
public enum Kind { KeyOrButton, Mouse, Axis }
public enum Axis { X, Y, Third, Fourth, Fifth, Sixth, Seventh, Eigth }
public enum Joy { All, First, Second }
public string name = "";
public string desc = "";
public string btnNegative = "";
public string btnPositive = "";
public string altBtnNegative = "";
public string altBtnPositive = "";
public float gravity = 0.0f;
public float deadZone = 0.0f;
public float sensitivity = 0.0f;
public bool snap = false;
public bool invert = false;
public Kind kind = Kind.Axis;
public Axis axis = Axis.X;
public Joy joystick = Joy.All;
bool InputAlreadyRegistered(string name, Kind kind, UnityEditor.SerializedProperty spAxes)
{
for (var i = 0; i < spAxes.arraySize; ++i )
{
var spAxis = spAxes.GetArrayElementAtIndex(i);
var axisName = spAxis.FindPropertyRelative("m_Name").stringValue;
var kindValue = spAxis.FindPropertyRelative("type").intValue;
if (axisName == name && (int)kind == kindValue)
return true;
}
return false;
}
public void WriteEntry(UnityEditor.SerializedProperty spAxes)
{
if(InputAlreadyRegistered(name, kind, spAxes))
return;
spAxes.InsertArrayElementAtIndex(spAxes.arraySize);
var spAxis = spAxes.GetArrayElementAtIndex(spAxes.arraySize - 1);
spAxis.FindPropertyRelative("m_Name").stringValue = name;
spAxis.FindPropertyRelative("descriptiveName").stringValue = desc;
spAxis.FindPropertyRelative("negativeButton").stringValue = btnNegative;
spAxis.FindPropertyRelative("altNegativeButton").stringValue = altBtnNegative;
spAxis.FindPropertyRelative("positiveButton").stringValue = btnPositive;
spAxis.FindPropertyRelative("altPositiveButton").stringValue = altBtnPositive;
spAxis.FindPropertyRelative("gravity").floatValue = gravity;
spAxis.FindPropertyRelative("dead").floatValue = deadZone;
spAxis.FindPropertyRelative("sensitivity").floatValue = sensitivity;
spAxis.FindPropertyRelative("snap").boolValue = snap;
spAxis.FindPropertyRelative("invert").boolValue = invert;
spAxis.FindPropertyRelative("type").intValue = (int)kind;
spAxis.FindPropertyRelative("axis").intValue = (int)axis;
spAxis.FindPropertyRelative("joyNum").intValue = (int)joystick;
}
}
#endif
}
}

14
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugItemHandler.cs


using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
using System;

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

public void OnEditorGUI()
{
if (m_DebugItem.runtimeOnly)
return;
if(OnEditorGUIImpl())
{
DebugMenuUI.changed = true;

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

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

6
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugItemUI.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering
{

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

3
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuManager.cs


using System;
using System.Linq;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

if(m_DebugMenuState != null && m_DebugMenuStateDirty)
{
m_DebugMenuStateDirty = false;
m_DebugMenuState.UpdateAllDebugItems();
m_DebugMenuState.ReInitializeDebugItemStates();
}
m_DebugMenuUI.Update();

56
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuState.cs


using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
[Serializable]
public abstract class DebugItemState
: ScriptableObject
{

#if UNITY_EDITOR
UnityEditor.Undo.undoRedoPerformed += OnUndoRedoPerformed;
#endif
DebugMenuManager.instance.SetDebugMenuState(this);
}
public void OnDisable()
{
DebugMenuManager.instance.SetDebugMenuState(null);
#if UNITY_EDITOR
UnityEditor.Undo.undoRedoPerformed -= OnUndoRedoPerformed;
#endif
}
public void ReInitializeDebugItemStates()
{
CleanUp();
// Populate item states
DebugMenuManager dmm = DebugMenuManager.instance;
for (int panelIdx = 0; panelIdx < dmm.panelCount; ++panelIdx)

if (debugItemState == null)
{
debugItemState = item.handler.CreateDebugItemState();
debugItemState.hideFlags = HideFlags.DontSave;
debugItemState.Initialize(item);
debugItemState.SetValue(item.GetValue());
AddDebugItemState(debugItemState);
if (debugItemState != null)
{
debugItemState.hideFlags = HideFlags.DontSave;
debugItemState.Initialize(item);
debugItemState.SetValue(item.GetValue());
AddDebugItemState(debugItemState);
}
else
{
Debug.LogWarning(String.Format("DebugItemState for item {0} of type {1} is not provided.\nDid you implement CreateDebugItemState in your custom Handler?", item.name, item.type));
}
DebugMenuManager.instance.SetDebugMenuState(this);
UpdateAllDebugItems();
public void OnDisable()
private void CleanUp()
#if UNITY_EDITOR
UnityEditor.Undo.undoRedoPerformed -= OnUndoRedoPerformed;
#endif
foreach (var item in m_ItemStateList)
{
Object.DestroyImmediate(item);
}
m_ItemStateList.Clear();
foreach(var item in m_ItemStateList)
{
Object.DestroyImmediate(item);
}
CleanUp();
}
void OnUndoRedoPerformed()

#endif
}
public void AddDebugItemState(DebugItemState state)
private void AddDebugItemState(DebugItemState state)
{
m_ItemStateList.Add(state);
}

return m_ItemStateList.Find(x => x.itemName == item.name && x.panelName == item.panelName);
}
public void UpdateAllDebugItems()
private void UpdateAllDebugItems()
{
foreach (var itemState in m_ItemStateList)
{

3
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuUI.cs


using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuUpdater.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering
{

14
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugPanel.cs


using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
using System;

public enum DebugItemFlag
{
None,
DynamicDisplay,
EditorOnly
None = 0,
DynamicDisplay = 1 << 0,
EditorOnly = 1 << 1,
RuntimeOnly = 1 << 2
}
public class DebugItem

public DebugItemHandler handler { get { return m_Handler; } }
public DebugItemFlag flags { get { return m_Flags; } }
public bool readOnly { get { return m_Setter == null; } }
public bool editorOnly { get { return (flags & DebugItemFlag.EditorOnly) != 0; } }
public bool runtimeOnly { get { return (flags & DebugItemFlag.RuntimeOnly) != 0; } }
public DebugItem(string name, string panelName, Type type, Func<object> getter, Action<object> setter, DebugItemFlag flags = DebugItemFlag.None, DebugItemHandler handler = null)
{

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

39
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugPanelUI.cs


using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
using System;

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

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

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

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

1
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Debugging.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

13
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Editor/DebugMenuEditor.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
using UnityEditor;
namespace UnityEngine.Experimental.Rendering

{
DebugItemState debugItemState = m_DebugMenuState.FindDebugItemState(item);
UnityEditor.Undo.RecordObject(debugItemState, "DebugMenu State Update");
debugItemState.SetValue(item.GetValue());
EditorUtility.SetDirty(m_DebugMenuState);
if(debugItemState != null)
{
UnityEditor.Undo.RecordObject(debugItemState, "DebugMenu State Update");
debugItemState.SetValue(item.GetValue());
EditorUtility.SetDirty(m_DebugMenuState);
}
}
void OnGUI()

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateBool.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering
{

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateColor.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering
{

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateFloat.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering
{

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateInt.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering
{

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateUInt.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
namespace UnityEngine.Experimental.Rendering
{

2
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderGenerator/Editor/CSharpToHLSL.cs


guard = "_" + guard;
writer.Write("//\n");
writer.Write("// This file was automatically generated from " + it.Key + ". Please don't edit by hand.\n");
writer.Write("// This file was automatically generated. Please don't edit by hand.\n");
writer.Write("//\n\n");
writer.Write("#ifndef " + guard + "\n");
writer.Write("#define " + guard + "\n");

193
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl


}
// Ref: Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, p. 19, 29.
float G_MaskingSmithGGX(float NdotV, float VdotH, float roughness)
float G_MaskingSmithGGX(float NdotV, float roughness)
{
// G1(V, H) = HeavisideStep(VdotH) / (1 + Λ(V)).
// Λ(V) = -0.5 + 0.5 * sqrt(1 + 1 / a²).

// Assume that (VdotH > 0), e.i. (acos(LdotV) < Pi).
float hs = VdotH > 0.0 ? 1.0 : 0.0;
return hs / (0.5 + 0.5 * sqrt(1.0 + a2 * (1.0 / z2 - 1.0)));
return 1 / (0.5 + 0.5 * sqrt(1.0 + a2 * (1.0 / z2 - 1.0)));
// Note that we pass 1.0 instead of 'VdotH' since the multiplication will already clamp.
return D_GGX(NdotH, roughness) * G_MaskingSmithGGX(NdotV, 1.0, roughness) * VdotH / NdotV;
return D_GGX(NdotH, roughness) * G_MaskingSmithGGX(NdotV, roughness) * VdotH / NdotV;
}
// Precompute part of lambdaV
float GetSmithJointGGXPartLambdaV(float NdotV, float roughness)
{
float a2 = roughness * roughness;
return sqrt((-NdotV * a2 + NdotV) * NdotV + a2);
// Note: V = G / (4 * NdotL * NdotV)
float V_SmithJointGGX(float NdotL, float NdotV, float roughness)
float V_SmithJointGGX(float NdotL, float NdotV, float roughness, float partLambdaV)
float a2 = roughness * roughness;
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;
// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
// G = 1 / (1 + lambda_v + lambda_l);
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5
// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5
// G = 1 / (1 + lambda_v + lambda_l);
float a = roughness;
float a2 = a * a;
// Reorder code to be more optimal
float lambdaV = NdotL * sqrt((-NdotV * a2 + NdotV) * NdotV + a2);
// Reorder code to be more optimal:
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
// Simplify visibility term: (2.0 * NdotL * NdotV) / ((4.0 * NdotL * NdotV) * (lambda_v + lambda_l));

// Precompute part of lambdaV
float GetSmithJointGGXLambdaV(float NdotV, float roughness)
float V_SmithJointGGX(float NdotL, float NdotV, float roughness)
float a = roughness;
float a2 = a * a;
return sqrt((-NdotV * a2 + NdotV) * NdotV + a2);
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
return V_SmithJointGGX(NdotL, NdotV, roughness, partLambdaV);
float V_SmithJointGGX(float NdotL, float NdotV, float roughness, float lambdaV)
// Inline D_GGX() * V_SmithJointGGX() together for better code generation.
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness, float partLambdaV)
float a = roughness;
float a2 = a * a;
// Reorder code to be more optimal
lambdaV *= NdotL;
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 lambdaV = NdotL * partLambdaV;
// Simplify visibility term: (2.0 * NdotL * NdotV) / ((4.0 * NdotL * NdotV) * (lambda_v + lambda_l));
return 0.5 / (lambdaV + lambdaL);
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5)
return (INV_PI * 0.5) * (D.x * G.x) / (D.y * G.y);
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness)
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness)
float a = roughness;
// Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough)
float lambdaV = NdotL * (NdotV * (1 - a) + a);
float lambdaL = NdotV * (NdotL * (1 - a) + a);
return 0.5 / (lambdaV + lambdaL);
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
return DV_SmithJointGGX(NdotH, NdotL, NdotV, roughness, partLambdaV);
// Precompute part of LambdaV
float GetSmithJointGGXApproxLambdaV(float NdotV, float roughness)
// Precompute a part of LambdaV.
// Note on this linear approximation.
// Exact for roughness values of 0 and 1. Also, exact when the cosine is 0 or 1.
// Otherwise, the worst case relative error is around 10%.
// https://www.desmos.com/calculator/wtp8lnjutx
float GetSmithJointGGXPartLambdaVApprox(float NdotV, float roughness)
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float lambdaV)
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float partLambdaV)
// Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough)
lambdaV *= NdotL;
float lambdaV = NdotL * partLambdaV;
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness)
{
float partLambdaV = GetSmithJointGGXPartLambdaVApprox(NdotV, roughness);
return V_SmithJointGGXApprox(NdotL, NdotV, roughness, partLambdaV);
}
float f = TdotH * TdotH / (roughnessT * roughnessT) + BdotH * BdotH / (roughnessB * roughnessB) + NdotH * NdotH;
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;
float f = TdotH * TdotH / aT2 + BdotH * BdotH / aB2 + NdotH * NdotH;
return 1.0 / (roughnessT * roughnessB * f * f);
}

}
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);
}
// Note: V = G / (4 * NdotL * NdotV)
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB)
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB, float partLambdaV)
float aT = roughnessT;
float aT2 = aT * aT;
float aB = roughnessB;
float aB2 = aB * aB;
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;
float lambdaV = NdotL * sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV);
float lambdaV = NdotL * partLambdaV;
float GetSmithJointGGXAnisoLambdaV(float TdotV, float BdotV, float NdotV, float roughnessT, float roughnessB)
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB)
float aT = roughnessT;
float aT2 = aT * aT;
float aB = roughnessB;
float aB2 = aB * aB;
return sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV);
float partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
return V_SmithJointGGXAniso(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB, partLambdaV);
float V_SmithJointGGXAnisoLambdaV(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB, float lambdaV)
// 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 TdotL, float BdotL, float NdotL,
float roughnessT, float roughnessB, float partLambdaV)
float aT = roughnessT;
float aT2 = aT * aT;
float aB = roughnessB;
float aB2 = aB * aB;
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;
lambdaV *= NdotL;
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 lambdaV = NdotL * partLambdaV;
return 0.5 / (lambdaV + lambdaL);
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5)
return (INV_PI * 0.5) * (D.x * G.x) / (D.y * G.y);
}
float DV_SmithJointGGXAniso(float TdotH, float BdotH, float NdotH,
float TdotV, float BdotV, float NdotV,
float TdotL, float BdotL, float NdotL,
float roughnessT, float roughnessB)
{
float partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
return DV_SmithJointGGXAniso(TdotH, BdotH, NdotH,
TdotV, BdotV, NdotV,
TdotL, BdotL, NdotL,
roughnessT, roughnessB, partLambdaV);
}
//-----------------------------------------------------------------------------

return INV_PI;
}
float DisneyDiffuseNoPI(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
float DisneyDiffuseNoPI(float NdotV, float NdotL, float LdotV, float perceptualRoughness)
float fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
// (2 * LdotH * LdotH) = 1 + LdotV
// float fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
float fd90 = 0.5 + (perceptualRoughness + perceptualRoughness * LdotV);
float viewScatter = F_Schlick(1.0, fd90, NdotV);
float viewScatter = F_Schlick(1.0, fd90, NdotV);
return lightScatter * viewScatter;
// Normalize the BRDF for polar view angles of up to (Pi/4).
// We use the worst case of (roughness = albedo = 1), and, for each view angle,
// integrate (brdf * cos(theta_light)) over all light directions.
// The resulting value is for (theta_view = 0), which is actually a little bit larger
// than the value of the integral for (theta_view = Pi/4).
// Hopefully, the compiler folds the constant together with (1/Pi).
return rcp(1.03571) * (lightScatter * viewScatter);
float DisneyDiffuse(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
float DisneyDiffuse(float NdotV, float NdotL, float LdotV, float perceptualRoughness)
return INV_PI * DisneyDiffuseNoPI(NdotV, NdotL, LdotH, perceptualRoughness);
return INV_PI * DisneyDiffuseNoPI(NdotV, NdotL, LdotV, perceptualRoughness);
float3 DiffuseGGXNoPI(float3 albedo, float NdotV, float NdotL, float NdotH, float LdotV, float perceptualRoughness)
float3 DiffuseGGXNoPI(float3 albedo, float NdotV, float NdotL, float NdotH, float LdotV, float roughness)
float facing = 0.5 + 0.5 * LdotV;
float rough = facing * (0.9 - 0.4 * facing) * ((0.5 + NdotH) / NdotH);
float facing = 0.5 + 0.5 * LdotV; // (LdotH)^2
float rough = facing * (0.9 - 0.4 * facing) * (0.5 / NdotH + 1);
float smooth = transmitL * transmitV * 1.05; // Normalize F_t over the hemisphere
float single = lerp(smooth, rough, perceptualRoughness); // Rescaled by PI
// This constant is picked s.t. setting perceptualRoughness, albedo and all angles to 1
// allows us to match the Lambertian and the Disney Diffuse models. Original value: 0.1159.
float multiple = perceptualRoughness * (0.079577 * PI); // Rescaled by PI
float smooth = transmitL * transmitV * 1.05; // Normalize F_t over the hemisphere
float single = lerp(smooth, rough, roughness); // Rescaled by PI
float multiple = roughness * (0.1159 * PI); // Rescaled by PI
float3 DiffuseGGX(float3 albedo, float NdotV, float NdotL, float NdotH, float LdotV, float perceptualRoughness)
float3 DiffuseGGX(float3 albedo, float NdotV, float NdotL, float NdotH, float LdotV, float roughness)
return INV_PI * DiffuseGGXNoPI(albedo, NdotV, NdotL, NdotH, LdotV, perceptualRoughness);
return INV_PI * DiffuseGGXNoPI(albedo, NdotV, NdotL, NdotH, LdotV, roughness);
}
#endif // UNITY_BSDF_INCLUDED

26
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


// The reason is that for compute shader we need to guarantee that the layout of CBs is consistent across kernels. Something that we can't control with the global namespace (uniforms get optimized out if not used, modifying the global CBuffer layout per kernel)
// Structure definition that are share between C# and hlsl.
// These structures need to be align on float4 to respectect various packing rules from sahder language.
// These structures need to be align on float4 to respect various packing rules from sahder language.
// This mean that these structure need to be padded.
// Do not use "in", only "out" or "inout" as califier, not "inline" keyword either, useless.

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

float3 FastSign(float x)
{
return saturate(x * FLT_MAX) * 2.0 - 1.0;
}
// Orthonormalize the basis vectors using the Gram-Schmidt process.
// We assume that the length of the surface normal is sufficiently close to 1.
// return orthonormalize tangent
float3 Orthonormalize(float3 tangent, float3 normal)
{
return normalize(tangent - dot(tangent, normal) * normal);
}
// ----------------------------------------------------------------------------

46
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl


}
// Ref: Moving Frostbite to PBR - Gotanda siggraph 2011
float GetSpecularOcclusion(float NdotV, float ambientOcclusion, float roughness)
// Return specular occlusion based on ambient occlusion (usually get from SSAO) and view/roughness info
float GetSpecularOcclusionFromAmbientOcclusion(float NdotV, float ambientOcclusion, float roughness)
}
// ref: Practical Realtime Strategies for Accurate Indirect Occlusion
// Update ambient occlusion to colored ambient occlusion based on statitics of how light is bouncing in an object and with the albedo of the object
float3 GTAOMultiBounce(float visibility, float3 albedo)
{
float3 a = 2.0404 * albedo - 0.3324;
float3 b = -4.7951 * albedo + 0.6417;
float3 c = 2.7552 * albedo + 0.6903;
float x = visibility;
return max(x, ((x * a + b) * x + c) * x);
}
// Based on Oat and Sander's 2008 technique
// Area/solidAngle of intersection of two cone
float SphericalCapIntersectionSolidArea(float cosC1, float cosC2, float cosB)
{
float r1 = FastACos(cosC1);
float r2 = FastACos(cosC2);
float rd = FastACos(cosB);
float area = 0.0;
if (rd <= max(r1, r2) - min(r1, r2))
{
// One cap is completely inside the other
area = TWO_PI - TWO_PI * max(cosC1, cosC2);
}
else if (rd >= r1 + r2)
{
// No intersection exists
area = 0.0;
}
else
{
float diff = abs(r1 - r2);
float den = r1 + r2 - diff;
float x = 1.0 - saturate((rd - diff) / den);
area = smoothstep(0.0, 1.0, x);
area *= TWO_PI - TWO_PI * max(cosC1, cosC2);
}
return area;
}
//-----------------------------------------------------------------------------

29
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl


// Convert anisotropic ratio (0->no isotropic; 1->full anisotropy in tangent direction) to roughness
void ConvertAnisotropyToRoughness(float roughness, float anisotropy, out float roughnessT, out float roughnessB)
{
// (0 <= anisotropy <= 1), therefore (0 <= anisoAspect <= 1)
// The 0.9 factor limits the aspect ratio to 10:1.
float anisoAspect = sqrt(1.0 - 0.9 * anisotropy);
roughnessT = roughness / anisoAspect; // Distort along tangent (rougher)
roughnessB = roughness * anisoAspect; // Straighten along bitangent (smoother)
}
// Ref: Donald Revie - Implementing Fur Using Deferred Shading (GPU Pro 2)
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to the normal.
// The returned normal is NOT normalized.
float3 ComputeGrainNormal(float3 grainDir, float3 V)
{
float3 B = cross(-V, grainDir);
return cross(B, grainDir);
}
// Fake anisotropic by distorting the normal.
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to N.
// Anisotropic ratio (0->no isotropic; 1->full anisotropy in tangent direction)
float3 GetAnisotropicModifiedNormal(float3 grainDir, float3 N, float3 V, float anisotropy)
{
float3 grainNormal = ComputeGrainNormal(grainDir, V);
// TODO: test whether normalizing 'grainNormal' is worth it.
return normalize(lerp(N, grainNormal, anisotropy));
// Use the parametrization of Sony Imageworks.
// Ref: Revisiting Physically Based Shading at Imageworks, p. 15.
roughnessT = roughness * (1 + anisotropy);
roughnessB = roughness * (1 - anisotropy);
}
//-----------------------------------------------------------------------------

13
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/EntityLighting.hlsl


}
// This sample a 3D volume storing SH
// Volume is store as 3D texture with 4 R, G, B, X set of 4 coefficient store atlas in same 3D texture. X unused.
// TODO: the packing here is innefficient as we will fetch values far away from each other and they may not fit into the cache
// Suggest we pack only RGB not X and continuous
float3 SampleProbeVolumeSH4(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float4x4 WorldToTexture, float texelSizeX)
// Volume is store as 3D texture with 4 R, G, B, X set of 4 coefficient store atlas in same 3D texture. X is use for occlusion.
// TODO: the packing here is inefficient as we will fetch values far away from each other and they may not fit into the cache - Suggest we pack only RGB continuously
// TODO: The calcul of texcoord could be perform with a single matrix multicplication calcualted on C++ side that will fold probeVolumeMin and probeVolumeSizeInv into it and handle the identity case, no reasons to do it in C++ (ask Ionut about it)
// It should also handle the camera relative path (if the render pipeline use it)
float3 SampleProbeVolumeSH4(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float4x4 WorldToTexture,
float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
float3 texCoord = mul(WorldToTexture, float4(positionWS, 1.0)).xyz;
float3 position = (transformToLocal == 1.0f) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
// Each component is store in the same texture 3D. Each use one quater on the x axis
// Here we get R component then increase by step size (0.25) to get other component. This assume 4 component
// but last one is not used.

8
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Fibonacci.hlsl


return float2(i / fibN1 + (0.5f / fibN1), frac(i * (fibN2 / fibN1)));
}
#define GOLDEN_RATIO 1.6180339887498948482
// Replaces the Fibonacci sequence in Fibonacci2dSeq() with the Golden ratio.
float2 Golden2dSeq(int i, float n)
{
return float2(i / n + (0.5f / n), frac(i * rcp(GOLDEN_RATIO)));
}
static const int k_FibonacciSeq[] = {
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181
};

174
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl


#include "BSDF.hlsl"
#include "Sampling.hlsl"
// TODO: We need to change this hard limit!
#ifndef UNITY_SPECCUBE_LOD_STEPS
#define UNITY_SPECCUBE_LOD_STEPS 6
#endif

// approximating the cone of the specular lobe, and then computing the MIP map level
// which (approximately) covers the footprint of the lobe with a single texel.
// Improves the perceptual roughness distribution.
float PerceptualRoughnessToMipmapLevel(float perceptualRoughness)
float PerceptualRoughnessToMipmapLevel(float perceptualRoughness, uint mipMapCount)
return perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
return perceptualRoughness * mipMapCount;
}
float PerceptualRoughnessToMipmapLevel(float perceptualRoughness)
{
return PerceptualRoughnessToMipmapLevel(perceptualRoughness, UNITY_SPECCUBE_LOD_STEPS);
}
// The *accurate* version of the non-linear remapping. It works by

return saturate(1.7 / 1.4 - sqrt(2.89 / 1.96 - (2.8 / 1.96) * perceptualRoughness));
}
//-----------------------------------------------------------------------------
// Anisotropic image based lighting
//-----------------------------------------------------------------------------
// Ref: Donald Revie - Implementing Fur Using Deferred Shading (GPU Pro 2)
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to the normal.
// The returned normal is NOT normalized.
float3 ComputeGrainNormal(float3 grainDir, float3 V)
{
float3 B = cross(grainDir, V);
return cross(B, grainDir);
}
// Fake anisotropy by distorting the normal (non-negative anisotropy values only).
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to N.
// Anisotropic ratio (0->no isotropic; 1->full anisotropy in tangent direction)
float3 GetAnisotropicModifiedNormal(float3 grainDir, float3 N, float3 V, float anisotropy)
{
float3 grainNormal = ComputeGrainNormal(grainDir, V);
return normalize(lerp(N, grainNormal, anisotropy));
}
// Ref: "Moving Frostbite to PBR", p. 69.
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness, float NdotV)
{

return lerp(N, R, lerpFactor);
}
//-----------------------------------------------------------------------------
// Anisotropic image based lighting
//-----------------------------------------------------------------------------
// To simulate the streching of highlight at grazing angle for IBL we shrink the roughness
// which allow to fake an anisotropic specular lobe.
// Ref: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/ - slide 84

// Compute { localL = reflect(-localV, localH) }
float3 localL = -localV + 2.0 * VdotH * localH;
NdotL = localL.z;
L = mul(localL, localToWorld);
}
// Ref: "A Simpler and Exact Sampling Routine for the GGX Distribution of Visible Normals".
void SampleVisibleAnisoGGXDir(float2 u, float3 V, float3x3 localToWorld,
float roughnessT, float roughnessB,
out float3 L,
out float NdotL,
out float NdotH,
out float VdotH,
bool VeqN = false)
{
float3 localV = mul(V, transpose(localToWorld));
// Construct an orthonormal basis around the stretched view direction.
float3x3 viewToLocal;
if (VeqN)
{
viewToLocal = k_identity3x3;
}
else
{
viewToLocal[2] = normalize(float3(roughnessT * localV.x, roughnessB * localV.y, localV.z));
viewToLocal[0] = (viewToLocal[2].z < 0.9999) ? normalize(cross(viewToLocal[2], float3(0, 0, 1))) : float3(1, 0, 0);
viewToLocal[1] = cross(viewToLocal[0], viewToLocal[2]);
}
// Compute a sample point with polar coordinates (r, phi).
float r = sqrt(u.x);
float b = viewToLocal[2].z + 1;
float a = rcp(b);
float c = (u.y < a) ? u.y * b : 1 + (u.y * b - 1) / viewToLocal[2].z;
float phi = PI * c;
float p1 = r * cos(phi);
float p2 = r * sin(phi) * ((u.y < a) ? 1 : viewToLocal[2].z);
// Unstretch.
float3 viewH = normalize(float3(roughnessT * p1, roughnessB * p2, sqrt(1 - p1 * p1 - p2 * p2)));
VdotH = viewH.z;
float3 localH = mul(viewH, viewToLocal);
NdotH = localH.z;
// Compute { localL = reflect(-localV, localH) }
float3 localL = -localV + 2 * VdotH * localH;
NdotL = localL.z;
L = mul(localL, localToWorld);

float3 N,
float roughness,
float index, // Current MIP level minus one
float lastMipLevel,
float invOmegaP,
uint sampleCount, // Must be a Fibonacci number
bool prefilter,

// Bias samples towards the mirror direction to reduce variance.
// This will have a side effect of making the reflection sharper.
// Ref: Stochastic Screen-Space Reflections, p. 67.
const float bias = 0.5 * roughness;
#ifndef USE_KARIS_APPROXIMATION
float NdotV = 1; // N == V
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
#endif
float3 lightInt = float3(0.0, 0.0, 0.0);
float cbsdfInt = 0.0;

float3 L;
float NdotL, NdotH, VdotH;
bool isValid;
float NdotL, NdotH, LdotH;
L = mul(localL, localToWorld);
NdotL = localL.z;
isValid = true;
L = mul(localL, localToWorld);
NdotL = localL.z;
LdotH = sqrt(0.5 + 0.5 * NdotL);
u.x = lerp(u.x, 0.0, bias);
SampleGGXDir(u, V, localToWorld, roughness, L, NdotL, NdotH, VdotH, true);
// Note: if (N == V), all of the microsurface normals are visible.
SampleGGXDir(u, V, localToWorld, roughness, L, NdotL, NdotH, LdotH, true);
isValid = NdotL > 0.0;
if (NdotL <= 0) continue; // Note that some samples will have 0 contribution
}
float mipLevel;

// in order to reduce the variance.
// Ref: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html
//
// pdf = D * NdotH * jacobian, where jacobian = 1.0 / (4* LdotH).
//
// Since L and V are symmetric around H, LdotH == VdotH.
// Since we pre-integrate the result for the normal direction,
// N == V and then NdotH == LdotH. Therefore, the BRDF's pdf
// can be simplified:
// pdf = D * NdotH / (4 * LdotH) = D * 0.25;
//
// - OmegaS : Solid angle associated with the sample
// - OmegaP : Solid angle associated with the texel of the cubemap
// - OmegaS: Solid angle associated with the sample
// - OmegaP: Solid angle associated with the texel of the cubemap
float omegaS;

}
else
{
float pdf = D_GGX(NdotH, roughness) * 0.25;
// TODO: check the accuracy of the sample's solid angle fit for GGX.
omegaS = rcp(sampleCount) / pdf;
// float PDF = D * NdotH * Jacobian, where Jacobian = 1 / (4 * LdotH).
// Since (N == V), NdotH == LdotH.
float pdf = 0.25 * D_GGX(NdotH, roughness);
// TODO: improve the accuracy of the sample's solid angle fit for GGX.
omegaS = rcp(sampleCount) * rcp(pdf);
// invOmegaP is precomputed on CPU and provide as a parameter of the function
// 'invOmegaP' is precomputed on CPU and provided as a parameter to the function.
mipLevel = 0.5 * log2(omegaS * invOmegaP);
const float mipBias = roughness;
mipLevel = 0.5 * log2(omegaS * invOmegaP) + mipBias;
if (isValid)
{
// Bias the MIP map level to compensate for the importance sampling bias.
// This will blur the reflection.
// TODO: find a more accurate MIP bias function.
mipLevel = lerp(mipLevel, lastMipLevel, bias);
// TODO: use a Gaussian-like filter to generate the MIP pyramid.
float3 val = SAMPLE_TEXTURECUBE_LOD(tex, sampl, L, mipLevel).rgb;
// TODO: use a Gaussian-like filter to generate the MIP pyramid.
float3 val = SAMPLE_TEXTURECUBE_LOD(tex, sampl, L, mipLevel).rgb;
// The goal of this function is to use Monte-Carlo integration to find
// X = Integral{Radiance(L) * CBSDF(L, N, V) dL} / Integral{CBSDF(L, N, V) dL}.
// Note: Integral{CBSDF(L, N, V) dL} is given by the FDG texture.
// CBSDF = F * D * G * NdotL / (4 * NdotL * NdotV) = F * D * G / (4 * NdotV).
// PDF = D * NdotH / (4 * LdotH).
// Weight = CBSDF / PDF = F * G * LdotH / (NdotV * NdotH).
// Since we perform filtering with the assumption that (V == N),
// (LdotH == NdotH) && (NdotV == 1) && (Weight == F * G).
// Therefore, after the Monte Carlo expansion of the integrals,
// X = Sum(Radiance(L) * Weight) / Sum(Weight) = Sum(Radiance(L) * F * G) / Sum(F * G).
// Our goal is to use Monte-Carlo integration with importance sampling to evaluate
// X(V) = Integral{Radiance(L) * CBSDF(L, N, V) dL} / Integral{CBSDF(L, N, V) dL}.
// CBSDF = F * D * G * NdotL / (4 * NdotL * NdotV) = F * D * G / (4 * NdotV).
// PDF = D * NdotH / (4 * LdotH).
// Weight = CBSDF / PDF = F * G * LdotH / (NdotV * NdotH).
// Since we perform filtering with the assumption that (V == N),
// (LdotH == NdotH) && (NdotV == 1) && (Weight == F * G).
// We use the approximation of Brian Karis from "Real Shading in Unreal Engine 4":
// Weight ≈ NdotL, which produces nearly identical results in practice.
#ifndef USE_KARIS_APPROXIMATION
// The choice of the Fresnel factor does not appear to affect the result.
float F = 1; // F_Schlick(F0, LdotH);
float V = V_SmithJointGGX(NdotL, NdotV, roughness, partLambdaV);
float G = V * NdotL * NdotV; // 4 cancels out
lightInt += NdotL * val;
cbsdfInt += NdotL;
}
lightInt += F * G * val;
cbsdfInt += F * G;
#else
// Use the approximation from "Real Shading in Unreal Engine 4": Weight ≈ NdotL.
lightInt += NdotL * val;
cbsdfInt += NdotL;
#endif
}
return float4(lightInt / cbsdfInt, 1.0);

9
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/PerPixelDisplacement.hlsl


// it return the offset to apply to the UVSet provide in PerPixelHeightDisplacementParam
// viewDirTS is view vector in texture space matching the UVSet
// ref: https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
float2 ParallaxOcclusionMapping(float lod, float lodThreshold, int numSteps, float3 viewDirTS, float maxHeight, PerPixelHeightDisplacementParam ppdParam, out float outHeight)
float2 ParallaxOcclusionMapping(float lod, float lodThreshold, int numSteps, float3 viewDirTS, PerPixelHeightDisplacementParam ppdParam, out float outHeight)
// TODO: explain this factor! Necessary to achieve parity between tessellation and POM w.r.t. height.
maxHeight *= 0.1;
// Convention: 1.0 is top, 0.0 is bottom - POM is always inward, no extrusion
float stepSize = 1.0 / (float)numSteps;

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

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

9
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/Shadow.hlsl


#ifndef SHADOW_HLSL
#ifndef SHADOW_HLSL
#define SHADOW_HLSL
//
// Shadow master include header.

#define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0 // only on >= sm 5.1
#define SHADOW_OPTIMIZE_REGISTER_USAGE 0 // redefine this as 1 in your ShadowContext.hlsl to optimize for register usage over instruction count
#include "../../../Core/Shadow/ShadowBase.cs.hlsl" // ShadowData definition, auto generated (don't modify)
#include "ShadowTexFetch.hlsl" // Resource sampling definitions (don't modify)

// Shadow context definition and initialization, i.e. resource binding (project header, must be kept in sync with C# runtime)
#define SHADOW_CONTEXT_INCLUDE
#include "../../ShadowIncludes.inl"
#include "../../ShadowIncludes.hlsl"
//#include "ShadowContext.hlsl"
// helper function to extract shadowmap data from the ShadowData struct
void UnpackShadowmapId( uint shadowmapId, out uint texIdx, out uint sampIdx, out float slice )

// include project specific shadow dispatcher. If this file is not empty, it MUST define which default shadows it's overriding
#define SHADOW_DISPATCH_INCLUDE
#include "../../ShadowIncludes.inl"
#include "../../ShadowIncludes.hlsl"
//#include "ShadowDispatch.hlsl"
// if shadow dispatch is empty we'll fall back to default shadow sampling implementations
#ifndef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL

310
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl


// calc TCs
float2 posTC = posNDC * 0.5 + 0.5;
closestSampleNDC = (floor(posTC * sd.textureSize.zw) + 0.5) * sd.texelSizeRcp.zw * 2.0 - 1.0.xx;
return (posTC * sd.scaleOffset.xy + sd.scaleOffset.zw) * sd.textureSize.xy;
return uint2( (posTC * sd.scaleOffset.xy + sd.scaleOffset.zw) * sd.textureSize.xy );
}
int EvalShadow_GetCubeFaceID( float3 dir )

//
#define kMaxShadowCascades 4
#define SHADOW_REPEAT_CASCADE( _x ) _x, _x, _x, _x
int EvalShadow_GetSplitSphereIndexForDirshadows( float3 positionWS, float4 dirShadowSplitSpheres[4], out float relDistance )
{

payloadOffset++;
float4 borders = asfloat( shadowContext.payloads[payloadOffset] );
payloadOffset++;
float border = borders[shadowSplitIndex];
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
// normal based bias

// Be careful of this code, we need it here before the if statement otherwise the compiler screws up optimizing dirShadowSplitSpheres VGPRs away
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz;
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz );
float3 wposDir = normalize( -splitSphere + positionWS );
float cascDot = dot( cascadeDir, wposDir );
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) );
// sample the texture
uint texIdx, sampIdx;
float slice;

UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
float border = borders[shadowSplitIndex];
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
float shadow1 = 1.0;
float shadow1 = 1.0;
float4 splitSphere = dirShadowSplitSpheres[shadowSplitIndex - 1];
float3 cascadeDir = normalize( -splitSphere.xyz + dirShadowSplitSpheres[shadowSplitIndex].xyz );
float3 wposDir = normalize( -splitSphere.xyz + positionWS );
float cascDot = dot( cascadeDir, wposDir );
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) );
[branch]
if( alpha > 0.0 )
{
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];

UnpackShadowmapId( sd.id, slice );
[branch]
if( all( abs( posNDC.xy ) <= (1.0 - sd.texelSizeRcp.zw * 0.5) ) )
shadow1 = SampleShadow_SelectAlgorithm( shadowContext, sd, orig_payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
}

}
#define EvalShadow_CascadedDepth_( _samplerType ) \
float EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
/* load the right shadow data for the current face */ \
float4 dirShadowSplitSpheres[kMaxShadowCascades]; \
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \
float relDistance; \
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres, relDistance ); \
if( shadowSplitIndex < 0 ) \
return 1.0; \
\
float4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
float4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* normal based bias */ \
float3 orig_pos = positionWS; \
uint orig_payloadOffset = payloadOffset; \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posNDC; \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
\
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
\
float border = borders[shadowSplitIndex]; \
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
\
shadowSplitIndex++; \
float shadow1 = 1.0; \
if( shadowSplitIndex < kMaxShadowCascades ) \
{ \
float4 splitSphere = dirShadowSplitSpheres[shadowSplitIndex - 1]; \
float3 cascadeDir = normalize( -splitSphere.xyz + dirShadowSplitSpheres[shadowSplitIndex].xyz ); \
float3 wposDir = normalize( -splitSphere.xyz + positionWS ); \
float cascDot = dot( cascadeDir, wposDir ); \
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) ); \
shadow1 = shadow; \
\
[branch] \
if( alpha > 0.0 ) \
{ \
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, false ); \
/* sample the texture */ \
UnpackShadowmapId( sd.id, slice ); \
\
if( all( abs( posNDC.xy ) <= (1.0 - sd.texelSizeRcp.zw * 0.5) ) ) \
shadow1 = SampleShadow_SelectAlgorithm( shadowContext, sd, orig_payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
} \
} \
shadow = lerp( shadow, shadow1, alpha ); \
return shadow; \
#define EvalShadow_CascadedDepth_( _samplerType ) \
float EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
/* load the right shadow data for the current face */ \
float4 dirShadowSplitSpheres[kMaxShadowCascades]; \
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \
float relDistance; \
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres, relDistance ); \
if( shadowSplitIndex < 0 ) \
return 1.0; \
\
float4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
float4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
float border = borders[shadowSplitIndex]; \
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* normal based bias */ \
float3 orig_pos = positionWS; \
uint orig_payloadOffset = payloadOffset; \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
/* Be careful of this code, we need it here before the if statement otherwise the compiler screws up optimizing dirShadowSplitSpheres VGPRs away */ \
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz ); \
float3 wposDir = normalize( -splitSphere + positionWS ); \
float cascDot = dot( cascadeDir, wposDir ); \
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) ); \
\
/* get shadowmap texcoords */ \
float3 posNDC; \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
\
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
\
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
float shadow1 = 1.0; \
\
shadowSplitIndex++; \
if( shadowSplitIndex < kMaxShadowCascades ) \
{ \
shadow1 = shadow; \
\
if( alpha > 0.0 ) \
{ \
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, false ); \
/* sample the texture */ \
UnpackShadowmapId( sd.id, slice ); \
\
[branch] \
if( all( abs( posNDC.xy ) <= (1.0 - sd.texelSizeRcp.zw * 0.5) ) ) \
shadow1 = SampleShadow_SelectAlgorithm( shadowContext, sd, orig_payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
} \
} \
shadow = lerp( shadow, shadow1, alpha ); \
return shadow; \
} \
\
float EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
uint shadowAlgorithms[kMaxShadowCascades] = { SHADOW_REPEAT_CASCADE( shadowAlgorithm ) }; \
return EvalShadow_CascadedDepth_Blend( shadowContext, shadowAlgorithms, tex, samp, positionWS, normalWS, index, L ); \
EvalShadow_CascadedDepth_( SamplerComparisonState )
EvalShadow_CascadedDepth_( SamplerState )
#undef EvalShadow_CascadedDepth_

float EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
{
// load the right shadow data for the current face
float4 dirShadowSplitSpheres[4];
float4 dirShadowSplitSpheres[kMaxShadowCascades];
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres );
float relDistance;
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres, relDistance );

float3 posNDC;
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true );
if( shadowSplitIndex < (kMaxShadowCascades-1) )
int nextSplit = min( shadowSplitIndex+1, kMaxShadowCascades-1 );
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz;
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( 3, shadowSplitIndex + 1 )].xyz );
float3 wposDir = normalize( -splitSphere + positionWS );
float cascDot = dot( cascadeDir, wposDir );
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) );
if( shadowSplitIndex < nextSplit && step( EvalShadow_hash12( posTC.xy ), alpha ) )
float4 splitSphere = dirShadowSplitSpheres[shadowSplitIndex];
float3 cascadeDir = normalize( -splitSphere.xyz + dirShadowSplitSpheres[shadowSplitIndex+1].xyz );
float3 wposDir = normalize( -splitSphere.xyz + positionWS );
float cascDot = dot( cascadeDir, wposDir );
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) );
if( step( EvalShadow_hash12( posTC.xy ), alpha ) )
{
shadowSplitIndex++;
sd = shadowContext.shadowDatas[index + 2 + shadowSplitIndex];
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex+1] * sd.texelSizeRcp.zw, sd.normalBias );
posTC = EvalShadow_GetTexcoords( sd, positionWS );
}
sd = shadowContext.shadowDatas[index + 1 + nextSplit];
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[nextSplit] * sd.texelSizeRcp.zw, sd.normalBias );
posTC = EvalShadow_GetTexcoords( sd, positionWS );
}
// sample the texture
uint texIdx, sampIdx;

return shadowSplitIndex < (kMaxShadowCascades-1) ? shadow : lerp( shadow, 1.0, alpha );
}
#define EvalShadow_CascadedDepth_( _samplerType ) \
float EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
/* load the right shadow data for the current face */ \
float4 dirShadowSplitSpheres[kMaxShadowCascades]; \
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \
float relDistance; \
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres, relDistance ); \
if( shadowSplitIndex < 0 ) \
return 1.0; \
\
float4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
float4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
float border = borders[shadowSplitIndex]; \
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* normal based bias */ \
float3 orig_pos = positionWS; \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posNDC; \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
\
if( shadowSplitIndex < (kMaxShadowCascades-1) ) \
{ \
float4 splitSphere = dirShadowSplitSpheres[shadowSplitIndex]; \
float3 cascadeDir = normalize( -splitSphere.xyz + dirShadowSplitSpheres[shadowSplitIndex+1].xyz ); \
float3 wposDir = normalize( -splitSphere.xyz + positionWS ); \
float cascDot = dot( cascadeDir, wposDir ); \
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) ); \
\
if( step( EvalShadow_hash12( posTC.xy ), alpha ) ) \
{ \
sd = shadowContext.shadowDatas[index + 2 + shadowSplitIndex]; \
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex+1] * sd.texelSizeRcp.zw, sd.normalBias ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
} \
} \
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
return shadowSplitIndex < (kMaxShadowCascades-1) ? shadow : lerp( shadow, 1.0, alpha ); \
#define EvalShadow_CascadedDepth_( _samplerType ) \
float EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
/* load the right shadow data for the current face */ \
float4 dirShadowSplitSpheres[kMaxShadowCascades]; \
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \
float relDistance; \
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres, relDistance ); \
if( shadowSplitIndex < 0 ) \
return 1.0; \
\
float4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
float4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
payloadOffset++; \
float border = borders[shadowSplitIndex]; \
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* normal based bias */ \
float3 orig_pos = positionWS; \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posNDC; \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
\
int nextSplit = min( shadowSplitIndex+1, kMaxShadowCascades-1 ); \
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[nextSplit].xyz ); \
float3 wposDir = normalize( -splitSphere + positionWS ); \
float cascDot = dot( cascadeDir, wposDir ); \
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) ); \
\
if( shadowSplitIndex != nextSplit && step( EvalShadow_hash12( posTC.xy ), alpha ) ) \
{ \
sd = shadowContext.shadowDatas[index + 1 + nextSplit]; \
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[nextSplit] * sd.texelSizeRcp.zw, sd.normalBias ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
} \
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
return shadowSplitIndex < (kMaxShadowCascades-1) ? shadow : lerp( shadow, 1.0, alpha ); \
} \
\
float EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
uint shadowAlgorithms[kMaxShadowCascades] = { SHADOW_REPEAT_CASCADE( shadowAlgorithm ) }; \
return EvalShadow_CascadedDepth_Dither( shadowContext, shadowAlgorithms, tex, samp, positionWS, normalWS, index, L ); \
EvalShadow_CascadedDepth_( SamplerComparisonState )
EvalShadow_CascadedDepth_( SamplerState )
#undef EvalShadow_CascadedDepth_

float4 closestWS = mul( closestNDC, sd.shadowToWorld );
return closestWS.xyz / closestWS.w;
}
float3 EvalShadow_GetClosestSample_Cascade( ShadowContext shadowContext, Texture2DArray tex, float3 positionWS, float3 normalWS, int index, float4 L )
{
// load the right shadow data for the current face
float4 dirShadowSplitSpheres[4];
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres );
float relDistance;
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres, relDistance );
if( shadowSplitIndex < 0 )
return 1.0;
float4 scales = asfloat( shadowContext.payloads[payloadOffset] );
payloadOffset++;
float4 borders = asfloat( shadowContext.payloads[payloadOffset] );
payloadOffset++;
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
float4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
// load the texel
uint texIdx, sampIdx;
float slice;
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice );
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, slice, 0 ).x;
// reconstruct depth position
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
return closestWS.xyz / closestWS.w;
}

46
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowSampling.hlsl


float2 fetchesUV[9];
SampleShadow_ComputeSamples_Tent_5x5(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
for (int i = 0; i < 9; i++)
for( int i = 0; i < 9; i++ )
return shadow;
}

float2 fetchesUV[16];
SampleShadow_ComputeSamples_Tent_7x7(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
for (int i = 0; i < 16; i++)
#if SHADOW_OPTIMIZE_REGISTER_USAGE == 1
int i;
[loop]
for( i = 0; i < 1; i++ )
{
shadow += fetchesWeights[ 0] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 0].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 1] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 1].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 2] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 2].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 3] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 3].xy, coord.z ), slice ).x;
}
[loop]
for( i = 0; i < 1; i++ )
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 4] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 4].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 5] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 5].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 6] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 6].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 7] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 7].xy, coord.z ), slice ).x;
[loop]
for( i = 0; i < 1; i++ )
{
shadow += fetchesWeights[ 8] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 8].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 9] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 9].xy, coord.z ), slice ).x;
shadow += fetchesWeights[10] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[10].xy, coord.z ), slice ).x;
shadow += fetchesWeights[11] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[11].xy, coord.z ), slice ).x;
}
[loop]
for( i = 0; i < 1; i++ )
{
shadow += fetchesWeights[12] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[12].xy, coord.z ), slice ).x;
shadow += fetchesWeights[13] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[13].xy, coord.z ), slice ).x;
shadow += fetchesWeights[14] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[14].xy, coord.z ), slice ).x;
shadow += fetchesWeights[15] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[15].xy, coord.z ), slice ).x;
}
#else
for( int i = 0; i < 16; i++ )
{
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[i].xy, coord.z ), slice ).x;
}
#endif
return shadow;
}

10
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl


return exp(-opticalDepth);
}
float TransmittanceIntegralOverHomogeneousInterval(float extinction, float start, float end)
{
return (exp(-extinction * start) - exp(-extinction * end)) / extinction;
}
float3 OpticalDepthHomogeneous(float3 extinction, float intervalLength)
{
return extinction * intervalLength;

{
return exp(-opticalDepth);
}
float3 TransmittanceIntegralOverHomogeneousInterval(float3 extinction, float start, float end)
{
return (exp(-extinction * start) - exp(-extinction * end)) / extinction;
}
float IsotropicPhaseFunction()

32
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Wind.hlsl


void ApplyWind( inout float3 worldPos,
inout float3 worldNormal,
float3 rootWP,
float stiffness,
float drag,
float shiverDrag,
float shiverDirectionality,
float initialBend,
float shiverMask,
float4 time)
void ApplyWindDisplacement( inout float3 positionWS,
float3 normalWS,
float3 rootWP,
float stiffness,
float drag,
float shiverDrag,
float shiverDirectionality,
float initialBend,
float shiverMask,
float4 time)
WindData wind = GetAnalyticalWind(worldPos, rootWP, drag, shiverDrag, initialBend, time);
WindData wind = GetAnalyticalWind(positionWS, rootWP, drag, shiverDrag, initialBend, time);
if(wind.Strength > 0.0f)
if (wind.Strength > 0.0f)
float att = AttenuateTrunk(distance(worldPos, rootWP), stiffness);
float att = AttenuateTrunk(distance(positionWS, rootWP), stiffness);
worldPos = Rotate(rootWP, worldPos, rotAxis, (wind.Strength) * 0.001 * att);
positionWS = Rotate(rootWP, positionWS, rotAxis, (wind.Strength) * 0.001 * att);
float3 shiverDirection = normalize(lerp(worldNormal, normalize(wind.Direction + wind.ShiverDirection), shiverDirectionality));
worldPos += wind.ShiverStrength * shiverDirection * shiverMask;
float3 shiverDirection = normalize(lerp(normalWS, normalize(wind.Direction + wind.ShiverDirection), shiverDirectionality));
positionWS += wind.ShiverStrength * shiverDirection * shiverMask;
}
}

2
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Singleton.cs


using UnityEngine.SceneManagement;
namespace UnityEngine.Experimental.Rendering
{
[ExecuteInEditMode]

90
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/TextureCache.cs


{
protected int m_NumMipLevels;
#if UNITY_EDITOR
static int s_TextureCacheIdGenerator = 0;
int m_TextureCacheId = 0;
static bool s_ForceReinjectGlobalFirst = false;
static bool s_ForceReinjectGlobalSecond = false;
static int s_GlobalSecondSetByTexCacheID = -1;
// here we receive the in-editor updated textures. These must be reinjected into
// any texture cache which has a stale copy of it. However, we don't have a this-pointer to the texture cache
// so instead we defer this to NewFrame() where we force reinject.
// Ideally we'd build up a list here of textures which are to be reinjected but unfortunately the texture we receive
// is an intermediate one and not the final compressed one. So instead we will have to reinject all in NewFrame().
internal class AssetReloader : UnityEditor.AssetPostprocessor
{
void OnPostprocessTexture(Texture texture)
{
s_ForceReinjectGlobalFirst = true;
s_ForceReinjectGlobalSecond = false;
s_GlobalSecondSetByTexCacheID = -1;
}
}
#endif
public static bool isMobileBuildTarget
{
get

private struct SSliceEntry
{
public uint texId;
public uint countLRU;
public uint texId;
public uint countLRU;
#if UNITY_EDITOR
public Hash128 hash;
#endif
};
private int m_NumTextures;

return sliceIndex;
var texId = (uint)texture.GetInstanceID();
#if UNITY_EDITOR
var hash = texture.imageContentsHash;
#endif
//assert(TexID!=g_InvalidTexID);
if (texId == g_InvalidTexID) return 0;

// search for existing copy
if (m_LocatorInSliceArray.ContainsKey(texId))
int cachedSlice;
if (m_LocatorInSliceArray.TryGetValue(texId, out cachedSlice))
sliceIndex = m_LocatorInSliceArray[texId];
sliceIndex = cachedSlice;
Debug.Assert(m_SliceArray[sliceIndex].texId == texId);
//assert(m_SliceArray[sliceIndex].TexID==TexID);
#if UNITY_EDITOR
bSwapSlice = bSwapSlice || (m_SliceArray[sliceIndex].hash != hash);
#endif
}
// If no existing copy found in the array

}
}
//assert(bFoundAvailOrExistingSlice);
Debug.Assert(bFoundAvailOrExistingSlice, "The texture cache doesn't have enough space to store all textures. Please either increase the size of the texture cache, or use fewer unique textures.");
if (bFoundAvailOrExistingSlice)
{
m_SliceArray[sliceIndex].countLRU = 0; // mark slice as in use this frame

#if UNITY_EDITOR
m_SliceArray[sliceIndex].hash = hash;
#endif
// transfer new slice to sliceIndex from source texture
TransferToSlice(sliceIndex, texture);
}

//for(int q=1; q<m_numTextures; q++)
// assert(m_SliceArray[m_SortedIdxArray[q-1]].CountLRU>=m_SliceArray[m_SortedIdxArray[q]].CountLRU);
#if UNITY_EDITOR
// one or more textures got updated in editor. Unfortunately we do not know exactly which since
// OnPostprocessTexture() receives intermediate uncompressed textures. So we will have to reinject all slices to force an update.
if(s_ForceReinjectGlobalSecond && s_GlobalSecondSetByTexCacheID==m_TextureCacheId)
{
s_ForceReinjectGlobalSecond = false;
s_GlobalSecondSetByTexCacheID = -1;
}
if(s_ForceReinjectGlobalFirst)
{
s_ForceReinjectGlobalSecond = true;
s_GlobalSecondSetByTexCacheID = m_TextureCacheId;
s_ForceReinjectGlobalFirst = false;
}
if(s_ForceReinjectGlobalSecond)
{
// all texture caches must loop through and force a reinject on all entries when this is true.
for(int i = 0; i < m_NumTextures; i++)
{
var texID = m_SliceArray[i].texId;
if(texID!=g_InvalidTexID)
{
Texture texture = (Texture) EditorUtility.InstanceIDToObject((int) texID);
if(texture!=null) TransferToSlice(i, texture);
}
}
}
#endif
}
protected TextureCache()

#if UNITY_EDITOR
m_TextureCacheId = s_TextureCacheIdGenerator; // assign an ID so we can tell the caches apart
++s_TextureCacheIdGenerator; // static/global
#endif
}
public virtual void TransferToSlice(int sliceIndex, Texture texture)

28
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LegacyShadersToLightweightPipelineUpgrader.cs


{
public class LegacyShadersToLightweightPipelineUpgrader
{
[MenuItem("RenderPipeline/LightweightPipeline/Material Upgraders/Upgrade Legacy Materials to LightweightPipeline - Project", false, 3)]
public static void UpgradeMaterialsToLDProject()
{
List<MaterialUpgrader> materialUpgraders = new List<MaterialUpgrader>();
GetUpgraders(ref materialUpgraders);
//[MenuItem("RenderPipeline/Lightweight Pipeline/Material Upgraders/Upgrade Legacy Materials to LightweightPipeline - Project", false, 3)]
//public static void UpgradeMaterialsToLDProject()
//{
// List<MaterialUpgrader> materialUpgraders = new List<MaterialUpgrader>();
// GetUpgraders(ref materialUpgraders);
MaterialUpgrader.UpgradeProjectFolder(materialUpgraders, "Upgrade to LD Materials");
}
// MaterialUpgrader.UpgradeProjectFolder(materialUpgraders, "Upgrade to LD Materials");
//}
[MenuItem("RenderPipeline/LightweightPipeline/Material Upgraders/Upgrade Legacy Materials to LightweightPipeline - Selection", false, 4)]
public static void UpgradeMaterialsToLDSelection()
{
List<MaterialUpgrader> materialUpgraders = new List<MaterialUpgrader>();
GetUpgraders(ref materialUpgraders);
//[MenuItem("RenderPipeline/Lightweight Pipeline/Material Upgraders/Upgrade Legacy Materials to LightweightPipeline - Selection", false, 4)]
//public static void UpgradeMaterialsToLDSelection()
//{
// List<MaterialUpgrader> materialUpgraders = new List<MaterialUpgrader>();
// GetUpgraders(ref materialUpgraders);
MaterialUpgrader.UpgradeSelection(materialUpgraders, "Upgrade to Lightweight Materials");
}
// MaterialUpgrader.UpgradeSelection(materialUpgraders, "Upgrade to Lightweight Materials");
//}
private static void GetUpgraders(ref List<MaterialUpgrader> materialUpgraders)
{

46
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightAssetInspector.cs


public static GUIContent renderingLabel = new GUIContent("Rendering");
public static GUIContent shadowLabel = new GUIContent("Shadows");
public static GUIContent defaults = new GUIContent("Defaults");
public static GUIContent linearRenderingLabel = new GUIContent("Linear Colorspace", "When enabled Lightweight shader will perform gamma to linear conversion when linear rendering is not supported or disabled");
public static GUIContent maxPixelLights = new GUIContent("Per-Object Pixel Lights",
"Max amount of dynamic per-object pixel lights.");
public static GUIContent renderScaleLabel = new GUIContent("Render Scale", "Allows game to render at a resolution different than native resolution. UI is always rendered at native resolution.");
public static GUIContent maxAdditionalPixelLightsLabel = new GUIContent("Max Additional Pixel Lights",
"Controls the additional per-pixel lights that run in fragment light loop.");
"Lightweight pipeline support at most 4 per-object lights between pixel and vertex. If value in pixel lights is set to max this settings has no effect.");
"If enabled, shades additional lights exceeding maxAdditionalPixelLights per-vertex up to the maximum of 8 lights.");
public static GUIContent enableLightmap = new GUIContent("Enable Lightmap",
"Enabled/Disable support for non-directional lightmaps.");
public static GUIContent enableAmbientProbe = new GUIContent("Enable Light Probes",
"Enables/Disable light probe support.");
public static GUIContent enableSoftParticles = new GUIContent("Enable Soft Particles", "By enabled this the pipeline will generate depth texture necessary for SoftParticles");
public static GUIContent shadowType = new GUIContent("Shadow Type",
"Single directional shadow supported. SOFT_SHADOWS applies shadow filtering.");

"Material to use when creating 3D objects");
public static GUIContent defaultParticleMaterial = new GUIContent("Default Particle Material",
"Material to use when creating Paticle Systems");
"Material to use when creating Particle Systems");
public static GUIContent defaultLineMaterial = new GUIContent("Default Line Material",
"Material to use when creating Line Renderers");

public static GUIContent defaultShader = new GUIContent("Default Shader",
"Shader to use when creating materials");
public static GUIContent msaaContent = new GUIContent("Anti Aliasing", "Controls the global anti aliasing quality. When set to disabled, MSAA will not be performed even if the camera allows it.");
public static GUIContent msaaContent = new GUIContent("Anti Aliasing (MSAA)", "Controls the global anti aliasing quality. When set to disabled, MSAA will not be performed even if the camera allows it.");
private SerializedProperty m_LinearRenderingProperty;
private SerializedProperty m_MaxPixelLights;
private int kMaxSupportedAdditionalPixelLights = 8;
private SerializedProperty m_RenderScale;
private SerializedProperty m_MaxAdditionalPixelLights;
private SerializedProperty m_EnableLightmapsProp;
private SerializedProperty m_EnableAmbientProbeProp;
private SerializedProperty m_SupportSoftParticlesProp;
private SerializedProperty m_ShadowTypeProp;
private SerializedProperty m_ShadowNearPlaneOffsetProp;
private SerializedProperty m_ShadowDistanceProp;

void OnEnable()
{
m_LinearRenderingProperty = serializedObject.FindProperty("m_LinearRendering");
m_MaxPixelLights = serializedObject.FindProperty("m_MaxPixelLights");
m_RenderScale = serializedObject.FindProperty("m_RenderScale");
m_MaxAdditionalPixelLights = serializedObject.FindProperty("m_MaxAdditionalPixelLights");
m_EnableLightmapsProp = serializedObject.FindProperty("m_EnableLightmaps");
m_EnableAmbientProbeProp = serializedObject.FindProperty("m_EnableAmbientProbe");
m_SupportSoftParticlesProp = serializedObject.FindProperty("m_SupportSoftParticles");
m_ShadowTypeProp = serializedObject.FindProperty("m_ShadowType");
m_ShadowNearPlaneOffsetProp = serializedObject.FindProperty("m_ShadowNearPlaneOffset");
m_ShadowDistanceProp = serializedObject.FindProperty("m_ShadowDistance");

EditorGUILayout.Space();
EditorGUILayout.LabelField(Styles.renderingLabel, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(m_LinearRenderingProperty, Styles.linearRenderingLabel);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(Styles.renderScaleLabel);
m_RenderScale.floatValue = EditorGUILayout.Slider(m_RenderScale.floatValue, 0.1f, 1.0f);
EditorGUILayout.EndHorizontal();
EditorGUILayout.LabelField(Styles.maxPixelLights);
m_MaxPixelLights.intValue = EditorGUILayout.IntSlider(m_MaxPixelLights.intValue, 0, 4);
EditorGUILayout.LabelField(Styles.maxAdditionalPixelLightsLabel);
m_MaxAdditionalPixelLights.intValue = EditorGUILayout.IntSlider(m_MaxAdditionalPixelLights.intValue, 0, kMaxSupportedAdditionalPixelLights);
EditorGUILayout.PropertyField(m_EnableLightmapsProp, Styles.enableLightmap);
EditorGUILayout.PropertyField(m_EnableAmbientProbeProp, Styles.enableAmbientProbe);
EditorGUILayout.PropertyField(m_SupportSoftParticlesProp, Styles.enableSoftParticles);
EditorGUILayout.PropertyField(m_MSAA, Styles.msaaContent);
EditorGUILayout.PropertyField(m_AttenuationTexture, Styles.attenuationTextureLabel);
EditorGUI.indentLevel--;

72
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightPipelineUpgraders.cs


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering.LightweightPipeline;
namespace UnityEditor.Experimental.Rendering.LightweightPipeline
{

blendMode = UpgradeBlendMode.Opaque,
specularSource = SpecularSource.NoSpecular,
glosinessSource = GlossinessSource.BaseAlpha,
reflectionSource = ReflectionSource.NoReflection
};
static public UpgradeParams specularOpaque = new UpgradeParams()

glosinessSource = GlossinessSource.BaseAlpha,
reflectionSource = ReflectionSource.NoReflection
};
static public UpgradeParams diffuseAlpha = new UpgradeParams()

glosinessSource = GlossinessSource.SpecularAlpha,
reflectionSource = ReflectionSource.NoReflection
};
static public UpgradeParams specularAlpha = new UpgradeParams()

glosinessSource = GlossinessSource.SpecularAlpha,
reflectionSource = ReflectionSource.NoReflection
};
static public UpgradeParams diffuseAlphaCutout = new UpgradeParams()

glosinessSource = GlossinessSource.SpecularAlpha,
reflectionSource = ReflectionSource.NoReflection
};
static public UpgradeParams specularAlphaCutout = new UpgradeParams()

glosinessSource = GlossinessSource.SpecularAlpha,
reflectionSource = ReflectionSource.NoReflection
};
static public UpgradeParams diffuseCubemap = new UpgradeParams()

glosinessSource = GlossinessSource.BaseAlpha,
reflectionSource = ReflectionSource.Cubemap
};
static public UpgradeParams specularCubemap = new UpgradeParams()

glosinessSource = GlossinessSource.BaseAlpha,
reflectionSource = ReflectionSource.Cubemap
};
static public UpgradeParams diffuseCubemapAlpha = new UpgradeParams()

glosinessSource = GlossinessSource.BaseAlpha,
reflectionSource = ReflectionSource.Cubemap
};
static public UpgradeParams specularCubemapAlpha = new UpgradeParams()

glosinessSource = GlossinessSource.BaseAlpha,
reflectionSource = ReflectionSource.Cubemap
};
}

{
RenameShader(oldShaderName, "ScriptableRenderPipeline/LightweightPipeline/NonPBR", UpdateMaterialKeywords);
RenameShader(oldShaderName, LightweightPipelineAsset.m_SimpleLightShaderPath, UpdateMaterialKeywords);
SetFloat("_ReflectionSource", (float)upgradeParams.reflectionSource);
if (oldShaderName.Contains("Legacy Shaders/Self-Illumin"))
{

public static void UpdateMaterialKeywords(Material material)
{
material.shaderKeywords = null;
UpdateMaterialReflectionSource(material);
LightweightShaderHelper.SetKeyword(material, "_CUBEMAP_REFLECTION", material.GetTexture("_Cube"));
LightweightShaderHelper.SetKeyword(material, "_EMISSION", material.GetTexture("_EmissionMap"));
// A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect
// or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.
// The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.
MaterialEditor.FixupEmissiveFlag(material);
bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
LightweightShaderHelper.SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
}
private static void UpdateMaterialSpecularSource(Material material)

{
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP", false);
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP_BASE_ALPHA", false);
}
else if (specSource == SpecularSource.SpecularTextureAndColor && material.GetTexture("_SpecGlossMap"))
{
GlossinessSource glossSource = (GlossinessSource)material.GetFloat("_GlossinessSource");
if (glossSource == GlossinessSource.BaseAlpha)
{
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP", false);
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP_BASE_ALPHA", true);
}
else
{
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP", true);
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP_BASE_ALPHA", false);
}
LightweightShaderHelper.SetKeyword(material, "_SPECULAR_COLOR", false);
LightweightShaderHelper.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", false);
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP", false);
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP_BASE_ALPHA", false);
LightweightShaderHelper.SetKeyword(material, "_SPECULAR_COLOR", true);
}
}
private static void UpdateMaterialReflectionSource(Material material)
{
LightweightShaderHelper.SetKeyword(material, "_REFLECTION_CUBEMAP", false);
LightweightShaderHelper.SetKeyword(material, "_REFLECTION_PROBE", false);
ReflectionSource reflectionSource = (ReflectionSource)material.GetFloat("_ReflectionSource");
if (reflectionSource == ReflectionSource.Cubemap && material.GetTexture("_Cube"))
{
LightweightShaderHelper.SetKeyword(material, "_REFLECTION_CUBEMAP", true);
}
else if (reflectionSource == ReflectionSource.ReflectionProbe)
{
LightweightShaderHelper.SetKeyword(material, "_REFLECTION_PROBE", true);
GlossinessSource glossSource = (GlossinessSource)material.GetFloat("_GlossinessSource");
bool hasGlossMap = material.GetTexture("_SpecGlossMap");
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP", hasGlossMap);
LightweightShaderHelper.SetKeyword(material, "_SPECULAR_COLOR", !hasGlossMap);
LightweightShaderHelper.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", glossSource == GlossinessSource.BaseAlpha);
}
}
}

public StandardUpgrader(string oldShaderName)
{
RenameShader(oldShaderName, "ScriptableRenderPipeline/LightweightPipeline/NonPBR");
RenameShader(oldShaderName, LightweightPipelineAsset.m_StandardShaderPath);
}
}

{
RenameShader(oldShaderName, "ScriptableRenderPipeline/LightweightPipeline/NonPBR");
RenameShader(oldShaderName, LightweightPipelineAsset.m_StandardShaderPath);
SetFloat("_Shininess", 1.0f);
}
}

3
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightUnlitGUI.cs


using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor.Experimental.Rendering.LightweightPipeline;
public class LightweightUnlitGUI : ShaderGUI

{
blendModeProp = FindProperty("_Mode", properties);
mainTexProp = FindProperty("_MainTex", properties);
mainColorProp = FindProperty("_Color", properties);
mainColorProp = FindProperty("_MainColor", properties);
alphaCutoffProp = FindProperty("_Cutoff", properties);
}

8
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/StandardToLightweightMaterialUpgrader.cs


{
public class StandardToLightweightMaterialUpgrader
{
[MenuItem("RenderPipeline/LightweightPipeline/Material Upgraders/Upgrade Standard Materials to Lightweight Mobile - Project Folder", false, 1)]
[MenuItem("RenderPipeline/Lightweight Pipeline/Material Upgraders/Upgrade Project Materials", false, 1)]
MaterialUpgrader.UpgradeProjectFolder(upgraders, "Upgrade to LD Materials");
MaterialUpgrader.UpgradeProjectFolder(upgraders, "Upgrade to Lightweight Pipeline Materials");
[MenuItem("RenderPipeline/LightweightPipeline/Material Upgraders/Upgrade Standard Materials to Lightweight Mobile - Selection", false, 2)]
[MenuItem("RenderPipeline/Lightweight Pipeline/Material Upgraders/Upgrade Selected Materials", false, 2)]
MaterialUpgrader.UpgradeSelection(upgraders, "Upgrade to LD Materials");
MaterialUpgrader.UpgradeSelection(upgraders, "Upgrade to Lightweight Pipeline Materials");
}
private static void GetUpgraders(ref List<MaterialUpgrader> upgraders)

1
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/UpgradeCommon.cs


public UpgradeBlendMode blendMode;
public SpecularSource specularSource;
public GlossinessSource glosinessSource;
public ReflectionSource reflectionSource;
}
}

888
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs


using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.XR;

public struct LightData
{
public int pixelLightsCount;
public int vertexLightsCount;
public int shadowLightIndex;
public bool isSingleLight;
public int pixelAdditionalLightsCount;
public int totalAdditionalLightsCount;
public int mainLightIndex;
public bool shadowsRendered;
}

// Max amount of visible lights. This controls the lights constant buffers in shader but not the max shaded lights.
// Lights are set per-object and the max shaded lights for each object are controlled by the max pixel lights in pipeline asset and kMaxVertexLights.
private static readonly int kMaxVisibleLights = 16;
private static readonly int kMaxPerObjectLights = 4;
// Maximum amount of visible lights the shader can process. This controls the constant global light buffer size.
// It must match the MAX_VISIBLE_LIGHTS in LightweightCore.cginc
private static readonly int kMaxVisibleAdditionalLights = 16;
private Vector4[] m_LightPositions = new Vector4[kMaxVisibleLights];
private Vector4[] m_LightColors = new Vector4[kMaxVisibleLights];
private Vector4[] m_LightAttenuations = new Vector4[kMaxVisibleLights];
private Vector4[] m_LightSpotDirections = new Vector4[kMaxVisibleLights];
// Lights are culled per-object. This holds the maximum amount of additional lights that can shade each object.
// The engine fills in the lights indices per-object in unity4_LightIndices0 and unity_4LightIndices1
private static readonly int kMaxPerObjectAdditionalLights = 8;
private Camera m_CurrCamera = null;
private LightType m_SingleLightType = LightType.Directional;
private Vector4[] m_LightPositions = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightColors = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightAttenuations = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightSpotDirections = new Vector4[kMaxVisibleAdditionalLights];
private int m_LightIndicesCount = 0;
private ComputeBuffer m_LightIndexListBuffer;
private Camera m_CurrCamera = null;
private int m_ShadowMapProperty;
private int m_CameraRTProperty;
private RenderTargetIdentifier m_ShadowMapRTID;
private RenderTargetIdentifier m_CameraRTID;
private int m_ShadowMapTexture;
private int m_CameraColorTexture;
private int m_CameraDepthTexture;
private int m_CameraCopyDepthTexture;
private RenderTargetIdentifier m_ShadowMapRT;
private RenderTargetIdentifier m_CameraColorRT;
private RenderTargetIdentifier m_CameraDepthRT;
private RenderTargetIdentifier m_CameraCopyDepthRT;
private bool m_RenderToIntermediateTarget = false;
private bool m_IntermediateTextureArray = false;
private const int kShadowDepthBufferBits = 16;

private static readonly ShaderPassName m_LitPassName = new ShaderPassName("LightweightForward");
private static readonly ShaderPassName m_UnlitPassName = new ShaderPassName("SRPDefaultUnlit");
private RenderTextureFormat m_ColorFormat = RenderTextureFormat.ARGB32;
private RenderTextureFormat m_ColorFormat;
private PostProcessLayer m_CameraPostProcessLayer;
private LightComparer m_LightCompararer = new LightComparer();
// Maps from sorted light indices to original unsorted. We need this for shadow rendering
// and per-object light lists.
private List<int> m_SortedLightIndexMap = new List<int>();
private Mesh m_BlitQuad;
private Material m_BlitMaterial;
private Material m_CopyDepthMaterial;
private int m_BlitTexID = Shader.PropertyToID("_BlitTex");
private CopyTextureSupport m_CopyTextureSupport;
public LightweightPipeline(LightweightPipelineAsset asset)
{

m_ShadowMapProperty = Shader.PropertyToID("_ShadowMap");
m_CameraRTProperty = Shader.PropertyToID("_CameraRT");
m_ShadowMapRTID = new RenderTargetIdentifier(m_ShadowMapProperty);
m_CameraRTID = new RenderTargetIdentifier(m_CameraRTProperty);
PerFrameBuffer._GlossyEnvironmentColor = Shader.PropertyToID("_GlossyEnvironmentColor");
PerFrameBuffer._AttenuationTexture = Shader.PropertyToID("_AttenuationTexture");
PerCameraBuffer._MainLightPosition = Shader.PropertyToID("_MainLightPosition");
PerCameraBuffer._MainLightColor = Shader.PropertyToID("_MainLightColor");
PerCameraBuffer._MainLightAttenuationParams = Shader.PropertyToID("_MainLightAttenuationParams");
PerCameraBuffer._MainLightSpotDir = Shader.PropertyToID("_MainLightSpotDir");
PerCameraBuffer._AdditionalLightCount = Shader.PropertyToID("_AdditionalLightCount");
PerCameraBuffer._AdditionalLightPosition = Shader.PropertyToID("_AdditionalLightPosition");
PerCameraBuffer._AdditionalLightColor = Shader.PropertyToID("_AdditionalLightColor");
PerCameraBuffer._AdditionalLightAttenuationParams = Shader.PropertyToID("_AdditionalLightAttenuationParams");
PerCameraBuffer._AdditionalLightSpotDir = Shader.PropertyToID("_AdditionalLightSpotDir");
m_ShadowMapTexture = Shader.PropertyToID("_ShadowMap");
m_CameraColorTexture = Shader.PropertyToID("_CameraColorTexture");
m_CameraDepthTexture = Shader.PropertyToID("_CameraDepthTexture");
m_CameraCopyDepthTexture = Shader.PropertyToID("_CameraCopyDepthTexture");
m_ShadowMapRT = new RenderTargetIdentifier(m_ShadowMapTexture);
m_CameraColorRT = new RenderTargetIdentifier(m_CameraColorTexture);
m_CameraDepthRT = new RenderTargetIdentifier(m_CameraDepthTexture);
m_CameraCopyDepthRT = new RenderTargetIdentifier(m_CameraCopyDepthTexture);
m_CopyTextureSupport = SystemInfo.copyTextureSupport;
// Let engine know we have MSAA on for cases where we support MSAA backbuffer
if (QualitySettings.antiAliasing != m_Asset.MSAASampleCount)

m_BlitQuad = LightweightUtils.CreateQuadMesh(false);
m_BlitMaterial = new Material(m_Asset.BlitShader)
{
hideFlags = HideFlags.HideAndDontSave
};
m_CopyDepthMaterial = new Material(m_Asset.CopyDepthShader)
{
hideFlags = HideFlags.HideAndDontSave
};
if (m_LightIndexListBuffer != null)
{
m_LightIndexListBuffer.Dispose();
m_LightIndexListBuffer = null;
m_LightIndicesCount = 0;
}
}
CullResults m_CullResults;

// instead this should be forced when using SRP, since all SRP use linear lighting.
GraphicsSettings.lightsUseLinearIntensity = true;
SetupPerFrameShaderConstants(ref context);
// Sort cameras array by camera depth
Array.Sort(cameras, m_CameraComparer);
foreach (Camera camera in cameras)
{

if (!CullResults.GetCullingParameters(m_CurrCamera, stereoEnabled, out cullingParameters))
continue;
cullingParameters.shadowDistance = Mathf.Min(m_ShadowSettings.maxShadowDistance, m_CurrCamera.farClipPlane);
CullResults.Cull(ref cullingParameters, context,ref m_CullResults);
cullingParameters.shadowDistance = Mathf.Min(m_ShadowSettings.maxShadowDistance,
m_CurrCamera.farClipPlane);
#if UNITY_EDITOR
// Emit scene view UI
if (camera.cameraType == CameraType.SceneView)
ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
#endif
CullResults.Cull(ref cullingParameters, context, ref m_CullResults);
// Render Shadow Map
if (lightData.shadowLightIndex > -1)
lightData.shadowsRendered = RenderShadows(ref m_CullResults, ref visibleLights[lightData.shadowLightIndex], lightData.shadowLightIndex, ref context);
ShadowPass(visibleLights, ref context, ref lightData);
ForwardPass(visibleLights, ref context, ref lightData, stereoEnabled);
// Setup camera matrices and RT
context.SetupCameraProperties(m_CurrCamera, stereoEnabled);
// Release temporary RT
var cmd = CommandBufferPool.Get("After Camera Render");
cmd.ReleaseTemporaryRT(m_ShadowMapTexture);
cmd.ReleaseTemporaryRT(m_CameraColorTexture);
cmd.ReleaseTemporaryRT(m_CameraDepthTexture);
cmd.ReleaseTemporaryRT(m_CameraCopyDepthTexture);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
// Setup light and shadow shader constants
SetupShaderLightConstants(visibleLights, ref lightData, ref m_CullResults, ref context);
if (lightData.shadowsRendered)
SetupShadowShaderConstants(ref context, ref visibleLights[lightData.shadowLightIndex], lightData.shadowLightIndex, m_ShadowCasterCascadesCount);
SetShaderKeywords(ref lightData, ref context);
context.Submit();
}
}
RendererConfiguration configuration = RendererConfiguration.PerObjectReflectionProbes;
if (m_Asset.EnableLightmap)
configuration |= RendererConfiguration.PerObjectLightmaps;
private void ShadowPass(VisibleLight[] visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
{
if (m_Asset.AreShadowsEnabled() && lightData.mainLightIndex != -1)
{
VisibleLight mainLight = visibleLights[lightData.mainLightIndex];
if (m_Asset.EnableAmbientProbe)
configuration |= RendererConfiguration.PerObjectLightProbe;
if (mainLight.light.shadows != LightShadows.None)
{
if (!LightweightUtils.IsSupportedShadowType(mainLight.lightType))
{
Debug.LogWarning("Only directional and spot shadows are supported by LightweightPipeline.");
return;
}
if (!lightData.isSingleLight)
configuration |= RendererConfiguration.PerObjectLightIndices8;
// There's no way to map shadow light indices. We need to pass in the original unsorted index.
// If no additional lights then no light sorting is performed and the indices match.
int shadowOriginalIndex = (lightData.totalAdditionalLightsCount > 0) ? GetLightUnsortedIndex(lightData.mainLightIndex) : lightData.mainLightIndex;
lightData.shadowsRendered = RenderShadows(ref m_CullResults, ref mainLight,
shadowOriginalIndex, ref context);
}
}
}
PostProcessLayer postProcessLayer = GetCurrCameraPostProcessLayer();
bool postProcessEnabled = postProcessLayer != null && postProcessLayer.enabled;
m_RenderToIntermediateTarget = postProcessEnabled || GetRenderToIntermediateTarget();
private void ForwardPass(VisibleLight[] visibleLights, ref ScriptableRenderContext context, ref LightData lightData, bool stereoEnabled)
{
FrameRenderingConfiguration frameRenderingConfiguration;
SetupFrameRendering(out frameRenderingConfiguration);
SetupIntermediateResources(frameRenderingConfiguration, ref context);
SetupShaderConstants(visibleLights, ref context, ref lightData);
BeginForwardRendering(ref context, stereoEnabled);
// SetupCameraProperties does the following:
// Setup Camera RenderTarget and Viewport
// VR Camera Setup and SINGLE_PASS_STEREO props
// Setup camera view, proj and their inv matrices.
// Setup properties: _WorldSpaceCameraPos, _ProjectionParams, _ScreenParams, _ZBufferParams, unity_OrthoParams
// Setup camera world clip planes props
// setup HDR keyword
// Setup global time properties (_Time, _SinTime, _CosTime)
context.SetupCameraProperties(m_CurrCamera, stereoEnabled);
var litDrawSettings = new DrawRendererSettings(m_CurrCamera, m_LitPassName);
litDrawSettings.sorting.flags = SortFlags.CommonOpaque;
litDrawSettings.rendererConfiguration = configuration;
RendererConfiguration rendererSettings = GetRendererSettings(ref lightData);
var unlitDrawSettings = new DrawRendererSettings(m_CurrCamera, m_UnlitPassName);
unlitDrawSettings.sorting.flags = SortFlags.CommonTransparent;
BeginForwardRendering(ref context, frameRenderingConfiguration);
RenderOpaques(ref context, rendererSettings);
AfterOpaque(ref context, frameRenderingConfiguration);
RenderTransparents(ref context, rendererSettings);
AfterTransparent(ref context, frameRenderingConfiguration);
EndForwardRendering(ref context, frameRenderingConfiguration);
}
// Render Opaques
var opaqueFilterSettings = new FilterRenderersSettings(true) {renderQueueRange = RenderQueueRange.opaque};
private void RenderOpaques(ref ScriptableRenderContext context, RendererConfiguration settings)
{
var opaqueDrawSettings = new DrawRendererSettings(m_CurrCamera, m_LitPassName);
opaqueDrawSettings.sorting.flags = SortFlags.CommonOpaque;
opaqueDrawSettings.rendererConfiguration = settings;
context.DrawRenderers(m_CullResults.visibleRenderers, ref litDrawSettings, opaqueFilterSettings);
var opaqueFilterSettings = new FilterRenderersSettings(true)
{
renderQueueRange = RenderQueueRange.opaque
};
// TODO: Check skybox shader
context.DrawSkybox(m_CurrCamera);
context.DrawRenderers(m_CullResults.visibleRenderers, ref opaqueDrawSettings, opaqueFilterSettings);
context.DrawSkybox(m_CurrCamera);
}
// Render Alpha blended
var transparentFilterSettings = new FilterRenderersSettings(true) {renderQueueRange = RenderQueueRange.transparent};
private void AfterOpaque(ref ScriptableRenderContext context, FrameRenderingConfiguration config)
{
if (!LightweightUtils.HasFlag(config, FrameRenderingConfiguration.RequireDepth))
return;
litDrawSettings.sorting.flags = SortFlags.CommonTransparent;
context.DrawRenderers(m_CullResults.visibleRenderers, ref litDrawSettings, transparentFilterSettings);
context.DrawRenderers(m_CullResults.visibleRenderers, ref unlitDrawSettings, transparentFilterSettings);
CommandBuffer cmd = CommandBufferPool.Get("After Opaque");
cmd.SetGlobalTexture(m_CameraDepthTexture, m_CameraDepthRT);
if (postProcessEnabled)
RenderPostProcess(ref context, postProcessLayer);
// When soft particles are enabled we have to copy depth to another RT so we can read and write to depth
if (m_Asset.SupportsSoftParticles)
{
RenderTargetIdentifier colorRT = (m_CurrCamera.targetTexture != null) ? BuiltinRenderTextureType.CameraTarget : m_CameraColorRT;
CopyTexture(cmd, m_CameraDepthRT, m_CameraCopyDepthTexture);
SetupRenderTargets(cmd, colorRT, m_CameraCopyDepthRT);
}
EndForwardRendering(ref context, stereoEnabled, postProcessEnabled);
// Only takes effect if custom BeforeTransparent PostProcessing effects are active
if (LightweightUtils.HasFlag(config, FrameRenderingConfiguration.PostProcess))
RenderPostProcess(cmd , true);
// Release temporary RT
var discardRT = CommandBufferPool.Get();
discardRT.ReleaseTemporaryRT(m_ShadowMapProperty);
discardRT.ReleaseTemporaryRT(m_CameraRTProperty);
context.ExecuteCommandBuffer(discardRT);
CommandBufferPool.Release(discardRT);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
context.Submit();
private void AfterTransparent(ref ScriptableRenderContext context, FrameRenderingConfiguration config)
{
if (!LightweightUtils.HasFlag(config, FrameRenderingConfiguration.PostProcess))
return;
CommandBuffer cmd = CommandBufferPool.Get("After Transparent");
RenderPostProcess(cmd, false);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
private void RenderTransparents(ref ScriptableRenderContext context, RendererConfiguration config)
{
var transparentSettings = new DrawRendererSettings(m_CurrCamera, m_LitPassName);
transparentSettings.SetShaderPassName(1, m_UnlitPassName);
transparentSettings.sorting.flags = SortFlags.CommonTransparent;
transparentSettings.rendererConfiguration = config;
var transparentFilterSettings = new FilterRenderersSettings(true)
{
renderQueueRange = RenderQueueRange.transparent
};
context.DrawRenderers(m_CullResults.visibleRenderers, ref transparentSettings, transparentFilterSettings);
}
private void BuildShadowSettings()

}
}
private void InitializeLightData(VisibleLight[] lights, out LightData lightData)
private void SetupFrameRendering(out FrameRenderingConfiguration configuration)
int lightsCount = lights.Length;
int maxPerPixelLights = Math.Min(m_Asset.MaxSupportedPixelLights, kMaxPerObjectLights);
lightData.pixelLightsCount = Math.Min(lightsCount, maxPerPixelLights);
lightData.vertexLightsCount = (m_Asset.SupportsVertexLight) ? Math.Min(lightsCount - lightData.pixelLightsCount, kMaxPerObjectLights) : 0;
configuration = (XRSettings.enabled) ? FrameRenderingConfiguration.Stereo : FrameRenderingConfiguration.None;
if (XRSettings.enabled && XRSettings.eyeTextureDesc.dimension == TextureDimension.Tex2DArray)
m_IntermediateTextureArray = true;
else
m_IntermediateTextureArray = false;
bool intermediateTexture = m_CurrCamera.targetTexture != null || m_CurrCamera.cameraType == CameraType.SceneView ||
m_Asset.RenderScale < 1.0f || m_CurrCamera.allowHDR;
m_ColorFormat = m_CurrCamera.allowHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32;
m_CameraPostProcessLayer = m_CurrCamera.GetComponent<PostProcessLayer>();
bool postProcessEnabled = m_CameraPostProcessLayer != null && m_CameraPostProcessLayer.enabled;
if (postProcessEnabled || m_Asset.SupportsSoftParticles)
{
configuration |= FrameRenderingConfiguration.RequireDepth;
intermediateTexture = true;
if (postProcessEnabled)
configuration |= FrameRenderingConfiguration.PostProcess;
}
// When post process or soft particles are enabled we disable msaa due to lack of depth resolve
// One can still use PostFX AA
else if (m_CurrCamera.allowMSAA && m_Asset.MSAASampleCount > 1)
{
configuration |= FrameRenderingConfiguration.Msaa;
intermediateTexture = !LightweightUtils.PlatformSupportsMSAABackBuffer();
}
Rect cameraRect = m_CurrCamera.rect;
if (cameraRect.x > 0.0f || cameraRect.y > 0.0f || cameraRect.width < 1.0f || cameraRect.height < 1.0f)
intermediateTexture = true;
else
configuration |= FrameRenderingConfiguration.DefaultViewport;
if (intermediateTexture)
configuration |= FrameRenderingConfiguration.IntermediateTexture;
}
// TODO: Handle Vertex lights in this case
lightData.isSingleLight = lightData.pixelLightsCount <= 1;
if (lightData.isSingleLight)
m_SingleLightType = (lightData.pixelLightsCount == 1) ? lights[0].lightType : LightType.Directional;
private void SetupIntermediateResources(FrameRenderingConfiguration renderingConfig, ref ScriptableRenderContext context)
{
CommandBuffer cmd = CommandBufferPool.Get("Setup Intermediate Resources");
float renderScale = (m_CurrCamera.cameraType == CameraType.Game) ? m_Asset.RenderScale : 1.0f;
int rtWidth = (int)((float)m_CurrCamera.pixelWidth * renderScale);
int rtHeight = (int)((float)m_CurrCamera.pixelHeight * renderScale);
int msaaSamples = (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.Msaa)) ? m_Asset.MSAASampleCount : 1;
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.IntermediateTexture))
{
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.Stereo))
{
RenderTextureDescriptor rtDesc = new RenderTextureDescriptor();
rtDesc = XRSettings.eyeTextureDesc;
rtDesc.colorFormat = m_ColorFormat;
rtDesc.msaaSamples = msaaSamples;
cmd.GetTemporaryRT(m_CameraColorTexture, rtDesc, FilterMode.Bilinear);
}
else if (m_CurrCamera.targetTexture == null)
{
cmd.GetTemporaryRT(m_CameraColorTexture, rtWidth, rtHeight, kCameraDepthBufferBits,
FilterMode.Bilinear, m_ColorFormat, RenderTextureReadWrite.Default, msaaSamples);
}
}
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.RequireDepth))
{
cmd.GetTemporaryRT(m_CameraDepthTexture, rtWidth, rtHeight, kCameraDepthBufferBits, FilterMode.Bilinear, RenderTextureFormat.Depth);
if (m_Asset.SupportsSoftParticles)
cmd.GetTemporaryRT(m_CameraCopyDepthTexture, rtWidth, rtHeight, kCameraDepthBufferBits, FilterMode.Bilinear, RenderTextureFormat.Depth);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
private void SetupShaderConstants(VisibleLight[] visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
{
CommandBuffer cmd = CommandBufferPool.Get("SetupShaderConstants");
SetupShaderLightConstants(cmd, visibleLights, ref lightData, ref m_CullResults, ref context);
SetShaderKeywords(cmd, ref lightData, visibleLights);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
private void InitializeLightData(VisibleLight[] visibleLights, out LightData lightData)
{
int visibleLightsCount = visibleLights.Length;
m_SortedLightIndexMap.Clear();
if (visibleLightsCount <= 1)
{
// If there's exactly one visible light that will be picked as main light.
// Otherwise we disable main light by setting its index to -1.
lightData.mainLightIndex = visibleLightsCount - 1;
lightData.pixelAdditionalLightsCount = 0;
lightData.totalAdditionalLightsCount = 0;
return;
}
InitializeMainShadowLightIndex(lights, out lightData.shadowLightIndex);
// We always support at least one per-pixel light, which is main light. Shade objects up to a limit of per-object
// pixel lights defined in the pipeline settings.
int maxSupportedPixelLights = Math.Min(m_Asset.MaxAdditionalPixelLights, kMaxPerObjectAdditionalLights) + 1;
int maxPixelLights = Math.Min(maxSupportedPixelLights, visibleLightsCount);
// If vertex lighting is enabled in the pipeline settings, then we shade the remaining visible lights per-vertex
// up to the maximum amount of per-object lights.
int vertexLights = (m_Asset.SupportsVertexLight) ? kMaxPerObjectAdditionalLights - maxPixelLights - 1: 0;
lightData.mainLightIndex = SortLights(visibleLights);
lightData.pixelAdditionalLightsCount = maxPixelLights - 1;
lightData.totalAdditionalLightsCount = lightData.pixelAdditionalLightsCount + vertexLights;
}
private int SortLights(VisibleLight[] visibleLights)
{
int totalVisibleLights = visibleLights.Length;
Dictionary<int, int> visibleLightsIDMap = new Dictionary<int, int>();
for (int i = 0; i < totalVisibleLights; ++i)
visibleLightsIDMap.Add(visibleLights[i].GetHashCode(), i);
// Sorts light so we have all directionals first, then local lights.
// Directionals are sorted further by shadow, cookie and intensity
// Locals are sorted further by shadow, cookie and distance to camera
m_LightCompararer.CurrCamera = m_CurrCamera;
Array.Sort(visibleLights, m_LightCompararer);
for (int i = 0; i < totalVisibleLights; ++i)
m_SortedLightIndexMap.Add(visibleLightsIDMap[visibleLights[i].GetHashCode()]);
return GetMainLight(visibleLights);
private void SetupShaderLightConstants(VisibleLight[] lights, ref LightData lightData, ref CullResults cullResults, ref ScriptableRenderContext context)
// How main light is decided:
// If shadows enabled, main light is always a shadow casting light. Directional has priority over local lights.
// Otherwise directional lights have priority based on cookie support and intensity
// If no directional light in the scene local lights based on cookie support and distance to camera
private int GetMainLight(VisibleLight[] visibleLights)
if (lightData.isSingleLight)
SetupShaderSingleLightConstants(lights, (lightData.pixelLightsCount > 0) ? 0 : -1, ref context);
else
SetupShaderLightListConstants(lights, ref lightData, ref context);
int totalVisibleLights = visibleLights.Length;
bool shadowsEnabled = m_Asset.AreShadowsEnabled();
// If shadows are supported and the first visible light has shadows then this is main light
if (shadowsEnabled && visibleLights[0].light.shadows != LightShadows.None)
return 0;
// We don't have any directional shadow casting light, skip until we find the first non directional light
int lightIndex = 0;
while (lightIndex < totalVisibleLights && visibleLights[lightIndex].lightType == LightType.Directional)
lightIndex++;
// If first non-directional light has shadows we return it, otherwise we return first light
return (lightIndex < totalVisibleLights && visibleLights[lightIndex].light.shadows != LightShadows.None) ? lightIndex : 0;
lightPos = Vector4.zero;
lightPos = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
// When no lights are available in the pipeline or maxPixelLights is set to 0
// In this case we want to initialize the lightData to default values and return
// When no lights are visible, main light will be set to -1.
// In this case we initialize it to default values and return
if (lightIndex < 0)
return;

Vector4 dir = light.localToWorld.GetColumn(2);
lightSpotDir = new Vector4(-dir.x, -dir.y, -dir.z, 0.0f);
// Spot Attenuation with a linear falloff can be defined as
// (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
// This can be rewritten as
// invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
// SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
// If we precompute the terms in a MAD instruction
float angleRange = cosInneAngle - cosOuterAngle;
lightAttenuationParams = new Vector4(cosOuterAngle,
Mathf.Approximately(angleRange, 0.0f) ? 1.0f : angleRange, quadAtten, rangeSq);
float smoothAngleRange = cosInneAngle - cosOuterAngle;
if (Mathf.Approximately(smoothAngleRange, 0.0f))
smoothAngleRange = 1.0f;
float invAngleRange = 1.0f / smoothAngleRange;
float add = -cosOuterAngle * invAngleRange;
lightAttenuationParams = new Vector4(invAngleRange, add, quadAtten, rangeSq);
lightAttenuationParams = new Vector4(-1.0f, 1.0f, quadAtten, rangeSq);
lightAttenuationParams = new Vector4(0.0f, 1.0f, quadAtten, rangeSq);
private void SetupShaderSingleLightConstants(VisibleLight[] lights, int lightIndex, ref ScriptableRenderContext context)
private void SetupPerFrameShaderConstants(ref ScriptableRenderContext context)
{
// When glossy reflections are OFF in the shader we set a constant color to use as indirect specular
SphericalHarmonicsL2 ambientSH = RenderSettings.ambientProbe;
Vector4 glossyEnvColor = new Vector4(ambientSH[0, 0], ambientSH[1, 0], ambientSH[2, 0]) * RenderSettings.reflectionIntensity;
CommandBuffer cmd = CommandBufferPool.Get("SetupPerFrameConstants");
cmd.SetGlobalVector(PerFrameBuffer._GlossyEnvironmentColor, glossyEnvColor);
if (m_Asset.AttenuationTexture != null) cmd.SetGlobalTexture(PerFrameBuffer._AttenuationTexture, m_Asset.AttenuationTexture);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release (cmd);
}
private void SetupShaderLightConstants(CommandBuffer cmd, VisibleLight[] lights, ref LightData lightData, ref CullResults cullResults, ref ScriptableRenderContext context)
{
// Main light has an optimized shader path for main light. This will benefit games that only care about a single light.
// Lightweight pipeline also supports only a single shadow light, if available it will be the main light.
SetupMainLightConstants(cmd, lights, lightData.mainLightIndex, ref context);
if (lightData.shadowsRendered)
SetupShadowShaderConstants(cmd, ref context, ref lights[lightData.mainLightIndex], m_ShadowCasterCascadesCount);
if (lightData.totalAdditionalLightsCount > 0)
SetupAdditionalListConstants(cmd, lights, ref lightData, ref context);
}
private void SetupMainLightConstants(CommandBuffer cmd, VisibleLight[] lights, int lightIndex, ref ScriptableRenderContext context)
CommandBuffer cmd = new CommandBuffer() { name = "SetupSingleLightConstants" };
cmd.SetGlobalVector("_LightPosition", lightPos);
cmd.SetGlobalColor("_LightColor", lightColor);
cmd.SetGlobalVector("_LightSpotDir", lightSpotDir);
cmd.SetGlobalVector("_LightAttenuationParams", lightAttenuationParams);
if (m_Asset.AttenuationTexture != null) cmd.SetGlobalTexture("_AttenuationTexture", m_Asset.AttenuationTexture);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
cmd.SetGlobalVector(PerCameraBuffer._MainLightPosition, lightPos);
cmd.SetGlobalColor(PerCameraBuffer._MainLightColor, lightColor);
cmd.SetGlobalVector(PerCameraBuffer._MainLightSpotDir, lightSpotDir);
cmd.SetGlobalVector(PerCameraBuffer._MainLightAttenuationParams, lightAttenuationParams);
private void SetupShaderLightListConstants(VisibleLight[] lights, ref LightData lightData, ref ScriptableRenderContext context)
private void SetupAdditionalListConstants(CommandBuffer cmd, VisibleLight[] lights, ref LightData lightData, ref ScriptableRenderContext context)
int maxLights = Math.Min(kMaxVisibleLights, lights.Length);
int additionalLightIndex = 0;
for (int i = 0; i < maxLights; ++i)
InitializeLightConstants(lights, i, out m_LightPositions[i], out m_LightColors[i], out m_LightSpotDirections[i], out m_LightAttenuations[i]);
// We need to update per-object light list with the proper map to our global additional light buffer
// First we initialize all lights in the map to -1 to tell the system to discard main light index and
// remaining lights in the scene that don't fit the max additional light buffer (kMaxVisibileAdditionalLights)
int[] perObjectLightIndexMap = m_CullResults.GetLightIndexMap();
for (int i = 0; i < lights.Length; ++i)
perObjectLightIndexMap[i] = -1;
// Lightweight pipeline only upload kMaxVisibleLights to shader cbuffer.
// We tell the pipe to disable remaining lights by setting it to -1.
int[] lightIndexMap = m_CullResults.GetLightIndexMap();
for (int i = kMaxVisibleLights; i < lightIndexMap.Length; ++i)
lightIndexMap[i] = -1;
m_CullResults.SetLightIndexMap(lightIndexMap);
for (int i = 0; i < lights.Length && additionalLightIndex < kMaxVisibleAdditionalLights; ++i)
{
if (i != lightData.mainLightIndex)
{
// The engine performs per-object light culling and initialize 8 light indices into two vec4 constants unity_4LightIndices0 and unity_4LightIndices1.
// In the shader we iterate over each visible light using the indices provided in these constants to index our global light buffer
// ex: first light position would be m_LightPosisitions[unity_4LightIndices[0]];
// However since we sorted the lights we need to tell the engine how to map the original/unsorted indices to our global buffer
// We do it by settings the perObjectLightIndexMap to the appropriate additionalLightIndex.
perObjectLightIndexMap[GetLightUnsortedIndex(i)] = additionalLightIndex;
InitializeLightConstants(lights, i, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightSpotDirections[additionalLightIndex],
out m_LightAttenuations[additionalLightIndex]);
additionalLightIndex++;
}
}
m_CullResults.SetLightIndexMap(perObjectLightIndexMap);
CommandBuffer cmd = CommandBufferPool.Get("SetupLightShaderConstants");
cmd.SetGlobalVector("globalLightCount", new Vector4 (lightData.pixelLightsCount, lightData.vertexLightsCount, 0.0f, 0.0f));
cmd.SetGlobalVectorArray ("globalLightPos", m_LightPositions);
cmd.SetGlobalVectorArray ("globalLightColor", m_LightColors);
cmd.SetGlobalVectorArray ("globalLightAtten", m_LightAttenuations);
cmd.SetGlobalVectorArray ("globalLightSpotDir", m_LightSpotDirections);
if (m_Asset.AttenuationTexture != null) cmd.SetGlobalTexture("_AttenuationTexture", m_Asset.AttenuationTexture);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, new Vector4 (lightData.pixelAdditionalLightsCount,
lightData.totalAdditionalLightsCount, 0.0f, 0.0f));
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightPosition, m_LightPositions);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightColor, m_LightColors);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightAttenuationParams, m_LightAttenuations);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightSpotDir, m_LightSpotDirections);
private void SetShaderKeywords(ref LightData lightData, ref ScriptableRenderContext context)
private void SetupShadowShaderConstants(CommandBuffer cmd, ref ScriptableRenderContext context, ref VisibleLight shadowLight, int cascadeCount)
CommandBuffer cmd = new CommandBuffer() { name = "SetShaderKeywords" };
SetShaderKeywords(cmd, lightData.shadowsRendered, lightData.isSingleLight, lightData.vertexLightsCount > 0);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
Vector3 shadowLightDir = Vector3.Normalize(shadowLight.localToWorld.GetColumn(2));
Light light = shadowLight.light;
float bias = light.shadowBias * 0.1f;
float normalBias = light.shadowNormalBias;
float shadowResolution = m_ShadowSlices[0].shadowResolution;
const int maxShadowCascades = 4;
Matrix4x4[] shadowMatrices = new Matrix4x4[maxShadowCascades];
for (int i = 0; i < cascadeCount; ++i)
shadowMatrices[i] = (cascadeCount >= i) ? m_ShadowSlices[i].shadowTransform : Matrix4x4.identity;
// TODO: shadow resolution per cascade in case cascades endup being supported.
float invShadowResolution = 1.0f / shadowResolution;
float[] pcfKernel =
{
-0.5f * invShadowResolution, 0.5f * invShadowResolution,
0.5f * invShadowResolution, 0.5f * invShadowResolution,
-0.5f * invShadowResolution, -0.5f * invShadowResolution,
0.5f * invShadowResolution, -0.5f * invShadowResolution
};
cmd.SetGlobalMatrixArray("_WorldToShadow", shadowMatrices);
cmd.SetGlobalVectorArray("_DirShadowSplitSpheres", m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector("_ShadowLightDirection", new Vector4(-shadowLightDir.x, -shadowLightDir.y, -shadowLightDir.z, 0.0f));
cmd.SetGlobalVector("_ShadowData", new Vector4(0.0f, bias, normalBias, 0.0f));
cmd.SetGlobalFloatArray("_PCFKernel", pcfKernel);
}
private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, VisibleLight[] visibleLights)
{
int vertexLightsCount = lightData.totalAdditionalLightsCount - lightData.pixelAdditionalLightsCount;
LightweightUtils.SetKeyword(cmd, "_VERTEX_LIGHTS", vertexLightsCount > 0);
int mainLightIndex = lightData.mainLightIndex;
LightweightUtils.SetKeyword (cmd, "_MAIN_DIRECTIONAL_LIGHT", mainLightIndex == -1 || visibleLights[mainLightIndex].lightType == LightType.Directional);
LightweightUtils.SetKeyword (cmd, "_MAIN_SPOT_LIGHT", mainLightIndex != -1 && visibleLights[mainLightIndex].lightType == LightType.Spot);
LightweightUtils.SetKeyword (cmd, "_MAIN_POINT_LIGHT", mainLightIndex != -1 && visibleLights[mainLightIndex].lightType == LightType.Point);
LightweightUtils.SetKeyword(cmd, "_ADDITIONAL_LIGHTS", lightData.totalAdditionalLightsCount > 0);
string[] shadowKeywords = new string[] { "_HARD_SHADOWS", "_SOFT_SHADOWS", "_HARD_SHADOWS_CASCADES", "_SOFT_SHADOWS_CASCADES" };
for (int i = 0; i < shadowKeywords.Length; ++i)
cmd.DisableShaderKeyword(shadowKeywords[i]);
if (m_Asset.AreShadowsEnabled() && lightData.shadowsRendered)
{
int keywordIndex = (int)m_Asset.ShadowSetting - 1;
if (m_Asset.CascadeCount > 1)
keywordIndex += 2;
cmd.EnableShaderKeyword(shadowKeywords[keywordIndex]);
}
LightweightUtils.SetKeyword(cmd, "SOFTPARTICLES_ON", m_Asset.SupportsSoftParticles);
}
private bool RenderShadows(ref CullResults cullResults, ref VisibleLight shadowLight, int shadowLightIndex, ref ScriptableRenderContext context)

var setRenderTargetCommandBuffer = CommandBufferPool.Get();
setRenderTargetCommandBuffer.name = "Render packed shadows";
setRenderTargetCommandBuffer.GetTemporaryRT(m_ShadowMapProperty, m_ShadowSettings.shadowAtlasWidth,
setRenderTargetCommandBuffer.GetTemporaryRT(m_ShadowMapTexture, m_ShadowSettings.shadowAtlasWidth,
setRenderTargetCommandBuffer.SetRenderTarget(m_ShadowMapRTID);
setRenderTargetCommandBuffer.SetRenderTarget(m_ShadowMapRT);
setRenderTargetCommandBuffer.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(setRenderTargetCommandBuffer);
CommandBufferPool.Release(setRenderTargetCommandBuffer);

return resolution;
}
private void SetupShadowShaderConstants(ref ScriptableRenderContext context, ref VisibleLight shadowLight, int shadowLightIndex, int cascadeCount)
{
Vector3 shadowLightDir = Vector3.Normalize(shadowLight.localToWorld.GetColumn(2));
float bias = shadowLight.light.shadowBias * 0.1f;
float normalBias = shadowLight.light.shadowNormalBias;
float shadowResolution = m_ShadowSlices[0].shadowResolution;
const int maxShadowCascades = 4;
Matrix4x4[] shadowMatrices = new Matrix4x4[maxShadowCascades];
for (int i = 0; i < cascadeCount; ++i)
shadowMatrices[i] = (cascadeCount >= i) ? m_ShadowSlices[i].shadowTransform : Matrix4x4.identity;
// TODO: shadow resolution per cascade in case cascades endup being supported.
float invShadowResolution = 1.0f / shadowResolution;
float[] pcfKernel =
{
-0.5f * invShadowResolution, 0.5f * invShadowResolution,
0.5f * invShadowResolution, 0.5f * invShadowResolution,
-0.5f * invShadowResolution, -0.5f * invShadowResolution,
0.5f * invShadowResolution, -0.5f * invShadowResolution
};
var setupShadow = CommandBufferPool.Get("SetupShadowShaderConstants");
setupShadow.SetGlobalMatrixArray("_WorldToShadow", shadowMatrices);
setupShadow.SetGlobalVectorArray("_DirShadowSplitSpheres", m_DirectionalShadowSplitDistances);
setupShadow.SetGlobalVector("_ShadowLightDirection", new Vector4(-shadowLightDir.x, -shadowLightDir.y, -shadowLightDir.z, 0.0f));
setupShadow.SetGlobalVector("_ShadowData", new Vector4(shadowLightIndex, bias, normalBias, 0.0f));
setupShadow.SetGlobalFloatArray("_PCFKernel", pcfKernel);
context.ExecuteCommandBuffer(setupShadow);
CommandBufferPool.Release(setupShadow);
}
private void SetShaderKeywords(CommandBuffer cmd, bool renderShadows, bool singleLight, bool vertexLightSupport)
{
LightweightUtils.SetKeyword(cmd, "LIGHTWEIGHT_LINEAR", m_Asset.ForceLinearRendering);
LightweightUtils.SetKeyword(cmd, "_VERTEX_LIGHTS", vertexLightSupport);
LightweightUtils.SetKeyword(cmd, "_ATTENUATION_TEXTURE", m_Asset.AttenuationTexture != null);
LightweightUtils.SetKeyword(cmd, "_LIGHT_PROBES_ON", m_Asset.EnableAmbientProbe);
LightweightUtils.SetKeyword(cmd, "LIGHTWEIGHT_LINEAR", m_Asset.ForceLinearRendering);
if (!singleLight)
{
LightweightUtils.SetKeyword(cmd, "_SINGLE_DIRECTIONAL_LIGHT", false);
LightweightUtils.SetKeyword(cmd, "_SINGLE_SPOT_LIGHT", false);
LightweightUtils.SetKeyword(cmd, "_SINGLE_POINT_LIGHT", false);
}
else
{
switch (m_SingleLightType)
{
case LightType.Directional:
LightweightUtils.SetKeyword(cmd, "_SINGLE_DIRECTIONAL_LIGHT", true);
LightweightUtils.SetKeyword(cmd, "_SINGLE_SPOT_LIGHT", false);
LightweightUtils.SetKeyword(cmd, "_SINGLE_POINT_LIGHT", false);
break;
case LightType.Spot:
LightweightUtils.SetKeyword(cmd, "_SINGLE_DIRECTIONAL_LIGHT", false);
LightweightUtils.SetKeyword(cmd, "_SINGLE_SPOT_LIGHT", true);
LightweightUtils.SetKeyword(cmd, "_SINGLE_POINT_LIGHT", false);
break;
case LightType.Point:
LightweightUtils.SetKeyword(cmd, "_SINGLE_DIRECTIONAL_LIGHT", false);
LightweightUtils.SetKeyword(cmd, "_SINGLE_SPOT_LIGHT", false);
LightweightUtils.SetKeyword(cmd, "_SINGLE_POINT_LIGHT", true);
break;
}
}
string[] shadowKeywords = new string[] { "_HARD_SHADOWS", "_SOFT_SHADOWS", "_HARD_SHADOWS_CASCADES", "_SOFT_SHADOWS_CASCADES" };
for (int i = 0; i < shadowKeywords.Length; ++i)
cmd.DisableShaderKeyword(shadowKeywords[i]);
if (renderShadows && m_Asset.CurrShadowType != ShadowType.NO_SHADOW)
{
int keywordIndex = (int)m_Asset.CurrShadowType - 1;
if (m_Asset.CascadeCount > 1)
keywordIndex += 2;
cmd.EnableShaderKeyword(shadowKeywords[keywordIndex]);
}
}
private void InitializeMainShadowLightIndex(VisibleLight[] lights, out int shadowIndex)
private void BeginForwardRendering(ref ScriptableRenderContext context, FrameRenderingConfiguration renderingConfig)
shadowIndex = -1;
if (m_Asset.CurrShadowType == ShadowType.NO_SHADOW)
return;
RenderTargetIdentifier colorRT = BuiltinRenderTextureType.CameraTarget;
RenderTargetIdentifier depthRT = BuiltinRenderTextureType.None;
float maxIntensity = -1;
for (int i = 0; i < lights.Length; ++i)
{
Light light = lights[i].light;
if (light.shadows != LightShadows.None && IsSupportedShadowType(light.type) && light.intensity > maxIntensity)
{
shadowIndex = i;
maxIntensity = light.intensity;
}
}
}
private bool IsSupportedShadowType(LightType type)
{
return (type == LightType.Directional || type == LightType.Spot);
}
private void BeginForwardRendering(ref ScriptableRenderContext context, bool stereoEnabled)
{
if (stereoEnabled)
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.Stereo))
var cmd = CommandBufferPool.Get("SetCameraRenderTarget");
if (m_RenderToIntermediateTarget)
CommandBuffer cmd = CommandBufferPool.Get("SetCameraRenderTarget");
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.IntermediateTexture))
{
m_IntermediateTextureArray = false;
if (stereoEnabled)
{
RenderTextureDescriptor xrDesc = XRSettings.eyeTextureDesc;
xrDesc.depthBufferBits = kCameraDepthBufferBits;
xrDesc.colorFormat = m_ColorFormat;
xrDesc.msaaSamples = m_Asset.MSAASampleCount;
colorRT = m_CameraColorRT;
m_IntermediateTextureArray = (xrDesc.dimension == TextureDimension.Tex2DArray);
cmd.GetTemporaryRT(m_CameraRTProperty, xrDesc, FilterMode.Bilinear);
}
else
{
cmd.GetTemporaryRT(m_CameraRTProperty, Screen.width, Screen.height, kCameraDepthBufferBits,
FilterMode.Bilinear, m_ColorFormat, RenderTextureReadWrite.Default, m_Asset.MSAASampleCount);
}
if (m_IntermediateTextureArray)
cmd.SetRenderTarget(m_CameraRTID, 0, CubemapFace.Unknown, -1);
else
cmd.SetRenderTarget(m_CameraRTID);
}
else
{
cmd.SetRenderTarget(new RenderTargetIdentifier(m_CurrCamera.activeTexture));
}
}
else
{
cmd.SetRenderTarget(BuiltinRenderTextureType.CurrentActive);
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.RequireDepth))
depthRT = m_CameraDepthRT;
if (!stereoEnabled)
{
Rect viewport = m_CurrCamera.rect;
if (m_CurrCamera.targetTexture == null)
{
viewport.x *= Screen.width;
viewport.y *= Screen.height;
viewport.width *= Screen.width;
viewport.height *= Screen.height;
}
else
{
viewport = new Rect(0.0f, 0.0f, m_CurrCamera.targetTexture.width, m_CurrCamera.targetTexture.height);
}
cmd.SetViewport(viewport);
}
SetupRenderTargets(cmd, colorRT, depthRT);
// Clear RenderTarget to avoid tile initialization on mobile GPUs
// https://community.arm.com/graphics/b/blog/posts/mali-performance-2-how-to-correctly-handle-framebuffers

CommandBufferPool.Release(cmd);
}
private void EndForwardRendering(ref ScriptableRenderContext context, bool stereoEnabled, bool postProcessing)
private void EndForwardRendering(ref ScriptableRenderContext context, FrameRenderingConfiguration renderingConfig)
// No additional rendering needs to be done if this is an offscren rendering camera (unless camera is scene view)
if (m_CurrCamera.targetTexture != null && m_CurrCamera.cameraType != CameraType.SceneView)
return;
if (m_RenderToIntermediateTarget || postProcessing)
var cmd = CommandBufferPool.Get("Blit");
if (m_IntermediateTextureArray)
var cmd = CommandBufferPool.Get("Blit");
if (m_IntermediateTextureArray)
{
cmd.SetRenderTarget(BuiltinRenderTextureType.CameraTarget, 0, CubemapFace.Unknown, -1);
cmd.Blit(m_CameraRTID, BuiltinRenderTextureType.CurrentActive);
}
// If PostProcessing is enabled, it is already blitted to CameraTarget.
else if (!postProcessing)
cmd.Blit(BuiltinRenderTextureType.CurrentActive, BuiltinRenderTextureType.CameraTarget);
cmd.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
cmd.SetRenderTarget(BuiltinRenderTextureType.CameraTarget, 0, CubemapFace.Unknown, -1);
cmd.Blit(m_CameraColorRT, BuiltinRenderTextureType.CurrentActive);
}
else if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.IntermediateTexture))
{
// If PostProcessing is enabled, it is already blit to CameraTarget.
if (!LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.PostProcess))
Blit(cmd, renderingConfig, BuiltinRenderTextureType.CurrentActive, BuiltinRenderTextureType.CameraTarget);
if (stereoEnabled)
SetupRenderTargets(cmd, BuiltinRenderTextureType.CameraTarget, BuiltinRenderTextureType.None);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.Stereo))
{
context.StopMultiEye(m_CurrCamera);
context.StereoEndRender(m_CurrCamera);

private void RenderPostProcess(ref ScriptableRenderContext renderContext, PostProcessLayer postProcessLayer)
RendererConfiguration GetRendererSettings(ref LightData lightData)
{
RendererConfiguration settings = RendererConfiguration.PerObjectReflectionProbes | RendererConfiguration.PerObjectLightmaps | RendererConfiguration.PerObjectLightProbe;
if (lightData.totalAdditionalLightsCount > 0)
settings |= RendererConfiguration.PerObjectLightIndices8;
return settings;
}
private void SetupRenderTargets(CommandBuffer cmd, RenderTargetIdentifier colorRT, RenderTargetIdentifier depthRT)
var postProcessCommand = CommandBufferPool.Get("Post Processing");
int depthSlice = (m_IntermediateTextureArray) ? -1 : 0;
if (depthRT != BuiltinRenderTextureType.None)
cmd.SetRenderTarget(colorRT, depthRT, 0, CubemapFace.Unknown, depthSlice);
else
cmd.SetRenderTarget(colorRT, 0, CubemapFace.Unknown, depthSlice);
}
private void RenderPostProcess(CommandBuffer cmd, bool opaqueOnly)
{
m_PostProcessRenderContext.command = postProcessCommand;
m_PostProcessRenderContext.command = cmd;
postProcessLayer.Render(m_PostProcessRenderContext);
renderContext.ExecuteCommandBuffer(postProcessCommand);
CommandBufferPool.Release(postProcessCommand);
if (opaqueOnly)
m_CameraPostProcessLayer.RenderOpaqueOnly(m_PostProcessRenderContext);
else
m_CameraPostProcessLayer.Render(m_PostProcessRenderContext);
private bool GetRenderToIntermediateTarget()
private int GetLightUnsortedIndex(int index)
{
Debug.Assert(index >= 0 && index < m_SortedLightIndexMap.Count, "Invalid index while accessing light index map. If you only have a single light in scene you should not try to map indices");
return m_SortedLightIndexMap[index];
}
private void Blit(CommandBuffer cmd, FrameRenderingConfiguration renderingConfig, RenderTargetIdentifier sourceRT, RenderTargetIdentifier destRT, Material material = null)
bool allowMSAA = m_CurrCamera.allowMSAA &&
m_Asset.MSAASampleCount > 1 &&
!LightweightUtils.PlatformSupportsMSAABackBuffer();
if (m_CurrCamera.cameraType == CameraType.SceneView || allowMSAA || m_CurrCamera.targetTexture != null)
return true;
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.DefaultViewport))
{
cmd.Blit(sourceRT, destRT, material);
}
else
{
if (m_BlitQuad == null)
m_BlitQuad = LightweightUtils.CreateQuadMesh(false);
return false;
cmd.SetGlobalTexture(m_BlitTexID, sourceRT);
cmd.SetRenderTarget(destRT);
cmd.SetViewport(m_CurrCamera.pixelRect);
cmd.DrawMesh(m_BlitQuad, Matrix4x4.identity, m_BlitMaterial);
}
private PostProcessLayer GetCurrCameraPostProcessLayer()
private void CopyTexture(CommandBuffer cmd, RenderTargetIdentifier sourceRT, RenderTargetIdentifier destRT)
return m_CurrCamera.GetComponent<PostProcessLayer>();
if (m_CopyTextureSupport != CopyTextureSupport.None)
cmd.CopyTexture(m_CameraDepthRT, m_CameraCopyDepthRT);
else
cmd.Blit(m_CameraDepthRT, m_CameraCopyDepthRT, m_CopyDepthMaterial);
}
}
}

13
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset


m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
m_Name: LightweightPipelineAsset
m_EditorClassIdentifier:
m_MaxPixelLights: 4
m_SupportsVertexLight: 1
m_EnableLightmaps: 1
m_EnableAmbientProbe: 1
m_MaxAdditionalPixelLights: 4
m_SupportsVertexLight: 0
m_SupportSoftParticles: 1
m_RenderScale: 1
m_ShadowType: 1
m_ShadowAtlasResolution: 1024
m_ShadowNearPlaneOffset: 2

m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467}
m_LinearRendering: 1
m_DefaultDiffuseMaterial: {fileID: 2100000, guid: 6a1143ee683302f4aa628c052723efc1,
m_DefaultDiffuseMaterial: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d,
type: 2}
m_DefaultParticleMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d,
type: 2}

type: 2}
m_DefaultUIMaterial: {fileID: 2100000, guid: 786cc499ea3906946b10ab7d24c8d0e7, type: 2}
m_DefaultShader: {fileID: 4800000, guid: 8d2bb70cbf9db8d4da26e15b26e74248, type: 3}
m_DefaultShader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}

98
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.cs


public class LightweightPipelineAsset : RenderPipelineAsset
{
private static readonly string m_PipelineFolder = "Assets/ScriptableRenderPipeline/LightweightPipeline";
public static readonly string m_SimpleLightShaderPath = "LightweightPipeline/Standard (Simple Lighting)";
public static readonly string m_StandardShaderPath = "LightweightPipeline/Standard (Physically Based)";
public static readonly string m_BlitShaderPath = "Hidden/LightweightPipeline/Blit";
public static readonly string m_CopyDephPath = "Hidden/LightweightPipeline/CopyDepth";
private static readonly string m_PipelineFolder = "Assets/LightweightPipeline";
[SerializeField] private int m_MaxAdditionalPixelLights = 1;
[SerializeField] private bool m_SupportsVertexLight = true;
[SerializeField] private bool m_SupportSoftParticles = false;
[SerializeField] private MSAAQuality m_MSAA = MSAAQuality.Disabled;
[SerializeField] private float m_RenderScale = 1.0f;
[SerializeField] private ShadowType m_ShadowType = ShadowType.HARD_SHADOWS;
[SerializeField] private ShadowResolution m_ShadowAtlasResolution = ShadowResolution._1024;
[SerializeField] private float m_ShadowNearPlaneOffset = 2.0f;
[SerializeField] private float m_ShadowDistance = 50.0f;
[SerializeField] private ShadowCascades m_ShadowCascades = ShadowCascades.NO_CASCADES;
[SerializeField] private float m_Cascade2Split = 0.25f;
[SerializeField] private Vector3 m_Cascade4Split = new Vector3(0.067f, 0.2f, 0.467f);
[SerializeField] private Texture2D m_AttenuationTexture;
[SerializeField] private Material m_DefaultDiffuseMaterial;
[SerializeField] private Material m_DefaultParticleMaterial;
[SerializeField] private Material m_DefaultLineMaterial;
[SerializeField] private Material m_DefaultSpriteMaterial;
[SerializeField] private Material m_DefaultUIMaterial;
[SerializeField] private Shader m_DefaultShader;
[UnityEditor.MenuItem("RenderPipeline/LightweightPipeline/Create Pipeline Asset", false, 15)]
[UnityEditor.MenuItem("RenderPipeline/Lightweight Pipeline/Create Pipeline Asset", false, 15)]
static void CreateLightweightPipeline()
{
var instance = ScriptableObject.CreateInstance<LightweightPipelineAsset>();

DestroyCreatedInstances();
}
#region PipelineAssetSettings
[SerializeField] private int m_MaxPixelLights = 1;
[SerializeField] private bool m_SupportsVertexLight = true;
[SerializeField] private bool m_EnableLightmaps = true;
[SerializeField] private bool m_EnableAmbientProbe = true;
[SerializeField] private MSAAQuality m_MSAA = MSAAQuality.Disabled;
[SerializeField] private ShadowType m_ShadowType = ShadowType.HARD_SHADOWS;
[SerializeField] private ShadowResolution m_ShadowAtlasResolution = ShadowResolution._1024;
[SerializeField] private float m_ShadowNearPlaneOffset = 2.0f;
[SerializeField] private float m_ShadowDistance = 50.0f;
[SerializeField] private ShadowCascades m_ShadowCascades = ShadowCascades.NO_CASCADES;
[SerializeField] private float m_Cascade2Split = 0.25f;
[SerializeField] private Vector3 m_Cascade4Split = new Vector3(0.067f, 0.2f, 0.467f);
[SerializeField] private bool m_LinearRendering = true;
[SerializeField] private Texture2D m_AttenuationTexture;
[SerializeField] private Material m_DefaultDiffuseMaterial;
[SerializeField] private Material m_DefaultParticleMaterial;
[SerializeField] private Material m_DefaultLineMaterial;
[SerializeField] private Material m_DefaultSpriteMaterial;
[SerializeField] private Material m_DefaultUIMaterial;
[SerializeField] private Shader m_DefaultShader;
public bool AreShadowsEnabled()
{
return ShadowSetting != ShadowType.NO_SHADOW;
}
public int MaxSupportedPixelLights
public int MaxAdditionalPixelLights
get { return m_MaxPixelLights; }
private set { m_MaxPixelLights = value; }
get { return m_MaxAdditionalPixelLights; }
private set { m_SupportsVertexLight = value; }
public bool EnableLightmap
public bool SupportsSoftParticles
get { return m_EnableLightmaps; }
private set { m_EnableLightmaps = value; }
get { return m_SupportSoftParticles; }
public bool EnableAmbientProbe
public int MSAASampleCount
get { return m_EnableAmbientProbe; }
private set { m_EnableAmbientProbe = value; }
get { return (int)m_MSAA; }
set { m_MSAA = (MSAAQuality)value; }
public int MSAASampleCount
public float RenderScale
get { return (int)m_MSAA; }
set { m_MSAA = (MSAAQuality)value; }
get { return m_RenderScale; }
set { m_RenderScale = value; }
public ShadowType CurrShadowType
public ShadowType ShadowSetting
{
get { return m_ShadowType; }
private set { m_ShadowType = value; }

private set { m_Cascade4Split = value; }
}
public bool ForceLinearRendering
{
get { return m_LinearRendering; }
set { m_LinearRendering = value; }
}
public Texture2D AttenuationTexture
{
get { return m_AttenuationTexture; }

#endregion
public override Material GetDefaultMaterial()
{
return m_DefaultDiffuseMaterial;

public override Shader GetDefaultShader()
{
return m_DefaultShader;
}
public Shader BlitShader
{
get { return Shader.Find(LightweightPipelineAsset.m_BlitShaderPath); }
}
public Shader CopyDepthShader
{
get { return Shader.Find(LightweightPipelineAsset.m_CopyDephPath); }
}
}
}

106
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineUtils.cs


using System.Collections.Generic;
using UnityEngine;
using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.LightweightPipeline

}
}
public class LightComparer : IComparer<VisibleLight>
{
public Camera CurrCamera { get; set; }
// Sorts on the following priority:
// Directionals have priority over local lights
// ShadowLight type
// Has Cookie
// Intensity if Directional, Distance to camera otherwise
public int Compare(VisibleLight lhs, VisibleLight rhs)
{
Light lhsLight = lhs.light;
Light rhsLight = rhs.light;
if (lhs.lightType != rhs.lightType)
{
if (lhs.lightType == LightType.Directional) return -1;
if (rhs.lightType == LightType.Directional) return 1;
}
// Particle Lights have the Light reference set to null
// They are at the end of the priority
if (lhsLight == null) return 1;
if (rhsLight == null) return -1;
// In the following priority: Soft, Hard, None
if (lhsLight.shadows != rhsLight.shadows)
return (int)rhsLight.shadows - (int)lhsLight.shadows;
if (lhsLight.cookie != rhsLight.cookie)
return (lhsLight.cookie != null) ? -1 : 1;
if (lhs.lightType == LightType.Directional)
return (int)(lhsLight.intensity*100.0f) - (int)(rhsLight.intensity*100.0f);
else
return (int)(SquaredDistanceToCamera(lhsLight.transform.position) - SquaredDistanceToCamera(rhsLight.transform.position));
}
public float SquaredDistanceToCamera(Vector3 lightPos)
{
Vector3 lightCameraVector = lightPos - CurrCamera.transform.position;
return Vector3.Dot(lightCameraVector, lightCameraVector);
}
}
[Flags]
public enum FrameRenderingConfiguration
{
None = 0,
Stereo = (1 << 0),
Msaa = (1 << 1),
PostProcess = (1 << 2),
RequireDepth = (1 << 3),
DefaultViewport = (1 << 4),
IntermediateTexture = (1 << 5),
}
public static class LightweightUtils
{
public static void SetKeyword(CommandBuffer cmd, string keyword, bool enable)

cmd.DisableShaderKeyword(keyword);
}
public static bool IsSupportedShadowType(LightType lightType)
{
return lightType == LightType.Directional || lightType == LightType.Spot;
}
public static bool PlatformSupportsMSAABackBuffer()
{
#if UNITY_ANDROID || UNITY_IPHONE || UNITY_TVOS || UNITY_SAMSUNGTV

#endif
}
public static bool HasFlag(FrameRenderingConfiguration mask, FrameRenderingConfiguration flag)
{
return (mask & flag) != 0;
}
public static Mesh CreateQuadMesh(bool uvStartsAtTop)
{
float topV, bottomV;
if (uvStartsAtTop)
{
topV = 0.0f;
bottomV = 1.0f;
}
else
{
topV = 1.0f;
bottomV = 0.0f;
}
Mesh mesh = new Mesh();
mesh.vertices = new Vector3[]
{
new Vector3(-1.0f, -1.0f, 0.0f),
new Vector3(-1.0f, 1.0f, 0.0f),
new Vector3( 1.0f, -1.0f, 0.0f),
new Vector3( 1.0f, 1.0f, 0.0f)
};
mesh.uv = new Vector2[]
{
new Vector2(0.0f, bottomV),
new Vector2(0.0f, topV),
new Vector2(1.0f, bottomV),
new Vector2(1.0f, topV)
};
mesh.triangles = new int[] { 0, 1, 2, 2, 1, 3 };
return mesh;
}
}
}

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-DefaultParticle.mat


m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Lightweight-DefaultParticle
m_Shader: {fileID: 207, guid: 0000000000000000f000000000000000, type: 0}
m_Shader: {fileID: 202, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0

m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:

2
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-StandardShader.mat


m_PrefabInternal: {fileID: 0}
m_Name: Lightweight-StandardShader
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_ShaderKeywords: _GLOSSYREFLECTIONS_ON _METALLIC_SETUP _SPECULARHIGHLIGHTS_ON
m_ShaderKeywords: _METALLIC_SETUP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

4
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-StandardSimpleLighting.mat


m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Lightweight-Default
m_Name: Lightweight-StandardSimpleLighting
m_ShaderKeywords: _SPECULAR_COLOR
m_ShaderKeywords: _GLOSSINESS_FROM_BASE_ALPHA _SPECULAR_COLOR
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

67
MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightUnlit.shader


Shader "ScriptableRenderPipeline/LightweightPipeline/Unlit"
Shader "LightweightPipeline/Unlit"
_Color("Color", Color) = (1, 1, 1, 1)
_MainColor("MainColor", Color) = (1, 1, 1, 1)
_Cutoff("AlphaCutout", Range(0.0, 1.0)) = 0.5
// BlendMode

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "CGIncludes/LightweightUnlit.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
float4 _MainTex_ST;
half4 _MainColor;
half _Cutoff;
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
#pragma vertex LightweightVertexUnlit
#pragma fragment LightweightFragmentUnlit
fixed4 frag(v2f i) : SV_Target
{
fixed4 texColor = tex2D(_MainTex, i.uv);
fixed alpha = texColor.a * _MainColor.a;
fixed3 color = texColor.rgb * _MainColor.rgb;
void DefineSurface(LightweightVertexOutputUnlit i, inout SurfaceUnlit s)
{
// Albedo
float4 c = tex2D(_MainTex, i.meshUV0);
s.Color = c.rgb * _Color.rgb;
// Alpha
s.Alpha = c.a * _Color.a;
clip(s.Alpha - _Cutoff);
clip(alpha - _Cutoff);
}
UNITY_APPLY_FOG(i.fogCoord, color);
#ifdef _ALPHABLEND_ON
return fixed4(color, alpha);
#else
return fixed4(color, 1.0);
#endif
}
ENDCG
}
}

11
MaterialGraphProject/Assets/Test.unity


m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1}
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0

m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 9
serializedVersion: 10
m_TextureWidth: 1024
m_TextureHeight: 1024
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1

m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: af7e4b21c055e104eb513f5aadb0bb50, type: 2}
- {fileID: 2100000, guid: d8745a7a276da8b4fa388ec0f8c421ab, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0

m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2102954616}
m_Enabled: 1
m_ExtensionPropertyValues: []
--- !u!124 &2102954618
Behaviour:
m_ObjectHideFlags: 0

m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
m_StereoMirrorMode: 0
--- !u!4 &2102954620
Transform:
m_ObjectHideFlags: 0

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/AssetCallbacks/CreateShaderGraph.cs


public override void Action(int instanceId, string pathName, string resourceFile)
{
var graph = new UnityEngine.MaterialGraph.MaterialGraph();
// graph.AddNode(new MetallicMasterNode());
graph.AddNode(new LightweightMetallicMasterNode());
File.WriteAllText(pathName, EditorJsonUtility.ToJson(graph));
AssetDatabase.Refresh();
}

1
MaterialGraphProject/Assets/UnityShaderEditor/Editor/AssetCallbacks/CreateShaderSubGraph.cs


using System.IO;
using System.IO;
using UnityEditor.ProjectWindowCallback;
using UnityEngine.MaterialGraph;

5
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs.meta


fileFormatVersion: 2
guid: 706886b5adec4e3409ceb9a30e04440e
guid: f329b5b280b7f6f449659f05937ac2f2
timeCreated: 1465559218
licenseType: Pro
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

321
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractMaterialGraph.cs


fullName = "UnityEngine.MaterialGraph.WorldPosNode",
assemblyName = "Assembly-CSharp"
};
result[worldPosNode] = SerializationHelper.GetTypeSerializableAsString(typeof(WorldSpacePositionNode));
result[worldPosNode] = SerializationHelper.GetTypeSerializableAsString(typeof(PositionNode));
class IndexedProperty
{
public int index;
public IShaderProperty property;
}
public override void ReplaceWith(IGraph other)
{
var otherMG = other as AbstractMaterialGraph;

using (var replacedPropertiesPooledObject = ListPool<IndexedProperty>.GetDisposable())
var replacedProperties = replacedPropertiesPooledObject.value;
var index = 0;
{
var otherProperty = otherMG.properties.FirstOrDefault(op => op.guid == property.guid);
if (otherProperty == null)
removedPropertyGuids.Add(property.guid);
else
replacedProperties.Add(new IndexedProperty { index = index, property = otherProperty });
index++;
}
removedPropertyGuids.Add(property.guid);
foreach (var indexedProperty in replacedProperties)
{
m_Properties[indexedProperty.index] = indexedProperty.property;
// TODO: Notify of change
}
foreach (var otherProperty in otherMG.properties)
{
if (!properties.Any(p => p.guid == otherProperty.guid))
AddShaderProperty(otherProperty);
}
}
foreach (var otherProperty in otherMG.properties)
{
if (!properties.Any(p => p.guid == otherProperty.guid))
AddShaderProperty(otherProperty);
}
}
base.ReplaceWith(other);

base.OnAfterDeserialize();
}
static ShaderGraphRequirements GetRequierments(AbstractMaterialNode nodeForRequirements)
protected static ShaderGraphRequirements GetRequierments(AbstractMaterialNode nodeForRequirements)
if (nodeForRequirements == null)
return ShaderGraphRequirements.none;
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, nodeForRequirements);

return reqs;
}
static void GenerateSpaceTranslationSurfaceInputs(
NeededCoordinateSpace neededSpaces,
ShaderGenerator surfaceInputs,
string objectSpaceName,
string viewSpaceName,
string worldSpaceName,
string tangentSpaceName)
{
if ((neededSpaces & NeededCoordinateSpace.Object) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", objectSpaceName), false);
if ((neededSpaces & NeededCoordinateSpace.World) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", worldSpaceName), false);
if ((neededSpaces & NeededCoordinateSpace.View) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", viewSpaceName), false);
if ((neededSpaces & NeededCoordinateSpace.Tangent) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", tangentSpaceName), false);
}
public string GetPreviewShader(AbstractMaterialNode node, out PreviewMode previewMode)
{

public string GetShader(AbstractMaterialNode node, GenerationMode mode, string name, out List<PropertyCollector.TextureInfo> configuredTextures, out PreviewMode previewMode)
protected static void GenerateSurfaceDescriptionStruct(ShaderGenerator surfaceDescriptionStruct, AbstractMaterialNode node, bool isMasterNode)
if (node == null)
throw new ArgumentNullException("node");
surfaceDescriptionStruct.AddShaderChunk("struct SurfaceDescription{", false);
surfaceDescriptionStruct.Indent();
if (isMasterNode)
{
foreach (var slot in node.GetInputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk(string.Format("{0} {1};", AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), slot.shaderOutputName), false);
}
else
{
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk(string.Format("{0} {1};", AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), node.GetVariableNameForSlot(slot.id)), false);
}
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);
var vertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var shaderFunctionVisitor = new ShaderGenerator();
var surfaceInputs = new ShaderGenerator();
var graphVertexInput = @"
struct GraphVertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord0 : TEXCOORD0;
float4 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};";
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var requirements = GetRequierments(node);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceNormal, ShaderGeneratorNames.ViewSpaceNormal,
ShaderGeneratorNames.WorldSpaceNormal, ShaderGeneratorNames.TangentSpaceNormal);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceTangent, ShaderGeneratorNames.ViewSpaceTangent,
ShaderGeneratorNames.WorldSpaceTangent, ShaderGeneratorNames.TangentSpaceTangent);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceBiTangent, ShaderGeneratorNames.ViewSpaceBiTangent,
ShaderGeneratorNames.WorldSpaceBiTangent, ShaderGeneratorNames.TangentSpaceBiTangent);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceViewDirection, ShaderGeneratorNames.ViewSpaceViewDirection,
ShaderGeneratorNames.WorldSpaceViewDirection, ShaderGeneratorNames.TangentSpaceViewDirection);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, surfaceInputs,
ShaderGeneratorNames.ObjectSpacePosition, ShaderGeneratorNames.ViewSpacePosition,
ShaderGeneratorNames.WorldSpacePosition, ShaderGeneratorNames.TangentSpacePosition);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
previewMode = PreviewMode.Preview2D;
foreach (var pNode in activeNodeList.OfType<AbstractMaterialNode>())
surfaceDescriptionStruct.AddShaderChunk("void ScaleSurfaceDescription(inout SurfaceDescription surface, float scale){", false);
surfaceDescriptionStruct.Indent();
if (isMasterNode)
if (pNode.previewMode == PreviewMode.Preview3D)
{
previewMode = PreviewMode.Preview3D;
break;
}
foreach (var slot in node.GetInputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk( string.Format("surface.{0} = scale * surface.{0};", slot.shaderOutputName), false);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
else
{
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk(string.Format("surface.{0} = scale * surface.{0};", node.GetVariableNameForSlot(slot.id)), false);
}
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);
vertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
vertexShader.Indent();
vertexShader.AddShaderChunk("return v;", false);
vertexShader.Deindent();
vertexShader.AddShaderChunk("}", false);
surfaceDescriptionStruct.AddShaderChunk("struct SurfaceDescription{", false);
surfaceDescriptionStruct.AddShaderChunk("void AddSurfaceDescription(inout SurfaceDescription base, in SurfaceDescription add){", false);
if (node is IMasterNode)
if (isMasterNode)
surfaceDescriptionStruct.AddShaderChunk(AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType) + " " + slot.shaderOutputName + ";", false);
{
var str = string.Format("base.{0} = base.{0} + add.{0};", slot.shaderOutputName);
surfaceDescriptionStruct.AddShaderChunk(str, false);
}
surfaceDescriptionStruct.AddShaderChunk(AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType) + " " + node.GetVariableNameForSlot(slot.id) + ";", false);
{
var str = string.Format("base.{0} = base.{0} + add.{0};", node.GetVariableNameForSlot(slot.id));
surfaceDescriptionStruct.AddShaderChunk(str, false);
}
}
surfaceDescriptionFunction.AddShaderChunk("SurfaceDescription PopulateSurfaceData(SurfaceInputs IN) {", false);
protected static void GenerateSurfaceDescription(
AbstractMaterialNode node,
ShaderGenerator surfaceDescriptionFunction,
ShaderGenerator shaderFunctionVisitor,
PropertyCollector shaderProperties,
ShaderGraphRequirements requirements,
GenerationMode mode,
bool isMasterNode,
string functionName = "PopulateSurfaceData",
string surfaceDescriptionName = "SurfaceDescription")
{
var graph = node.owner as AbstractMaterialGraph;
if (graph == null)
return;
surfaceDescriptionFunction.AddShaderChunk(string.Format("{0} {1}(SurfaceInputs IN) {{", surfaceDescriptionName, functionName), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.Position)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.Position)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.Position)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Position)), false);
if (requirements.requiresScreenPosition)
surfaceDescriptionFunction.AddShaderChunk(string.Format("float4 {0} = IN.{0};", ShaderGeneratorNames.ScreenPosition), false);

foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceDescriptionFunction.AddShaderChunk(string.Format("half4 {0} = IN.{0};", channel.GetUVName()), false);
var shaderProperties = new PropertyCollector();
CollectShaderProperties(shaderProperties, mode);
graph.CollectShaderProperties(shaderProperties, mode);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
{
if (activeNode is IGeneratesFunction)

activeNode.CollectShaderProperties(shaderProperties, mode);
}
surfaceDescriptionFunction.AddShaderChunk("SurfaceDescription surface = (SurfaceDescription)0;", false);
if (node is IMasterNode)
surfaceDescriptionFunction.AddShaderChunk(string.Format("{0} surface = ({0})0;", surfaceDescriptionName), false);
if (isMasterNode)
var foundEdges = GetEdges(input.slotReference).ToArray();
var foundEdges = graph.GetEdges(input.slotReference).ToArray();
var fromNode = GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
var fromNode = graph.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", input.shaderOutputName, fromNode.GetVariableNameForSlot(outputRef.slotId)), true);
}
else

surfaceDescriptionFunction.Deindent();
surfaceDescriptionFunction.AddShaderChunk("}", false);
ListPool<INode>.Release(activeNodeList);
}
public string GetShader(AbstractMaterialNode node, GenerationMode mode, string name, out List<PropertyCollector.TextureInfo> configuredTextures, out PreviewMode previewMode)
{
if (node == null)
throw new ArgumentNullException("node");
var vertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var shaderFunctionVisitor = new ShaderGenerator();
var surfaceInputs = new ShaderGenerator();
var graphVertexInput = @"
struct GraphVertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord0 : TEXCOORD0;
float4 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};";
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var requirements = GetRequierments(node);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
previewMode = PreviewMode.Preview2D;
foreach (var pNode in activeNodeList.OfType<AbstractMaterialNode>())
{
if (pNode.previewMode == PreviewMode.Preview3D)
{
previewMode = PreviewMode.Preview3D;
break;
}
}
ListPool<INode>.Release(activeNodeList);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
vertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
vertexShader.Indent();
vertexShader.AddShaderChunk("return v;", false);
vertexShader.Deindent();
vertexShader.AddShaderChunk("}", false);
GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, node, node is IMasterNode);
var shaderProperties = new PropertyCollector();
GenerateSurfaceDescription(
node,
surfaceDescriptionFunction,
shaderFunctionVisitor,
shaderProperties,
requirements,
mode,
node is IMasterNode);
var finalShader = new ShaderGenerator();
finalShader.AddShaderChunk(string.Format(@"Shader ""{0}""", name), false);

34
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractShaderProperty.cs


namespace UnityEngine.MaterialGraph
{
[Serializable]
public abstract class AbstractShaderProperty<T> : ISerializationCallbackReceiver, IShaderProperty
public abstract class AbstractShaderProperty<T> : IShaderProperty
[SerializeField]
private string m_Description;
[NonSerialized]
private Guid m_Guid;
private string m_GuidSerialized;
private bool m_GeneratePropertyBlock = true;
private bool m_GeneratePropertyBlock = true;
protected AbstractShaderProperty()
{
m_Guid = Guid.NewGuid();
}
private SerializableGuid m_Guid = new SerializableGuid();
public T value
{

get
{
if (string.IsNullOrEmpty(m_Name))
return m_Guid.ToString();
return guid.ToString();
return m_Name;
}
set { m_Name = value; }

public Guid guid
{
get { return m_Guid; }
get { return m_Guid.guid; }
}
public bool generatePropertyBlock

}
public abstract PreviewProperty GetPreviewMaterialProperty();
public virtual void OnBeforeSerialize()
{
m_GuidSerialized = m_Guid.ToString();
}
public virtual void OnAfterDeserialize()
{
if (!string.IsNullOrEmpty(m_GuidSerialized))
m_Guid = new Guid(m_GuidSerialized);
else
m_Guid = Guid.NewGuid();
}
}
}

8
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialGraph.cs


namespace UnityEngine.MaterialGraph
{
[Serializable]
public class MaterialGraph : AbstractMaterialGraph
public class MaterialGraph : AbstractMaterialGraph, IShaderGraph
{
public IMasterNode masterNode
{

PreviewMode pmode;
return GetShader(masterNode as AbstractMaterialNode, mode, name, out configuredTextures, out pmode);
}
public override void OnAfterDeserialize()
{
base.OnAfterDeserialize();
}
}
}

665
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialSlot.cs


namespace UnityEngine.MaterialGraph
{
public interface IMaterialSlotHasVaule<T>
{
T defaultValue { get; }
T value { get; }
}
public class MaterialSlot : SerializableSlot
public class Vector1MaterialSlot : MaterialSlot, IMaterialSlotHasVaule<float>
SlotValueType m_ValueType;
private float m_Value;
Vector4 m_DefaultValue;
private float m_DefaultValue;
public Vector1MaterialSlot()
{
}
public Vector1MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
float value,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
m_DefaultValue = value;
m_Value = value;
}
public float defaultValue { get { return m_DefaultValue; } }
public float value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return value.ToString();
}
public override SlotValueType valueType { get { return SlotValueType.Vector1; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector1; } }
public override PreviewProperty GetPreviewProperty(string name)
{
var pp = new PreviewProperty
{
m_Name = name,
m_PropType = ConvertConcreteSlotValueTypeToPropertyType(concreteValueType),
m_Vector4 = new Vector4(value, value, value, value),
m_Float = value,
m_Color = new Vector4(value, value, value, value),
};
return pp;
}
}
[Serializable]
public class Vector2MaterialSlot : MaterialSlot, IMaterialSlotHasVaule<Vector2>
{
[SerializeField]
private Vector2 m_Value;
[SerializeField]
private Vector2 m_DefaultValue;
public Vector2MaterialSlot()
{
}
public Vector2MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector2 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
m_Value = value;
}
public Vector2 defaultValue { get { return m_DefaultValue; } }
public Vector2 value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "2 (" + value.x + "," + value.y + ")";
}
public override PreviewProperty GetPreviewProperty(string name)
{
var pp = new PreviewProperty
{
m_Name = name,
m_PropType = ConvertConcreteSlotValueTypeToPropertyType(concreteValueType),
m_Vector4 = new Vector4(value.x, value.y, 0, 0),
m_Float = value.x,
m_Color = new Vector4(value.x, value.x, 0, 0),
};
return pp;
}
public override SlotValueType valueType { get { return SlotValueType.Vector2; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector2; } }
}
[Serializable]
public class Vector3MaterialSlot : MaterialSlot, IMaterialSlotHasVaule<Vector3>
{
Vector4 m_CurrentValue;
private Vector3 m_Value;
ConcreteSlotValueType m_ConcreteValueType;
private Vector3 m_DefaultValue;
public Vector3MaterialSlot()
{
}
public Vector3MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector3 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
m_Value = value;
}
public Vector3 defaultValue { get { return m_DefaultValue; } }
public Vector3 value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "3 (" + value.x + "," + value.y + "," + value.z + ")";
}
public override PreviewProperty GetPreviewProperty(string name)
{
var pp = new PreviewProperty
{
m_Name = name,
m_PropType = ConvertConcreteSlotValueTypeToPropertyType(concreteValueType),
m_Vector4 = new Vector4(value.x, value.y, value.z, 0),
m_Float = value.x,
m_Color = new Vector4(value.x, value.x, value.z, 0),
};
return pp;
}
public override SlotValueType valueType { get { return SlotValueType.Vector3; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector3; } }
}
[Serializable]
public class Vector4MaterialSlot : MaterialSlot, IMaterialSlotHasVaule<Vector4>
{
string m_ShaderOutputName;
private Vector4 m_Value;
ShaderStage m_ShaderStage;
private Vector4 m_DefaultValue;
public Vector4MaterialSlot()
{
}
public Vector4MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
m_Value = value;
}
public Vector4 defaultValue { get { return m_DefaultValue; } }
public Vector4 value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "4 (" + value.x + "," + value.y + "," + value.z + "," + value.w + ")";
}
public override PreviewProperty GetPreviewProperty(string name)
{
var pp = new PreviewProperty
{
m_Name = name,
m_PropType = ConvertConcreteSlotValueTypeToPropertyType(concreteValueType),
m_Vector4 = new Vector4(value.x, value.y, value.z, value.w),
m_Float = value.x,
m_Color = new Vector4(value.x, value.x, value.z, value.w),
};
return pp;
}
public override SlotValueType valueType { get { return SlotValueType.Vector4; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector4; } }
}
[Serializable]
public class Matrix2MaterialSlot : MaterialSlot
{
public Matrix2MaterialSlot()
{
}
public Matrix2MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "2x2 (1,0,0,1)";
}
public override SlotValueType valueType { get { return SlotValueType.Matrix2; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Matrix2; } }
}
[Serializable]
public class Matrix3MaterialSlot : MaterialSlot
{
public Matrix3MaterialSlot()
{
}
public Matrix3MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "3x3 (1,0,0,0,1,0,0,0,1)";
}
public override SlotValueType valueType { get { return SlotValueType.Matrix3; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Matrix3; } }
}
[Serializable]
public class Matrix4MaterialSlot : MaterialSlot
{
public Matrix4MaterialSlot()
{
}
public Matrix4MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "4x4 (1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)";
}
public override SlotValueType valueType { get { return SlotValueType.Matrix4; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Matrix4; } }
}
[Serializable]
public class Texture2DMaterialSlot : MaterialSlot
{
public Texture2DMaterialSlot()
{
}
public Texture2DMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
}
public MaterialSlot() { }
public override SlotValueType valueType { get { return SlotValueType.Texture2D; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Texture2D; } }
}
[Serializable]
public class SamplerStateMaterialSlot : MaterialSlot
{
public SamplerStateMaterialSlot()
{
}
public SamplerStateMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
}
public override SlotValueType valueType { get { return SlotValueType.SamplerState; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.SamplerState; } }
}
[Serializable]
public class DynamicVectorMaterialSlot : MaterialSlot, IMaterialSlotHasVaule<Vector4>
{
[SerializeField]
private Vector4 m_Value;
[SerializeField]
private Vector4 m_DefaultValue;
private ConcreteSlotValueType m_ConcreteValueType = ConcreteSlotValueType.Vector4;
public DynamicVectorMaterialSlot()
{
}
public DynamicVectorMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
:base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
m_Value = value;
}
public Vector4 defaultValue { get { return m_DefaultValue; } }
public Vector4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override SlotValueType valueType { get { return SlotValueType.Dynamic; } }
public MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, SlotValueType valueType, Vector4 defaultValue, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, slotType, hidden)
public override ConcreteSlotValueType concreteValueType
{
get { return m_ConcreteValueType; }
}
public void SetConcreteType(ConcreteSlotValueType valueType)
SharedInitialize(shaderOutputName, valueType, defaultValue, shaderStage);
m_ConcreteValueType = valueType;
void SharedInitialize(string inShaderOutputName, SlotValueType inValueType, Vector4 inDefaultValue, ShaderStage shaderStage)
public override PreviewProperty GetPreviewProperty(string name)
m_ShaderOutputName = inShaderOutputName;
valueType = inValueType;
m_DefaultValue = inDefaultValue;
m_CurrentValue = inDefaultValue;
var pp = new PreviewProperty
{
m_Name = name,
m_PropType = ConvertConcreteSlotValueTypeToPropertyType(concreteValueType),
m_Vector4 = new Vector4(value.x, value.y, value.z, value.w),
m_Float = value.x,
m_Color = new Vector4(value.x, value.x, value.z, value.w),
};
return pp;
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "4 (" + value.x + "," + value.y + "," + value.z + "," + value.w + ")";
}
}
[Serializable]
public abstract class MaterialSlot : SerializableSlot
{
[SerializeField]
string m_ShaderOutputName;
[SerializeField]
ShaderStage m_ShaderStage;
private bool m_HasError;
protected MaterialSlot() { }
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, slotType, hidden)
{
m_ShaderOutputName = shaderOutputName;
this.shaderStage = shaderStage;
}

set { base.displayName = value; }
}
public Vector4 defaultValue
public string RawDisplayName()
get { return m_DefaultValue; }
set { m_DefaultValue = value; }
return displayName;
public SlotValueType valueType
public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
get { return m_ValueType; }
set
switch (type)
switch (value)
{
case SlotValueType.Vector1:
concreteValueType = ConcreteSlotValueType.Vector1;
break;
case SlotValueType.Vector2:
concreteValueType = ConcreteSlotValueType.Vector2;
break;
case SlotValueType.Vector3:
concreteValueType = ConcreteSlotValueType.Vector3;
break;
case SlotValueType.Matrix2:
concreteValueType = ConcreteSlotValueType.Matrix2;
break;
case SlotValueType.Matrix3:
concreteValueType = ConcreteSlotValueType.Matrix3;
break;
case SlotValueType.Matrix4:
concreteValueType = ConcreteSlotValueType.Matrix4;
break;
case SlotValueType.Texture2D:
concreteValueType = ConcreteSlotValueType.Texture2D;
break;
case SlotValueType.SamplerState:
concreteValueType = ConcreteSlotValueType.SamplerState;
break;
default:
concreteValueType = ConcreteSlotValueType.Vector4;
break;
}
m_ValueType = value;
case SlotValueType.SamplerState:
return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Matrix4:
return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Matrix3:
return new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Matrix2:
return new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Texture2D:
return new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Dynamic:
return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
case SlotValueType.Vector4:
return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
case SlotValueType.Vector3:
return new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
case SlotValueType.Vector2:
return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
case SlotValueType.Vector1:
return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStage, hidden);
throw new ArgumentOutOfRangeException("type", type, null);
public Vector4 currentValue
{
get { return m_CurrentValue; }
set { m_CurrentValue = value; }
}
public abstract SlotValueType valueType { get; }
public ConcreteSlotValueType concreteValueType
{
get { return m_ConcreteValueType; }
set { m_ConcreteValueType = value; }
}
public abstract ConcreteSlotValueType concreteValueType { get; }
public string shaderOutputName
{

set { m_ShaderStage = value; }
}
public bool IsCompatibleWithInputSlotType(SlotValueType inputType)
public bool hasError
switch (valueType)
get { return m_HasError; }
set { m_HasError = value; }
}
public bool IsCompatibleWithInputSlotType(ConcreteSlotValueType inputType)
{
switch (concreteValueType)
case SlotValueType.SamplerState:
return inputType == SlotValueType.SamplerState;
case SlotValueType.Matrix4:
return inputType == SlotValueType.Matrix4
|| inputType == SlotValueType.Matrix3
|| inputType == SlotValueType.Matrix2;
case SlotValueType.Matrix3:
return inputType == SlotValueType.Matrix3
|| inputType == SlotValueType.Matrix2;
case SlotValueType.Matrix2:
return inputType == SlotValueType.Matrix2;
case SlotValueType.Texture2D:
return inputType == SlotValueType.Texture2D;
case SlotValueType.Vector4:
return inputType == SlotValueType.Vector4
|| inputType == SlotValueType.Vector3
|| inputType == SlotValueType.Vector2
|| inputType == SlotValueType.Vector1
|| inputType == SlotValueType.Dynamic;
case SlotValueType.Vector3:
return inputType == SlotValueType.Vector3
|| inputType == SlotValueType.Vector2
|| inputType == SlotValueType.Vector1
|| inputType == SlotValueType.Dynamic;
case SlotValueType.Vector2:
return inputType == SlotValueType.Vector2
|| inputType == SlotValueType.Vector1
|| inputType == SlotValueType.Dynamic;
case SlotValueType.Dynamic:
case SlotValueType.Vector1:
return inputType == SlotValueType.Vector4
|| inputType == SlotValueType.Vector3
|| inputType == SlotValueType.Vector2
|| inputType == SlotValueType.Vector1
|| inputType == SlotValueType.Dynamic;
case ConcreteSlotValueType.SamplerState:
return inputType == ConcreteSlotValueType.SamplerState;
case ConcreteSlotValueType.Matrix4:
return inputType == ConcreteSlotValueType.Matrix4
|| inputType == ConcreteSlotValueType.Matrix3
|| inputType == ConcreteSlotValueType.Matrix2;
case ConcreteSlotValueType.Matrix3:
return inputType == ConcreteSlotValueType.Matrix3
|| inputType == ConcreteSlotValueType.Matrix2;
case ConcreteSlotValueType.Matrix2:
return inputType == ConcreteSlotValueType.Matrix2;
case ConcreteSlotValueType.Texture2D:
return inputType == ConcreteSlotValueType.Texture2D;
case ConcreteSlotValueType.Vector4:
return inputType == ConcreteSlotValueType.Vector4
|| inputType == ConcreteSlotValueType.Vector3
|| inputType == ConcreteSlotValueType.Vector2
|| inputType == ConcreteSlotValueType.Vector1;
case ConcreteSlotValueType.Vector3:
return inputType == ConcreteSlotValueType.Vector3
|| inputType == ConcreteSlotValueType.Vector2
|| inputType == ConcreteSlotValueType.Vector1;
case ConcreteSlotValueType.Vector2:
return inputType == ConcreteSlotValueType.Vector2
|| inputType == ConcreteSlotValueType.Vector1;
case ConcreteSlotValueType.Vector1:
return inputType == ConcreteSlotValueType.Vector4
|| inputType == ConcreteSlotValueType.Vector3
|| inputType == ConcreteSlotValueType.Vector2
|| inputType == ConcreteSlotValueType.Vector1;
public string GetDefaultValue(GenerationMode generationMode)
public bool IsCompatibleWith(MaterialSlot otherSlot)
{
return otherSlot != null
&& otherSlot.owner != owner
&& otherSlot.isInputSlot != isInputSlot
&& (isInputSlot
? otherSlot.IsCompatibleWithInputSlotType(concreteValueType)
: IsCompatibleWithInputSlotType(otherSlot.concreteValueType));
}
public virtual string GetDefaultValue(GenerationMode generationMode)
{
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)

return DefaultTextureName;
return Texture2DMaterialSlot.DefaultTextureName;
switch (concreteValueType)
{
case ConcreteSlotValueType.Vector1:
return m_CurrentValue.x.ToString();
case ConcreteSlotValueType.Vector2:
return matOwner.precision + "2 (" + m_CurrentValue.x + "," + m_CurrentValue.y + ")";
case ConcreteSlotValueType.Vector3:
return matOwner.precision + "3 (" + m_CurrentValue.x + "," + m_CurrentValue.y + "," + m_CurrentValue.z + ")";
case ConcreteSlotValueType.Vector4:
return matOwner.precision + "4 (" + m_CurrentValue.x + "," + m_CurrentValue.y + "," + m_CurrentValue.z + "," + m_CurrentValue.w + ")";
case ConcreteSlotValueType.Matrix2:
return matOwner.precision + "2x2 (" + m_CurrentValue.x + ", " + m_CurrentValue.x + ", " + m_CurrentValue.y + ", " + m_CurrentValue.y + ")";
case ConcreteSlotValueType.Matrix3:
return matOwner.precision + "3x3 (" + m_CurrentValue.x + ", " + m_CurrentValue.x + ", " + m_CurrentValue.x + ", " + m_CurrentValue.y + ", " + m_CurrentValue.y + ", " + m_CurrentValue.y + ", " + m_CurrentValue.z + ", " + m_CurrentValue.z + ", " + m_CurrentValue.z + ")";
case ConcreteSlotValueType.Matrix4:
return matOwner.precision + "4x4 (" + m_CurrentValue.x + ", " + m_CurrentValue.x + ", " + m_CurrentValue.x + ", " + m_CurrentValue.x + ", " + m_CurrentValue.y + ", " + m_CurrentValue.y + ", " + m_CurrentValue.y + ", " + m_CurrentValue.y + ", " + m_CurrentValue.z + ", " + m_CurrentValue.z + ", " + m_CurrentValue.z + ", " + m_CurrentValue.z + ", " + m_CurrentValue.w + ", " + m_CurrentValue.w + ", " + m_CurrentValue.w + ", " + m_CurrentValue.w + ")";
default:
return "error";
}
return ConcreteSlotValueAsVariable(matOwner.precision);
}
protected virtual string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return "error";
}
public void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)

{
var prop = new TextureShaderProperty();
prop.overrideReferenceName = DefaultTextureName;
prop.overrideReferenceName = Texture2DMaterialSlot.DefaultTextureName;
prop.modifiable = false;
prop.generatePropertyBlock = true;
properties.AddShaderProperty(prop);

property.generatePropertyBlock = false;
properties.AddShaderProperty(property);
}
protected static PropertyType ConvertConcreteSlotValueTypeToPropertyType(ConcreteSlotValueType slotValue)
{
switch (slotValue)
{
case ConcreteSlotValueType.Texture2D:
return PropertyType.Texture;
case ConcreteSlotValueType.Vector1:
return PropertyType.Float;
case ConcreteSlotValueType.Vector2:
return PropertyType.Vector2;
case ConcreteSlotValueType.Vector3:
return PropertyType.Vector3;
case ConcreteSlotValueType.Vector4:
return PropertyType.Vector4;
case ConcreteSlotValueType.Matrix2:
return PropertyType.Matrix2;
case ConcreteSlotValueType.Matrix3:
return PropertyType.Matrix3;
case ConcreteSlotValueType.Matrix4:
return PropertyType.Matrix4;
case ConcreteSlotValueType.SamplerState:
return PropertyType.SamplerState;
default:
return PropertyType.Vector4;
}
}
public virtual PreviewProperty GetPreviewProperty(string name)
{
return null;
}
}
}

20
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Interfaces/MaterialGraphChange.cs


public Guid guid { get; private set; }
}
public class LayerAdded : GraphChange
{
public LayerAdded(LayeredShaderGraph.Layer layer)
{
this.layer = layer;
}
public LayeredShaderGraph.Layer layer { get; private set; }
}
public class LayerRemoved : GraphChange
{
public LayerRemoved(Guid id)
{
this.id = id;
}
public Guid id { get; private set; }
}
}

50
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Interfaces/NeededCoordinateSpace.cs


public enum NeededCoordinateSpace
{
None = 0,
Object = 1<<0,
View = 1<<1,
World = 1<<2,
Tangent = 1<<3
Object = 1 << 0,
View = 1 << 1,
World = 1 << 2,
Tangent = 1 << 3
}
public enum CoordinateSpace : int
{
Object,
View,
World,
Tangent
}
public enum InterpolatorType
{
Normal,
BiTangent,
Tangent,
ViewDirection,
Position
}
public static class CoordinateSpaceNameExtensions
{
public static string ToVariableName(this CoordinateSpace space, InterpolatorType type)
{
return string.Format("{0}Space{1}", space, type);
}
public static NeededCoordinateSpace ToNeededCoordinateSpace(this CoordinateSpace space)
{
switch (space)
{
case CoordinateSpace.Object:
return NeededCoordinateSpace.Object;
case CoordinateSpace.View:
return NeededCoordinateSpace.View;
case CoordinateSpace.World:
return NeededCoordinateSpace.World;
case CoordinateSpace.Tangent:
return NeededCoordinateSpace.Tangent;
default:
throw new ArgumentOutOfRangeException("space", space, null);
}
}
}
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/AbstractLightweightMasterNode.cs


{
public abstract class AbstractLightweightMasterNode : MasterNode
{
private const int kMaxInterpolators = 8;
protected abstract IEnumerable<int> masterSurfaceInputs { get; }
protected abstract IEnumerable<int> masterVertexInputs { get; }
protected abstract string GetTemplateName();

ShaderGenerator.GenerateStandardTransforms(
GetInterpolatorStartIndex(),
10,
GetNodeSpecificRequirements());
GetNodeSpecificRequirements(),
CoordinateSpace.World);
ShaderGenerator defines = new ShaderGenerator();
ShaderGenerator surfaceOutputRemap = new ShaderGenerator();

14
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightMetallicMasterNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, SlotValueType.Vector3, new Vector4(0.5f, 0.5f, 0.5f), ShaderStage.Fragment));
AddSlot(new MaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, SlotType.Input, SlotValueType.Vector3, new Vector4(0,0,1), ShaderStage.Fragment));
AddSlot(new MaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(MetallicSlotId, MetallicSlotName, MetallicSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.one, ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, new Vector4(0.5f, 0.5f, 0.5f), ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, SlotType.Input, new Vector3(0,0,1), ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, Vector3.zero, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(MetallicSlotId, MetallicSlotName, MetallicSlotName, SlotType.Input,0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0.5f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, 1f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 0, ShaderStage.Fragment));
// clear out slot names that do not match the slots
// we support

14
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightSpecularMasterNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, SlotValueType.Vector3, new Vector4(0.5f, 0.5f, 0.5f, 0.5f), ShaderStage.Fragment));
AddSlot(new MaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, SlotType.Input, SlotValueType.Vector3, new Vector4(0,0,1), ShaderStage.Fragment));
AddSlot(new MaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(SpecularSlotId, SpecularSlotName, SpecularSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.one, ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, new Vector3(0.5f, 0.5f, 0.5f), ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, SlotType.Input, new Vector3(0,0,1), ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, Vector3.zero, ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(SpecularSlotId, SpecularSlotName, SpecularSlotName, SlotType.Input, Vector3.zero, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input,0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1, ShaderStage.Fragment));
// clear out slot names that do not match the slots
// we support

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightUnlitMasterNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(ColorSlotId, ColorSlotName, ColorSlotName, SlotType.Input, SlotValueType.Vector3, Vector4.zero, ShaderStage.Fragment));
AddSlot(new MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero, ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(ColorSlotId, ColorSlotName, ColorSlotName, SlotType.Input, Vector3.zero, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 0, ShaderStage.Fragment));
// clear out slot names that do not match the slots
// we support

172
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/AbstractMaterialNode.cs


get { return true; }
}
public virtual bool allowedInMainGraph
{
get { return true; }
}
public virtual bool allowedInLayerGraph
{
get { return true; }
}
public override bool hasError
{
get { return m_HasError; }

return inputSlot.GetDefaultValue(generationMode);
}
private ConcreteSlotValueType FindCommonChannelType(ConcreteSlotValueType from, ConcreteSlotValueType to)
{
if (ImplicitConversionExists(from, to))
return to;
return ConcreteSlotValueType.Error;
}
private static ConcreteSlotValueType ToConcreteType(SlotValueType svt)
{
switch (svt)
{
case SlotValueType.Vector1:
return ConcreteSlotValueType.Vector1;
case SlotValueType.Vector2:
return ConcreteSlotValueType.Vector2;
case SlotValueType.Vector3:
return ConcreteSlotValueType.Vector3;
case SlotValueType.Vector4:
return ConcreteSlotValueType.Vector4;
case SlotValueType.Texture2D:
return ConcreteSlotValueType.Texture2D;
case SlotValueType.Matrix2:
return ConcreteSlotValueType.Matrix2;
case SlotValueType.Matrix3:
return ConcreteSlotValueType.Matrix3;
case SlotValueType.Matrix4:
return ConcreteSlotValueType.Matrix4;
case SlotValueType.SamplerState:
return ConcreteSlotValueType.SamplerState;
}
return ConcreteSlotValueType.Error;
}
private static bool ImplicitConversionExists(ConcreteSlotValueType from, ConcreteSlotValueType to)
{
if (from == to)

private ConcreteSlotValueType ConvertDynamicInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
{
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList();
if (concreteSlotValueTypes.Any(x => x == ConcreteSlotValueType.Error))
return ConcreteSlotValueType.Error;
var inputTypesDistinct = concreteSlotValueTypes.Distinct().ToList();
switch (inputTypesDistinct.Count)
{

return ordered.FirstOrDefault();
break;
}
return ConcreteSlotValueType.Error;
return ConcreteSlotValueType.Vector1;
var isInError = false;
var isInError = false;
inputSlot.hasError = false;
foreach (var edge in edges)
foreach (var edge in edges)
{
var fromSocketRef = edge.outputSlot;
var outputNode = owner.GetNodeFromGuid(fromSocketRef.nodeGuid);

}
}
var dynamicInputSlotsToCompare = DictionaryPool<MaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicSlots = ListPool<MaterialSlot>.Get();
var dynamicInputSlotsToCompare = DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicSlots = ListPool<DynamicVectorMaterialSlot>.Get();
var inputType = inputSlot.valueType;
if (inputType != SlotValueType.Dynamic)
inputSlot.concreteValueType = ToConcreteType(inputType);
else
skippedDynamicSlots.Add(inputSlot);
if (inputSlot is DynamicVectorMaterialSlot)
skippedDynamicSlots.Add(inputSlot as DynamicVectorMaterialSlot);
continue;
}

if (outputSlot == null)
continue;
var outputConcreteType = outputSlot.concreteValueType;
// if we have a standard connection... just check the types work!
if (inputType != SlotValueType.Dynamic)
if (outputSlot.hasError)
var inputConcreteType = ToConcreteType(inputType);
inputSlot.concreteValueType = FindCommonChannelType(outputConcreteType, inputConcreteType);
inputSlot.hasError = true;
var outputConcreteType = outputSlot.concreteValueType;
dynamicInputSlotsToCompare.Add(inputSlot, outputConcreteType);
if (inputSlot is DynamicVectorMaterialSlot)
{
dynamicInputSlotsToCompare.Add((DynamicVectorMaterialSlot) inputSlot, outputConcreteType);
continue;
}
// if we have a standard connection... just check the types work!
if (!ImplicitConversionExists(outputConcreteType, inputSlot.concreteValueType))
inputSlot.hasError = true;
}
// we can now figure out the dynamic slotType

dynamicKvP.Key.concreteValueType = dynamicType;
dynamicKvP.Key.SetConcreteType(dynamicType);
skippedSlot.concreteValueType = dynamicType;
skippedSlot.SetConcreteType(dynamicType);
var inputError = GetInputSlots<MaterialSlot>().Any(x => x.concreteValueType == ConcreteSlotValueType.Error);
var inputError = GetInputSlots<MaterialSlot>().Any(x => x.hasError);
// configure the output slots now
// their slotType will either be the default output slotType

{
outputSlot.hasError = false;
outputSlot.concreteValueType = ConcreteSlotValueType.Error;
outputSlot.hasError = true;
if (outputSlot.valueType == SlotValueType.Dynamic)
if (outputSlot is DynamicVectorMaterialSlot)
outputSlot.concreteValueType = dynamicType;
(outputSlot as DynamicVectorMaterialSlot).SetConcreteType(dynamicType);
outputSlot.concreteValueType = ToConcreteType(outputSlot.valueType);
isInError |= GetOutputSlots<MaterialSlot>().Any(x => x.concreteValueType == ConcreteSlotValueType.Error);
isInError |= GetOutputSlots<MaterialSlot>().Any(x => x.hasError);
isInError |= CalculateNodeHasError();
hasError = isInError;

}
ListPool<MaterialSlot>.Release(skippedDynamicSlots);
DictionaryPool<MaterialSlot, ConcreteSlotValueType>.Release(dynamicInputSlotsToCompare);
ListPool<DynamicVectorMaterialSlot>.Release(skippedDynamicSlots);
DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Release(dynamicInputSlotsToCompare);
}

{
return false;
}
[Obsolete("Call new override", false)]
public static string ConvertConcreteSlotValueTypeToString(ConcreteSlotValueType slotValue)
public static string GetSlotDimension(ConcreteSlotValueType slotValue)
{
switch (slotValue)
{

return "3";
case ConcreteSlotValueType.Vector4:
return "4";
case ConcreteSlotValueType.Texture2D:
return "Texture2D";
case ConcreteSlotValueType.Matrix2:
return "2x2";
case ConcreteSlotValueType.Matrix3:

case ConcreteSlotValueType.SamplerState:
return "SamplerState";
default:
return "Error";
}

}
}
public static PropertyType ConvertConcreteSlotValueTypeToPropertyType(ConcreteSlotValueType slotValue)
{
switch (slotValue)
{
case ConcreteSlotValueType.Texture2D:
return PropertyType.Texture;
case ConcreteSlotValueType.Vector1:
return PropertyType.Float;
case ConcreteSlotValueType.Vector2:
return PropertyType.Vector2;
case ConcreteSlotValueType.Vector3:
return PropertyType.Vector3;
case ConcreteSlotValueType.Vector4:
return PropertyType.Vector4;
case ConcreteSlotValueType.Matrix2:
return PropertyType.Matrix2;
case ConcreteSlotValueType.Matrix3:
return PropertyType.Matrix3;
case ConcreteSlotValueType.Matrix4:
return PropertyType.Matrix4;
case ConcreteSlotValueType.SamplerState:
return PropertyType.SamplerState;
default:
return PropertyType.Vector4;
}
}
public virtual void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
{
var validSlots = GetInputSlots<MaterialSlot>().ToArray();

if (edges.Any())
continue;
var pp = new PreviewProperty
{
m_Name = GetVariableNameForSlot(s.id),
m_PropType = ConvertConcreteSlotValueTypeToPropertyType(s.concreteValueType),
m_Vector4 = s.currentValue,
m_Float = s.currentValue.x,
m_Color = s.currentValue
};
properties.Add(pp);
var item = s.GetPreviewProperty(GetVariableNameForSlot(s.id));
if (item == null)
continue;
properties.Add(item);
}
}

if (foundSlot == null)
return;
// preserve the old current value.
addingSlot.currentValue = foundSlot.currentValue;
// now copy over values :)
if (addingSlot is DynamicVectorMaterialSlot && foundSlot is DynamicVectorMaterialSlot)
(addingSlot as DynamicVectorMaterialSlot).value = (foundSlot as DynamicVectorMaterialSlot).value;
if (addingSlot is Vector1MaterialSlot && foundSlot is Vector1MaterialSlot)
(addingSlot as Vector1MaterialSlot).value = (foundSlot as Vector1MaterialSlot).value;
if (addingSlot is Vector2MaterialSlot && foundSlot is Vector2MaterialSlot)
(addingSlot as Vector2MaterialSlot).value = (foundSlot as Vector2MaterialSlot).value;
if (addingSlot is Vector3MaterialSlot && foundSlot is Vector3MaterialSlot)
(addingSlot as Vector3MaterialSlot).value = (foundSlot as Vector3MaterialSlot).value;
if (addingSlot is Vector4MaterialSlot && foundSlot is Vector4MaterialSlot)
(addingSlot as Vector4MaterialSlot).value = (foundSlot as Vector4MaterialSlot).value;
}
}
}

11
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Art/Adjustments/LevelsNode.cs


[Title("Art/Adjustments/Levels")]
public class LevelsNode : CodeFunctionNode
{
[SerializeField]
private float m_InputMin = 0.0f;
[SerializeField]
private float m_InputMax = 1.0f;
[SerializeField]
private float m_InputGamma = 1.0f;
[SerializeField]
private float m_OutputMin = 0.0f;
[SerializeField]
private float m_OutputMax = 1.0f;
public LevelsNode()
{
name = "Levels";

10
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Channel/SplitNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector4.zero));
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0));
RemoveSlotsNameNotMatching(s_ValidSlots);
}

47
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/HLSLNode.cs


case Binding.None:
return "ERROR!";
case Binding.ObjectSpaceNormal:
return ShaderGeneratorNames.ObjectSpaceNormal;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.ObjectSpaceTangent;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.ObjectSpaceBiTangent;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.ObjectSpacePosition;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.Position);
return ShaderGeneratorNames.ViewSpaceNormal;
return CoordinateSpace.View.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.ViewSpaceTangent;
return CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.ViewSpaceBiTangent;
return CoordinateSpace.View.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.ViewSpacePosition;
return CoordinateSpace.View.ToVariableName(InterpolatorType.Position);
return ShaderGeneratorNames.WorldSpaceNormal;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.WorldSpaceTangent;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.WorldSpaceBiTangent;
return CoordinateSpace.World.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.WorldSpacePosition;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Position);
return ShaderGeneratorNames.TangentSpaceNormal;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.TangentSpaceTangent;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.TangentSpaceBiTangent;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.TangentSpacePosition;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Position);
case Binding.MeshUV0:
return UVChannel.uv0.GetUVName();
case Binding.MeshUV1:

case Binding.ScreenPosition:
return ShaderGeneratorNames.ScreenPosition;
case Binding.ObjectSpaceViewDirection:
return ShaderGeneratorNames.ObjectSpaceViewDirection;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.ViewDirection);
return ShaderGeneratorNames.ViewSpaceViewDirection;
return CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection);
return ShaderGeneratorNames.WorldSpaceViewDirection;
return CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection);
return ShaderGeneratorNames.TangentSpaceViewDirection;
return CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection);
case Binding.VertexColor:
return ShaderGeneratorNames.VertexColor;
default:

{
var attribute = GetSlotAttribute(par);
slots.Add(new MaterialSlot(attribute.slotId, par.Name, par.Name, par.IsOut ? SlotType.Output : SlotType.Input,
ConvertTypeToSlotValueType(par), attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden));
slots.Add(MaterialSlot.CreateMaterialSlot(ConvertTypeToSlotValueType(par), attribute.slotId, par.Name, par.Name, par.IsOut ? SlotType.Output : SlotType.Input,
attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden));
m_Slots.Add(attribute);
}

foreach (var slot in GetSlots<MaterialSlot>())
{
var toReplace = string.Format("{{slot{0}dimension}}", slot.id);
var replacement = ConvertConcreteSlotValueTypeToString(slot.concreteValueType);
var replacement = GetSlotDimension(slot.concreteValueType);
result = result.Replace(toReplace, replacement);
}
return result;

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/ColorNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new Vector4MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

8
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix2Node.cs


}
void SetRow(ref Vector2 row, Vector2 value)
{
{
return;
return;
if (onModified != null)
if (onModified != null)
onModified(this, ModificationScope.Graph);
}

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Matrix2, Vector2.zero));
AddSlot(new Matrix2MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix3Node.cs


[MultiFloatControl("", " ", " ", " ", " ")]
public Vector3 row1
{
{
get { return m_Row1; }
set { SetRow(ref m_Row1, value); }
}

if (value == row)
return;
row = value;
if (onModified != null)
if (onModified != null)
onModified(this, ModificationScope.Graph);
}

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Matrix3, Vector3.zero));
AddSlot(new Matrix3MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix4Node.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Matrix4, Vector4.zero));
AddSlot(new Matrix4MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/MatrixCommonNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Matrix4, Vector4.zero));
AddSlot(new Matrix4MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/SceneData/CameraDirNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new Vector4MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/SceneData/CameraPosNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new Vector4MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/SceneData/ScreenPosNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlot1Id, kOutputSlot1Name, kOutputSlot1Name, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(kOutputSlot2Id, kOutputSlot2Name, kOutputSlot2Name, SlotType.Output, SlotValueType.Vector3, Vector3.zero));
AddSlot(new Vector4MaterialSlot(kOutputSlot1Id, kOutputSlot1Name, kOutputSlot1Name, SlotType.Output, Vector4.zero));
AddSlot(new Vector3MaterialSlot(kOutputSlot2Id, kOutputSlot2Name, kOutputSlot2Name, SlotType.Output, Vector3.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlot1Id, kOutputSlot2Id });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Time/SinTimeNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.one));
AddSlot(new Vector4MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.one));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

10
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Time/TimeNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdX, kOutputSlotNameX, kOutputSlotNameX, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdY, kOutputSlotNameY, kOutputSlotNameY, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdZ, kOutputSlotNameZ, kOutputSlotNameZ, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotIdW, kOutputSlotNameW, kOutputSlotNameW, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
AddSlot(new Vector1MaterialSlot(OutputSlotIdX, kOutputSlotNameX, kOutputSlotNameX, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotIdY, kOutputSlotNameY, kOutputSlotNameY, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotIdZ, kOutputSlotNameZ, kOutputSlotNameZ, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotIdW, kOutputSlotNameW, kOutputSlotNameW, SlotType.Output, 0));
RemoveSlotsNameNotMatching(validSlots);
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector1Node.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new Vector1MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output,0));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector2Node.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector2, Vector4.zero));
AddSlot(new Vector2MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector3Node.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector3, Vector4.zero));
AddSlot(new Vector3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Vector/Vector4Node.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
}

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

正在加载...
取消
保存