浏览代码

Merge pull request #224 from Unity-Technologies/node-matrix

Node Matrix
/main
GitHub 7 年前
当前提交
9641212d
共有 44 个文件被更改,包括 1788 次插入454 次删除
  1. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicVectorMaterialSlot.cs
  2. 33
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialSlot.cs
  3. 56
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix2MaterialSlot.cs
  4. 53
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix3MaterialSlot.cs
  5. 53
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix4MaterialSlot.cs
  6. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/PreviewProperty.cs
  7. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Implementation/NodeUtils.cs
  8. 65
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/AbstractMaterialNode.cs
  9. 8
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Channel/CombineNode.cs
  10. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Channel/SplitNode.cs
  11. 32
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/CodeFunctionNode.cs
  12. 96
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix2Node.cs
  13. 110
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix3Node.cs
  14. 132
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Matrix/Matrix4Node.cs
  15. 379
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Basic/MultiplyNode.cs
  16. 20
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixTransposeNode.cs
  17. 32
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/SlotValue.cs
  18. 1
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/SubGraph/SubGraph.cs
  19. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Util/ShaderGenerator.cs
  20. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/GraphEditorView.cs
  21. 116
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicMatrixMaterialSlot.cs
  22. 11
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicMatrixMaterialSlot.cs.meta
  23. 139
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicValueMaterialSlot.cs
  24. 11
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicValueMaterialSlot.cs.meta
  25. 34
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix2ShaderProperty.cs
  26. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix2ShaderProperty.cs.meta
  27. 35
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix3ShaderProperty.cs
  28. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix3ShaderProperty.cs.meta
  29. 31
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix4ShaderProperty.cs
  30. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix4ShaderProperty.cs.meta
  31. 30
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MatrixShaderProperty.cs
  32. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MatrixShaderProperty.cs.meta
  33. 121
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixConstructionNode.cs
  34. 8
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixConstructionNode.cs.meta
  35. 31
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixDeterminantNode.cs
  36. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixDeterminantNode.cs.meta
  37. 278
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs
  38. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs.meta
  39. 19
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/Slots/LabelSlotControlView.cs
  40. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/Slots/LabelSlotControlView.cs.meta
  41. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyByVectorNode.cs.meta
  42. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyNode.cs.meta
  43. 106
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyByVectorNode.cs
  44. 118
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyNode.cs

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
{

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


{
case SlotValueType.SamplerState:
return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.DynamicMatrix:
return new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Matrix4:
return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
case SlotValueType.Matrix3:

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);
}

{
case SlotValueType.SamplerState:
return inputType == SlotValueType.SamplerState;
case SlotValueType.DynamicMatrix:
|| inputType == SlotValueType.Matrix2;
|| inputType == SlotValueType.Matrix2
|| inputType == SlotValueType.DynamicMatrix
|| inputType == SlotValueType.Dynamic;
|| inputType == SlotValueType.Matrix2;
|| inputType == SlotValueType.Matrix2
|| inputType == SlotValueType.DynamicMatrix
|| inputType == SlotValueType.Dynamic;
return inputType == SlotValueType.Matrix2;
return inputType == SlotValueType.Matrix2
|| 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;

56
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix2MaterialSlot.cs


using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
public class Matrix2MaterialSlot : MaterialSlot
public class Matrix2MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
public Matrix2MaterialSlot()
{
}

{
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "2x2 (1,0,0,1)";

{}
{
if (!generationMode.IsPreview())
return;
public override void CopyValuesFrom(MaterialSlot foundSlot)
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)));
var property = new Matrix2ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override PreviewProperty GetPreviewProperty(string name)
var pp = new PreviewProperty(PropertyType.Matrix2)
{
name = name,
vector4Value = new Vector4(value.GetRow(0).x, value.GetRow(0).y, 0, 0)
};
return pp;
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Matrix2MaterialSlot;
if (slot != null)
value = slot.value;
}
}
}

53
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix3MaterialSlot.cs


using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
public class Matrix3MaterialSlot : MaterialSlot
public class Matrix3MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
public Matrix3MaterialSlot()
{
}

{
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
return precision + "3x3 (1,0,0,0,1,0,0,0,1)";

{
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)));
var property = new Matrix3ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
public override void CopyValuesFrom(MaterialSlot foundSlot)
public override PreviewProperty GetPreviewProperty(string name)
var pp = new PreviewProperty(PropertyType.Matrix3)
{
name = name,
vector4Value = new Vector4(value.GetRow(0).x, value.GetRow(0).y, value.GetRow(0).z, 0)
};
return pp;
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Matrix3MaterialSlot;
if (slot != null)
value = slot.value;
}
}
}

53
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix4MaterialSlot.cs


using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
public class Matrix4MaterialSlot : MaterialSlot
public class Matrix4MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
public Matrix4MaterialSlot()
{
}

{
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
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)";

{
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)));
var property = new Matrix4ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
public override void CopyValuesFrom(MaterialSlot foundSlot)
public override PreviewProperty GetPreviewProperty(string name)
var pp = new PreviewProperty(PropertyType.Matrix4)
{
name = name,
vector4Value = new Vector4(value.GetRow(0).x, value.GetRow(0).y, value.GetRow(0).z, value.GetRow(0).w)
};
return pp;
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Matrix4MaterialSlot;
if (slot != null)
value = slot.value;
}
}
}

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;
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Implementation/NodeUtils.cs


case ConcreteSlotValueType.Cubemap:
return "Cubemap";
case ConcreteSlotValueType.Matrix2:
return "Matrix2x2";
return p + "2x2";
return "Matrix3x3";
return p + "3x3";
return "Matrix4x4";
return p + "4x4";
case ConcreteSlotValueType.SamplerState:
return "SamplerState";
default:

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


