using System; using System.IO; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; #if UNITY_EDITOR namespace Quixel { public class MegascansDecalTools : MonoBehaviour { /* * Terrain material blend setup steps: 1. Create a material with HDRenderPipeline/Decal shader. 2. Create a new Rendering>Decal Projector object in scene. 3. Assign that material to newly created decal projector. 4. Assign textures to that material. */ public static void SetupDecalProjector() { try { #if !HDRP Debug.Log("HDRP features are disabled. You can enable them by going to Windows > Quixel > Enable HDRP Features"); return; #endif #pragma warning disable string decalBlendStr = EditorPrefs.GetString("QuixelDefaultDecalBlend", "100"); string decalSizeStr = EditorPrefs.GetString("QuixelDefaultDecalSize", "1"); float decalBlend = 100f; try { decalBlend = (0.01f * Mathf.Clamp(float.Parse(decalBlendStr), 0f, 100f)); } catch (Exception ex) { decalBlend = 100f; Debug.Log("Exception: " + ex.ToString()); } Material selectedMaterial = GetSelectedMaterial(); if (selectedMaterial == null) { Debug.Log("Error creating decal projector. No material selected."); return; } float decalSize = 1f; try { decalSize = float.Parse(decalSizeStr); } catch (Exception ex) { Debug.Log("Exception: " + ex.ToString()); decalSize = 1f; } string path = AssetDatabase.GetAssetPath(selectedMaterial); Material decalMaterial = CreateDecalMaterial(path, selectedMaterial, decalBlend); CreateDecalPrefab(path, decalMaterial, decalSize); Debug.Log("Decal Projector created!"); } catch (Exception ex) { Debug.Log("Error creating decal projector."); Debug.Log(ex); } } public static Material GetSelectedMaterial() { foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets)) { if (obj.GetType() == typeof(Material)) return (Material)obj; } return null; } public static Material CreateDecalMaterial(string selectedMaterialPath, Material selectedMaterial, float decalBlend) { Material decalMaterial = new Material(Shader.Find("Standard")); #if UNITY_2018_3 || UNITY_2018_4 || UNITY_2019 decalMaterial.shader = Shader.Find("HDRP/Decal"); #else decalMaterial.shader = Shader.Find("HDRenderPipeline/Decal"); #endif string decalMaterialPath = selectedMaterialPath.Replace(".mat", "_Decal.mat"); AssetDatabase.CreateAsset(decalMaterial, decalMaterialPath); AssetDatabase.Refresh(); decalMaterial.enableInstancing = true; //Enable material keywords decalMaterial.EnableKeyword("_ALPHATEST_ON"); decalMaterial.EnableKeyword("_ALBEDOCONTRIBUTION"); decalMaterial.EnableKeyword("_COLORMAP"); decalMaterial.EnableKeyword("_DISPLACEMENT_LOCK_TILING_SCALE"); decalMaterial.EnableKeyword("_DOUBLESIDED_ON"); decalMaterial.EnableKeyword("_MASKMAP"); decalMaterial.EnableKeyword("_METALLICSPECGLOSSMAP"); decalMaterial.EnableKeyword("_NORMALMAP"); decalMaterial.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); decalMaterial.EnableKeyword("_PIXEL_DISPLACEMENT"); decalMaterial.EnableKeyword("_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE"); //Set material textures decalMaterial.SetTexture("_BaseColorMap", selectedMaterial.mainTexture); decalMaterial.SetTexture("_MaskMap", selectedMaterial.GetTexture("_MaskMap")); decalMaterial.SetTexture("_NormalMap", selectedMaterial.GetTexture("_NormalMap")); //Set material keywords decalMaterial.SetFloat("_AlbedoMode", 1f); if (!MegascansUtilities.isLegacy()) { decalMaterial.SetFloat("_MaskBlendSrc", 0f); } decalMaterial.SetFloat("_DecalBlend", decalBlend); return decalMaterial; } public static void CreateDecalPrefab(string materialPath, Material decalMaterial, float size) { #if HDRP string assetPath = materialPath.Substring(0, materialPath.IndexOf("/Materials/")); string materialName = Path.GetFileName(materialPath); string prefabName = materialName.Replace(".mat", ""); string prefabPath = MegascansUtilities.ValidateFolderCreate(assetPath, "Prefabs"); GameObject g = new GameObject(prefabName); #if UNITY_2019_4 || UNITY_2020 || UNITY_2021 g.transform.rotation = Quaternion.Euler(45f, 45f, 45f); #endif #if UNITY_2019_3 || UNITY_2019_4 || UNITY_2020 || UNITY_2021 g.AddComponent<UnityEngine.Rendering.HighDefinition.DecalProjector>(); UnityEngine.Rendering.HighDefinition.DecalProjector decalProjector = g.GetComponent<UnityEngine.Rendering.HighDefinition.DecalProjector>(); #elif UNITY_2018_3 || UNITY_2018_4 || UNITY_2019_1 || UNITY_2019_2 g.AddComponent<UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent>(); UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent decalProjector = g.GetComponent<UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent>(); #endif #if UNITY_2018_3 || UNITY_2018_4 || UNITY_2019_1 decalProjector.m_Material = decalMaterial; decalProjector.m_Size = new Vector3(size, size, size); #else decalProjector.material = decalMaterial; decalProjector.size = new Vector3(size, size, size); #endif string finalName = prefabPath + "/" + prefabName + "_Decal" + ".prefab"; UnityEngine.Object pf = null; try { pf = AssetDatabase.LoadAssetAtPath(finalName, typeof(UnityEngine.Object)); } catch (Exception ex) { Debug.Log("Error verifying prefab."); Debug.Log(ex); } if (!pf) { PrefabUtility.CreatePrefab(finalName, g); } else { PrefabUtility.ReplacePrefab(g, pf, ReplacePrefabOptions.ReplaceNameBased); } DestroyImmediate(g); #endif } } } #endif