No Description
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.

ShaderKeyword.cs 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEditor.ShaderGraph.Internal;
  6. using UnityEngine.Serialization;
  7. namespace UnityEditor.ShaderGraph
  8. {
  9. [Serializable]
  10. class ShaderKeyword : ShaderInput
  11. {
  12. public const string kVariantLimitWarning = "Graph is generating too many variants. Either delete Keywords, reduce Keyword variants or increase the Shader Variant Limit in Preferences > Shader Graph.";
  13. public ShaderKeyword()
  14. {
  15. }
  16. public ShaderKeyword(KeywordType keywordType)
  17. {
  18. this.displayName = keywordType.ToString();
  19. this.keywordType = keywordType;
  20. // Add sensible default entries for Enum type
  21. if (keywordType == KeywordType.Enum)
  22. {
  23. m_Entries = new List<KeywordEntry>();
  24. m_Entries.Add(new KeywordEntry(1, "A", "A"));
  25. m_Entries.Add(new KeywordEntry(2, "B", "B"));
  26. m_Entries.Add(new KeywordEntry(3, "C", "C"));
  27. }
  28. }
  29. public static ShaderKeyword CreateBuiltInKeyword(KeywordDescriptor descriptor)
  30. {
  31. if (descriptor.entries != null)
  32. {
  33. for (int i = 0; i < descriptor.entries.Length; i++)
  34. {
  35. if (descriptor.entries[i].id == -1)
  36. descriptor.entries[i].id = i + 1;
  37. }
  38. }
  39. return new ShaderKeyword()
  40. {
  41. isBuiltIn = true,
  42. displayName = descriptor.displayName,
  43. overrideReferenceName = descriptor.referenceName,
  44. keywordType = descriptor.type,
  45. keywordDefinition = descriptor.definition,
  46. keywordScope = descriptor.scope,
  47. value = descriptor.value,
  48. entries = descriptor.entries.ToList(),
  49. };
  50. }
  51. [SerializeField]
  52. private KeywordType m_KeywordType = KeywordType.Boolean;
  53. public KeywordType keywordType
  54. {
  55. get => m_KeywordType;
  56. set => m_KeywordType = value;
  57. }
  58. [SerializeField]
  59. private KeywordDefinition m_KeywordDefinition = KeywordDefinition.ShaderFeature;
  60. public KeywordDefinition keywordDefinition
  61. {
  62. get => m_KeywordDefinition;
  63. set => m_KeywordDefinition = value;
  64. }
  65. [SerializeField]
  66. private KeywordScope m_KeywordScope = KeywordScope.Local;
  67. public KeywordScope keywordScope
  68. {
  69. get => m_KeywordScope;
  70. set => m_KeywordScope = value;
  71. }
  72. [SerializeField]
  73. private KeywordShaderStage m_KeywordStages = KeywordShaderStage.All;
  74. public KeywordShaderStage keywordStages
  75. {
  76. get => m_KeywordStages;
  77. set => m_KeywordStages = value;
  78. }
  79. [SerializeField]
  80. private List<KeywordEntry> m_Entries;
  81. public List<KeywordEntry> entries
  82. {
  83. get => m_Entries;
  84. set => m_Entries = value;
  85. }
  86. [SerializeField]
  87. private int m_Value;
  88. public int value
  89. {
  90. get => m_Value;
  91. set => m_Value = value;
  92. }
  93. [SerializeField]
  94. private bool m_IsEditable = true; // this serializes !isBuiltIn
  95. public bool isBuiltIn
  96. {
  97. get => !m_IsEditable;
  98. set => m_IsEditable = !value;
  99. }
  100. internal override bool isCustomSlotAllowed => false;
  101. internal override bool isExposable => !isBuiltIn && (keywordDefinition != KeywordDefinition.Predefined);
  102. internal override bool isRenamable => !isBuiltIn;
  103. internal override ConcreteSlotValueType concreteShaderValueType => keywordType.ToConcreteSlotValueType();
  104. public override string GetOldDefaultReferenceName()
  105. {
  106. // _ON suffix is required for exposing Boolean type to Material
  107. var suffix = string.Empty;
  108. if (keywordType == KeywordType.Boolean)
  109. {
  110. suffix = "_ON";
  111. }
  112. return $"{keywordType.ToString()}_{objectId}{suffix}".ToUpper();
  113. }
  114. public void AppendPropertyBlockStrings(ShaderStringBuilder builder)
  115. {
  116. if (isExposed)
  117. {
  118. switch (keywordType)
  119. {
  120. case KeywordType.Enum:
  121. string enumTagString = $"[KeywordEnum({string.Join(", ", entries.Select(x => x.displayName))})]";
  122. builder.AppendLine($"{enumTagString}{referenceName}(\"{displayName}\", Float) = {value}");
  123. break;
  124. case KeywordType.Boolean:
  125. if (referenceName.EndsWith("_ON"))
  126. builder.AppendLine($"[Toggle]{referenceName.Remove(referenceName.Length - 3, 3)}(\"{displayName}\", Float) = {value}");
  127. else
  128. builder.AppendLine($"[Toggle({referenceName})]{referenceName}(\"{displayName}\", Float) = {value}");
  129. break;
  130. default:
  131. break;
  132. }
  133. }
  134. }
  135. public void AppendKeywordDeclarationStrings(ShaderStringBuilder builder)
  136. {
  137. if (keywordDefinition != KeywordDefinition.Predefined)
  138. {
  139. if (keywordType == KeywordType.Boolean)
  140. KeywordUtil.GenerateBooleanKeywordPragmaStrings(referenceName, keywordDefinition, keywordScope, keywordStages, str => builder.AppendLine(str));
  141. else
  142. KeywordUtil.GenerateEnumKeywordPragmaStrings(referenceName, keywordDefinition, keywordScope, keywordStages, entries, str => builder.AppendLine(str));
  143. }
  144. }
  145. public string GetKeywordPreviewDeclarationString()
  146. {
  147. switch (keywordType)
  148. {
  149. case KeywordType.Boolean:
  150. return value == 1 ? $"#define {referenceName}" : string.Empty;
  151. case KeywordType.Enum:
  152. return $"#define {referenceName}_{entries[value].referenceName}";
  153. default:
  154. throw new ArgumentOutOfRangeException();
  155. }
  156. }
  157. internal override ShaderInput Copy()
  158. {
  159. // Keywords copy reference name
  160. // This is because keywords are copied between graphs
  161. // When copying dependent nodes
  162. return new ShaderKeyword()
  163. {
  164. displayName = displayName,
  165. value = value,
  166. isBuiltIn = isBuiltIn,
  167. keywordType = keywordType,
  168. keywordDefinition = keywordDefinition,
  169. keywordScope = keywordScope,
  170. entries = entries,
  171. keywordStages = keywordStages,
  172. overrideReferenceName = overrideReferenceName
  173. };
  174. }
  175. public override int latestVersion => 1;
  176. public override void OnAfterDeserialize(string json)
  177. {
  178. if (sgVersion == 0)
  179. {
  180. // we now allow keywords to control whether they are exposed (for Material control) or not.
  181. // old exposable keywords set their exposed state to maintain previous behavior
  182. // (where bool keywords only showed up in the material when ending in "_ON")
  183. if (isExposable)
  184. {
  185. if (m_KeywordType == KeywordType.Boolean)
  186. generatePropertyBlock = referenceName.EndsWith("_ON");
  187. else // KeywordType.Enum
  188. generatePropertyBlock = true;
  189. }
  190. ChangeVersion(1);
  191. }
  192. }
  193. }
  194. }