材质上可以通过material.shaderKeywords来获取使用到的宏,接着使用ShaderVariantCollection就可以动态创建变种收集器了。
ShaderVariantCollection shaderVariantCollection = new ShaderVariantCollection();
shaderVariantCollection.Add(new ShaderVariantCollection.ShaderVariant(shader, /*passtype*/, keyword));
AssetDatabase.CreateAsset(shaderVariantCollection, collectionPath);
这里面有个巨大的坑就是passtype,比如这里有两个宏A和B同时开启时,因为他俩在不同的LightMode中,所以对应的passType是不同的。
SubShader
{
Pass
{
#pragma multi_feature _ A
}
Pass
{
Tags{"LightMode" = "ShadowCaster"}
#pragma multi_feature _ B
}
}
上个项目我就没有彻底解决它, 今天决定仔细研究研究。我们需要获取每个Pass中定义的宏,以及它们的passType,最终发现还是反射大法好。 核心方法就是通过反射设置每个PassIdentifier在调用shader.FindPassTagValue获取每个Pass设置的LightMode的名称,在通过ShaderUtil.GetPassKeywords获取每个Pass中定义的宏。
for (int i = 0; i < shader.passCount; i++)
{
string shaderTag = shader.FindPassTagValue(i, new ShaderTagId("LightMode")).name;
PassIdentifier identifier = new PassIdentifier();
Type myType = typeof(PassIdentifier);
FieldInfo myFieldInfo = myType.GetField("m_PassIndex", BindingFlags.NonPublic | BindingFlags.Instance);
object asObject = identifier;
myFieldInfo.SetValue(asObject, (uint)i);
identifier = (PassIdentifier)asObject;
Debug.Log(shaderTag); //LightMode 名称
List<string> keyword = new List<string>();
foreach (var item in ShaderUtil.GetPassKeywords(shader, identifier))
{
if(item.type== ShaderKeywordType.UserDefined)
{
keyword.Add(item.name);
}
}
//输出LightMode定义的宏
Debug.Log(string.Join(",", keyword.ToArray()));
}
这里我用URP自带的Lit Shader输出的,可以发现每个Pass下的宏都能找出来了。
有了以上信息就可以带入passtype来生成着色器变种了。 以上代码在Unity2022.1中跑通。
- 本文固定链接: https://www.xuanyusong.com/archives/5027
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!


大哥了,人家分享知识你感谢还来不及呢,更没有义务回复你,还“我也不会见怪的”
虽然你是专精unity的,但是我抱着试试看的态度还是想问一下,你对ue的项目转移到unity上有什么好的见解么?当然不回答我也不会见怪的