在URP中PBR的材质是Lit.shader,由于项目组需要拓展不得不仿照它的写法在写一堆C#的代码来配合面板的显示,一方面容易出BUG另一方面非常麻烦。
首先复制一个Lit.shader改成MyLit.shader放到Asset目录下,Properties属性面板中下面写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Properties { //... [ext][Foldout] _MytestName("溶解面板",Range (0,1)) = 0 [ext][if(_MytestName)] [Toggle(GAME_TEST)] _Mytest ("启动溶解宏", Float) = 0 [ext][if(_MytestName)] _Value("溶解参数1",Range (0,1)) = 0 [ext][if(_MytestName)] [SingleLine] _MainTex2 ("溶解图", 2D) = "white" {} [ext][if(_MytestName)] [SingleLine] [Normal] _MainTex3 ("溶解图2", 2D) = "white" {} [ext][if(_MytestName)] [PowerSlider(3.0)] _Shininess ("溶解参数3", Range (0.01, 1)) = 0.08 [ext][if(_MytestName)] [IntRange] _Alpha ("溶解参数4", Range (0, 255)) = 100 [ext][Foldout] _Mytest2Name("特殊面板",Range (0,1)) = 0 [ext][if(_Mytest2Name)] [Toggle] _Mytest2 ("启动特殊宏", Float) = 0 [ext][if(_Mytest2Name)] _FirstColor("特殊颜色", Color) = (1, 1, 1, 1) [ext][if(_Mytest2Name)] _FirstValue("特殊向量", Vector) = (1, 1, 1, 1) } |
[ext]标签用于区分这个属性是我们新加的还是URP自带的。
[Foldout]标签用于面板展开关闭
[if(xxx)]标签表示将一种效果所用到的属性归类。
在Shader的最下面使用自己的面板
CustomEditor “LitShader”
由于原版的LitShader.cs是内部类,需要拷贝出来一份,我这里使用partial类将它们分开。如下代码所示
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
using System; using System.Collections.Generic; using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; partial class LitShader : BaseShaderGUI { //自定义效果-单行显示图片 internal class SingleLineDrawer : MaterialPropertyDrawer { public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { editor.TexturePropertySingleLine(label, prop); } public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) { return 0; } } //自定义效果-折行显示图片 internal class FoldoutDrawer : MaterialPropertyDrawer { bool showPosition; public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) { showPosition = EditorGUILayout.Foldout(showPosition, label); prop.floatValue = Convert.ToSingle(showPosition); } public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) { return 0; } } static Dictionary<string, MaterialProperty> s_MaterialProperty = new Dictionary<string, MaterialProperty>(); static List<MaterialData> s_List = new List<MaterialData>(); public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties) { base.OnGUI(materialEditorIn, properties); EditorGUILayout.Space(); Shader shader = (materialEditor.target as Material).shader; s_List.Clear(); s_MaterialProperty.Clear(); for (int i = 0; i < properties.Length; i++) { var propertie = properties[i]; var attributes = shader.GetPropertyAttributes(i); foreach (var item in attributes) { if (item.Contains("ext")) { if (!s_MaterialProperty.ContainsKey(propertie.name)) { s_MaterialProperty[propertie.name] = propertie; s_List.Add(new MaterialData() { prop = propertie, indentLevel = false }); } } else if (item.Contains("Toggle")) { //根据Toggle标签每帧启动宏 if (s_MaterialProperty.TryGetValue(propertie.name, out var __)) { if (propertie.type == MaterialProperty.PropType.Float) { string keyword = ""; Match match = Regex.Match(item, @"(\w+)\s*\((.*)\)"); if (match.Success) keyword = match.Groups[2].Value.Trim(); if(string.IsNullOrEmpty(keyword)) keyword = propertie.name.ToUpperInvariant() + "_ON"; foreach (Material material in propertie.targets) { if (propertie.floatValue == 1.0f) material.EnableKeyword(keyword); else material.DisableKeyword(keyword); } } } } else if (item.StartsWith("if")) { Match match = Regex.Match(item, @"(\w+)\s*\((.*)\)"); if (match.Success) { var name = match.Groups[2].Value.Trim(); if (s_MaterialProperty.TryGetValue(name, out var a)) { if (a.floatValue == 0f) { //如果有if标签,并且Foldout没有展开不进行绘制 s_List.RemoveAt(s_List.Count - 1); } else s_List[s_List.Count - 1].indentLevel = true; } } } } } PropertiesDefaultGUI(materialEditor, s_List); } public class MaterialData { public MaterialProperty prop; public bool indentLevel = false; } public void PropertiesDefaultGUI(MaterialEditor materialEditor, List<MaterialData> props) { for (int i = 0; i < props.Count; i++) { MaterialProperty prop = props[i].prop; bool indentLevel = props[i].indentLevel; if ((prop.flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) == MaterialProperty.PropFlags.None) { float propertyHeight = materialEditor.GetPropertyHeight(prop, prop.displayName); Rect controlRect = EditorGUILayout.GetControlRect(true, propertyHeight, EditorStyles.layerMaskField); if (indentLevel) EditorGUI.indentLevel++; materialEditor.ShaderProperty(controlRect, prop, prop.displayName); if (indentLevel) EditorGUI.indentLevel--; } } } } |
OK,面板已经拓展在原版Lit.shader下面了,开关启动Toggle就可以不需要在写GUI面板了。
- 本文固定链接: https://www.xuanyusong.com/archives/4947
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!