return inputSlot.GetDefaultValue(generationMode);
}
private static bool ImplicitConversionExists(ConcreteSlotValueType from, ConcreteSlotValueType to)
public static bool ImplicitConversionExists(ConcreteSlotValueType from, ConcreteSlotValueType to)
{
if (from == to)
return true;

// can convert from v1 vectors :)
if (from == ConcreteSlotValueType.Vector1 && toCount > 0)
if (toCount > 0 && fromCount > 0)
if (toCount == 0)
return false;
if (toCount <= fromCount)
return true;
private ConcreteSlotValueType ConvertDynamicInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
public virtual ConcreteSlotValueType ConvertDynamicInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
{
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList();

return ConcreteSlotValueType.Vector1;
}
public virtual 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;
}
public virtual void ValidateNode()
{
var isInError = false;

var dynamicInputSlotsToCompare = DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicSlots = ListPool<DynamicVectorMaterialSlot>.Get();
var dynamicMatrixInputSlotsToCompare = DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicMatrixSlots = ListPool<DynamicMatrixMaterialSlot>.Get();
// iterate the input slots
s_TempSlots.Clear();

{
if (inputSlot is DynamicVectorMaterialSlot)
skippedDynamicSlots.Add(inputSlot as DynamicVectorMaterialSlot);
if (inputSlot is DynamicMatrixMaterialSlot)
skippedDynamicMatrixSlots.Add(inputSlot as DynamicMatrixMaterialSlot);
continue;
}

dynamicInputSlotsToCompare.Add((DynamicVectorMaterialSlot)inputSlot, outputConcreteType);
continue;
}
else if (inputSlot is DynamicMatrixMaterialSlot)
{
dynamicMatrixInputSlotsToCompare.Add((DynamicMatrixMaterialSlot)inputSlot, outputConcreteType);
continue;
}
// if we have a standard connection... just check the types work!
if (!ImplicitConversionExists(outputConcreteType, inputSlot.concreteValueType))

foreach (var skippedSlot in skippedDynamicSlots)
skippedSlot.SetConcreteType(dynamicType);
// and now dynamic matrices
var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicMatrixInputSlotsToCompare.Values);
foreach (var dynamicKvP in dynamicMatrixInputSlotsToCompare)
dynamicKvP.Key.SetConcreteType(dynamicMatrixType);
foreach (var skippedSlot in skippedDynamicMatrixSlots)
skippedSlot.SetConcreteType(dynamicMatrixType);
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);
var inputError = s_TempSlots.Any(x => x.hasError);

(outputSlot as DynamicVectorMaterialSlot).SetConcreteType(dynamicType);
continue;
}
else if (outputSlot is DynamicMatrixMaterialSlot)
{
(outputSlot as DynamicMatrixMaterialSlot).SetConcreteType(dynamicMatrixType);
continue;
}
}
isInError |= inputError;

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

8
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Channel/CombineNode.cs


[Slot(1, Binding.None)] Vector1 G,
[Slot(2, Binding.None)] Vector1 B,
[Slot(3, Binding.None)] Vector1 A,
[Slot(4, Binding.None)] out Vector4 RGBA)
[Slot(4, Binding.None)] out Vector4 RGBA,
[Slot(5, Binding.None)] out Vector3 RGB,
[Slot(6, Binding.None)] out Vector2 RG)
RGB = Vector3.zero;
RG = Vector2.zero;
RGB = float3(R, G, B);
RG = float2(R, G);
}
";
}

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


[Title("Channel", "Split")]
public class SplitNode : AbstractMaterialNode, IGeneratesBodyCode
{
const string kInputSlotName = "Input";
const string kInputSlotName = "In";
const string kOutputSlotRName = "R";
const string kOutputSlotGName = "G";
const string kOutputSlotBName = "B";

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


protected struct DynamicDimensionVector
{}
protected struct ColorRGBA
{}
protected struct ColorRGB
{}
protected struct Matrix3x3
{}
protected struct Matrix2x2
{}
protected struct DynamicDimensionMatrix
{ }
protected enum Binding
{
None,

protected abstract MethodInfo GetFunctionToConvert();
public class ColorRGBA { };
public class ColorRGB { };
private static SlotValueType ConvertTypeToSlotValueType(ParameterInfo p)
{
Type t = p.ParameterType;

}
if (t == typeof(DynamicDimensionVector))
{
return SlotValueType.Dynamic;
return SlotValueType.DynamicVector;
}
if (t == typeof(Matrix3x3))
{
return SlotValueType.Matrix3;
}
if (t == typeof(Matrix2x2))
{
return SlotValueType.Matrix2;
}
if (t == typeof(DynamicDimensionMatrix))
{
return SlotValueType.DynamicMatrix;
}
throw new ArgumentException("Unsupported type " + t);
}

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


using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEngine;
using UnityEditor.Graphing;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{

const int kOutputSlotId = 0;
public const int OutputSlotId = 0;
const string kOutputSlotName = "Out";
[SerializeField]

if (value == row)
return;
row = value;
Dirty(ModificationScope.Graph);
Dirty(ModificationScope.Node);
}
public Matrix2Node()

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Matrix2MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
AddSlot(new Matrix2MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
public string propertyName
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
get
if (!generationMode.IsPreview())
return;
properties.AddShaderProperty(new Vector2ShaderProperty()
return string.Format("{0}_{1}_Uniform", name, GetVariableNameForNode());
}
}
overrideReferenceName = string.Format("_{0}_m0", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row0
});
public override string GetVariableNameForSlot(int slotId)
{
return propertyName;
properties.AddShaderProperty(new Vector2ShaderProperty()
{
overrideReferenceName = string.Format("_{0}_m1", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row1
});
//if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
// return;
visitor.AddShaderChunk(precision + "2 " + name + " = " + precision + "2x2 (" + m_Row0.x + ", " + m_Row0.y + ", " + m_Row1.x + ", " + m_Row1.y + ");", true);
}
[SerializeField]
string m_Description = string.Empty;
public string description
{
get
var sb = new ShaderStringBuilder();
if (!generationMode.IsPreview())
return string.IsNullOrEmpty(m_Description) ? name : m_Description;
sb.AppendLine("{0}2 _{1}_m0 = {0}2 ({2}, {3});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row0.x),
NodeUtils.FloatToShaderValue(m_Row0.y));
sb.AppendLine("{0}2 _{1}_m1 = {0}2 ({2}, {3});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row1.x),
NodeUtils.FloatToShaderValue(m_Row1.y));
set { m_Description = value; }
sb.AppendLine("{0}2x2 {1} = {0}2x2 (_{1}_m0.x, _{1}_m0.y, _{1}_m1.x, _{1}_m1.y);",
precision, GetVariableNameForNode());
visitor.AddShaderChunk(sb.ToString(), false);
// TODO - Remove Property entries everywhere?
// Matrix cant be a shader property
/*public override PropertyType propertyType
{
get { return PropertyType.Matrix2; }
}*/
/*public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
if (exposedState == ExposedState.Exposed)
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_Value, PropertyChunk.HideState.Visible));
}*/
properties.Add(new PreviewProperty(PropertyType.Vector2)
{
name = string.Format("_{0}_m0", GetVariableNameForNode()),
vector4Value = m_Row0
});
/*public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
visitor.AddShaderChunk(precision + "2 " + propertyName + ";", true);
}*/
properties.Add(new PreviewProperty(PropertyType.Vector2)
{
name = string.Format("_{0}_m1", GetVariableNameForNode()),
vector4Value = m_Row1
});
}
/*public override PreviewProperty GetPreviewProperty()
public override string GetVariableNameForSlot(int slotId)
return new PreviewProperty
{
m_Name = propertyName,
m_PropType = PropertyType.Vector2,
m_Vector2 = m_Value
};
}*/
return GetVariableNameForNode();
}
}
}

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


