材质上可以通过material.shaderKeywords来获取使用到的宏,接着使用ShaderVariantCollection就可以动态创建变种收集器了。
1 2 3 4 5 |
ShaderVariantCollection shaderVariantCollection = new ShaderVariantCollection(); shaderVariantCollection.Add(new ShaderVariantCollection.ShaderVariant(shader, /*passtype*/, keyword)); AssetDatabase.CreateAsset(shaderVariantCollection, collectionPath); |
这里面有个巨大的坑就是passtype,比如这里有两个宏A和B同时开启时,因为他俩在不同的LightMode中,所以对应的passType是不同的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
SubShader { Pass { #pragma multi_feature _ A } Pass { Tags{"LightMode" = "ShadowCaster"} #pragma multi_feature _ B } } |
上个项目我就没有彻底解决它, 今天决定仔细研究研究。我们需要获取每个Pass中定义的宏,以及它们的passType,最终发现还是反射大法好。 核心方法就是通过反射设置每个PassIdentifier在调用shader.FindPassTagValue获取每个Pass设置的LightMode的名称,在通过ShaderUtil.GetPassKeywords获取每个Pass中定义的宏。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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上有什么好的见解么?当然不回答我也不会见怪的