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.

LitGUI.cs 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. using UnityEngine;
  2. using UnityEngine.Rendering;
  3. namespace UnityEditor.Rendering.Universal.ShaderGUI
  4. {
  5. /// <summary>
  6. /// Editor script for the Lit material inspector.
  7. /// </summary>
  8. public static class LitGUI
  9. {
  10. /// <summary>
  11. /// Workflow modes for the shader.
  12. /// </summary>
  13. public enum WorkflowMode
  14. {
  15. /// <summary>
  16. /// Use this for specular workflow.
  17. /// </summary>
  18. Specular = 0,
  19. /// <summary>
  20. /// Use this for metallic workflow.
  21. /// </summary>
  22. Metallic
  23. }
  24. /// <summary>
  25. /// Options to select the texture channel where the smoothness value is stored.
  26. /// </summary>
  27. public enum SmoothnessMapChannel
  28. {
  29. /// <summary>
  30. /// Use this when smoothness is stored in the alpha channel of the Specular/Metallic Map.
  31. /// </summary>
  32. SpecularMetallicAlpha,
  33. /// <summary>
  34. /// Use this when smoothness is stored in the alpha channel of the Albedo Map.
  35. /// </summary>
  36. AlbedoAlpha,
  37. }
  38. /// <summary>
  39. /// Container for the text and tooltips used to display the shader.
  40. /// </summary>
  41. public static class Styles
  42. {
  43. /// <summary>
  44. /// The text and tooltip for the workflow Mode GUI.
  45. /// </summary>
  46. public static GUIContent workflowModeText = EditorGUIUtility.TrTextContent("Workflow Mode",
  47. "Select a workflow that fits your textures. Choose between Metallic or Specular.");
  48. /// <summary>
  49. /// The text and tooltip for the specular Map GUI.
  50. /// </summary>
  51. public static GUIContent specularMapText =
  52. EditorGUIUtility.TrTextContent("Specular Map", "Designates a Specular Map and specular color determining the apperance of reflections on this Material's surface.");
  53. /// <summary>
  54. /// The text and tooltip for the metallic Map GUI.
  55. /// </summary>
  56. public static GUIContent metallicMapText =
  57. EditorGUIUtility.TrTextContent("Metallic Map", "Sets and configures the map for the Metallic workflow.");
  58. /// <summary>
  59. /// The text and tooltip for the smoothness GUI.
  60. /// </summary>
  61. public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent("Smoothness",
  62. "Controls the spread of highlights and reflections on the surface.");
  63. /// <summary>
  64. /// The text and tooltip for the smoothness source GUI.
  65. /// </summary>
  66. public static GUIContent smoothnessMapChannelText =
  67. EditorGUIUtility.TrTextContent("Source",
  68. "Specifies where to sample a smoothness map from. By default, uses the alpha channel for your map.");
  69. /// <summary>
  70. /// The text and tooltip for the specular Highlights GUI.
  71. /// </summary>
  72. public static GUIContent highlightsText = EditorGUIUtility.TrTextContent("Specular Highlights",
  73. "When enabled, the Material reflects the shine from direct lighting.");
  74. /// <summary>
  75. /// The text and tooltip for the environment Reflections GUI.
  76. /// </summary>
  77. public static GUIContent reflectionsText =
  78. EditorGUIUtility.TrTextContent("Environment Reflections",
  79. "When enabled, the Material samples reflections from the nearest Reflection Probes or Lighting Probe.");
  80. /// <summary>
  81. /// The text and tooltip for the height map GUI.
  82. /// </summary>
  83. public static GUIContent heightMapText = EditorGUIUtility.TrTextContent("Height Map",
  84. "Defines a Height Map that will drive a parallax effect in the shader making the surface seem displaced.");
  85. /// <summary>
  86. /// The text and tooltip for the occlusion map GUI.
  87. /// </summary>
  88. public static GUIContent occlusionText = EditorGUIUtility.TrTextContent("Occlusion Map",
  89. "Sets an occlusion map to simulate shadowing from ambient lighting.");
  90. /// <summary>
  91. /// The names for smoothness alpha options available for metallic workflow.
  92. /// </summary>
  93. public static readonly string[] metallicSmoothnessChannelNames = { "Metallic Alpha", "Albedo Alpha" };
  94. /// <summary>
  95. /// The names for smoothness alpha options available for specular workflow.
  96. /// </summary>
  97. public static readonly string[] specularSmoothnessChannelNames = { "Specular Alpha", "Albedo Alpha" };
  98. /// <summary>
  99. /// The text and tooltip for the enabling/disabling clear coat GUI.
  100. /// </summary>
  101. public static GUIContent clearCoatText = EditorGUIUtility.TrTextContent("Clear Coat",
  102. "A multi-layer material feature which simulates a thin layer of coating on top of the surface material." +
  103. "\nPerformance cost is considerable as the specular component is evaluated twice, once per layer.");
  104. /// <summary>
  105. /// The text and tooltip for the clear coat Mask GUI.
  106. /// </summary>
  107. public static GUIContent clearCoatMaskText = EditorGUIUtility.TrTextContent("Mask",
  108. "Specifies the amount of the coat blending." +
  109. "\nActs as a multiplier of the clear coat map mask value or as a direct mask value if no map is specified." +
  110. "\nThe map specifies clear coat mask in the red channel and clear coat smoothness in the green channel.");
  111. /// <summary>
  112. /// The text and tooltip for the clear coat smoothness GUI.
  113. /// </summary>
  114. public static GUIContent clearCoatSmoothnessText = EditorGUIUtility.TrTextContent("Smoothness",
  115. "Specifies the smoothness of the coating." +
  116. "\nActs as a multiplier of the clear coat map smoothness value or as a direct smoothness value if no map is specified.");
  117. }
  118. /// <summary>
  119. /// Container for the properties used in the <c>LitGUI</c> editor script.
  120. /// </summary>
  121. public struct LitProperties
  122. {
  123. // Surface Option Props
  124. /// <summary>
  125. /// The MaterialProperty for workflow mode.
  126. /// </summary>
  127. public MaterialProperty workflowMode;
  128. // Surface Input Props
  129. /// <summary>
  130. /// The MaterialProperty for metallic value.
  131. /// </summary>
  132. public MaterialProperty metallic;
  133. /// <summary>
  134. /// The MaterialProperty for specular color.
  135. /// </summary>
  136. public MaterialProperty specColor;
  137. /// <summary>
  138. /// The MaterialProperty for metallic Smoothness map.
  139. /// </summary>
  140. public MaterialProperty metallicGlossMap;
  141. /// <summary>
  142. /// The MaterialProperty for specular smoothness map.
  143. /// </summary>
  144. public MaterialProperty specGlossMap;
  145. /// <summary>
  146. /// The MaterialProperty for smoothness value.
  147. /// </summary>
  148. public MaterialProperty smoothness;
  149. /// <summary>
  150. /// The MaterialProperty for smoothness alpha channel.
  151. /// </summary>
  152. public MaterialProperty smoothnessMapChannel;
  153. /// <summary>
  154. /// The MaterialProperty for normal map.
  155. /// </summary>
  156. public MaterialProperty bumpMapProp;
  157. /// <summary>
  158. /// The MaterialProperty for normal map scale.
  159. /// </summary>
  160. public MaterialProperty bumpScaleProp;
  161. /// <summary>
  162. /// The MaterialProperty for height map.
  163. /// </summary>
  164. public MaterialProperty parallaxMapProp;
  165. /// <summary>
  166. /// The MaterialProperty for height map scale.
  167. /// </summary>
  168. public MaterialProperty parallaxScaleProp;
  169. /// <summary>
  170. /// The MaterialProperty for occlusion strength.
  171. /// </summary>
  172. public MaterialProperty occlusionStrength;
  173. /// <summary>
  174. /// The MaterialProperty for occlusion map.
  175. /// </summary>
  176. public MaterialProperty occlusionMap;
  177. // Advanced Props
  178. /// <summary>
  179. /// The MaterialProperty for specular highlights.
  180. /// </summary>
  181. public MaterialProperty highlights;
  182. /// <summary>
  183. /// The MaterialProperty for environment reflections.
  184. /// </summary>
  185. public MaterialProperty reflections;
  186. /// <summary>
  187. /// The MaterialProperty for enabling/disabling clear coat.
  188. /// </summary>
  189. public MaterialProperty clearCoat; // Enable/Disable dummy property
  190. /// <summary>
  191. /// The MaterialProperty for clear coat map.
  192. /// </summary>
  193. public MaterialProperty clearCoatMap;
  194. /// <summary>
  195. /// The MaterialProperty for clear coat mask.
  196. /// </summary>
  197. public MaterialProperty clearCoatMask;
  198. /// <summary>
  199. /// The MaterialProperty for clear coat smoothness.
  200. /// </summary>
  201. public MaterialProperty clearCoatSmoothness;
  202. /// <summary>
  203. /// Constructor for the <c>LitProperties</c> container struct.
  204. /// </summary>
  205. /// <param name="properties"></param>
  206. public LitProperties(MaterialProperty[] properties)
  207. {
  208. // Surface Option Props
  209. workflowMode = BaseShaderGUI.FindProperty("_WorkflowMode", properties, false);
  210. // Surface Input Props
  211. metallic = BaseShaderGUI.FindProperty("_Metallic", properties);
  212. specColor = BaseShaderGUI.FindProperty("_SpecColor", properties, false);
  213. metallicGlossMap = BaseShaderGUI.FindProperty("_MetallicGlossMap", properties);
  214. specGlossMap = BaseShaderGUI.FindProperty("_SpecGlossMap", properties, false);
  215. smoothness = BaseShaderGUI.FindProperty("_Smoothness", properties, false);
  216. smoothnessMapChannel = BaseShaderGUI.FindProperty("_SmoothnessTextureChannel", properties, false);
  217. bumpMapProp = BaseShaderGUI.FindProperty("_BumpMap", properties, false);
  218. bumpScaleProp = BaseShaderGUI.FindProperty("_BumpScale", properties, false);
  219. parallaxMapProp = BaseShaderGUI.FindProperty("_ParallaxMap", properties, false);
  220. parallaxScaleProp = BaseShaderGUI.FindProperty("_Parallax", properties, false);
  221. occlusionStrength = BaseShaderGUI.FindProperty("_OcclusionStrength", properties, false);
  222. occlusionMap = BaseShaderGUI.FindProperty("_OcclusionMap", properties, false);
  223. // Advanced Props
  224. highlights = BaseShaderGUI.FindProperty("_SpecularHighlights", properties, false);
  225. reflections = BaseShaderGUI.FindProperty("_EnvironmentReflections", properties, false);
  226. clearCoat = BaseShaderGUI.FindProperty("_ClearCoat", properties, false);
  227. clearCoatMap = BaseShaderGUI.FindProperty("_ClearCoatMap", properties, false);
  228. clearCoatMask = BaseShaderGUI.FindProperty("_ClearCoatMask", properties, false);
  229. clearCoatSmoothness = BaseShaderGUI.FindProperty("_ClearCoatSmoothness", properties, false);
  230. }
  231. }
  232. /// <summary>
  233. /// Draws the surface inputs GUI.
  234. /// </summary>
  235. /// <param name="properties"></param>
  236. /// <param name="materialEditor"></param>
  237. /// <param name="material"></param>
  238. public static void Inputs(LitProperties properties, MaterialEditor materialEditor, Material material)
  239. {
  240. DoMetallicSpecularArea(properties, materialEditor, material);
  241. BaseShaderGUI.DrawNormalArea(materialEditor, properties.bumpMapProp, properties.bumpScaleProp);
  242. if (HeightmapAvailable(material))
  243. DoHeightmapArea(properties, materialEditor);
  244. if (properties.occlusionMap != null)
  245. {
  246. materialEditor.TexturePropertySingleLine(Styles.occlusionText, properties.occlusionMap,
  247. properties.occlusionMap.textureValue != null ? properties.occlusionStrength : null);
  248. }
  249. // Check that we have all the required properties for clear coat,
  250. // otherwise we will get null ref exception from MaterialEditor GUI helpers.
  251. if (ClearCoatAvailable(material))
  252. DoClearCoat(properties, materialEditor, material);
  253. }
  254. private static bool ClearCoatAvailable(Material material)
  255. {
  256. return material.HasProperty("_ClearCoat")
  257. && material.HasProperty("_ClearCoatMap")
  258. && material.HasProperty("_ClearCoatMask")
  259. && material.HasProperty("_ClearCoatSmoothness");
  260. }
  261. private static bool HeightmapAvailable(Material material)
  262. {
  263. return material.HasProperty("_Parallax")
  264. && material.HasProperty("_ParallaxMap");
  265. }
  266. private static void DoHeightmapArea(LitProperties properties, MaterialEditor materialEditor)
  267. {
  268. materialEditor.TexturePropertySingleLine(Styles.heightMapText, properties.parallaxMapProp,
  269. properties.parallaxMapProp.textureValue != null ? properties.parallaxScaleProp : null);
  270. }
  271. private static bool ClearCoatEnabled(Material material)
  272. {
  273. return material.HasProperty("_ClearCoat") && material.GetFloat("_ClearCoat") > 0.0;
  274. }
  275. /// <summary>
  276. /// Draws the clear coat GUI.
  277. /// </summary>
  278. /// <param name="properties"></param>
  279. /// <param name="materialEditor"></param>
  280. /// <param name="material"></param>
  281. public static void DoClearCoat(LitProperties properties, MaterialEditor materialEditor, Material material)
  282. {
  283. materialEditor.ShaderProperty(properties.clearCoat, Styles.clearCoatText);
  284. var coatEnabled = material.GetFloat("_ClearCoat") > 0.0;
  285. EditorGUI.BeginDisabledGroup(!coatEnabled);
  286. {
  287. EditorGUI.indentLevel += 2;
  288. materialEditor.TexturePropertySingleLine(Styles.clearCoatMaskText, properties.clearCoatMap, properties.clearCoatMask);
  289. // Texture and HDR color controls
  290. materialEditor.ShaderProperty(properties.clearCoatSmoothness, Styles.clearCoatSmoothnessText);
  291. EditorGUI.indentLevel -= 2;
  292. }
  293. EditorGUI.EndDisabledGroup();
  294. }
  295. /// <summary>
  296. /// Draws the metallic/specular area GUI.
  297. /// </summary>
  298. /// <param name="properties"></param>
  299. /// <param name="materialEditor"></param>
  300. /// <param name="material"></param>
  301. public static void DoMetallicSpecularArea(LitProperties properties, MaterialEditor materialEditor, Material material)
  302. {
  303. string[] smoothnessChannelNames;
  304. bool hasGlossMap = false;
  305. if (properties.workflowMode == null ||
  306. (WorkflowMode)properties.workflowMode.floatValue == WorkflowMode.Metallic)
  307. {
  308. hasGlossMap = properties.metallicGlossMap.textureValue != null;
  309. smoothnessChannelNames = Styles.metallicSmoothnessChannelNames;
  310. materialEditor.TexturePropertySingleLine(Styles.metallicMapText, properties.metallicGlossMap,
  311. hasGlossMap ? null : properties.metallic);
  312. }
  313. else
  314. {
  315. hasGlossMap = properties.specGlossMap.textureValue != null;
  316. smoothnessChannelNames = Styles.specularSmoothnessChannelNames;
  317. BaseShaderGUI.TextureColorProps(materialEditor, Styles.specularMapText, properties.specGlossMap,
  318. hasGlossMap ? null : properties.specColor);
  319. }
  320. DoSmoothness(materialEditor, material, properties.smoothness, properties.smoothnessMapChannel, smoothnessChannelNames);
  321. }
  322. internal static bool IsOpaque(Material material)
  323. {
  324. bool opaque = true;
  325. if (material.HasProperty(Property.SurfaceType))
  326. opaque = ((BaseShaderGUI.SurfaceType)material.GetFloat(Property.SurfaceType) == BaseShaderGUI.SurfaceType.Opaque);
  327. return opaque;
  328. }
  329. /// <summary>
  330. /// Draws the smoothness GUI.
  331. /// </summary>
  332. /// <param name="materialEditor"></param>
  333. /// <param name="material"></param>
  334. /// <param name="smoothness"></param>
  335. /// <param name="smoothnessMapChannel"></param>
  336. /// <param name="smoothnessChannelNames"></param>
  337. public static void DoSmoothness(MaterialEditor materialEditor, Material material, MaterialProperty smoothness, MaterialProperty smoothnessMapChannel, string[] smoothnessChannelNames)
  338. {
  339. EditorGUI.indentLevel += 2;
  340. materialEditor.ShaderProperty(smoothness, Styles.smoothnessText);
  341. if (smoothnessMapChannel != null) // smoothness channel
  342. {
  343. var opaque = IsOpaque(material);
  344. EditorGUI.indentLevel++;
  345. EditorGUI.showMixedValue = smoothnessMapChannel.hasMixedValue;
  346. if (opaque)
  347. {
  348. MaterialEditor.BeginProperty(smoothnessMapChannel);
  349. EditorGUI.BeginChangeCheck();
  350. var smoothnessSource = (int)smoothnessMapChannel.floatValue;
  351. smoothnessSource = EditorGUILayout.Popup(Styles.smoothnessMapChannelText, smoothnessSource, smoothnessChannelNames);
  352. if (EditorGUI.EndChangeCheck())
  353. smoothnessMapChannel.floatValue = smoothnessSource;
  354. MaterialEditor.EndProperty();
  355. }
  356. else
  357. {
  358. EditorGUI.BeginDisabledGroup(true);
  359. EditorGUILayout.Popup(Styles.smoothnessMapChannelText, 0, smoothnessChannelNames);
  360. EditorGUI.EndDisabledGroup();
  361. }
  362. EditorGUI.showMixedValue = false;
  363. EditorGUI.indentLevel--;
  364. }
  365. EditorGUI.indentLevel -= 2;
  366. }
  367. /// <summary>
  368. /// Retrieves the alpha channel used for smoothness.
  369. /// </summary>
  370. /// <param name="material"></param>
  371. /// <returns>The Alpha channel used for Smoothness.</returns>
  372. public static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)
  373. {
  374. int ch = (int)material.GetFloat("_SmoothnessTextureChannel");
  375. if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)
  376. return SmoothnessMapChannel.AlbedoAlpha;
  377. return SmoothnessMapChannel.SpecularMetallicAlpha;
  378. }
  379. // (shared by all lit shaders, including shadergraph Lit Target and Lit.shader)
  380. internal static void SetupSpecularWorkflowKeyword(Material material, out bool isSpecularWorkflow)
  381. {
  382. isSpecularWorkflow = false; // default is metallic workflow
  383. if (material.HasProperty(Property.SpecularWorkflowMode))
  384. isSpecularWorkflow = ((WorkflowMode)material.GetFloat(Property.SpecularWorkflowMode)) == WorkflowMode.Specular;
  385. CoreUtils.SetKeyword(material, "_SPECULAR_SETUP", isSpecularWorkflow);
  386. }
  387. /// <summary>
  388. /// Sets up the keywords for the Lit shader and material.
  389. /// </summary>
  390. /// <param name="material"></param>
  391. public static void SetMaterialKeywords(Material material)
  392. {
  393. SetupSpecularWorkflowKeyword(material, out bool isSpecularWorkFlow);
  394. // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
  395. // (MaterialProperty value might come from renderer material property block)
  396. var specularGlossMap = isSpecularWorkFlow ? "_SpecGlossMap" : "_MetallicGlossMap";
  397. var hasGlossMap = material.GetTexture(specularGlossMap) != null;
  398. CoreUtils.SetKeyword(material, "_METALLICSPECGLOSSMAP", hasGlossMap);
  399. if (material.HasProperty("_SpecularHighlights"))
  400. CoreUtils.SetKeyword(material, "_SPECULARHIGHLIGHTS_OFF",
  401. material.GetFloat("_SpecularHighlights") == 0.0f);
  402. if (material.HasProperty("_EnvironmentReflections"))
  403. CoreUtils.SetKeyword(material, "_ENVIRONMENTREFLECTIONS_OFF",
  404. material.GetFloat("_EnvironmentReflections") == 0.0f);
  405. if (material.HasProperty("_OcclusionMap"))
  406. CoreUtils.SetKeyword(material, "_OCCLUSIONMAP", material.GetTexture("_OcclusionMap"));
  407. if (material.HasProperty("_ParallaxMap"))
  408. CoreUtils.SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
  409. if (material.HasProperty("_SmoothnessTextureChannel"))
  410. {
  411. var opaque = IsOpaque(material);
  412. CoreUtils.SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A",
  413. GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha && opaque);
  414. }
  415. // Clear coat keywords are independent to remove possibility of invalid combinations.
  416. if (ClearCoatEnabled(material))
  417. {
  418. var hasMap = material.HasProperty("_ClearCoatMap") && material.GetTexture("_ClearCoatMap") != null;
  419. if (hasMap)
  420. {
  421. CoreUtils.SetKeyword(material, "_CLEARCOAT", false);
  422. CoreUtils.SetKeyword(material, "_CLEARCOATMAP", true);
  423. }
  424. else
  425. {
  426. CoreUtils.SetKeyword(material, "_CLEARCOAT", true);
  427. CoreUtils.SetKeyword(material, "_CLEARCOATMAP", false);
  428. }
  429. }
  430. else
  431. {
  432. CoreUtils.SetKeyword(material, "_CLEARCOAT", false);
  433. CoreUtils.SetKeyword(material, "_CLEARCOATMAP", false);
  434. }
  435. }
  436. }
  437. }