using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEngine;
using UnityEditor.Graphing;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{

const int kOutputSlotId = 0;
public const int OutputSlotId = 0;
const string kOutputSlotName = "Out";
[SerializeField]

if (value == row)
return;
row = value;
Dirty(ModificationScope.Graph);
Dirty(ModificationScope.Node);
}
public Matrix3Node()

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Matrix3MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
AddSlot(new Matrix3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
public string propertyName
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
get { return string.Format("{0}_{1}_Uniform", name, GetVariableNameForNode()); }
}
if (!generationMode.IsPreview())
return;
public override string GetVariableNameForSlot(int slotId)
{
return propertyName;
}
properties.AddShaderProperty(new Vector3ShaderProperty()
{
overrideReferenceName = string.Format("_{0}_m0", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row0
});
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
//if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
// return;
properties.AddShaderProperty(new Vector3ShaderProperty()
{
overrideReferenceName = string.Format("_{0}_m1", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row1
});
visitor.AddShaderChunk(precision + "3x3 " + propertyName + " = " + precision + "3x3 (" + m_Row0.x + ", " + m_Row0.y + ", " + m_Row0.z + ", " + m_Row1.x + ", " + m_Row1.y + ", " + m_Row1.z + ", " + m_Row2.x + ", " + m_Row2.y + ", " + m_Row2.z + ");", true);
properties.AddShaderProperty(new Vector3ShaderProperty()
{
overrideReferenceName = string.Format("_{0}_m2", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row2
});
[SerializeField]
string m_Description = string.Empty;
public string description
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
get
var sb = new ShaderStringBuilder();
if (!generationMode.IsPreview())
return string.IsNullOrEmpty(m_Description) ? name : m_Description;
sb.AppendLine("{0}3 _{1}_m0 = {0}3 ({2}, {3}, {4});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row0.x),
NodeUtils.FloatToShaderValue(m_Row0.y),
NodeUtils.FloatToShaderValue(m_Row0.z));
sb.AppendLine("{0}3 _{1}_m1 = {0}3 ({2}, {3}, {4});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row1.x),
NodeUtils.FloatToShaderValue(m_Row1.y),
NodeUtils.FloatToShaderValue(m_Row1.z));
sb.AppendLine("{0}3 _{1}_m2 = {0}3 ({2}, {3}, {4});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row2.x),
NodeUtils.FloatToShaderValue(m_Row2.y),
NodeUtils.FloatToShaderValue(m_Row2.z));
set { m_Description = value; }
sb.AppendLine("{0}3x3 {1} = {0}3x3 (_{1}_m0.x, _{1}_m0.y, _{1}_m0.z, _{1}_m1.x, _{1}_m1.y, _{1}_m1.z, _{1}_m2.x, _{1}_m2.y, _{1}_m2.z);",
precision, GetVariableNameForNode());
visitor.AddShaderChunk(sb.ToString(), false);
// TODO - Remove Property entries everywhere?
// Matrix cant be a shader property
/*public override PropertyType propertyType
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
get { return PropertyType.Matrix2; }
}*/
properties.Add(new PreviewProperty(PropertyType.Vector3)
{
name = string.Format("_{0}_m0", GetVariableNameForNode()),
vector4Value = m_Row0
});
/*public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
if (exposedState == ExposedState.Exposed)
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_Value, PropertyChunk.HideState.Visible));
}*/
properties.Add(new PreviewProperty(PropertyType.Vector3)
{
name = string.Format("_{0}_m1", GetVariableNameForNode()),
vector4Value = m_Row1
});
/*public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
visitor.AddShaderChunk(precision + "2 " + propertyName + ";", true);
}*/
properties.Add(new PreviewProperty(PropertyType.Vector3)
{
name = string.Format("_{0}_m2", GetVariableNameForNode()),
vector4Value = m_Row2
});
}
/*public override PreviewProperty GetPreviewProperty()
public override string GetVariableNameForSlot(int slotId)
return new PreviewProperty
{
m_Name = propertyName,
m_PropType = PropertyType.Vector2,
m_Vector3 = m_Value
};
}*/
return GetVariableNameForNode();
}
}
}

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


