설명 없음
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BlockNode.cs 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. using System;
  2. using System.Linq;
  3. using UnityEngine;
  4. using UnityEditor.Graphing;
  5. using UnityEditor.ShaderGraph.Internal;
  6. using System.Collections.Generic;
  7. using System.Text.RegularExpressions;
  8. using UnityEngine.Rendering.ShaderGraph;
  9. namespace UnityEditor.ShaderGraph
  10. {
  11. class BlockNode : AbstractMaterialNode
  12. , IMayRequireNormal
  13. , IMayRequireTangent
  14. , IMayRequireBitangent
  15. , IMayRequireMeshUV
  16. , IMayRequireScreenPosition
  17. , IMayRequireNDCPosition
  18. , IMayRequirePixelPosition
  19. , IMayRequireViewDirection
  20. , IMayRequirePosition
  21. , IMayRequirePositionPredisplacement
  22. , IMayRequireVertexColor
  23. {
  24. [SerializeField]
  25. string m_SerializedDescriptor;
  26. [NonSerialized]
  27. ContextData m_ContextData;
  28. [NonSerialized]
  29. BlockFieldDescriptor m_Descriptor;
  30. public override bool canCutNode => false;
  31. public override bool canCopyNode => false;
  32. public override string documentationURL => Documentation.GetPageLink("Block-Node");
  33. // Because the GraphData is deserialized after its child elements
  34. // the descriptor list is not built (and owner is not set)
  35. // at the time of node deserialization
  36. // Therefore we need to deserialize this element at GraphData.OnAfterDeserialize
  37. public string serializedDescriptor => m_SerializedDescriptor;
  38. public ContextData contextData
  39. {
  40. get => m_ContextData;
  41. set => m_ContextData = value;
  42. }
  43. public int index => contextData.blocks.IndexOf(this);
  44. public BlockFieldDescriptor descriptor
  45. {
  46. get => m_Descriptor;
  47. set => m_Descriptor = value;
  48. }
  49. const string k_CustomBlockDefaultName = "CustomInterpolator";
  50. internal enum CustomBlockType { Float = 1, Vector2 = 2, Vector3 = 3, Vector4 = 4 }
  51. internal bool isCustomBlock { get => m_Descriptor?.isCustom ?? false; }
  52. internal string customName
  53. {
  54. get => m_Descriptor.name;
  55. set => OnCustomBlockFieldModified(value, customWidth);
  56. }
  57. internal CustomBlockType customWidth
  58. {
  59. get => (CustomBlockType)ControlToWidth(m_Descriptor.control);
  60. set => OnCustomBlockFieldModified(customName, value);
  61. }
  62. public void Init(BlockFieldDescriptor fieldDescriptor)
  63. {
  64. m_Descriptor = fieldDescriptor;
  65. // custom blocks can be "copied" via a custom Field Descriptor, we'll use the CI name instead though.
  66. name = !isCustomBlock
  67. ? $"{fieldDescriptor.tag}.{fieldDescriptor.name}"
  68. : $"{BlockFields.VertexDescription.name}.{k_CustomBlockDefaultName}";
  69. // TODO: This exposes the MaterialSlot API
  70. // TODO: This needs to be removed but is currently required by HDRP for DiffusionProfileInputMaterialSlot
  71. if (m_Descriptor is CustomSlotBlockFieldDescriptor customSlotDescriptor)
  72. {
  73. var newSlot = customSlotDescriptor.createSlot();
  74. AddSlot(newSlot);
  75. RemoveSlotsNameNotMatching(new int[] { 0 });
  76. return;
  77. }
  78. AddSlotFromControlType();
  79. }
  80. internal void InitCustomDefault()
  81. {
  82. Init(MakeCustomBlockField(k_CustomBlockDefaultName, CustomBlockType.Vector4));
  83. }
  84. private void AddSlotFromControlType(bool attemptToModifyExisting = true)
  85. {
  86. // TODO: this should really just use callbacks like the CustomSlotBlockFieldDescriptor. then we wouldn't need this switch to make a copy
  87. var stageCapability = m_Descriptor.shaderStage.GetShaderStageCapability();
  88. switch (descriptor.control)
  89. {
  90. case PositionControl positionControl:
  91. AddSlot(new PositionMaterialSlot(0, descriptor.displayName, descriptor.name, positionControl.space, stageCapability), attemptToModifyExisting);
  92. break;
  93. case NormalControl normalControl:
  94. AddSlot(new NormalMaterialSlot(0, descriptor.displayName, descriptor.name, normalControl.space, stageCapability), attemptToModifyExisting);
  95. break;
  96. case TangentControl tangentControl:
  97. AddSlot(new TangentMaterialSlot(0, descriptor.displayName, descriptor.name, tangentControl.space, stageCapability), attemptToModifyExisting);
  98. break;
  99. case VertexColorControl vertexColorControl:
  100. AddSlot(new VertexColorMaterialSlot(0, descriptor.displayName, descriptor.name, stageCapability), attemptToModifyExisting);
  101. break;
  102. case ColorControl colorControl:
  103. var colorMode = colorControl.hdr ? ColorMode.HDR : ColorMode.Default;
  104. AddSlot(new ColorRGBMaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, colorControl.value, colorMode, stageCapability), attemptToModifyExisting);
  105. break;
  106. case ColorRGBAControl colorRGBAControl:
  107. AddSlot(new ColorRGBAMaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, colorRGBAControl.value, stageCapability), attemptToModifyExisting);
  108. break;
  109. case FloatControl floatControl:
  110. AddSlot(new Vector1MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, floatControl.value, stageCapability), attemptToModifyExisting);
  111. break;
  112. case Vector2Control vector2Control:
  113. AddSlot(new Vector2MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, vector2Control.value, stageCapability), attemptToModifyExisting);
  114. break;
  115. case Vector3Control vector3Control:
  116. AddSlot(new Vector3MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, vector3Control.value, stageCapability), attemptToModifyExisting);
  117. break;
  118. case Vector4Control vector4Control:
  119. AddSlot(new Vector4MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, vector4Control.value, stageCapability), attemptToModifyExisting);
  120. break;
  121. }
  122. RemoveSlotsNameNotMatching(new int[] { 0 });
  123. }
  124. public override string GetVariableNameForNode()
  125. {
  126. // Temporary block nodes have temporary guids that cannot be used to set preview data
  127. // Since each block is unique anyway we just omit the guid
  128. return NodeUtils.GetHLSLSafeName(name);
  129. }
  130. public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
  131. {
  132. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  133. return NeededCoordinateSpace.None;
  134. if (m_Descriptor.control == null)
  135. return NeededCoordinateSpace.None;
  136. var requirements = m_Descriptor.control.GetRequirements();
  137. return requirements.requiresNormal;
  138. }
  139. public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
  140. {
  141. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  142. return NeededCoordinateSpace.None;
  143. if (m_Descriptor.control == null)
  144. return NeededCoordinateSpace.None;
  145. var requirements = m_Descriptor.control.GetRequirements();
  146. return requirements.requiresViewDir;
  147. }
  148. public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
  149. {
  150. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  151. return NeededCoordinateSpace.None;
  152. if (m_Descriptor.control == null)
  153. return NeededCoordinateSpace.None;
  154. var requirements = m_Descriptor.control.GetRequirements();
  155. return requirements.requiresPosition;
  156. }
  157. public NeededCoordinateSpace RequiresPositionPredisplacement(ShaderStageCapability stageCapability)
  158. {
  159. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  160. return NeededCoordinateSpace.None;
  161. if (m_Descriptor.control == null)
  162. return NeededCoordinateSpace.None;
  163. var requirements = m_Descriptor.control.GetRequirements();
  164. return requirements.requiresPositionPredisplacement;
  165. }
  166. public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
  167. {
  168. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  169. return NeededCoordinateSpace.None;
  170. if (m_Descriptor.control == null)
  171. return NeededCoordinateSpace.None;
  172. var requirements = m_Descriptor.control.GetRequirements();
  173. return requirements.requiresTangent;
  174. }
  175. public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
  176. {
  177. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  178. return NeededCoordinateSpace.None;
  179. if (m_Descriptor.control == null)
  180. return NeededCoordinateSpace.None;
  181. var requirements = m_Descriptor.control.GetRequirements();
  182. return requirements.requiresBitangent;
  183. }
  184. public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
  185. {
  186. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  187. return false;
  188. if (m_Descriptor.control == null)
  189. return false;
  190. var requirements = m_Descriptor.control.GetRequirements();
  191. return requirements.requiresMeshUVs.Contains(channel);
  192. }
  193. public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
  194. {
  195. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  196. return false;
  197. if (m_Descriptor.control == null)
  198. return false;
  199. var requirements = m_Descriptor.control.GetRequirements();
  200. return requirements.requiresScreenPosition;
  201. }
  202. public bool RequiresNDCPosition(ShaderStageCapability stageCapability)
  203. {
  204. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  205. return false;
  206. if (m_Descriptor.control == null)
  207. return false;
  208. var requirements = m_Descriptor.control.GetRequirements();
  209. return requirements.requiresNDCPosition;
  210. }
  211. public bool RequiresPixelPosition(ShaderStageCapability stageCapability)
  212. {
  213. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  214. return false;
  215. if (m_Descriptor.control == null)
  216. return false;
  217. var requirements = m_Descriptor.control.GetRequirements();
  218. return requirements.requiresPixelPosition;
  219. }
  220. public bool RequiresVertexColor(ShaderStageCapability stageCapability)
  221. {
  222. if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
  223. return false;
  224. if (m_Descriptor.control == null)
  225. return false;
  226. var requirements = m_Descriptor.control.GetRequirements();
  227. return requirements.requiresVertexColor;
  228. }
  229. private void OnCustomBlockFieldModified(string name, CustomBlockType width)
  230. {
  231. if (!isCustomBlock)
  232. {
  233. Debug.LogWarning(String.Format("{0} is not a custom interpolator.", this.name));
  234. return;
  235. }
  236. m_Descriptor = MakeCustomBlockField(name, width);
  237. // TODO: Preserve the original slot's value and try to reapply after the slot is updated.
  238. AddSlotFromControlType(false);
  239. owner?.ValidateGraph();
  240. }
  241. public override void OnBeforeSerialize()
  242. {
  243. base.OnBeforeSerialize();
  244. if (descriptor != null)
  245. {
  246. if (isCustomBlock)
  247. {
  248. int width = ControlToWidth(m_Descriptor.control);
  249. m_SerializedDescriptor = $"{m_Descriptor.tag}.{m_Descriptor.name}#{width}";
  250. }
  251. else
  252. {
  253. m_SerializedDescriptor = $"{m_Descriptor.tag}.{m_Descriptor.name}";
  254. }
  255. }
  256. }
  257. public override void OnAfterDeserialize()
  258. {
  259. // TODO: Go find someone to tell @esme not to do this.
  260. if (m_SerializedDescriptor.Contains("#"))
  261. {
  262. string descName = k_CustomBlockDefaultName;
  263. CustomBlockType descWidth = CustomBlockType.Vector4;
  264. var descTag = BlockFields.VertexDescription.name;
  265. name = $"{descTag}.{descName}";
  266. var wsplit = m_SerializedDescriptor.Split(new char[] { '#', '.' });
  267. try
  268. {
  269. descWidth = (CustomBlockType)int.Parse(wsplit[2]);
  270. }
  271. catch
  272. {
  273. Debug.LogWarning(String.Format("Bad width found while deserializing custom interpolator {0}, defaulting to 4.", m_SerializedDescriptor));
  274. descWidth = CustomBlockType.Vector4;
  275. }
  276. IControl control;
  277. try { control = (IControl)FindSlot<MaterialSlot>(0).InstantiateControl(); }
  278. catch { control = WidthToControl((int)descWidth); }
  279. descName = NodeUtils.ConvertToValidHLSLIdentifier(wsplit[1]);
  280. m_Descriptor = new BlockFieldDescriptor(descTag, descName, "", control, ShaderStage.Vertex, isCustom: true);
  281. }
  282. }
  283. #region CustomInterpolatorHelpers
  284. private static BlockFieldDescriptor MakeCustomBlockField(string name, CustomBlockType width)
  285. {
  286. name = NodeUtils.ConvertToValidHLSLIdentifier(name);
  287. var referenceName = name;
  288. var define = "";
  289. IControl control = WidthToControl((int)width);
  290. var tag = BlockFields.VertexDescription.name;
  291. return new BlockFieldDescriptor(tag, referenceName, define, control, ShaderStage.Vertex, isCustom: true);
  292. }
  293. private static IControl WidthToControl(int width)
  294. {
  295. switch (width)
  296. {
  297. case 1: return new FloatControl(default(float));
  298. case 2: return new Vector2Control(default(Vector2));
  299. case 3: return new Vector3Control(default(Vector3));
  300. case 4: return new Vector4Control(default(Vector4));
  301. default: return null;
  302. }
  303. }
  304. private static int ControlToWidth(IControl control)
  305. {
  306. switch (control)
  307. {
  308. case FloatControl a: return 1;
  309. case Vector2Control b: return 2;
  310. case Vector3Control c: return 3;
  311. case Vector4Control d: return 4;
  312. default: return -1;
  313. }
  314. }
  315. #endregion
  316. }
  317. }