From d50995731b308ef419cb52dd1d190d6d2f042338 Mon Sep 17 00:00:00 2001 From: Elizabeth LeGros Date: Fri, 16 Oct 2020 14:57:53 -0500 Subject: [PATCH 1/4] Deprecate view direction and add function call with conditional normalization to new version --- .../Nodes/Input/Geometry/ViewDirectionNode.cs | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs index d859a3d4779..4e23cb4e6ce 100644 --- a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs +++ b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs @@ -6,10 +6,11 @@ namespace UnityEditor.ShaderGraph { [FormerName("UnityEngine.MaterialGraph.ViewDirectionNode")] [Title("Input", "Geometry", "View Direction")] - class ViewDirectionNode : GeometryNode, IMayRequireViewDirection + class ViewDirectionNode : GeometryNode, IMayRequireViewDirection, IGeneratesFunction { private const int kOutputSlotId = 0; public const string kOutputSlotName = "Out"; + public override int latestVersion => 1; public ViewDirectionNode() { @@ -31,12 +32,46 @@ public sealed override void UpdateNodeAfterDeserialization() public override string GetVariableNameForSlot(int slotId) { - return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection)); + switch(m_SGVersion) + { + case 0: + return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection)); + case 1: + return string.Format("{0}(IN.{1})",functionName, space.ToVariableName(InterpolatorType.ViewDirection)); + default: + return null; + } } public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability) { return space.ToNeededCoordinateSpace(); } + + private readonly string functionName = "NormalizeIfURP"; + + public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode) + { + switch (sgVersion) + { + case 0: + break; + case 1: + default: + registry.ProvideFunction(functionName, s => + { + s.AppendLine("$precision3 {0} ($precision3 In)", functionName); + using (s.BlockScope()) + { + s.AppendLine("#ifdef UNIVERSAL_PIPELINE_CORE_INCLUDED"); + s.AppendLine("\treturn normalize(In);"); + s.AppendLine("#else"); + s.AppendLine("\treturn In;"); + s.AppendLine("#endif"); + } + }); + break; + } + } } } From 64e0aa4a88812e15553768f04d1e4f057c68fe33 Mon Sep 17 00:00:00 2001 From: Elizabeth LeGros Date: Mon, 16 Nov 2020 12:28:09 -0600 Subject: [PATCH 2/4] created basic interface to allow declaration of variables in body code --- .../Data/Interfaces/IGeneratesVariables.cs | 7 +++ .../Interfaces/IGeneratesVariables.cs.meta | 11 ++++ .../Nodes/Input/Geometry/ViewDirectionNode.cs | 52 +++++++++++++++- .../Editor/Data/Util/VariableRegistry.cs | 60 +++++++++++++++++++ .../Editor/Data/Util/VariableRegistry.cs.meta | 11 ++++ .../Generation/Processors/GenerationUtils.cs | 27 ++++++++- .../Processors/ShaderStringBuilder.cs | 5 ++ 7 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs create mode 100644 com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs.meta create mode 100644 com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs create mode 100644 com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs.meta diff --git a/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs b/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs new file mode 100644 index 00000000000..d3d3562c88b --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs @@ -0,0 +1,7 @@ +namespace UnityEditor.ShaderGraph +{ + interface IGeneratesVariables + { + void GenerateNodeVariables(VariableRegistry registry, GenerationMode generationMode); + } +} diff --git a/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs.meta b/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs.meta new file mode 100644 index 00000000000..3a1d95fbf91 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Interfaces/IGeneratesVariables.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82a52d95058d6154ea95e33d47e84c97 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs index 4e23cb4e6ce..50c1508a82a 100644 --- a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs +++ b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs @@ -1,12 +1,13 @@ using UnityEngine; using UnityEditor.Graphing; using UnityEditor.ShaderGraph.Internal; +using System; namespace UnityEditor.ShaderGraph { [FormerName("UnityEngine.MaterialGraph.ViewDirectionNode")] [Title("Input", "Geometry", "View Direction")] - class ViewDirectionNode : GeometryNode, IMayRequireViewDirection, IGeneratesFunction + class ViewDirectionNode : GeometryNode, IMayRequireViewDirection, IGeneratesFunction, IGeneratesVariables { private const int kOutputSlotId = 0; public const string kOutputSlotName = "Out"; @@ -37,7 +38,7 @@ public override string GetVariableNameForSlot(int slotId) case 0: return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection)); case 1: - return string.Format("{0}(IN.{1})",functionName, space.ToVariableName(InterpolatorType.ViewDirection)); + return GetVariableName(); default: return null; } @@ -55,6 +56,17 @@ public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode gener switch (sgVersion) { case 0: + if(generationMode == GenerationMode.Preview) + { + registry.ProvideFunction(functionName, s => + { + s.AppendLine("$precision3 {0} ($precision3 In)", functionName); + using (s.BlockScope()) + { + s.AppendLine("return normalize(In);"); + } + }); + } break; case 1: default: @@ -73,5 +85,41 @@ public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode gener break; } } + + public void GenerateNodeVariables(VariableRegistry registry, GenerationMode generationMode) + { + switch (sgVersion) + { + case 0: + if(generationMode == GenerationMode.Preview) + { + registry.ProvideVariable(GetVariableName(), s => + { + s.AppendLine("$precision3 {0} = {1}(IN.{2});", + GetVariableName(), + functionName, + space.ToVariableName(InterpolatorType.ViewDirection) + ); + }); + } + break; + case 1: + default: + registry.ProvideVariable(GetVariableName(), s => + { + s.AppendLine("$precision3 {0} = {1}(IN.{2});", + GetVariableName(), + functionName, + space.ToVariableName(InterpolatorType.ViewDirection) + ); + }); + break; + } + } + + private string GetVariableName() + { + return "normalizedViewDirection"; + } } } diff --git a/com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs b/com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs new file mode 100644 index 00000000000..a106d5e0e4c --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityEditor.ShaderGraph +{ + struct VariableSource + { + public string code; + public HashSet nodes; + } + + class VariableRegistry + { + Dictionary m_Sources = new Dictionary(); + bool m_Validate = false; + ShaderStringBuilder m_Builder; + + public VariableRegistry(ShaderStringBuilder builder, bool validate = false) + { + m_Builder = builder; + m_Validate = validate; + } + + internal ShaderStringBuilder builder => m_Builder; + + public Dictionary sources => m_Sources; + + public List names { get; } = new List(); + + public void ProvideVariable(string name, Action generator) + { + VariableSource existingSource; + if (m_Sources.TryGetValue(name, out existingSource)) + { + existingSource.nodes.Add(builder.currentNode); + if (m_Validate) + { + var startIndex = builder.length; + generator(builder); + var length = builder.length - startIndex; + var code = builder.ToString(startIndex, length); + builder.length -= length; + if (code != existingSource.code) + Debug.LogErrorFormat(@"Variable `{0}` has varying implementations:{1}{1}{2}{1}{1}{3}", name, Environment.NewLine, code, existingSource); + } + } + else + { + builder.AppendNewLine(); + var startIndex = builder.length; + generator(builder); + var length = builder.length - startIndex; + var code = m_Validate ? builder.ToString(startIndex, length) : string.Empty; + m_Sources.Add(name, new VariableSource { code = code, nodes = new HashSet {builder.currentNode} }); + names.Add(name); + } + } + } +} diff --git a/com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs.meta b/com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs.meta new file mode 100644 index 00000000000..48fef6922ba --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Util/VariableRegistry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d821e6a856fe09e4cab539f9cb97b869 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.shadergraph/Editor/Generation/Processors/GenerationUtils.cs b/com.unity.shadergraph/Editor/Generation/Processors/GenerationUtils.cs index 10e9e150006..c200b867894 100644 --- a/com.unity.shadergraph/Editor/Generation/Processors/GenerationUtils.cs +++ b/com.unity.shadergraph/Editor/Generation/Processors/GenerationUtils.cs @@ -796,15 +796,19 @@ internal static void GenerateSurfaceDescriptionFunction( using (surfaceDescriptionFunction.BlockScope()) { surfaceDescriptionFunction.AppendLine("{0} surface = ({0})0;", surfaceDescriptionName); + surfaceDescriptionFunction.AppendLine("$variables"); + VariableRegistry variableRegistry = new VariableRegistry(new ShaderStringBuilder(1)); for(int i = 0; i < nodes.Count; i++) { - GenerateDescriptionForNode(nodes[i], keywordPermutationsPerNode[i], functionRegistry, surfaceDescriptionFunction, + GenerateDescriptionForNode(nodes[i], keywordPermutationsPerNode[i], functionRegistry, variableRegistry, surfaceDescriptionFunction, shaderProperties, shaderKeywords, graph, mode); } + variableRegistry.builder.currentNode = null; functionRegistry.builder.currentNode = null; surfaceDescriptionFunction.currentNode = null; + surfaceDescriptionFunction.ReplaceEverywhere("$variables", variableRegistry.builder.ToString()); GenerateSurfaceDescriptionRemap(graph, rootNode, slots, surfaceDescriptionFunction, mode); @@ -826,12 +830,27 @@ static void GenerateDescriptionForNode( AbstractMaterialNode activeNode, List keywordPermutations, FunctionRegistry functionRegistry, + VariableRegistry variableRegistry, ShaderStringBuilder descriptionFunction, PropertyCollector shaderProperties, KeywordCollector shaderKeywords, GraphData graph, GenerationMode mode) { + + if(activeNode is IGeneratesVariables variablesNode) + { + if(keywordPermutations != null) + descriptionFunction.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(keywordPermutations)); + + variableRegistry.builder.currentNode = activeNode; + variablesNode.GenerateNodeVariables(variableRegistry, mode); + variableRegistry.builder.ReplaceInCurrentMapping(PrecisionUtil.Token, activeNode.concretePrecision.ToShaderString()); + + if(keywordPermutations != null) + descriptionFunction.AppendLine("#endif"); + } + if (activeNode is IGeneratesFunction functionNode) { functionRegistry.builder.currentNode = activeNode; @@ -963,15 +982,19 @@ internal static void GenerateVertexDescriptionFunction( using (builder.BlockScope()) { builder.AppendLine("{0} description = ({0})0;", graphOutputStructName); + builder.AppendLine("$variables"); + VariableRegistry variableRegistry = new VariableRegistry(new ShaderStringBuilder(1)); for(int i = 0; i < nodes.Count; i++) { - GenerateDescriptionForNode(nodes[i], keywordPermutationsPerNode[i], functionRegistry, builder, + GenerateDescriptionForNode(nodes[i], keywordPermutationsPerNode[i], functionRegistry, variableRegistry, builder, shaderProperties, shaderKeywords, graph, mode); } + variableRegistry.builder.currentNode = null; functionRegistry.builder.currentNode = null; builder.currentNode = null; + builder.ReplaceEverywhere("$variables", variableRegistry.builder.ToString()); if(slots.Count != 0) { diff --git a/com.unity.shadergraph/Editor/Generation/Processors/ShaderStringBuilder.cs b/com.unity.shadergraph/Editor/Generation/Processors/ShaderStringBuilder.cs index a1ff57e6d25..9618ff604b0 100644 --- a/com.unity.shadergraph/Editor/Generation/Processors/ShaderStringBuilder.cs +++ b/com.unity.shadergraph/Editor/Generation/Processors/ShaderStringBuilder.cs @@ -216,6 +216,11 @@ public void ReplaceInCurrentMapping(string oldValue, string newValue) m_StringBuilder.Replace(oldValue, newValue, start, end ); } + public void ReplaceEverywhere(string oldValue, string newValue) + { + m_StringBuilder.Replace(oldValue, newValue); + } + public string ToCodeBlock() { // Remove new line From eda88b49a663b34c29d92210cdac972246dfff63 Mon Sep 17 00:00:00 2001 From: Elizabeth LeGros Date: Mon, 16 Nov 2020 12:33:15 -0600 Subject: [PATCH 3/4] pushing some unsaved work --- .../Nodes/Input/Geometry/ViewDirectionNode.cs | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs index 50c1508a82a..87564848e97 100644 --- a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs +++ b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs @@ -56,17 +56,6 @@ public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode gener switch (sgVersion) { case 0: - if(generationMode == GenerationMode.Preview) - { - registry.ProvideFunction(functionName, s => - { - s.AppendLine("$precision3 {0} ($precision3 In)", functionName); - using (s.BlockScope()) - { - s.AppendLine("return normalize(In);"); - } - }); - } break; case 1: default: @@ -91,17 +80,6 @@ public void GenerateNodeVariables(VariableRegistry registry, GenerationMode gene switch (sgVersion) { case 0: - if(generationMode == GenerationMode.Preview) - { - registry.ProvideVariable(GetVariableName(), s => - { - s.AppendLine("$precision3 {0} = {1}(IN.{2});", - GetVariableName(), - functionName, - space.ToVariableName(InterpolatorType.ViewDirection) - ); - }); - } break; case 1: default: From 489bb72543fc6d490f6ca9ec7b4999f968227d8b Mon Sep 17 00:00:00 2001 From: Elizabeth LeGros Date: Wed, 18 Nov 2020 12:44:16 -0600 Subject: [PATCH 4/4] fixing preview --- .../Nodes/Input/Geometry/ViewDirectionNode.cs | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs index 87564848e97..1bb07b18f20 100644 --- a/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs +++ b/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs @@ -83,14 +83,21 @@ public void GenerateNodeVariables(VariableRegistry registry, GenerationMode gene break; case 1: default: - registry.ProvideVariable(GetVariableName(), s => + if (generationMode == GenerationMode.Preview) { - s.AppendLine("$precision3 {0} = {1}(IN.{2});", - GetVariableName(), - functionName, - space.ToVariableName(InterpolatorType.ViewDirection) - ); - }); + registry.ProvideVariable(GetVariableName(), s => s.AppendLine("$precision3 {0} = normalize(IN.{1});", GetVariableName(), space.ToVariableName(InterpolatorType.ViewDirection))); + } + else + { + registry.ProvideVariable(GetVariableName(), s => + { + s.AppendLine("$precision3 {0} = {1}(IN.{2});", + GetVariableName(), + functionName, + space.ToVariableName(InterpolatorType.ViewDirection) + ); + }); + } break; } }