using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEngine;
using UnityEditor.Graphing;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{

const int kOutputSlotId = 0;
public const int OutputSlotId = 0;
const string kOutputSlotName = "Out";
[SerializeField]

if (value == row)
return;
row = value;
Dirty(ModificationScope.Graph);
Dirty(ModificationScope.Node);
}
public Matrix4Node()

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Matrix4MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
AddSlot(new Matrix4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
public string propertyName
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
get
if (!generationMode.IsPreview())
return;
properties.AddShaderProperty(new Vector4ShaderProperty()
return string.Format("{0}_{1}_Uniform", name, GetVariableNameForNode());
}
}
overrideReferenceName = string.Format("_{0}_m0", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row0
});
public override string GetVariableNameForSlot(int slotId)
{
return propertyName;
}
properties.AddShaderProperty(new Vector4ShaderProperty()
{
overrideReferenceName = string.Format("_{0}_m1", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row1
});
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
//if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
// return;
properties.AddShaderProperty(new Vector4ShaderProperty()
{
overrideReferenceName = string.Format("_{0}_m2", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row2
});
visitor.AddShaderChunk(precision + "4x4 " + propertyName + " = " + precision + "4x4 (" + row0.x + ", " + row0.y + ", " + row0.z + ", " + row0.w + ", " + m_Row1.x + ", " + m_Row1.y + ", " + m_Row1.z + ", " + m_Row1.w + ", " + m_Row2.x + ", " + m_Row2.y + ", " + m_Row2.z + ", " + m_Row2.w + ", " + m_Row3.x + ", " + m_Row3.y + ", " + m_Row3.z + ", " + m_Row3.w + ");", true);
properties.AddShaderProperty(new Vector4ShaderProperty()
{
overrideReferenceName = string.Format("_{0}_m3", GetVariableNameForNode()),
generatePropertyBlock = false,
value = m_Row3
});
[SerializeField]
string m_Description = string.Empty;
public string description
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
get
var sb = new ShaderStringBuilder();
if (!generationMode.IsPreview())
return string.IsNullOrEmpty(m_Description) ? name : m_Description;
sb.AppendLine("{0}4 _{1}_m0 = {0}4 ({2}, {3}, {4}, {5});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row0.x),
NodeUtils.FloatToShaderValue(m_Row0.y),
NodeUtils.FloatToShaderValue(m_Row0.z),
NodeUtils.FloatToShaderValue(m_Row0.w));
sb.AppendLine("{0}4 _{1}_m1 = {0}4 ({2}, {3}, {4}, {5});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row1.x),
NodeUtils.FloatToShaderValue(m_Row1.y),
NodeUtils.FloatToShaderValue(m_Row1.z),
NodeUtils.FloatToShaderValue(m_Row1.w));
sb.AppendLine("{0}4 _{1}_m2 = {0}4 ({2}, {3}, {4}, {5});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row2.x),
NodeUtils.FloatToShaderValue(m_Row2.y),
NodeUtils.FloatToShaderValue(m_Row2.z),
NodeUtils.FloatToShaderValue(m_Row2.w));
sb.AppendLine("{0}4 _{1}_m3 = {0}4 ({2}, {3}, {4}, {5});", precision, GetVariableNameForNode(),
NodeUtils.FloatToShaderValue(m_Row3.x),
NodeUtils.FloatToShaderValue(m_Row3.y),
NodeUtils.FloatToShaderValue(m_Row3.z),
NodeUtils.FloatToShaderValue(m_Row3.w));
set { m_Description = value; }
sb.AppendLine("{0}4x4 {1} = {0}4x4 (_{1}_m0.x, _{1}_m0.y, _{1}_m0.z, _{1}_m0.w, _{1}_m1.x, _{1}_m1.y, _{1}_m1.z, _{1}_m1.w, _{1}_m2.x, _{1}_m2.y, _{1}_m2.z, _{1}_m2.w, _{1}_m3.x, _{1}_m3.y, _{1}_m3.z, _{1}_m3.w);",
precision, GetVariableNameForNode());
visitor.AddShaderChunk(sb.ToString(), false);
// TODO - Remove Property entries everywhere?
// Matrix cant be a shader property
/*public override PropertyType propertyType
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
get { return PropertyType.Matrix2; }
}*/
properties.Add(new PreviewProperty(PropertyType.Vector4)
{
name = string.Format("_{0}_m0", GetVariableNameForNode()),
vector4Value = m_Row0
});
/*public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode)
{
if (exposedState == ExposedState.Exposed)
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_Value, PropertyChunk.HideState.Visible));
}*/
properties.Add(new PreviewProperty(PropertyType.Vector4)
{
name = string.Format("_{0}_m1", GetVariableNameForNode()),
vector4Value = m_Row1
});
/*public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
visitor.AddShaderChunk(precision + "2 " + propertyName + ";", true);
}*/
properties.Add(new PreviewProperty(PropertyType.Vector4)
{
name = string.Format("_{0}_m2", GetVariableNameForNode()),
vector4Value = m_Row2
});
properties.Add(new PreviewProperty(PropertyType.Vector4)
{
name = string.Format("_{0}_m3", GetVariableNameForNode()),
vector4Value = m_Row3
});
}
/*public override PreviewProperty GetPreviewProperty()
public override string GetVariableNameForSlot(int slotId)
return new PreviewProperty
{
m_Name = propertyName,
m_PropType = PropertyType.Vector2,
m_Vector4 = m_Value
};
}*/
return GetVariableNameForNode();
}
}
}

379
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();
}
public override string documentationURL

protected override MethodInfo GetFunctionToConvert()
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 enum MultiplyType
{
Vector,
Matrix,
Mixed
}
MultiplyType m_MultiplyType;
public override bool hasPreview
{
get { return m_MultiplyType != MultiplyType.Matrix; }
}
string GetFunctionHeader()
{
return string.Format("Unity_Multiply_{0}", 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});", GetFunctionHeader(), input1Value, input2Value, outputValue);
visitor.AddShaderChunk(sb.ToString(), false);
}
string GetFunctionName()
{
return string.Format("{0}_{1}_{2}",
GetFunctionHeader(),
FindInputSlot<MaterialSlot>(Input1SlotId).concreteValueType.ToString(precision),
FindInputSlot<MaterialSlot>(Input2SlotId).concreteValueType.ToString(precision));
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{
s.AppendLine("void {0} ({1} A, {2} B, out {3} Out)",
GetFunctionHeader(),
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 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 = SlotValueHelper.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 = SlotValueHelper.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);
}
protected override bool CalculateNodeHasError()
{
if(m_MultiplyType == MultiplyType.Matrix)
{
foreach (var slot in this.GetOutputSlots<ISlot>())
{
foreach (var edge in owner.GetEdges(slot.slotReference))
{
var inputNode = owner.GetNodeFromGuid(edge.inputSlot.nodeGuid);
List<MaterialSlot> slots = new List<MaterialSlot>();
inputNode.GetInputSlots(slots);
foreach(var s in slots)
{
foreach(var inputEdge in inputNode.owner.GetEdges(s.slotReference))
{
if(inputEdge == edge)
{
if(s as DynamicValueMaterialSlot == null)
{
if(s.concreteValueType != ConcreteSlotValueType.Matrix4
&& s.concreteValueType != ConcreteSlotValueType.Matrix3
&& s.concreteValueType != ConcreteSlotValueType.Matrix2)
{
Debug.Log("ERROR: slot "+s.displayName+" cannot accept a Matrix type input");
return true;
}
}
}
}
}
}
}
}
return false;
}
private MultiplyType GetMultiplyType(IEnumerable<ConcreteSlotValueType> inputTypes)
return GetType().GetMethod("Unity_Multiply", BindingFlags.Static | BindingFlags.NonPublic);
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;
static string Unity_Multiply(
[Slot(0, Binding.None, 0, 0, 0, 0)] DynamicDimensionVector A,
[Slot(1, Binding.None, 2, 2, 2, 2)] DynamicDimensionVector B,
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
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)
return
@"
{
Out = A * B;
}
";
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);
}
}
}

20
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixTransposeNode.cs


