MegascansDecalTools.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEditor;
  6. using UnityEngine;
  7. #if UNITY_EDITOR
  8. namespace Quixel
  9. {
  10. public class MegascansDecalTools : MonoBehaviour
  11. {
  12. /*
  13. * Terrain material blend setup steps:
  14. 1. Create a material with HDRenderPipeline/Decal shader.
  15. 2. Create a new Rendering>Decal Projector object in scene.
  16. 3. Assign that material to newly created decal projector.
  17. 4. Assign textures to that material.
  18. */
  19. public static void SetupDecalProjector()
  20. {
  21. try
  22. {
  23. #if !HDRP
  24. Debug.Log("HDRP features are disabled. You can enable them by going to Windows > Quixel > Enable HDRP Features");
  25. return;
  26. #endif
  27. #pragma warning disable
  28. string decalBlendStr = EditorPrefs.GetString("QuixelDefaultDecalBlend", "100");
  29. string decalSizeStr = EditorPrefs.GetString("QuixelDefaultDecalSize", "1");
  30. float decalBlend = 100f;
  31. try
  32. {
  33. decalBlend = (0.01f * Mathf.Clamp(float.Parse(decalBlendStr), 0f, 100f));
  34. }
  35. catch (Exception ex)
  36. {
  37. decalBlend = 100f;
  38. Debug.Log("Exception: " + ex.ToString());
  39. }
  40. Material selectedMaterial = GetSelectedMaterial();
  41. if (selectedMaterial == null)
  42. {
  43. Debug.Log("Error creating decal projector. No material selected.");
  44. return;
  45. }
  46. float decalSize = 1f;
  47. try
  48. {
  49. decalSize = float.Parse(decalSizeStr);
  50. }
  51. catch (Exception ex)
  52. {
  53. Debug.Log("Exception: " + ex.ToString());
  54. decalSize = 1f;
  55. }
  56. string path = AssetDatabase.GetAssetPath(selectedMaterial);
  57. Material decalMaterial = CreateDecalMaterial(path, selectedMaterial, decalBlend);
  58. CreateDecalPrefab(path, decalMaterial, decalSize);
  59. Debug.Log("Decal Projector created!");
  60. }
  61. catch (Exception ex)
  62. {
  63. Debug.Log("Error creating decal projector.");
  64. Debug.Log(ex);
  65. }
  66. }
  67. public static Material GetSelectedMaterial()
  68. {
  69. foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets))
  70. {
  71. if (obj.GetType() == typeof(Material))
  72. return (Material)obj;
  73. }
  74. return null;
  75. }
  76. public static Material CreateDecalMaterial(string selectedMaterialPath, Material selectedMaterial, float decalBlend)
  77. {
  78. Material decalMaterial = new Material(Shader.Find("Standard"));
  79. #if UNITY_2018_3 || UNITY_2018_4 || UNITY_2019
  80. decalMaterial.shader = Shader.Find("HDRP/Decal");
  81. #else
  82. decalMaterial.shader = Shader.Find("HDRenderPipeline/Decal");
  83. #endif
  84. string decalMaterialPath = selectedMaterialPath.Replace(".mat", "_Decal.mat");
  85. AssetDatabase.CreateAsset(decalMaterial, decalMaterialPath);
  86. AssetDatabase.Refresh();
  87. decalMaterial.enableInstancing = true;
  88. //Enable material keywords
  89. decalMaterial.EnableKeyword("_ALPHATEST_ON");
  90. decalMaterial.EnableKeyword("_ALBEDOCONTRIBUTION");
  91. decalMaterial.EnableKeyword("_COLORMAP");
  92. decalMaterial.EnableKeyword("_DISPLACEMENT_LOCK_TILING_SCALE");
  93. decalMaterial.EnableKeyword("_DOUBLESIDED_ON");
  94. decalMaterial.EnableKeyword("_MASKMAP");
  95. decalMaterial.EnableKeyword("_METALLICSPECGLOSSMAP");
  96. decalMaterial.EnableKeyword("_NORMALMAP");
  97. decalMaterial.EnableKeyword("_NORMALMAP_TANGENT_SPACE");
  98. decalMaterial.EnableKeyword("_PIXEL_DISPLACEMENT");
  99. decalMaterial.EnableKeyword("_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE");
  100. //Set material textures
  101. decalMaterial.SetTexture("_BaseColorMap", selectedMaterial.mainTexture);
  102. decalMaterial.SetTexture("_MaskMap", selectedMaterial.GetTexture("_MaskMap"));
  103. decalMaterial.SetTexture("_NormalMap", selectedMaterial.GetTexture("_NormalMap"));
  104. //Set material keywords
  105. decalMaterial.SetFloat("_AlbedoMode", 1f);
  106. if (!MegascansUtilities.isLegacy())
  107. {
  108. decalMaterial.SetFloat("_MaskBlendSrc", 0f);
  109. }
  110. decalMaterial.SetFloat("_DecalBlend", decalBlend);
  111. return decalMaterial;
  112. }
  113. public static void CreateDecalPrefab(string materialPath, Material decalMaterial, float size)
  114. {
  115. #if HDRP
  116. string assetPath = materialPath.Substring(0, materialPath.IndexOf("/Materials/"));
  117. string materialName = Path.GetFileName(materialPath);
  118. string prefabName = materialName.Replace(".mat", "");
  119. string prefabPath = MegascansUtilities.ValidateFolderCreate(assetPath, "Prefabs");
  120. GameObject g = new GameObject(prefabName);
  121. #if UNITY_2019_4 || UNITY_2020 || UNITY_2021
  122. g.transform.rotation = Quaternion.Euler(45f, 45f, 45f);
  123. #endif
  124. #if UNITY_2019_3 || UNITY_2019_4 || UNITY_2020 || UNITY_2021
  125. g.AddComponent<UnityEngine.Rendering.HighDefinition.DecalProjector>();
  126. UnityEngine.Rendering.HighDefinition.DecalProjector decalProjector = g.GetComponent<UnityEngine.Rendering.HighDefinition.DecalProjector>();
  127. #elif UNITY_2018_3 || UNITY_2018_4 || UNITY_2019_1 || UNITY_2019_2
  128. g.AddComponent<UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent>();
  129. UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent decalProjector = g.GetComponent<UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent>();
  130. #endif
  131. #if UNITY_2018_3 || UNITY_2018_4 || UNITY_2019_1
  132. decalProjector.m_Material = decalMaterial;
  133. decalProjector.m_Size = new Vector3(size, size, size);
  134. #else
  135. decalProjector.material = decalMaterial;
  136. decalProjector.size = new Vector3(size, size, size);
  137. #endif
  138. string finalName = prefabPath + "/" + prefabName + "_Decal" + ".prefab";
  139. UnityEngine.Object pf = null;
  140. try
  141. {
  142. pf = AssetDatabase.LoadAssetAtPath(finalName, typeof(UnityEngine.Object));
  143. }
  144. catch (Exception ex)
  145. {
  146. Debug.Log("Error verifying prefab.");
  147. Debug.Log(ex);
  148. }
  149. if (!pf)
  150. {
  151. PrefabUtility.CreatePrefab(finalName, g);
  152. }
  153. else
  154. {
  155. PrefabUtility.ReplacePrefab(g, pf, ReplacePrefabOptions.ReplaceNameBased);
  156. }
  157. DestroyImmediate(g);
  158. #endif
  159. }
  160. }
  161. }
  162. #endif