浏览代码

First pass dynamic Multiply node

- Temp adding of test graph
/main
Matt Dean 7 年前
当前提交
41740d78
共有 12 个文件被更改,包括 799 次插入23 次删除
  1. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicVectorMaterialSlot.cs
  2. 27
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialSlot.cs
  3. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/PreviewProperty.cs
  4. 10
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/AbstractMaterialNode.cs
  5. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/CodeFunctionNode.cs
  6. 515
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Basic/MultiplyNode.cs
  7. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/SlotValue.cs
  8. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/GraphEditorView.cs
  9. 99
      MaterialGraphProject/Assets/New Shader Graph.ShaderGraph
  10. 7
      MaterialGraphProject/Assets/New Shader Graph.ShaderGraph.meta
  11. 139
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicValueMaterialSlot.cs
  12. 11
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicValueMaterialSlot.cs.meta

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicVectorMaterialSlot.cs


return new MultiFloatSlotControlView(owner, components, () => value, (newValue) => value = newValue);
}
public override SlotValueType valueType { get { return SlotValueType.Dynamic; } }
public override SlotValueType valueType { get { return SlotValueType.DynamicVector; } }
public override ConcreteSlotValueType concreteValueType
{

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


return slotType == SlotType.Input
? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Dynamic:
case SlotValueType.DynamicVector:
return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
case SlotValueType.Vector4:
return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);

return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
case SlotValueType.Vector1:
return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStage, hidden);
case SlotValueType.Dynamic:
return new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStage, hidden);
case SlotValueType.Boolean:
return new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStage, hidden);
}

return inputType == SlotValueType.Matrix4
|| inputType == SlotValueType.Matrix3
|| inputType == SlotValueType.Matrix2
|| inputType == SlotValueType.DynamicMatrix;
|| inputType == SlotValueType.DynamicMatrix
|| inputType == SlotValueType.Dynamic;
|| inputType == SlotValueType.DynamicMatrix;
|| inputType == SlotValueType.DynamicMatrix
|| inputType == SlotValueType.Dynamic;
|| inputType == SlotValueType.DynamicMatrix;
|| inputType == SlotValueType.DynamicMatrix
|| inputType == SlotValueType.Dynamic;
case SlotValueType.Dynamic:
case SlotValueType.DynamicVector:
case SlotValueType.Vector4:
case SlotValueType.Vector3:
case SlotValueType.Vector2:

|| inputType == SlotValueType.Vector2
|| inputType == SlotValueType.Vector1
|| inputType == SlotValueType.DynamicVector
|| inputType == SlotValueType.Dynamic;
case SlotValueType.Dynamic:
return inputType == SlotValueType.Matrix4
|| inputType == SlotValueType.Matrix3
|| inputType == SlotValueType.Matrix2
|| inputType == SlotValueType.DynamicMatrix
|| inputType == SlotValueType.Vector4
|| inputType == SlotValueType.Vector3
|| inputType == SlotValueType.Vector2
|| inputType == SlotValueType.Vector1
|| inputType == SlotValueType.DynamicVector
|| inputType == SlotValueType.Dynamic;
case SlotValueType.Boolean:
return inputType == SlotValueType.Boolean;

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/PreviewProperty.cs


}
set
{
if (propType != PropertyType.Vector2 && propType != PropertyType.Vector3 && propType != PropertyType.Vector4)
if (propType != PropertyType.Vector2 && propType != PropertyType.Vector3 && propType != PropertyType.Vector4
&& propType != PropertyType.Matrix2 && propType != PropertyType.Matrix3 && propType != PropertyType.Matrix4)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Vector4, propType));
m_Data.vector4Value = value;
}

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


foreach (var skippedSlot in skippedDynamicMatrixSlots)
skippedSlot.SetConcreteType(dynamicMatrixType);
// now override dynamic output type if one or more input is a matrix
if (dynamicMatrixType == ConcreteSlotValueType.Matrix2)
dynamicType = ConcreteSlotValueType.Vector2;
else if (dynamicMatrixType == ConcreteSlotValueType.Matrix3)
dynamicType = ConcreteSlotValueType.Vector3;
else if (dynamicMatrixType == ConcreteSlotValueType.Matrix4)
dynamicType = ConcreteSlotValueType.Vector4;
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);
var inputError = s_TempSlots.Any(x => x.hasError);

DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Release(dynamicMatrixInputSlotsToCompare);
}
public int version { get; private set; }
public int version { get; set; }
//True if error
protected virtual bool CalculateNodeHasError()

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/CodeFunctionNode.cs


}
if (t == typeof(DynamicDimensionVector))
{
return SlotValueType.Dynamic;
return SlotValueType.DynamicVector;
}
if (t == typeof(Matrix4x4))
{

515
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Basic/MultiplyNode.cs


using System.Reflection;
//using System.Reflection;
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
using System.Linq;
public class MultiplyNode : CodeFunctionNode
public class MultiplyNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
UpdateNodeAfterDeserialization();
}
const int Input1SlotId = 0;
const int Input2SlotId = 1;
const int OutputSlotId = 2;
const string kInput1SlotName = "A";
const string kInput2SlotName = "B";
const string kOutputSlotName = "Out";
public override bool hasPreview
{
get { return m_MultiplyType != MultiplyType.Matrix; }
//get { return false; }
}
string GetFunctionName()
{
return string.Format("Unity_Multiply_{0}_{1}",
FindInputSlot<MaterialSlot>(Input1SlotId).concreteValueType.ToString(precision),
FindInputSlot<MaterialSlot>(Input2SlotId).concreteValueType.ToString(precision));
}
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new DynamicValueMaterialSlot(Input1SlotId, kInput1SlotName, kInput1SlotName, SlotType.Input, Matrix4x4.zero));
AddSlot(new DynamicValueMaterialSlot(Input2SlotId, kInput2SlotName, kInput2SlotName, SlotType.Input, new Matrix4x4(new Vector4(2,2,2,2), Vector4.zero, Vector4.zero, Vector4.zero)));
AddSlot(new DynamicValueMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Matrix4x4.zero));
RemoveSlotsNameNotMatching(new[] { Input1SlotId, Input2SlotId, OutputSlotId });
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var sb = new ShaderStringBuilder();
var input1Value = GetSlotValue(Input1SlotId, generationMode);
var input2Value = GetSlotValue(Input2SlotId, generationMode);
var outputValue = GetSlotValue(OutputSlotId, generationMode);
sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType), GetVariableNameForSlot(OutputSlotId));
sb.AppendLine("{0}({1}, {2}, {3});", GetFunctionName(), input1Value, input2Value, outputValue);
visitor.AddShaderChunk(sb.ToString(), false);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{
s.AppendLine("void {0} ({1} A, {2} B, out {3} Out)",
GetFunctionName(),
FindInputSlot<MaterialSlot>(Input1SlotId).concreteValueType.ToString(precision),
FindInputSlot<MaterialSlot>(Input2SlotId).concreteValueType.ToString(precision),
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToString(precision));
using (s.BlockScope())
{
switch(m_MultiplyType)
{
case MultiplyType.Vector:
s.AppendLine("Out = A * B;");
break;
default:
s.AppendLine("Out = mul(A, B);");
break;
}
}
});
}
// Internal validation
// -------------------------------------------------
public enum MultiplyType
{
Vector,
Matrix,
Mixed
}
MultiplyType m_MultiplyType;
public override void ValidateNode()
{
var isInError = false;
// all children nodes needs to be updated first
// so do that here
var slots = ListPool<MaterialSlot>.Get();
GetInputSlots(slots);
foreach (var inputSlot in slots)
{
inputSlot.hasError = false;
var edges = owner.GetEdges(inputSlot.slotReference);
foreach (var edge in edges)
{
var fromSocketRef = edge.outputSlot;
var outputNode = owner.GetNodeFromGuid(fromSocketRef.nodeGuid);
if (outputNode == null)
continue;
outputNode.ValidateNode();
if (outputNode.hasError)
isInError = true;
}
}
ListPool<MaterialSlot>.Release(slots);
var dynamicInputSlotsToCompare = DictionaryPool<DynamicValueMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicSlots = ListPool<DynamicValueMaterialSlot>.Get();
// iterate the input slots
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);
foreach (var inputSlot in s_TempSlots)
{
// if there is a connection
var edges = owner.GetEdges(inputSlot.slotReference).ToList();
if (!edges.Any())
{
if (inputSlot is DynamicValueMaterialSlot)
skippedDynamicSlots.Add(inputSlot as DynamicValueMaterialSlot);
continue;
}
// get the output details
var outputSlotRef = edges[0].outputSlot;
var outputNode = owner.GetNodeFromGuid(outputSlotRef.nodeGuid);
if (outputNode == null)
continue;
var outputSlot = outputNode.FindOutputSlot<MaterialSlot>(outputSlotRef.slotId);
if (outputSlot == null)
continue;
if (outputSlot.hasError)
{
inputSlot.hasError = true;
continue;
}
var outputConcreteType = outputSlot.concreteValueType;
// dynamic input... depends on output from other node.
// we need to compare ALL dynamic inputs to make sure they
// are compatable.
if (inputSlot is DynamicValueMaterialSlot)
{
dynamicInputSlotsToCompare.Add((DynamicValueMaterialSlot)inputSlot, outputConcreteType);
continue;
}
// if we have a standard connection... just check the types work!
if (!ImplicitConversionExists(outputConcreteType, inputSlot.concreteValueType))
inputSlot.hasError = true;
}
m_MultiplyType = GetMultiplyType(dynamicInputSlotsToCompare.Values);
// Resolve dynamics depending on matrix/vector configuration
switch(m_MultiplyType)
{
// If all matrix resolve as per dynamic matrix
case MultiplyType.Matrix:
var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicInputSlotsToCompare.Values);
foreach (var dynamicKvP in dynamicInputSlotsToCompare)
dynamicKvP.Key.SetConcreteType(dynamicMatrixType);
foreach (var skippedSlot in skippedDynamicSlots)
skippedSlot.SetConcreteType(dynamicMatrixType);
break;
// If mixed handle differently:
// Iterate all slots and set their concretes based on their edges
// Find matrix slot and convert its type to a vector type
// Reiterate all slots and set non matrix slots to the vector type
case MultiplyType.Mixed:
foreach (var dynamicKvP in dynamicInputSlotsToCompare)
{
SetConcreteValueTypeFromEdge(dynamicKvP.Key);
}
MaterialSlot matrixSlot = GetMatrixSlot();
ConcreteSlotValueType vectorType = ConvertMatrixToVectorType(matrixSlot.concreteValueType);
foreach (var dynamicKvP in dynamicInputSlotsToCompare)
{
if(dynamicKvP.Key != matrixSlot)
dynamicKvP.Key.SetConcreteType(vectorType);
}
foreach (var skippedSlot in skippedDynamicSlots)
{
skippedSlot.SetConcreteType(vectorType);
}
break;
// If all vector resolve as per dynamic vector
default:
var dynamicVectorType = ConvertDynamicInputTypeToConcrete(dynamicInputSlotsToCompare.Values);
foreach (var dynamicKvP in dynamicInputSlotsToCompare)
dynamicKvP.Key.SetConcreteType(dynamicVectorType);
foreach (var skippedSlot in skippedDynamicSlots)
skippedSlot.SetConcreteType(dynamicVectorType);
break;
}
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);
var inputError = s_TempSlots.Any(x => x.hasError);
// configure the output slots now
// their slotType will either be the default output slotType
// or the above dynanic slotType for dynamic nodes
// or error if there is an input error
s_TempSlots.Clear();
GetOutputSlots(s_TempSlots);
foreach (var outputSlot in s_TempSlots)
{
outputSlot.hasError = false;
if (inputError)
{
outputSlot.hasError = true;
continue;
}
if (outputSlot is DynamicValueMaterialSlot)
{
// Apply similar logic to output slot
switch(m_MultiplyType)
{
// As per dynamic matrix
case MultiplyType.Matrix:
var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicInputSlotsToCompare.Values);
(outputSlot as DynamicValueMaterialSlot).SetConcreteType(dynamicMatrixType);
break;
// Mixed configuration
// Find matrix slot and convert type to vector
// Set output concrete to vector
case MultiplyType.Mixed:
MaterialSlot matrixSlot = GetMatrixSlot();
ConcreteSlotValueType vectorType = ConvertMatrixToVectorType(matrixSlot.concreteValueType);
(outputSlot as DynamicValueMaterialSlot).SetConcreteType(vectorType);
break;
// As per dynamic vector
default:
var dynamicVectorType = ConvertDynamicInputTypeToConcrete(dynamicInputSlotsToCompare.Values);
(outputSlot as DynamicValueMaterialSlot).SetConcreteType(dynamicVectorType);
break;
}
continue;
}
}
isInError |= inputError;
s_TempSlots.Clear();
GetOutputSlots(s_TempSlots);
isInError |= s_TempSlots.Any(x => x.hasError);
isInError |= CalculateNodeHasError();
hasError = isInError;
if (!hasError)
{
++version;
}
ListPool<DynamicValueMaterialSlot>.Release(skippedDynamicSlots);
DictionaryPool<DynamicValueMaterialSlot, ConcreteSlotValueType>.Release(dynamicInputSlotsToCompare);
List<MaterialSlot> inSlots = new List<MaterialSlot>();
List<MaterialSlot> outSlots = new List<MaterialSlot>();
GetInputSlots<MaterialSlot>(inSlots);
GetOutputSlots<MaterialSlot>(outSlots);
// Debugs
foreach(MaterialSlot i in inSlots)
Debug.Log("Node: "+this.guid +" slot "+i.displayName+" to type "+i.concreteValueType);
foreach(MaterialSlot o in outSlots)
Debug.Log("Node: "+this.guid +" slot "+o.displayName+" to type "+o.concreteValueType);
}
private static bool ImplicitConversionExists(ConcreteSlotValueType from, ConcreteSlotValueType to)
{
if (from == to)
return true;
var fromCount = SlotValueHelper.GetChannelCount(from);
var toCount = SlotValueHelper.GetChannelCount(to);
// can convert from v1 vectors :)
if (from == ConcreteSlotValueType.Vector1 && toCount > 0)
return true;
if (toCount == 0)
return false;
if (toCount <= fromCount)
return true;
return false;
}
private MultiplyType GetMultiplyType(IEnumerable<ConcreteSlotValueType> inputTypes)
{
var concreteSlotValueTypes = inputTypes as List<ConcreteSlotValueType> ?? inputTypes.ToList();
int matrixCount = 0;
int vectorCount = 0;
for (int i = 0; i < concreteSlotValueTypes.Count; i++)
{
if(concreteSlotValueTypes[i] == ConcreteSlotValueType.Vector4
|| concreteSlotValueTypes[i] == ConcreteSlotValueType.Vector3
|| concreteSlotValueTypes[i] == ConcreteSlotValueType.Vector2
|| concreteSlotValueTypes[i] == ConcreteSlotValueType.Vector1)
{
vectorCount++;
}
else if(concreteSlotValueTypes[i] == ConcreteSlotValueType.Matrix4
|| concreteSlotValueTypes[i] == ConcreteSlotValueType.Matrix3
|| concreteSlotValueTypes[i] == ConcreteSlotValueType.Matrix2)
{
matrixCount++;
}
}
if(matrixCount == 2)
return MultiplyType.Matrix;
else if(vectorCount == 2)
return MultiplyType.Vector;
else if(matrixCount == 1)
return MultiplyType.Mixed;
else
return MultiplyType.Vector;
}
private MaterialSlot GetMatrixSlot()
{
List<MaterialSlot> slots = new List<MaterialSlot>();
GetInputSlots(slots);
for (int i = 0; i < slots.Count; i++)
{
var edges = owner.GetEdges(slots[i].slotReference).ToList();
if(!edges.Any())
continue;
var outputNode = owner.GetNodeFromGuid(edges[0].outputSlot.nodeGuid);
var outputSlot = outputNode.FindOutputSlot<MaterialSlot>(edges[0].outputSlot.slotId);
if(outputSlot.concreteValueType == ConcreteSlotValueType.Matrix4
|| outputSlot.concreteValueType == ConcreteSlotValueType.Matrix3
|| outputSlot.concreteValueType == ConcreteSlotValueType.Matrix2)
return slots[i];
}
return null;
}
private void SetConcreteValueTypeFromEdge(DynamicValueMaterialSlot slot)
{
var edges = owner.GetEdges(slot.slotReference).ToList();
if(!edges.Any())
return;
var outputNode = owner.GetNodeFromGuid(edges[0].outputSlot.nodeGuid);
var outputSlot = outputNode.FindOutputSlot<MaterialSlot>(edges[0].outputSlot.slotId);
slot.SetConcreteType(outputSlot.concreteValueType);
}
private ConcreteSlotValueType ConvertMatrixToVectorType(ConcreteSlotValueType matrixType)
{
switch(matrixType)
{
case ConcreteSlotValueType.Matrix4:
return ConcreteSlotValueType.Vector4;
case ConcreteSlotValueType.Matrix3:
return ConcreteSlotValueType.Vector3;
default:
return ConcreteSlotValueType.Vector2;
}
}
private ConcreteSlotValueType ConvertDynamicInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
{
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList();
var inputTypesDistinct = concreteSlotValueTypes.Distinct().ToList();
switch (inputTypesDistinct.Count)
{
case 0:
return ConcreteSlotValueType.Vector1;
case 1:
return inputTypesDistinct.FirstOrDefault();
default:
// find the 'minumum' channel width excluding 1 as it can promote
inputTypesDistinct.RemoveAll(x => x == ConcreteSlotValueType.Vector1);
var ordered = inputTypesDistinct.OrderByDescending(x => x);
if (ordered.Any())
return ordered.FirstOrDefault();
break;
}
return ConcreteSlotValueType.Vector1;
}
private ConcreteSlotValueType ConvertDynamicMatrixInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
{
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList();
var inputTypesDistinct = concreteSlotValueTypes.Distinct().ToList();
switch (inputTypesDistinct.Count)
{
case 0:
return ConcreteSlotValueType.Matrix2;
case 1:
return inputTypesDistinct.FirstOrDefault();
default:
var ordered = inputTypesDistinct.OrderByDescending(x => x);
if (ordered.Any())
return ordered.FirstOrDefault();
break;
}
return ConcreteSlotValueType.Matrix2;
}
/*private ConcreteSlotValueType ConvertDynamicOutputType(List<ConcreteSlotValueType> inputTypesDistinct)
{
// If dynamics contain vectors return a vector
if(DynamicsContainVectors(inputTypesDistinct))
{
int vectorLength;
// If mul(matrix, vector) return matrix length
if(DynamicsContainMatrices(inputTypesDistinct, out vectorLength))
{
switch(vectorLength)
{
case 2:
return ConcreteSlotValueType.Vector2;
case 3:
return ConcreteSlotValueType.Vector3;
case 4:
return ConcreteSlotValueType.Vector4;
default:
return ConcreteSlotValueType.Vector1;
}
}
// find the 'minumum' channel width excluding 1 as it can promote
inputTypesDistinct.RemoveAll(x => x == ConcreteSlotValueType.Vector1);
var ordered = inputTypesDistinct.OrderByDescending(x => x);
if (ordered.Any())
return ordered.FirstOrDefault();
return ConcreteSlotValueType.Vector1;
}
// Otherwise return a matrix
else
{
var ordered = inputTypesDistinct.OrderByDescending(x => x);
if (ordered.Any())
return ordered.FirstOrDefault();
return ConcreteSlotValueType.Vector1;
}
}
private bool DynamicsContainVectors(IList<ConcreteSlotValueType> inputTypes)
{
for (int i = 0; i < inputTypes.Count; i++)
{
if(inputTypes[i] == ConcreteSlotValueType.Vector4
|| inputTypes[i] == ConcreteSlotValueType.Vector3
|| inputTypes[i] == ConcreteSlotValueType.Vector2
|| inputTypes[i] == ConcreteSlotValueType.Vector1)
{
return true;
}
}
return false;
}
private bool DynamicsContainMatrices(IList<ConcreteSlotValueType> inputTypes, out int vectorLength)
{
for (int i = 0; i < inputTypes.Count; i++)
{
if(DynamicIsMatrix(inputTypes[i], out vectorLength))
return true;
}
vectorLength = 0;
return false;
}
private bool DynamicIsMatrix(ConcreteSlotValueType type, out int vectorLength)
{
if(type == ConcreteSlotValueType.Matrix4)
{
vectorLength = 4;
return true;
}
else if(type == ConcreteSlotValueType.Matrix3)
{
vectorLength = 3;
return true;
}
else if(type == ConcreteSlotValueType.Matrix2)
{
vectorLength = 2;
return true;
}
else
vectorLength = 1;
return false;
}*/
/*public MultiplyNode()
{
name = "Multiply";
}
protected override MethodInfo GetFunctionToConvert()

Out = A * B;
}
";
}
}*/
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/SlotValue.cs