namespace UnityEditor.ShaderGraph
{
[Title("Math", "Matrix", "TransposeMatrix")]
[Title("Math", "Matrix", "Matrix Transpose")]
name = "TransposeMatrix";
name = "Matrix Transpose";
}
public override bool hasPreview
{
get { return false; }
return GetType().GetMethod("unity_MatrixTranspose_", BindingFlags.Static | BindingFlags.NonPublic);
return GetType().GetMethod("Unity_MatrixTranspose", BindingFlags.Static | BindingFlags.NonPublic);
static string unity_MatrixTranspose_(
[Slot(0, Binding.None)] Matrix4x4 inMatrix,
[Slot(1, Binding.None)] out Matrix4x4 outMatrix)
static string Unity_MatrixTranspose(
[Slot(0, Binding.None)] DynamicDimensionMatrix In,
[Slot(1, Binding.None)] out DynamicDimensionMatrix Out)
outMatrix = Matrix4x4.identity;
outMatrix = transpose(inMatrix);
Out = transpose(In);
}
";
}

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


public enum SlotValueType
{
SamplerState,
DynamicMatrix,
Dynamic,
DynamicVector,
Dynamic,
Boolean
}

return 1;
default:
return 0;
}
}
public static int GetMatrixDimension(ConcreteSlotValueType type)
{
switch (type)
{
case ConcreteSlotValueType.Matrix4:
return 4;
case ConcreteSlotValueType.Matrix3:
return 3;
case ConcreteSlotValueType.Matrix2:
return 2;
default:
return 0;
}
}
public static ConcreteSlotValueType ConvertMatrixToVectorType(ConcreteSlotValueType matrixType)
{
switch(matrixType)
{
case ConcreteSlotValueType.Matrix4:
return ConcreteSlotValueType.Vector4;
case ConcreteSlotValueType.Matrix3:
return ConcreteSlotValueType.Vector3;
default:
return ConcreteSlotValueType.Vector2;
}
}

1
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/SubGraph/SubGraph.cs


