shader打包到AB包后,没有包含到UnityShaderVariant导致模型变黑的问题

ShaderVariant
    在shader最终编译时,根据上层的宏定义,根据不同的组合编译出多套底层shader.
    Unity的Shader中通过multi_compile和shader_feature来定义宏(keyword)。最终编译的时候也是根据这些宏来编译成多种组合形式的Shader源码。其中每一种组合就是这个Uniy Shader的一个Variant
Material与ShaderVariant的关系
    一个Material同一时刻只能对应它所使用的Shader的一个variant。进行切换的要使用Material.EnableKeyword()和Material.DisableKeyword()来开关对应的宏,
    Unity会根据你设定的组合来匹配响应的shader variant进行渲染
    Shader.EnableKeyword,和Shader.DisableKeyword是对Shader进行全局宏设置
    built-in Shader的源码中的StandardShaderGUI.cs可以看到unity是怎么处理对于StandardShader的keyword设置的
multi_compile和shader_feature的区别
    如果你在shader中添加了
    #pragma multi_compile  _A _B
    #pragma multi_compile  _C _D
  那么无论这些宏是否真的被用到,你的shader都会被Unity编译成四个variant,分别包含了_A _C,_A _D, _B _C,_B _D四种keyword组合的代码
    如果是
    #pragma shader_feature _A _B
    #pragma shader_feature _C _D
  那么你的shader只会保留生成被用到的keyword组合的variant
判定feature是否被用到的机制
    1.如果shader没有与使用它的材质打在一个AB中,那么shader_feature的所有宏相关的代码都不会被包含进AB包中(有一种例外,就是当shader_feature _A这种形式的时候是可以的),这个shader最终被程序从AB包中拿出来使用也会是错误的(粉红色).
  2.把shader和使用它的材质放到一个AB包中,但是材质中没有保存任何的keyword信息(你再编辑器中也是这种情况),shader_feature会默认的把第一个keyword也就是上面的_A和_C(即每个shader_feature的第一个)作为你的选择。而不会把_A _D,_B _C,_B _D这三种组合的代码编译到AB包中。
  3.把shader和使用它的材质放到一个AB包中,并且材质保存了keyword信息(_A _C)为例,那么这个AB包就只包含_A _C的shaderVariant.
解决方案是 ShaderVariantCollection
    ShaderVariantCollection(简称SVC),这个SVC文件可以指定某个shader要编译都要编译带有哪些keyword的变种。并且在ProjectSetting->Graphics界面新加了一个Preloaded Shaders列表,
    可以把SVC文件放进去,编译时指定的Shader就会按照SVC中的设置进行正确的variant生成,而不会像Always Include Shaders列表中的那样全部变种都生成
另外2种方法,但会编译所有变体,导致包体变大
1.把Shader放到在ProjectSetting->Graphics->Always Include Shaders列表里,Unity就会编译所有的组合变种。
2.把Shader放到Resources文件夹下,也会正确处理,也应该是全部keyword组合都编译

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章