Matrix2,
Texture2D,
Cubemap,
Dynamic,
DynamicVector,
Dynamic,
Boolean
}

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/GraphEditorView.cs


foreach (var edgeView in anchorView.connections.OfType<Edge>())
{
var targetSlot = edgeView.input.GetSlot();
if (targetSlot.valueType == SlotValueType.Dynamic)
if (targetSlot.valueType == SlotValueType.DynamicVector)
{
var connectedNodeView = edgeView.input.node as MaterialNodeView;
if (connectedNodeView != null && !nodeViews.Contains(connectedNodeView))

foreach (var anchorView in nodeView.inputContainer.Children().OfType<Port>())
{
var targetSlot = anchorView.GetSlot();
if (targetSlot.valueType != SlotValueType.Dynamic)
if (targetSlot.valueType != SlotValueType.DynamicVector)
continue;
foreach (var edgeView in anchorView.connections.OfType<Edge>())
{

99
MaterialGraphProject/Assets/New Shader Graph.ShaderGraph
文件差异内容过多而无法显示
查看文件

7
MaterialGraphProject/Assets/New Shader Graph.ShaderGraph.meta


fileFormatVersion: 2
guid: 3128537d5706b43ad99fd9cd6b5c7edf
ScriptedImporter:
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}

139
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicValueMaterialSlot.cs


using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
public class DynamicValueMaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
{
[SerializeField]
private Matrix4x4 m_Value;
[SerializeField]
private Matrix4x4 m_DefaultValue;
private ConcreteSlotValueType m_ConcreteValueType = ConcreteSlotValueType.Vector4;
public DynamicValueMaterialSlot()
{
}
public DynamicValueMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Matrix4x4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
m_Value = value;
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override VisualElement InstantiateControl()
{
int components =
concreteValueType == ConcreteSlotValueType.Vector4 ? 4 :
concreteValueType == ConcreteSlotValueType.Vector3 ? 3 :
concreteValueType == ConcreteSlotValueType.Vector2 ? 2 :
concreteValueType == ConcreteSlotValueType.Vector1 ? 1 : 0;
return new MultiFloatSlotControlView(owner, components, () => value.GetRow(0), (newValue) => value = new Matrix4x4(newValue, value.GetRow(1), value.GetRow(2), value.GetRow(3)));
}
public override SlotValueType valueType { get { return SlotValueType.Dynamic; } }
public override ConcreteSlotValueType concreteValueType
{
get { return m_ConcreteValueType; }
}
public void SetConcreteType(ConcreteSlotValueType valueType)
{
m_ConcreteValueType = valueType;
}
public override PreviewProperty GetPreviewProperty(string name)
{
var propType = ConvertConcreteSlotValueTypeToPropertyType(concreteValueType);
var pp = new PreviewProperty(propType) { name = name };
if (propType == PropertyType.Vector1)
pp.floatValue = value.m00;
else
pp.vector4Value = new Vector4(value.m00, value.m01, value.m02, value.m03);
return pp;
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
var channelCount = SlotValueHelper.GetChannelCount(concreteValueType);
string values = NodeUtils.FloatToShaderValue(value.m00);
if (channelCount == 1)
return values;
for (var i = 1; i < channelCount; i++)
values += ", " + value.GetRow(0)[i];
return string.Format("{0}{1}({2})", precision, channelCount, values);
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
IShaderProperty property;
switch (concreteValueType)
{
case ConcreteSlotValueType.Vector4:
property = new Vector4ShaderProperty();
break;
case ConcreteSlotValueType.Vector3:
property = new Vector3ShaderProperty();
break;
case ConcreteSlotValueType.Vector2:
property = new Vector2ShaderProperty();
break;
case ConcreteSlotValueType.Vector1:
property = new Vector1ShaderProperty();
break;
case ConcreteSlotValueType.Matrix4:
property = new Matrix4ShaderProperty();
break;
case ConcreteSlotValueType.Matrix3:
property = new Matrix3ShaderProperty();
break;
case ConcreteSlotValueType.Matrix2:
property = new Matrix2ShaderProperty();
break;
default:
throw new ArgumentOutOfRangeException();
}
property.overrideReferenceName = matOwner.GetVariableNameForSlot(id);
property.generatePropertyBlock = false;
properties.AddShaderProperty(property);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as DynamicValueMaterialSlot;
if (slot != null)
value = slot.value;
}
}
}

11
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicValueMaterialSlot.cs.meta


fileFormatVersion: 2
guid: 38b2d4645340d4274a793e2e12ec097c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存