SwizzleNode.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using UnityEditor.Graphing;
  5. using UnityEditor.ShaderGraph.Drawing.Controls;
  6. using UnityEditor.ShaderGraph.Internal;
  7. using UnityEngine;
  8. namespace UnityEditor.ShaderGraph
  9. {
  10. [Title("Channel", "Swizzle")]
  11. class SwizzleNode : AbstractMaterialNode, IGeneratesBodyCode
  12. {
  13. public SwizzleNode()
  14. {
  15. name = "Swizzle";
  16. UpdateNodeAfterDeserialization();
  17. }
  18. const int InputSlotId = 0;
  19. const int OutputSlotId = 1;
  20. const string kInputSlotName = "In";
  21. const string kOutputSlotName = "Out";
  22. public override bool hasPreview
  23. {
  24. get { return true; }
  25. }
  26. public sealed override void UpdateNodeAfterDeserialization()
  27. {
  28. AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector4.zero));
  29. AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
  30. RemoveSlotsNameNotMatching(new[] { InputSlotId, OutputSlotId });
  31. }
  32. static Dictionary<TextureChannel, string> s_ComponentList = new Dictionary<TextureChannel, string>
  33. {
  34. {TextureChannel.Red, "r" },
  35. {TextureChannel.Green, "g" },
  36. {TextureChannel.Blue, "b" },
  37. {TextureChannel.Alpha, "a" },
  38. };
  39. [SerializeField]
  40. TextureChannel m_RedChannel;
  41. [ChannelEnumControl("Red Out")]
  42. public TextureChannel redChannel
  43. {
  44. get { return m_RedChannel; }
  45. set
  46. {
  47. if (m_RedChannel == value)
  48. return;
  49. m_RedChannel = value;
  50. Dirty(ModificationScope.Node);
  51. }
  52. }
  53. [SerializeField]
  54. TextureChannel m_GreenChannel;
  55. [ChannelEnumControl("Green Out")]
  56. public TextureChannel greenChannel
  57. {
  58. get { return m_GreenChannel; }
  59. set
  60. {
  61. if (m_GreenChannel == value)
  62. return;
  63. m_GreenChannel = value;
  64. Dirty(ModificationScope.Node);
  65. }
  66. }
  67. [SerializeField]
  68. TextureChannel m_BlueChannel;
  69. [ChannelEnumControl("Blue Out")]
  70. public TextureChannel blueChannel
  71. {
  72. get { return m_BlueChannel; }
  73. set
  74. {
  75. if (m_BlueChannel == value)
  76. return;
  77. m_BlueChannel = value;
  78. Dirty(ModificationScope.Node);
  79. }
  80. }
  81. [SerializeField]
  82. TextureChannel m_AlphaChannel;
  83. [ChannelEnumControl("Alpha Out")]
  84. public TextureChannel alphaChannel
  85. {
  86. get { return m_AlphaChannel; }
  87. set
  88. {
  89. if (m_AlphaChannel == value)
  90. return;
  91. m_AlphaChannel = value;
  92. Dirty(ModificationScope.Node);
  93. }
  94. }
  95. void ValidateChannelCount()
  96. {
  97. var channelCount = SlotValueHelper.GetChannelCount(FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType);
  98. if ((int)redChannel >= channelCount)
  99. redChannel = TextureChannel.Red;
  100. if ((int)greenChannel >= channelCount)
  101. greenChannel = TextureChannel.Red;
  102. if ((int)blueChannel >= channelCount)
  103. blueChannel = TextureChannel.Red;
  104. if ((int)alphaChannel >= channelCount)
  105. alphaChannel = TextureChannel.Red;
  106. }
  107. public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
  108. {
  109. ValidateChannelCount();
  110. var outputSlotType = FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString();
  111. var outputName = GetVariableNameForSlot(OutputSlotId);
  112. var inputValue = GetSlotValue(InputSlotId, generationMode);
  113. var inputValueType = FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType;
  114. if (inputValueType == ConcreteSlotValueType.Vector1)
  115. sb.AppendLine(string.Format("{0} {1} = {2};", outputSlotType, outputName, inputValue));
  116. else if (generationMode == GenerationMode.ForReals)
  117. sb.AppendLine("{0} {1} = {2}.{3}{4}{5}{6};",
  118. outputSlotType,
  119. outputName,
  120. inputValue,
  121. s_ComponentList[m_RedChannel].ToString(CultureInfo.InvariantCulture),
  122. s_ComponentList[m_GreenChannel].ToString(CultureInfo.InvariantCulture),
  123. s_ComponentList[m_BlueChannel].ToString(CultureInfo.InvariantCulture),
  124. s_ComponentList[m_AlphaChannel].ToString(CultureInfo.InvariantCulture));
  125. else
  126. sb.AppendLine("{0} {1} = {0}({3}[((int){2} >> 0) & 3], {3}[((int){2} >> 2) & 3], {3}[((int){2} >> 4) & 3], {3}[((int){2} >> 6) & 3]);", outputSlotType, outputName, GetVariableNameForNode(), inputValue);
  127. }
  128. public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
  129. {
  130. base.CollectShaderProperties(properties, generationMode);
  131. if (generationMode != GenerationMode.Preview)
  132. return;
  133. properties.AddShaderProperty(new Vector1ShaderProperty
  134. {
  135. overrideReferenceName = GetVariableNameForNode(),
  136. generatePropertyBlock = false
  137. });
  138. }
  139. public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
  140. {
  141. base.CollectPreviewMaterialProperties(properties);
  142. // Encode swizzle values into an integer
  143. var value = ((int)redChannel) | ((int)greenChannel << 2) | ((int)blueChannel << 4) | ((int)alphaChannel << 6);
  144. properties.Add(new PreviewProperty(PropertyType.Vector1)
  145. {
  146. name = GetVariableNameForNode(),
  147. floatValue = value
  148. });
  149. }
  150. }
  151. }