304 lines
12 KiB
C#
304 lines
12 KiB
C#
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
|
||
} |