unity中multi_complie产生shaderVariant,ShaderVariantCollection优化shaderVariant

Unity Shader Variant详解
本文深入解析Unity中的Shader Variant,探讨HLSL编译原理,对比multi_compile与shader_feature的使用,介绍ShaderVariantCollection的预热机制及应用技巧,旨在帮助开发者优化游戏性能,避免资源冗余。

HLSL 可以被编译为虚拟机字节码(IL或者DXIL), 就表示允许着色器程序被编译和离线存储。
shader.WarmupAllShaders 是不可控的, 会把shader的所有的变体 都warmup一遍,

而shaderVariantCollection.WarmUp 预热的只有你会使用到的shader的变体
shaderVariantCollection: 所以在 首包安装 加载所有的shader, 执行 ShaderVariantCollection.WarmUp, 这样所有的shader就编译和catch了
再次运行游戏,如果已经 shader 已经预热过了,再执行 shaderVariantCollection.WarmUp 就什么也不做,没有消耗(详见 官方文档),

一. shaderVariant的缺失,可能会造成不同平台的差异(unity工程editor模式和真机模式表现不一致)
例如:如果你在unity中editor模式下表现正常,但是打包到真机后出现黑片(lightMap未正常表现)?紫片(shader直接丢失)?--------------恭喜你----原因很可能是shader的变体 shaderVariant没有正常表现。
核查问题的方法:
(1)在editor模式下frameDebug 查看正常的表现shader的属性和使用编译情况(查看编译后的变体代码Show generated code)
(2)真机连接frameDebug调试核查表现失常的shader的属性中是否缺失属性例如:是谁偷走了我的lightmap?? 没能切换使用正确的shaderVariant
那么解决问题就是:首先确定 shaderVariant是否打包进去了(用bundle拆解工具 AssetStudio核查bundle内的信息),第二是否执行命令“切换到lightmap_on的shaderVariant”.
(附加上查看bundle的工具:链接: https://pan.baidu.com/s/18YC-KZsW0Xjls8DVKle-lQ 提取码: gyjg)

二.shaderVariant到底是啥玩意?!
举个例子,对于一个支持法线贴图的Shader来说,用户肯定希望无论是否为Shader提供法线贴图这个Shader都能正确的进行渲染处理。一般有两种方法来保证这种需求:

1.在底层shader(GLSL,HLSL等)定义一个由外部传进来的变量(如int),有没有提供法线贴图由外部来判断并给这个shader传参,若是有则传0,否则传1,在Shader用if对这个变量进行判断,然后在两个分支中进行对应的处理。

2.对底层shader封装,如Unity的ShaderLab就是这种,然后在上层为用户提供定义宏的功能,并决定宏在被定义和未被定义下如何处理。最终编译时,根据上层的宏定义,根据不同的组合编译出多套底层shader.

上述两种方法,各有利弊,对于前者由于引入了条件判断,会影响最终shader在GPU上的执行效率。而后者则会导致生成的shader源码(或二进制文件)变大。Unity采取的是后者,我们这里也只讨论Unity对后者的使用。
  Unity的Shader中通过multi_compile和shader_feature来定义宏(keyword)。
  在这里插入图片描述

#pragma
### Unity 中如何使用 Shader Variant Collection 优化 Shader 变体管理 Shader 变体Shader Variants)是 Unity 根据不同材质属性、光照模型、渲染队列等生成的不同 Shader 版本。虽然这些变体提供了灵活的渲染选项,但过多的变体会显著增加构建体积和加载时间。为了解决这一问题,Unity 提供了 **Shader Variant Collection** 工具,用于集中管理和优化变体的使用[^2]。 #### 创建与配置 Shader Variant Collection 在 Unity 编辑器中,可以通过菜单 `Create > Shader > Shader Variant Collection` 创建一个 Shader Variant Collection 文件。该文件可以包含多个 Shader变体组合,并支持手动添加或自动收集变体[^3]。 ```csharp // 示例:通过脚本加载 Shader Variant Collection 并进行预加载 ShaderVariantCollection svc = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>("Assets/MyShaderVariants.shadervariants"); svc.WarmUp(); ``` #### 变体剔除与优化 Shader Variant Collection 支持在构建时进行变体剔除(Shader Variant Stripping),即根据设定的规则剔除未使用的变体。这可以通过设置特定的关键字组合来控制哪些变体被保留,哪些被移除。这样可以减少最终构建的包体积和运行时的内存占用[^1]。 此外,Unity 2022.3 开始支持“严格的着色器变体匹配(Strict Shader Variant Matching)”选项,确保 Unity 只尝试加载与所需本地和全局关键字组合完全匹配的变体,从而进一步优化变体加载效率[^4]。 #### 预编译与运行时 Warmup Shader Variant Collection 还支持预编译机制。通过调用 `WarmUp()` 方法,可以在运行时或启动时预加载所有指定的变体,避免在实际渲染时因变体未编译而导致性能抖动。这种方式特别适用于 Addressable 资源加载流程中,可以显著减少重复编译的开销。 #### 与 Addressable 资源系统的集成 在 Addressable Asset System 中,将 Shader Variant Collection 作为独立资源打包,并在构建时加载这些集合,可以有效控制 Shader 变体的编译时机和频率。通过资源依赖分析,仅在 Shader 或其依赖项发生变化时才重新构建相关资源包,从而避免不必要的 Shader 编译[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值