A game about forced loneliness, made by TACStudios
1using System;
2using UnityEngine;
3using UnityEditor.Graphing;
4using UnityEditor.ShaderGraph.Drawing.Controls;
5
6namespace UnityEditor.ShaderGraph
7{
8 [Title("Math", "Matrix", "Matrix Construction")]
9 class MatrixConstructionNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
10 {
11 const string kInputSlotM0Name = "M0";
12 const string kInputSlotM1Name = "M1";
13 const string kInputSlotM2Name = "M2";
14 const string kInputSlotM3Name = "M3";
15 const string kOutput4x4SlotName = "4x4";
16 const string kOutput3x3SlotName = "3x3";
17 const string kOutput2x2SlotName = "2x2";
18
19 public const int InputSlotM0Id = 0;
20 public const int InputSlotM1Id = 1;
21 public const int InputSlotM2Id = 2;
22 public const int InputSlotM3Id = 3;
23 public const int Output4x4SlotId = 4;
24 public const int Output3x3SlotId = 5;
25 public const int Output2x2SlotId = 6;
26
27 public MatrixConstructionNode()
28 {
29 name = "Matrix Construction";
30 UpdateNodeAfterDeserialization();
31 }
32
33 [SerializeField]
34 MatrixAxis m_Axis;
35
36 [EnumControl("")]
37 MatrixAxis axis
38 {
39 get { return m_Axis; }
40 set
41 {
42 if (m_Axis.Equals(value))
43 return;
44 m_Axis = value;
45 Dirty(ModificationScope.Graph);
46 }
47 }
48
49 string GetFunctionName()
50 {
51 return $"Unity_MatrixConstruction_{axis}_$precision";
52 }
53
54 public sealed override void UpdateNodeAfterDeserialization()
55 {
56 AddSlot(new Vector4MaterialSlot(InputSlotM0Id, kInputSlotM0Name, kInputSlotM0Name, SlotType.Input, Vector4.zero));
57 AddSlot(new Vector4MaterialSlot(InputSlotM1Id, kInputSlotM1Name, kInputSlotM1Name, SlotType.Input, Vector4.zero));
58 AddSlot(new Vector4MaterialSlot(InputSlotM2Id, kInputSlotM2Name, kInputSlotM2Name, SlotType.Input, Vector4.zero));
59 AddSlot(new Vector4MaterialSlot(InputSlotM3Id, kInputSlotM3Name, kInputSlotM3Name, SlotType.Input, Vector4.zero));
60 AddSlot(new Matrix4MaterialSlot(Output4x4SlotId, kOutput4x4SlotName, kOutput4x4SlotName, SlotType.Output));
61 AddSlot(new Matrix3MaterialSlot(Output3x3SlotId, kOutput3x3SlotName, kOutput3x3SlotName, SlotType.Output));
62 AddSlot(new Matrix2MaterialSlot(Output2x2SlotId, kOutput2x2SlotName, kOutput2x2SlotName, SlotType.Output));
63 RemoveSlotsNameNotMatching(new int[] { InputSlotM0Id, InputSlotM1Id, InputSlotM2Id, InputSlotM3Id, Output4x4SlotId, Output3x3SlotId, Output2x2SlotId });
64 }
65
66 public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
67 {
68 var inputM0Value = GetSlotValue(InputSlotM0Id, generationMode);
69 var inputM1Value = GetSlotValue(InputSlotM1Id, generationMode);
70 var inputM2Value = GetSlotValue(InputSlotM2Id, generationMode);
71 var inputM3Value = GetSlotValue(InputSlotM3Id, generationMode);
72
73 sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(Output4x4SlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(Output4x4SlotId));
74 sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(Output3x3SlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(Output3x3SlotId));
75 sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(Output2x2SlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(Output2x2SlotId));
76 sb.AppendLine("{0}({1}, {2}, {3}, {4}, {5}, {6}, {7});",
77 GetFunctionName(),
78 inputM0Value,
79 inputM1Value,
80 inputM2Value,
81 inputM3Value,
82 GetVariableNameForSlot(Output4x4SlotId),
83 GetVariableNameForSlot(Output3x3SlotId),
84 GetVariableNameForSlot(Output2x2SlotId));
85 }
86
87 public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
88 {
89 registry.ProvideFunction(GetFunctionName(), s =>
90 {
91 s.AppendLine("void {0} ({1} M0, {1} M1, {1} M2, {1} M3, out {2} Out4x4, out {3} Out3x3, out {4} Out2x2)",
92 GetFunctionName(),
93 FindInputSlot<MaterialSlot>(InputSlotM0Id).concreteValueType.ToShaderString(),
94 FindOutputSlot<MaterialSlot>(Output4x4SlotId).concreteValueType.ToShaderString(),
95 FindOutputSlot<MaterialSlot>(Output3x3SlotId).concreteValueType.ToShaderString(),
96 FindOutputSlot<MaterialSlot>(Output2x2SlotId).concreteValueType.ToShaderString());
97 using (s.BlockScope())
98 {
99 switch (m_Axis)
100 {
101 case MatrixAxis.Column:
102 s.AppendLine("Out4x4 = $precision4x4(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);");
103 s.AppendLine("Out3x3 = $precision3x3(M0.x, M1.x, M2.x, M0.y, M1.y, M2.y, M0.z, M1.z, M2.z);");
104 s.AppendLine("Out2x2 = $precision2x2(M0.x, M1.x, M0.y, M1.y);");
105 break;
106 default:
107 s.AppendLine("Out4x4 = $precision4x4(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);");
108 s.AppendLine("Out3x3 = $precision3x3(M0.x, M0.y, M0.z, M1.x, M1.y, M1.z, M2.x, M2.y, M2.z);");
109 s.AppendLine("Out2x2 = $precision2x2(M0.x, M0.y, M1.x, M1.y);");
110 break;
111 }
112 }
113 });
114 }
115 }
116}