{
foreach (var node in activeNodes)
{
node.ValidateNode();
if (node is IGeneratesFunction)
(node as IGeneratesFunction).GenerateNodeFunction(registry, generationMode);
}

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Util/ShaderGenerator.cs


default:
return kErrorString;
}
case ConcreteSlotValueType.Matrix3:
return rawOutput;
case ConcreteSlotValueType.Matrix2:
return rawOutput;
default:
return kErrorString;
}

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 || targetSlot.valueType == SlotValueType.DynamicMatrix || targetSlot.valueType == SlotValueType.Dynamic)
{
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>())
{

116
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/DynamicMatrixMaterialSlot.cs


using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
public class DynamicMatrixMaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
{
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
private ConcreteSlotValueType m_ConcreteValueType = ConcreteSlotValueType.Matrix4;
public DynamicMatrixMaterialSlot()
{
}
public DynamicMatrixMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
{
m_Value = value;
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override SlotValueType valueType { get { return SlotValueType.DynamicMatrix; } }
public override ConcreteSlotValueType concreteValueType
{
get { return m_ConcreteValueType; }
}
public void SetConcreteType(ConcreteSlotValueType valueType)
{
m_ConcreteValueType = valueType;
}
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
{
var channelCount = (int)SlotValueHelper.GetMatrixDimension(concreteValueType);
var values = "";
bool isFirst = true;
for (var r = 0; r < channelCount; r++)
{
for (var c = 0; c < channelCount; c++)
{
if(!isFirst)
values += ", ";
isFirst = false;
values += value.GetRow(r)[c];
}
}
return string.Format("{0}{1}x{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.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 DynamicMatrixMaterialSlot;
if (slot != null)
value = slot.value;
}
}
}

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


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

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:

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


using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
public class Matrix2ShaderProperty : MatrixShaderProperty
{
public Matrix2ShaderProperty()
{
displayName = "Matrix2";
}
public override PropertyType propertyType
{
get { return PropertyType.Matrix2; }
}
public override string GetPropertyDeclarationString(string delimiter = ";")
{
return "float4x4 " + referenceName + " = float4x4(1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)" + delimiter;
}
public override INode ToConcreteNode()
{
return new Matrix2Node
{
row0 = new Vector2(value.m00, value.m01),
row1 = new Vector2(value.m10, value.m11)
};
}
}
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix2ShaderProperty.cs.meta


fileFormatVersion: 2
guid: 0755d7f7a7e11cb4294563bbd0d434cc
timeCreated: 1505346935

35
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix3ShaderProperty.cs


using System;
using UnityEngine;
using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph
{
[Serializable]
public class Matrix3ShaderProperty : MatrixShaderProperty
{
public Matrix3ShaderProperty()
{
displayName = "Matrix3";
}
public override PropertyType propertyType
{
get { return PropertyType.Matrix3; }
}
public override string GetPropertyDeclarationString(string delimiter = ";")
{
return "float4x4 " + referenceName + " = float4x4(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0)" + delimiter;
}
public override INode ToConcreteNode()
{
return new Matrix3Node
{
row0 = new Vector3(value.m00, value.m01, value.m02),
row1 = new Vector3(value.m10, value.m11, value.m12),
row2 = new Vector3(value.m20, value.m21, value.m22)
};
}
}
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix3ShaderProperty.cs.meta


fileFormatVersion: 2
guid: 95c9c50f50c70c8479180b855a3bd255
timeCreated: 1505346935

31
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix4ShaderProperty.cs


using System;
using UnityEngine;
using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph
{
[Serializable]
public class Matrix4ShaderProperty : MatrixShaderProperty
{
public Matrix4ShaderProperty()
{
displayName = "Matrix4";
}
public override PropertyType propertyType
{
get { return PropertyType.Matrix4; }
}
public override INode ToConcreteNode()
{
return new Matrix4Node
{
row0 = new Vector4(value.m00, value.m01, value.m02, value.m03),
row1 = new Vector4(value.m10, value.m11, value.m12, value.m13),
row2 = new Vector4(value.m20, value.m21, value.m22, value.m23),
row3 = new Vector4(value.m30, value.m31, value.m32, value.m33)
};
}
}
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/Matrix4ShaderProperty.cs.meta


fileFormatVersion: 2
guid: 6379ce3fb15957343ba875d18f87efbc
timeCreated: 1505346935

30
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MatrixShaderProperty.cs


using System;
using System.Text;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
public abstract class MatrixShaderProperty : AbstractShaderProperty<Matrix4x4>
{
public override string GetPropertyBlockString()
{
return string.Empty;
}
public override Vector4 defaultValue
{
get { return new Vector4(); }
}
public override string GetPropertyDeclarationString(string delimiter = ";")
{
return "float4x4 " + referenceName + " = float4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)" + delimiter;
}
public override PreviewProperty GetPreviewMaterialProperty()
{
return default(PreviewProperty);
}
}
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MatrixShaderProperty.cs.meta


fileFormatVersion: 2
guid: 79075442664faac49b00b4c93d28e08b
timeCreated: 1505408377

121
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixConstructionNode.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Controls;
namespace UnityEditor.ShaderGraph
{
[Title("Math", "Matrix", "Matrix Construction")]
public class MatrixConstructionNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
{
const string kInputSlotM0Name = "M0";
const string kInputSlotM1Name = "M1";
const string kInputSlotM2Name = "M2";
const string kInputSlotM3Name = "M3";
const string kOutput4x4SlotName = "4x4";
const string kOutput3x3SlotName = "3x3";
const string kOutput2x2SlotName = "2x2";
public const int InputSlotM0Id = 0;
public const int InputSlotM1Id = 1;
public const int InputSlotM2Id = 2;
public const int InputSlotM3Id = 3;
public const int Output4x4SlotId = 4;
public const int Output3x3SlotId = 5;
public const int Output2x2SlotId = 6;
public MatrixConstructionNode()
{
name = "Matrix Construction";
UpdateNodeAfterDeserialization();
}
[SerializeField]
MatrixAxis m_Axis;
[EnumControl("")]
MatrixAxis axis
{
get { return m_Axis; }
set
{
if (m_Axis.Equals(value))
return;
m_Axis = value;
Dirty(ModificationScope.Graph);
}
}
string GetFunctionName()
{
return string.Format("Unity_MatrixConstruction_{0}", precision);
}
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Vector4MaterialSlot(InputSlotM0Id, kInputSlotM0Name, kInputSlotM0Name, SlotType.Input, Vector4.zero));
AddSlot(new Vector4MaterialSlot(InputSlotM1Id, kInputSlotM1Name, kInputSlotM1Name, SlotType.Input, Vector4.zero));
AddSlot(new Vector4MaterialSlot(InputSlotM2Id, kInputSlotM2Name, kInputSlotM2Name, SlotType.Input, Vector4.zero));
AddSlot(new Vector4MaterialSlot(InputSlotM3Id, kInputSlotM3Name, kInputSlotM3Name, SlotType.Input, Vector4.zero));
AddSlot(new Matrix4MaterialSlot(Output4x4SlotId, kOutput4x4SlotName, kOutput4x4SlotName, SlotType.Output));
AddSlot(new Matrix3MaterialSlot(Output3x3SlotId, kOutput3x3SlotName, kOutput3x3SlotName, SlotType.Output));
AddSlot(new Matrix2MaterialSlot(Output2x2SlotId, kOutput2x2SlotName, kOutput2x2SlotName, SlotType.Output));
RemoveSlotsNameNotMatching(new int[] { InputSlotM0Id, InputSlotM1Id, InputSlotM2Id, InputSlotM3Id, Output4x4SlotId, Output3x3SlotId, Output2x2SlotId });
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var sb = new ShaderStringBuilder();
var inputM0Value = GetSlotValue(InputSlotM0Id, generationMode);
var inputM1Value = GetSlotValue(InputSlotM1Id, generationMode);
var inputM2Value = GetSlotValue(InputSlotM2Id, generationMode);
var inputM3Value = GetSlotValue(InputSlotM3Id, generationMode);
sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(Output4x4SlotId).concreteValueType), GetVariableNameForSlot(Output4x4SlotId));
sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(Output3x3SlotId).concreteValueType), GetVariableNameForSlot(Output3x3SlotId));
sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(Output2x2SlotId).concreteValueType), GetVariableNameForSlot(Output2x2SlotId));
sb.AppendLine("{0}({1}, {2}, {3}, {4}, {5}, {6}, {7});",
GetFunctionName(),
inputM0Value,
inputM1Value,
inputM2Value,
inputM3Value,
GetVariableNameForSlot(Output4x4SlotId),
GetVariableNameForSlot(Output3x3SlotId),
GetVariableNameForSlot(Output2x2SlotId));
visitor.AddShaderChunk(sb.ToString(), false);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{
s.AppendLine("void {0} ({1} M0, {1} M1, {1} M2, {1} M3, out {2} Out4x4, out {3} Out3x3, out {4} Out2x2)",
GetFunctionName(),
FindInputSlot<MaterialSlot>(InputSlotM0Id).concreteValueType.ToString(precision),
FindOutputSlot<MaterialSlot>(Output4x4SlotId).concreteValueType.ToString(precision),
FindOutputSlot<MaterialSlot>(Output3x3SlotId).concreteValueType.ToString(precision),
FindOutputSlot<MaterialSlot>(Output2x2SlotId).concreteValueType.ToString(precision));
using (s.BlockScope())
{
switch(m_Axis)
{
case MatrixAxis.Column:
s.AppendLine("Out4x4 = {0}4x4(M0.x, M1.x, M2.x, M3.x, M0.y, M1.y, M2.y, M3.y, M0.z, M1.z, M2.z, M3.z, M0.w, M1.w, M2.w, M3.w);", precision);
s.AppendLine("Out3x3 = {0}3x3(M0.x, M1.x, M2.x, M0.y, M1.y, M2.y, M0.z, M1.z, M2.z);", precision);
s.AppendLine("Out2x2 = {0}2x2(M0.x, M1.x, M0.y, M1.y);", precision);
break;
default:
s.AppendLine("Out4x4 = {0}4x4(M0.x, M0.y, M0.z, M0.w, M1.x, M1.y, M1.z, M1.w, M2.x, M2.y, M2.z, M2.w, M3.x, M3.y, M3.z, M3.w);", precision);
s.AppendLine("Out3x3 = {0}3x3(M0.x, M0.y, M0.z, M1.x, M1.y, M1.z, M2.x, M2.y, M2.z);", precision);
s.AppendLine("Out2x2 = {0}2x2(M0.x, M0.y, M1.x, M1.y);", precision);
break;
}
}
});
}
}
}

8
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixConstructionNode.cs.meta


fileFormatVersion: 2
guid: 7f3857db61fc34eaabd871901ae5a2b6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

31
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixDeterminantNode.cs


using System.Reflection;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Title("Math", "Matrix", "Matrix Determinant")]
public class MatrixDeterminantNode : CodeFunctionNode
{
public MatrixDeterminantNode()
{
name = "Matrix Determinant";
}
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_MatrixDeterminant", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_MatrixDeterminant(
[Slot(0, Binding.None)] DynamicDimensionMatrix In,
[Slot(1, Binding.None)] out Vector1 Out)
{
return
@"
{
Out = determinant(In);
}
";
}
}
}

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixDeterminantNode.cs.meta


