Files
ZHGD_Web/Assets/Quixel/Scripts/BridgeImporter/MegascansDecalTools.cs

178 lines
7.0 KiB
C#
Raw Permalink Normal View History

2025-07-13 23:16:20 +08:00
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