Unity3d : analyse du code de collection de variantes de shaders YooAsset

commencer à collectionner

YooAsset.Editor.ShaderVariantCollector.Run

Créer des scènes temporaires

// 创建临时测试场景
			CreateTempScene();

			_steps = ESteps.Prepare;
			EditorApplication.update += EditorUpdate;

Phase de préparation

Reflection appelle ShaderUtil.ClearCurrentShaderVariantCollection pour effacer les variantes collectées par le projet en cours, et nous devons les collecter à nouveau ;

EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "ClearCurrentShaderVariantCollection");

Comment appeler de manière réfléchie

		/// <summary>
		/// 调用私有的静态方法
		/// </summary>
		/// <param name="type">类的类型</param>
		/// <param name="method">类里要调用的方法名</param>
		/// <param name="parameters">调用方法传入的参数</param>
		public static object InvokeNonPublicStaticMethod(System.Type type, string method, params object[] parameters)
		{
    
    
			var methodInfo = type.GetMethod(method, BindingFlags.NonPublic | BindingFlags.Static);
			if (methodInfo == null)
			{
    
    
				UnityEngine.Debug.LogError($"{
      
      type.FullName} not found method : {
      
      method}");
				return null;
			}
			return methodInfo.Invoke(null, parameters);
		}

Collectionne tous les shaders

YooAsset.Editor.ShaderVariantCollector.GetAllMaterials
tous les actifs dépendant du collecteur

// 获取所有打包的资源
			CollectResult collectResult = AssetBundleCollectorSettingData.Setting.GetPackageAssets(EBuildMode.DryRunBuild, _packageName);
			foreach (var assetInfo in collectResult.CollectAssets)
			{
    
    
				string[] depends = AssetDatabase.GetDependencies(assetInfo.AssetPath, true);
				foreach (var dependAsset in depends)
				{
    
    
					if (allAssets.Contains(dependAsset) == false)
						allAssets.Add(dependAsset);
				}

Collectez tous les shaders qui dépendent de l'actif

List<string> allMaterial = new List<string>(1000);
			foreach (var assetPath in allAssets)
			{
    
    
				System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
				if (assetType == typeof(UnityEngine.Material))
				{
    
    
					allMaterial.Add(assetPath);
				}

Collectez les variantes, la caméra illumine tous les shaders une fois

Collection de variantes, ne traitez qu'un maximum de 1000 shaders à chaque fois, s'il dépasse, attendez que le prochain lot soit à nouveau
traité
_allMaterials, puis traiter la gamme actuelle

int count = Mathf.Min(_processMaxNum, _allMaterials.Count);
				List<string> range = _allMaterials.GetRange(0, count);
				_allMaterials.RemoveRange(0, count);

Créez un ensemble de géométries de sphères dans la scène et organisez-les soigneusement, puis alignez la caméra de rendu sur elles et assurez-vous qu'elles sont toutes visibles ; attribuez
ces ressources matérielles à ces géométries de sphères par lots et effectuez le rendu pendant 100 ms ;
insérez la description de l'image ici

traitement complet

Chemin de collection de variantes YooAsset.Editor.ShaderVariantCollectorSetting.SavePath = "Assets/MyShaderVariants.shadervariants"
appel de réflexion ShaderUtil.SaveCurrentShaderVariantCollection pour enregistrer dans une ressource de collection de variantes globale

EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "SaveCurrentShaderVariantCollection", savePath);

Le fichier de sortie
MyShaderVariants.shadervariants sera empaqueté dans le package unityshaders.bundle
insérez la description de l'image ici

Sortie json, vous pouvez afficher le mot-clé pour faire l'élimination correspondante

AssetPath": "Resources/unity_builtin_extra",
            "ShaderName": "Standard",
            "ShaderVariantElements": [
                {
    
    
                    "PassType": 4,
                    "Keywords": [
                        "DIRECTIONAL",
                        "LIGHTPROBE_SH",
                        "SHADOWS_SCREEN",
                        "SHADOWS_SPLIT_SPHERES"
                    ]
                },
                {
    
    
                    "PassType": 4,
                    "Keywords": [
                        "DIRECTIONAL",
                        "LIGHTPROBE_SH",
                        "SHADOWS_SCREEN",
                        "SHADOWS_SPLIT_SPHERES",
                        "_EMISSION"
                    ]
                },

Supprimer l'exemple de code de mot-clé lors de l'emballage

public class StripInstancingOnKeyword : IPreprocessShaders
{
    
    
    public int callbackOrder
    {
    
    
        //多个回调处理的处理顺序
        get {
    
     return 0; }
    }

    //在执行打包assetbundle会处理
    public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> inputData)
    {
    
    
        Debug.Log(string.Format("shader:{0}", shader.name));

        //反向遍历,有利于删除
        for (int i = inputData.Count - 1; i >= 0; i--)
        {
    
    
            ShaderCompilerData input = inputData[i];
            //Global And Local Keyword
            if (input.shaderKeywordSet.IsEnabled(new ShaderKeyword("DIRECTIONAL")) || 
                input.shaderKeywordSet.IsEnabled(new ShaderKeyword(shader, "DIRECTIONAL")))
            {
    
    
                Debug.Log(string.Format("剔除shader:{0},变体{1}", shader.name, "DIRECTIONAL"));
                inputData.RemoveAt(i);
            }
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/luoyikun/article/details/131757641
Recomendado
Clasificación