前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >unity3d:YooAsset shader变体收集代码解析

unity3d:YooAsset shader变体收集代码解析

作者头像
立羽
发布2023-08-24 15:46:46
6300
发布2023-08-24 15:46:46
举报
文章被收录于专栏:Unity3d程序开发Unity3d程序开发

开始收集

YooAsset.Editor.ShaderVariantCollector.Run

创建临时场景

代码语言:javascript
复制
// 创建临时测试场景
			CreateTempScene();

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

准备阶段

反射调用ShaderUtil.ClearCurrentShaderVariantCollection清空当前项目搜集到的变体,我们需要重新搜集一次;

代码语言:javascript
复制
EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "ClearCurrentShaderVariantCollection");

如何反射调用

代码语言:javascript
复制
		/// <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);
		}

收集全部材质球

YooAsset.Editor.ShaderVariantCollector.GetAllMaterials 所有收集器的依赖asset

代码语言:javascript
复制
// 获取所有打包的资源
			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);
				}

收集所有依赖asset的材质球

代码语言:javascript
复制
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);
				}

收集变体,摄像机照射所有材质球一遍

变体收集,每次只处理最大1000个材质球,超过的,等下一批再处理 YooAsset.Editor.ShaderVariantCollectorSetting.ProcessCapacity = 1000 每次处理一批时,总材质球列表_allMaterials去掉0-count,然后处理当前的range

代码语言:javascript
复制
int count = Mathf.Min(_processMaxNum, _allMaterials.Count);
				List<string> range = _allMaterials.GetRange(0, count);
				_allMaterials.RemoveRange(0, count);

在场景中创建一堆sphere几何体,并排列整齐,然后把渲染相机对齐它们,并保证它们都可以看见; 分批次把这些材质资源赋予这些sphere几何体,渲染100ms;

在这里插入图片描述
在这里插入图片描述

完成处理

变体收集到路径YooAsset.Editor.ShaderVariantCollectorSetting.SavePath = “Assets/MyShaderVariants.shadervariants” 反射调用ShaderUtil.SaveCurrentShaderVariantCollection保存到一个整体变体集合资源中去

代码语言:javascript
复制
EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "SaveCurrentShaderVariantCollection", savePath);

输出文件 MyShaderVariants.shadervariants会打包进入unityshaders.bundle包里

在这里插入图片描述
在这里插入图片描述

输出json,可以查看keyword做相应的剔除

代码语言:javascript
复制
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"
                    ]
                },

打包时去掉keyword代码示例

代码语言:javascript
复制
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);
            }
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-07-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开始收集
  • 创建临时场景
  • 准备阶段
  • 收集全部材质球
  • 收集变体,摄像机照射所有材质球一遍
  • 完成处理
  • 打包时去掉keyword代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档