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详解

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

被折叠的 条评论
为什么被折叠?