fileFormatVersion: 2
guid: 41d69945fb0fa45ec8e14292dfb9074d
timeCreated: 1495542985
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

278
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Controls;
namespace UnityEditor.ShaderGraph
{
public enum MatrixAxis
{
Row,
Column
}
[Title("Math", "Matrix", "Matrix Split")]
public class MatrixSplitNode : AbstractMaterialNode, IGeneratesBodyCode
{
const string kInputSlotName = "In";
const string kOutputSlotM0Name = "M0";
const string kOutputSlotM1Name = "M1";
const string kOutputSlotM2Name = "M2";
const string kOutputSlotM3Name = "M3";
public const int InputSlotId = 0;
public const int OutputSlotRId = 1;
public const int OutputSlotGId = 2;
public const int OutputSlotBId = 3;
public const int OutputSlotAId = 4;
public MatrixSplitNode()
{
name = "Matrix Split";
UpdateNodeAfterDeserialization();
}
[SerializeField]
MatrixAxis m_Axis;
[EnumControl("")]
MatrixAxis axis
{
get { return m_Axis; }
set
{
if (m_Axis.Equals(value))
return;
m_Axis = value;
Dirty(ModificationScope.Graph);
}
}
static string[] s_ComponentList = new string[4] { "r", "g", "b", "a" };
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new DynamicMatrixMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotRId, kOutputSlotM0Name, kOutputSlotM0Name, SlotType.Output, Vector4.zero));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotGId, kOutputSlotM1Name, kOutputSlotM1Name, SlotType.Output, Vector4.zero));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotBId, kOutputSlotM2Name, kOutputSlotM2Name, SlotType.Output, Vector4.zero));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotAId, kOutputSlotM3Name, kOutputSlotM3Name, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new int[] { InputSlotId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId });
}
static int[] s_OutputSlots = {OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId};
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var inputValue = GetSlotValue(InputSlotId, generationMode);
var inputSlot = FindInputSlot<MaterialSlot>(InputSlotId);
var numInputRows = 0;
bool useIndentity = false;
if (inputSlot != null)
{
numInputRows = SlotValueHelper.GetMatrixDimension(inputSlot.concreteValueType);
if (numInputRows > 4)
numInputRows = 0;
if (!owner.GetEdges(inputSlot.slotReference).Any())
{
numInputRows = 0;
useIndentity = true;
}
}
int concreteRowCount = useIndentity ? 2 : numInputRows;
for (var r = 0; r < 4; r++)
{
string outputValue;
if(r >= numInputRows)
{
outputValue = string.Format("{0}{1}(", precision, concreteRowCount);
for(int c = 0; c < concreteRowCount; c++)
{
if(c!= 0)
outputValue += ", ";
outputValue += Matrix4x4.identity.GetRow(r)[c];
}
outputValue += ")";
}
else
{
switch(m_Axis)
{
case MatrixAxis.Column:
outputValue = string.Format("{0}{1}(", precision, numInputRows);
for(int c = 0; c < numInputRows; c++)
{
if(c!= 0)
outputValue += ", ";
outputValue += string.Format("{0}[{1}].{2}", inputValue, c, s_ComponentList[r]);
}
outputValue += ")";
break;
default:
outputValue = string.Format("{0}[{1}]", inputValue, r);
break;
}
}
visitor.AddShaderChunk(string.Format("{0}{1} {2} = {3};", precision, concreteRowCount, GetVariableNameForSlot(s_OutputSlots[r]), outputValue), true);
}
}
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<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicSlots = ListPool<DynamicVectorMaterialSlot>.Get();
var dynamicMatrixInputSlotsToCompare = DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicMatrixSlots = ListPool<DynamicMatrixMaterialSlot>.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 DynamicVectorMaterialSlot)
skippedDynamicSlots.Add(inputSlot as DynamicVectorMaterialSlot);
if (inputSlot is DynamicMatrixMaterialSlot)
skippedDynamicMatrixSlots.Add(inputSlot as DynamicMatrixMaterialSlot);
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 DynamicVectorMaterialSlot)
{
dynamicInputSlotsToCompare.Add((DynamicVectorMaterialSlot)inputSlot, outputConcreteType);
continue;
}
else if (inputSlot is DynamicMatrixMaterialSlot)
{
dynamicMatrixInputSlotsToCompare.Add((DynamicMatrixMaterialSlot)inputSlot, outputConcreteType);
continue;
}
// if we have a standard connection... just check the types work!
if (!AbstractMaterialNode.ImplicitConversionExists(outputConcreteType, inputSlot.concreteValueType))
inputSlot.hasError = true;
}
// and now dynamic matrices
var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicMatrixInputSlotsToCompare.Values);
foreach (var dynamicKvP in dynamicMatrixInputSlotsToCompare)
dynamicKvP.Key.SetConcreteType(dynamicMatrixType);
foreach (var skippedSlot in skippedDynamicMatrixSlots)
skippedSlot.SetConcreteType(dynamicMatrixType);
// we can now figure out the dynamic slotType
// from here set all the
var dynamicType = SlotValueHelper.ConvertMatrixToVectorType(dynamicMatrixType);
foreach (var dynamicKvP in dynamicInputSlotsToCompare)
dynamicKvP.Key.SetConcreteType(dynamicType);
foreach (var skippedSlot in skippedDynamicSlots)
skippedSlot.SetConcreteType(dynamicType);
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 DynamicVectorMaterialSlot)
{
(outputSlot as DynamicVectorMaterialSlot).SetConcreteType(dynamicType);
continue;
}
else if (outputSlot is DynamicMatrixMaterialSlot)
{
(outputSlot as DynamicMatrixMaterialSlot).SetConcreteType(dynamicMatrixType);
continue;
}
}
isInError |= inputError;
s_TempSlots.Clear();
GetOutputSlots(s_TempSlots);
isInError |= s_TempSlots.Any(x => x.hasError);
isInError |= CalculateNodeHasError();
hasError = isInError;
if (!hasError)
{
++version;
}
ListPool<DynamicVectorMaterialSlot>.Release(skippedDynamicSlots);
DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Release(dynamicInputSlotsToCompare);
ListPool<DynamicMatrixMaterialSlot>.Release(skippedDynamicMatrixSlots);
DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Release(dynamicMatrixInputSlotsToCompare);
}
}
}

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs.meta


fileFormatVersion: 2
guid: 03599e40507c24caba0dd9b596f3b5dc
timeCreated: 1490896965
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

