MatrixConstructionNode.cs 5.8 KB

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