JJBB/Assets/Editor/Scripts/ShaderVariantTool.cs
2024-08-23 15:49:34 +08:00

304 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Games.GlobeDefine;
using UnityEditor;
using UnityEngine;
public static class ShaderVariantTool
{
// public const string variantCollectionPath = "Assets/Project/Shader/ShaderVariants.shadervariants";
// public const string shadowDepthKeyword = "SHADOWS_DEPTH";
// public const string fogKeyword = "FOG_LINEAR";
// public const string lightmapKeyword = "LIGHTMAP_ON";
// public const string directionalKeyword = "DIRECTIONAL";
//
// private const string _fogCompileWord = "fog";
// private const string _forwardBaseCompileWord = "fwdbase";
public static readonly string[] excludeKeywords =
{
"UNITY_HDR_ON",
"DIRLIGHTMAP_COMBINED",
"DIRLIGHTMAP_SEPARATE"
};
// public static void BuildVariantForShaders(IList<string> assetPaths)
// {
// var data = new List<ShaderVariantsSetting>();
// for (var i = 0; i < assetPaths.Count; i++)
// {
// var path = assetPaths[i];
// var shader = AssetDatabase.LoadAssetAtPath<Shader>(path);
// var shaderSettings = CreateVariants(path, shader);
// data.Add(shaderSettings);
// }
//
// var collection = new ShaderVariantCollection();
// for (var i = 0; i < data.Count; i++)
// {
// var varients = data[i].ParseToVarients();
// for (var j = 0; j < varients.Length; j++)
// collection.Add(varients[j]);
// }
//
// AssetDatabase.CreateAsset(collection, variantCollectionPath);
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// Debug.LogWarning("Build Shader Variant Collection for " + assetPaths.Count);
// }
// public static ShaderVariantsSetting CreateVariants(string assetPath, Shader shader)
// {
// var filePath = Application.dataPath.Open(assetPath.Substring("Assets".Length));
// var keywordList = new List<string>();
// var useForwardBase = false;
// var useShadow = false;
// var lines = File.ReadAllLines(filePath);
// var regex = new Regex("(?<=#pragma multi_compile).+");
// var shadowRegex = new Regex("\"LightMode\"\\s*=\\s*\"ShadowCaster\"");
// foreach (var line in lines)
// {
// var match = regex.Match(line);
// if (match.Success)
// {
// var result = match.Value.Trim('_', ' ');
// // Unity内置Keyword
// if (match.Value.StartsWith("_"))
// {
// switch (result)
// {
// case _fogCompileWord:
// if (!keywordList.Contains(fogKeyword))
// keywordList.Add(fogKeyword);
// break;
// case _forwardBaseCompileWord:
// useForwardBase = true;
// break;
// }
// }
// else if (match.Value.Contains("__"))
// {
// if (!result.Contains(" ") && !excludeKeywords.Contain(result) && !keywordList.Contains(result))
// keywordList.Add(result);
// }
// else
// {
// Debug.LogWarning("无法处理 " + line.TrimStart());
// }
// }
// else
// {
// match = shadowRegex.Match(line);
// if (match.Success)
// useShadow = true;
// }
// }
//
// // 注useForwardBase的物体都是景物仅仅需要烘培阴影
// if (useForwardBase)
// useShadow = false;
// var fixedKeywords = useForwardBase ? new[] {lightmapKeyword, directionalKeyword} : new string[0];
// var toggleKeywords = keywordList.ToArray();
// return new ShaderVariantsSetting(shader.name, useForwardBase ? PassType.ForwardBase : PassType.Normal,
// fixedKeywords, toggleKeywords, useShadow);
// }
// public class ShaderVariantsSetting
// {
// public readonly string[] fixedKeywords;
// public readonly PassType passType;
// public readonly string shaderName;
// public readonly bool shadow;
// public readonly string[] toggleKeywords;
//
// public ShaderVariantsSetting(string name, PassType pass, string[] fixedMacro, string[] toggleMacro,
// bool useShadow = false)
// {
// shaderName = name;
// passType = pass;
// fixedKeywords = fixedMacro;
// toggleKeywords = toggleMacro;
// shadow = useShadow;
// }
//
// public ShaderVariantCollection.ShaderVariant[] ParseToVarients()
// {
// var shader = Shader.Find(shaderName);
// if (shader == null)
// throw new ArgumentException("无法获得Shader " + shaderName);
// var end = 1 << toggleKeywords.Length;
// var variants = new ShaderVariantCollection.ShaderVariant[end + (shadow ? 1 : 0)];
// for (var i = 0; i < end; i++)
// {
// var index = 0;
// var count = EditorCommonUtility.GetMaskCount(i);
// var keywords = new string[count + fixedKeywords.Length];
// for (var j = 0; j < toggleKeywords.Length; j++)
// {
// var num = j.ToFlag();
// if (i.ContainFlag(num))
// {
// keywords[index] = toggleKeywords[j];
// index++;
// }
// }
//
// for (var j = 0; j < fixedKeywords.Length; j++)
// keywords[count + j] = fixedKeywords[j];
// variants[i] = new ShaderVariantCollection.ShaderVariant
// {
// shader = shader,
// passType = passType,
// keywords = keywords
// };
// }
//
// if (shadow)
// variants[end] = new ShaderVariantCollection.ShaderVariant
// {
// shader = shader,
// passType = PassType.ShadowCaster,
// keywords = new[] {shadowDepthKeyword}
// };
//
// return variants;
// }
// }
#region DummyMaterial
public static void CreateAllDummyMaterials(List<string> assetPaths, string bundlePath)
{
var recordPath = GlobeVar.testConfigPath.Open("DummyMatRecord.txt");
var create = true;
assetPaths.Sort();
var builder = new StringBuilder();
foreach (var assetPath in assetPaths)
builder.AppendLine(assetPath);
var newHash = ClassifyBundles.GetStringHash(builder.ToString());
if (File.Exists(recordPath))
{
var oldHash = File.ReadAllText(recordPath);
if (oldHash.Equals(newHash, StringComparison.Ordinal))
create = false;
}
if (create)
{
var data = new List<DummyMaterialBuilder>();
var dummyFilePath = EditorCommonUtility.AssetToFilePath(ClassifyBundles.dummyMaterialPath);
if (Directory.Exists(dummyFilePath))
Directory.Delete(dummyFilePath, true);
Directory.CreateDirectory(dummyFilePath);
AssetDatabase.Refresh();
for (var i = 0; i < assetPaths.Count; i++)
{
var path = assetPaths[i];
var shader = AssetDatabase.LoadAssetAtPath<Shader>(path);
var shaderSettings = CreateDummyMaterials(path, shader);
data.Add(shaderSettings);
}
for (var i = 0; i < data.Count; i++)
{
var variants = data[i];
variants.SaveToVariants(bundlePath);
}
File.WriteAllText(recordPath, newHash);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.LogWarning("Build Shader Variant Collection for " + assetPaths.Count);
}
else
Debug.LogWarning("Skip Shader Variant as Hash matched!");
}
public static DummyMaterialBuilder CreateDummyMaterials(string assetPath, Shader shader)
{
var filePath = Application.dataPath.Open(assetPath.Substring("Assets".Length));
var keywordList = new List<string>();
var lines = File.ReadAllLines(filePath);
var regex = new Regex("(?<=#pragma multi_compile).+");
foreach (var line in lines)
{
var match = regex.Match(line);
if (match.Success)
{
var result = match.Value.Trim('_', ' ');
// Unity内置Keyword
if (match.Value.StartsWith("_"))
{
}
else if (match.Value.Contains("__"))
{
if (!result.Contains(" ") && !excludeKeywords.Contain(result) && !keywordList.Contains(result))
keywordList.Add(result);
}
else
{
Debug.LogWarning("无法处理 " + line.TrimStart());
}
}
}
// 注useForwardBase的物体都是景物仅仅需要烘培阴影
return new DummyMaterialBuilder(shader, keywordList.ToArray());
}
public class DummyMaterialBuilder
{
public readonly Shader shader;
public readonly string[] toggleKeywords;
public DummyMaterialBuilder(Shader name, string[] toggleMacro)
{
shader = name;
toggleKeywords = toggleMacro;
}
public void SaveToVariants(string bundleName)
{
if (!shader)
throw new ArgumentException("无法获得Shader!");
var end = 1 << toggleKeywords.Length;
var variants = new Material[end];
for (var i = 0; i < end; i++)
{
var index = 0;
var count = EditorCommonUtility.GetMaskCount(i);
var keywords = new string[count];
for (var j = 0; j < toggleKeywords.Length; j++)
{
var num = j.ToFlag();
if (i.ContainFlag(num))
{
keywords[index] = toggleKeywords[j];
index++;
}
}
variants[i] = new Material(shader);
for (var j = 0; j < keywords.Length; j++)
variants[i].EnableKeyword(keywords[j]);
variants[i].name = shader.name + "_" + i;
}
for (var i = 0; i < variants.Length; i++)
{
var assetPath =
ClassifyBundles.dummyMaterialPath.Open(ClassifyBundles.GetStringHash(variants[i].name) + AssetConst.materialExtension);
AssetDatabase.CreateAsset(variants[i], assetPath);
var importer = AssetImporter.GetAtPath(assetPath);
importer.assetBundleName = bundleName;
importer.assetBundleVariant = LoadAssetBundle.bundleFileExtension;
}
}
}
#endregion
}