19
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/Slots/LabelSlotControlView.cs


using System;
using UnityEditor.Experimental.UIElements;
using UnityEditor.Graphing;
using UnityEngine;
using UnityEngine.Experimental.UIElements;
using UnityEngine.Experimental.UIElements.StyleSheets;
using Object = UnityEngine.Object;
namespace UnityEditor.ShaderGraph.Drawing.Slots
{
public class LabelSlotControlView : VisualElement
{
public LabelSlotControlView(string label)
{
var labelField = new Label (label);
Add(labelField);
}
}
}

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/Slots/LabelSlotControlView.cs.meta


fileFormatVersion: 2
guid: b7e0bdc2deb5a43aca74fd1e84c94cfa
timeCreated: 1509718979

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyByVectorNode.cs.meta


fileFormatVersion: 2
guid: ad9cec4b346abf749b3eb1730875ee5d
timeCreated: 1495542985
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyNode.cs.meta


fileFormatVersion: 2
guid: 8eb82c17970f84fc2b84d060df718533
timeCreated: 1495542985
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

106
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyByVectorNode.cs


using UnityEngine;
using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph
{
[Title("Math", "Matrix", "MultiplyMatrixByVector")]
public class MatrixMultiplyByVectorNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
{
protected const string kInputSlot1ShaderName = "Input1";
protected const string kInputSlot2ShaderName = "Input2";
protected const string kOutputSlotShaderName = "Output";
public const int InputSlot1Id = 0;
public const int InputSlot2Id = 1;
public const int OutputSlotId = 2;
public override bool hasPreview
{
get { return false; }
}
public MatrixMultiplyByVectorNode()
{
name = "MultiplyMatrixByVector";
UpdateNodeAfterDeserialization();
}
protected string GetFunctionName()
{
return "unity_matrix_multiplybyvector_" + precision;
}
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(GetInputSlot1());
AddSlot(GetInputSlot2());
AddSlot(GetOutputSlot());
RemoveSlotsNameNotMatching(validSlots);
}
protected int[] validSlots
{
get { return new[] { InputSlot1Id, InputSlot2Id, OutputSlotId }; }
}
protected MaterialSlot GetInputSlot1()
{
return new Matrix4MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input);
}
protected MaterialSlot GetInputSlot2()
{
return new Vector4MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, Vector4.zero);
}
protected MaterialSlot GetOutputSlot()
{
return new Vector4MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, Vector4.zero);
}
protected virtual string GetInputSlot1Name()
{
return "Input1";
}
protected virtual string GetInputSlot2Name()
{
return "Input2";
}
protected string GetOutputSlotName()
{
return "Output";
}
protected string GetFunctionPrototype(string arg1Name, string arg2Name)
{
return string.Format("inline {0} {1} ({2} {3}, {4} {5})", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType), GetFunctionName(), NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot1Id).concreteValueType), arg1Name, NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType), arg2Name);
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
NodeUtils.SlotConfigurationExceptionIfBadConfiguration(this, new[] { InputSlot1Id, InputSlot2Id }, new[] { OutputSlotId });
string input1Value = GetSlotValue(InputSlot1Id, generationMode);
string input2Value = GetSlotValue(InputSlot2Id, generationMode);
visitor.AddShaderChunk(string.Format("{0} {1} = {2};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType), GetVariableNameForSlot(OutputSlotId), GetFunctionCallBody(input1Value, input2Value)), true);
}
protected string GetFunctionCallBody(string input1Value, string input2Value)
{
return string.Format("{0} ({1}, {2})", GetFunctionName(), input1Value, input2Value);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{
s.AppendLine(GetFunctionPrototype("arg1", "arg2"));
using (s.BlockScope())
{
s.AppendLine("return mul(arg1, arg2);");
}
});
}
}
}

118
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixMultiplyNode.cs


using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph
{
[Title("Math", "Matrix", "MultiplyMatrix")]
public class MatrixMultiplyNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
{
protected const string kInputSlot1ShaderName = "Input1";
protected const string kInputSlot2ShaderName = "Input2";
protected const string kOutputSlotShaderName = "Output";
public const int InputSlot1Id = 0;
public const int InputSlot2Id = 1;
public const int OutputSlotId = 2;
public override bool hasPreview
{
get { return false; }
}
public MatrixMultiplyNode()
{
name = "MultiplyMatrix";
UpdateNodeAfterDeserialization();
}
protected string GetFunctionName()
{
return "unity_matrix_multiply_" + precision;
}
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(GetInputSlot1());
AddSlot(GetInputSlot2());
AddSlot(GetOutputSlot());
RemoveSlotsNameNotMatching(validSlots);
}
protected int[] validSlots
{
get { return new[] { InputSlot1Id, InputSlot2Id, OutputSlotId }; }
}
protected MaterialSlot GetInputSlot1()
{
return new Matrix4MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input);
}
protected MaterialSlot GetInputSlot2()
{
return new Matrix4MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input);
}
protected MaterialSlot GetOutputSlot()
{
return new Matrix4MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output);
}
protected virtual string GetInputSlot1Name()
{
return "Input1";
}
protected virtual string GetInputSlot2Name()
{
return "Input2";
}
protected string GetOutputSlotName()
{
return "Output";
}
protected string GetFunctionPrototype(string arg1Name, string arg2Name)
{
return string.Format("inline {0} {1} ({2} {3}, {4} {5})", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType), GetFunctionName(), NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot1Id).concreteValueType), arg1Name, NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType), arg2Name);
}
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
NodeUtils.SlotConfigurationExceptionIfBadConfiguration(this, new[] { InputSlot1Id, InputSlot2Id }, new[] { OutputSlotId });
string input1Value = GetSlotValue(InputSlot1Id, generationMode);
string input2Value = GetSlotValue(InputSlot2Id, generationMode);
visitor.AddShaderChunk(string.Format("{0} {1} = {2};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputSlot2Id).concreteValueType), GetVariableNameForSlot(OutputSlotId), GetFunctionCallBody(input1Value, input2Value)), true);
}
protected string GetFunctionCallBody(string input1Value, string input2Value)
{
return GetFunctionName() + " (" + input1Value + ", " + input2Value + ")";
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return mul(arg1, arg2);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
{
registry.ProvideFunction(GetFunctionName(), s =>
{
s.AppendLine(GetFunctionPrototype("arg1", "arg2"));
using (s.BlockScope())
{
s.AppendLine("return mul(arg1, arg2);");
}
});
}
}
}
正在加载...
取消
保存