bool ShaderVariantsEqual(ShaderVariantCollection.ShaderVariant a, ShaderVariantCollection.ShaderVariant b) { if (a.shader != b.shader || a.passType != b.passType) { return(false); } if ((a.keywords == null) != (b.keywords == null)) { return(false); } if (a.keywords.Length != b.keywords.Length) { return(false); } _tempCompareShaderVariants.Clear(); _tempCompareShaderVariants.AddRange(a.keywords); for (int i = 0; i < b.keywords.Length; ++i) { if (!_tempCompareShaderVariants.Contains(b.keywords[i])) { return(false); } } return(true); }
void AddKeywords( ShaderVariantCollection collection, Shader shader, PassType pass, string[] keywordList) { if (CheckKeywords(shader, pass, keywordList)) { List <string> keywords = new List <string>(keywordList); // special case overrides if (shader.name != "Hidden/VideoDecodeAndroid" && shader.name != "Oculus/Texture2D Blit" && !keywords.Contains("SHADOWS_DEPTH")) { keywords.Add("STEREO_MULTIVIEW_ON"); } ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant(); variant.shader = shader; variant.passType = pass; variant.keywords = keywords.ToArray(); collection.Add(variant); } }
/// <summary> /// CSVを読み込んだ文字列リストから要素を作成 /// </summary> /// <param name="csvStrings"></param> /// <returns></returns> private List <ShaderVariantCollection.ShaderVariant> MakeShaderVariantListFromStringList(List <string[]> csvStrings, int keywordColumn, int shderNameColumn) { var returnList = new List <ShaderVariantCollection.ShaderVariant>(); foreach (var csvstr in csvStrings) { var shaderName = csvstr[shderNameColumn]; //shader取得 var sd = Shader.Find(shaderName); if (sd == null) { continue; } //keyword取得 var leywd = GetKeywordFromCSVList(csvstr, keywordColumn); var sdkw = new ShaderVariantCollection.ShaderVariant(); sdkw.shader = sd; sdkw.keywords = leywd; UnityEngine.Rendering.PassType pt; if (GetPassType(csvstr, passTypeColumn, out pt)) { sdkw.passType = pt; } returnList.Add(sdkw); } return(returnList); }
private void ShowShaderVariant(ShaderVariantCollection.ShaderVariant sv, bool isShowShaderName, string expend = "") { using (new GUILayout.HorizontalScope(new GUILayoutOption[0])) { string passTypeName = sv.passType.ToString(); string keysords = ""; if (isShowShaderName) { keysords += sv.shader.name; } for (int j = 0; j < sv.keywords.Length; j++) { if (keysords.Length > 0) { keysords += ","; } keysords += ((keysords.Length > 0) ? "," : "") + sv.keywords[j]; } if (keysords.Length < 1) { keysords = @"<no keywards>"; } if (!string.IsNullOrEmpty(expend)) { keysords += " [" + expend + "]"; } EditorGUILayout.LabelField(passTypeName, keysords); } }
bool CheckKeywords(Shader shader, PassType pass, string[] keywords) { bool valid = false; try { ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant( shader, pass, keywords ); valid = true; } catch (System.ArgumentException) { // if (shader.name == "GUI/Text Shader") // { // Debug.LogFormat( // "Shader {0} pass {1} keywords '{2}' not found", // shader.name, // pass.ToString(), // string.Join(" ", keywords)); // } if (internalShaders.Contains(shader.name) && keywords.Length == 0) { valid = true; } } return(valid); }
/// <summary> /// Collect shader variants from shader files which are under the given path. /// </summary> public void CollectShaderVariants() { if (folders.Length <= 0) { string msg = "Empty folders.\nSpecify folder where shader files are.\nNote the path should start with 'Assets/'."; EditorUtility.DisplayDialog("Error", msg, "OK"); return; } var collection = new ShaderVariantCollection(); var shaders = AssetDatabase.FindAssets("t:Shader", folders); try { foreach (var guid in shaders) { var path = AssetDatabase.GUIDToAssetPath(guid); var shader = AssetDatabase.LoadAssetAtPath <Shader>(path); var variant = new ShaderVariantCollection.ShaderVariant(shader, passType, keywords); collection.Add(variant); } } catch (Exception e) { // Throw an ArgumentException if shader is null, // pass type does not exist or variant with the passed keywords is not found. EditorUtility.DisplayDialog("Error", e.Message, "OK"); } // save as asset. string assetPath = Path.Combine(outputPath, assetFileName + assetFileExt); AssetDatabase.CreateAsset(collection, assetPath); }
private void Draw(Rect windowRect) { Rect rect = new Rect(2f, 2f, windowRect.width - 4f, 16f); this.DrawSectionHeader(ref rect, "Pick shader keywords to narrow down variant list:", false); this.DrawKeywordsList(ref rect, this.m_AvailableKeywords, true); this.DrawSectionHeader(ref rect, "Selected keywords:", true); this.DrawKeywordsList(ref rect, this.m_SelectedKeywords, false); this.DrawSectionHeader(ref rect, "Shader variants with these keywords (click to select):", true); if (this.m_FilteredVariants.Count > 0) { int b = (int)(this.CalcVerticalSpaceForVariants() / 16f); for (int i = 0; i < Mathf.Min(this.m_FilteredVariants.Count, b); i++) { int index = this.m_FilteredVariants[i]; PassType type = (PassType)this.m_Data.types[index]; bool flag = this.m_SelectedVariants.Contains(index); string text = type.ToString() + " " + string.Join(" ", this.m_Data.keywords[index]).ToLowerInvariant(); bool flag2 = GUI.Toggle(rect, flag, text, Styles.sMenuItem); rect.y += rect.height; if (flag2 && !flag) { this.m_SelectedVariants.Add(index); } else if (!flag2 && flag) { this.m_SelectedVariants.Remove(index); } } if (this.m_FilteredVariants.Count > b) { GUI.Label(rect, $"[{this.m_FilteredVariants.Count - b} more variants skipped]", EditorStyles.miniLabel); rect.y += rect.height; } } else { GUI.Label(rect, "No variants with these keywords"); rect.y += rect.height; } rect.y = ((windowRect.height - 2f) - 6f) - 16f; rect.height = 16f; using (new EditorGUI.DisabledScope(this.m_SelectedVariants.Count == 0)) { if (GUI.Button(rect, $"Add {this.m_SelectedVariants.Count} selected variants")) { Undo.RecordObject(this.m_Data.collection, "Add variant"); for (int j = 0; j < this.m_SelectedVariants.Count; j++) { int num5 = this.m_SelectedVariants[j]; ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant(this.m_Data.shader, (PassType)this.m_Data.types[num5], this.m_Data.keywords[num5]); this.m_Data.collection.Add(variant); } base.Close(); GUIUtility.ExitGUI(); } } }
private void Draw(Rect windowRect) { Rect position = new Rect(2f, 2f, windowRect.width - 4f, 16f); this.DrawSectionHeader(ref position, "Pick shader keywords to narrow down variant list:", false); this.DrawKeywordsList(ref position, this.m_AvailableKeywords, true); this.DrawSectionHeader(ref position, "Selected keywords:", true); this.DrawKeywordsList(ref position, this.m_SelectedKeywords, false); this.DrawSectionHeader(ref position, "Shader variants with these keywords (click to select):", true); if (this.m_FilteredVariants.Count > 0) { int num = (int)(this.CalcVerticalSpaceForVariants() / 16f); for (int i = 0; i < Mathf.Min(this.m_FilteredVariants.Count, num); i++) { int num2 = this.m_FilteredVariants[i]; PassType passType = (PassType)this.m_Data.types[num2]; bool flag = this.m_SelectedVariants.Contains(num2); string text = passType.ToString() + " " + string.Join(" ", this.m_Data.keywords[num2]).ToLowerInvariant(); bool flag2 = GUI.Toggle(position, flag, text, AddShaderVariantWindow.Styles.sMenuItem); position.y += position.height; if (flag2 && !flag) { this.m_SelectedVariants.Add(num2); } else if (!flag2 && flag) { this.m_SelectedVariants.Remove(num2); } } if (this.m_FilteredVariants.Count > num) { GUI.Label(position, string.Format("[{0} more variants skipped]", this.m_FilteredVariants.Count - num), EditorStyles.miniLabel); position.y += position.height; } } else { GUI.Label(position, "No variants with these keywords"); position.y += position.height; } position.y = windowRect.height - 2f - 6f - 16f; position.height = 16f; using (new EditorGUI.DisabledScope(this.m_SelectedVariants.Count == 0)) { if (GUI.Button(position, string.Format("Add {0} selected variants", this.m_SelectedVariants.Count))) { Undo.RecordObject(this.m_Data.collection, "Add variant"); for (int j = 0; j < this.m_SelectedVariants.Count; j++) { int num3 = this.m_SelectedVariants[j]; ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant(this.m_Data.shader, (PassType)this.m_Data.types[num3], this.m_Data.keywords[num3]); this.m_Data.collection.Add(variant); } base.Close(); GUIUtility.ExitGUI(); } } }
static ShaderVariantCollection.ShaderVariant CreateVariant(Material mat) { var result = new ShaderVariantCollection.ShaderVariant(); result.shader = mat.shader; result.keywords = mat.shaderKeywords; result.passType = PassType.ScriptableRenderPipeline; return(result); }
private void AddVariantMenuSelected(object userData, string[] options, int selected) { AddVariantMenuData data = (AddVariantMenuData)userData; char[] separator = new char[] { ' ' }; string[] keywords = data.keywords[selected].Split(separator); ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant(data.shader, (PassType)data.types[selected], keywords); Undo.RecordObject(data.collection, "Add variant"); data.collection.Add(variant); }
private void AddVariantMenuSelected(object userData, string[] options, int selected) { ShaderVariantCollectionInspector.AddVariantMenuData addVariantMenuData = (ShaderVariantCollectionInspector.AddVariantMenuData)userData; string[] keywords = addVariantMenuData.keywords[selected].Split(new char[] { ' ' }); ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant(addVariantMenuData.shader, (PassType)addVariantMenuData.types[selected], keywords); Undo.RecordObject(addVariantMenuData.collection, "Add variant"); addVariantMenuData.collection.Add(variant); }
protected void KeywordsChanged() { foreach (PassType passType in GetPassTypes()) { try { ShaderVariantCollection.ShaderVariant shaderVariant = new ShaderVariantCollection.ShaderVariant(GetShader(), passType, keywordsEnabled.ToArray()); if (!shaderVariants.Contains(shaderVariant)) { shaderVariants.Add(shaderVariant); } } catch (Exception _) { // ignored } } }
static void CollectShaderVariants() { var collection = new ShaderVariantCollection(); var folders = new string[] { "Assets/Shaders" }; var shaders = AssetDatabase.FindAssets("t:Shader", folders); foreach (var guid in shaders) { var path = AssetDatabase.GUIDToAssetPath(guid); var shader = AssetDatabase.LoadAssetAtPath <Shader>(path); var variant = new ShaderVariantCollection.ShaderVariant(shader, PassType.ForwardAdd, "DIRECTIONAL", "SHADOWS_OFF"); collection.Add(variant); } AssetDatabase.CreateAsset(collection, "Assets/AutoGenerated.shadervariants"); }
public void LoadShaders(Action initOK = null) { var list = new List <ShaderCollectionInfo>(); resMgr.LoadAssetAsync <Shader>("Shaders", null, delegate(UnityEngine.Object[] objs) { foreach (var item in objs) { var shader = item as Shader; var shaderVarList = new ShaderVariantCollection(); var shaderVariant = new ShaderVariantCollection.ShaderVariant(); shaderVariant.shader = shader; shaderVarList.Add(shaderVariant); list.Add(new ShaderCollectionInfo(shader.name, shaderVarList)); this.AddShader(shader.name, shader); } Utility.Util.StartCoroutine(InitShaderInternal(list, initOK)); }); }
public virtual void AddShaderVariantToCollection(Material material, string extensionCode = null) { if (disableShaderVariantCollection) { return; } #if UNITY_EDITOR if (!Application.isPlaying && shaderBindings != null && shaderVariantCollection != null && !string.IsNullOrEmpty(material.shader.name) && material) { Shader instancedShader = shaderBindings.GetInstancedShader(material.shader.name, extensionCode); if (instancedShader != null) { ShaderVariantCollection.ShaderVariant shaderVariant = new ShaderVariantCollection.ShaderVariant(); shaderVariant.shader = instancedShader; shaderVariant.keywords = material.shaderKeywords; shaderVariantCollection.Add(shaderVariant); } } #endif }
/// <summary> /// 创建Variant /// </summary> /// <param name="shader"></param> /// <param name="passType"></param> /// <param name="keywords"></param> /// <returns></returns> ShaderVariantCollection.ShaderVariant CreateVariant(Shader shader, PassType passType, string[] keywords) { // foreach (var k in keywords) // { // Debug.Log($"{shader.name}:{passType}:{k}"); // } try { // var variant = new ShaderVariantCollection.ShaderVariant(shader, passType, keywords);//这构造函数就是个摆设,铁定抛异常(╯‵□′)╯︵┻━┻ var variant = new ShaderVariantCollection.ShaderVariant(); variant.shader = shader; variant.passType = passType; variant.keywords = keywords; return(variant); } catch (System.Exception e) { Debug.LogError(e); return(new ShaderVariantCollection.ShaderVariant()); } }
// Start is called before the first frame update void Start() { string [] keywords = new string [] { "DIRECTIONAL", "LIGHTPROBE_SH", "_ALPHAPREMULTIPLY_ON" }; ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant( Shader.Find("Standard"), PassType.ForwardBase, keywords); bool match = variants.Contains(variant); Debug.LogFormat( "Shader {0} pass {1} keywords {2} found {3}", variant.shader.name, variant.passType, string.Join(" ", variant.keywords), match); }
public virtual void AddShaderVariantToCollection(string shaderName, string extensionCode = null) { if (disableShaderVariantCollection) { return; } #if UNITY_EDITOR if (!Application.isPlaying && shaderBindings != null && shaderVariantCollection != null && !string.IsNullOrEmpty(shaderName)) { Shader instancedShader = shaderBindings.GetInstancedShader(shaderName, extensionCode); if (instancedShader != null) { ShaderVariantCollection.ShaderVariant shaderVariant = new ShaderVariantCollection.ShaderVariant(); shaderVariant.shader = instancedShader; //shaderVariant.passType = PassType.Normal; shaderVariantCollection.Add(shaderVariant); // To add only the shader without the passtype or keywords, remove the specific variant but the shader remains shaderVariantCollection.Remove(shaderVariant); } } #endif }
public List <ShaderVariantCollection.ShaderVariant> CreateShaderVariantList(EFlag flags) { List <ShaderVariantCollection.ShaderVariant> shaderVariants = new List <ShaderVariantCollection.ShaderVariant>(); var shaderInstance = Shader.Find(this.shader); if (shaderInstance == null) { Debug.LogError("Shader not found " + this.shader); return(shaderVariants); } if (!ShouldExecute(shaderInstance, flags)) { return(shaderVariants); } foreach (var info in shaderDrawInfo) { string[] keywordArray; if (string.IsNullOrEmpty(info.keywords)) { keywordArray = new string[] { "" }; } else { keywordArray = info.keywords.Split(' '); } try { var passType = GetPassType(info.passLightMode); // Debug.Log(info.passLightMode + "->" + passType); ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant(shaderInstance, passType, keywordArray); shaderVariants.Add(variant); } catch (System.Exception e) { Debug.LogError(e); } } return(shaderVariants); }
private void BuildShaderInfos() { var shaderPaths = AssetDatabase.FindAssets("t:shader") .Select(x => AssetDatabase.GUIDToAssetPath(x)) .ToArray(); if (targetFolder != null) { var folderPath = AssetDatabase.GetAssetPath(targetFolder); shaderPaths = shaderPaths.Where(x => x.StartsWith(folderPath)).ToArray(); } shaderInfos.Clear(); foreach (var shaderPath in shaderPaths) { var shader = AssetDatabase.LoadMainAssetAtPath(shaderPath) as Shader; if (shader == null) { continue; } var shaderVariant = new ShaderVariantCollection.ShaderVariant(); shaderVariant.shader = shader; var info = new ShaderInfo() { assetPath = shaderPath, shader = shader, add = shaderVariantCollection.Contains(shaderVariant), shaderVariant = shaderVariant, }; shaderInfos.Add(info); } }
private static void CreateSVC(string svcFileName, List <VariantInfo> variantInfos) { if (variantInfos == null || variantInfos.Count == 0) { return; } ShaderVariantCollection athenaSVC = new ShaderVariantCollection(); for (int i = 0; i < variantInfos.Count; i++) { VariantInfo info = variantInfos[i]; if (info == null || info.keywords == null) { continue; } for (int j = 0; j < info.keywords.Length; j++) { ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant() { shader = info.shader, keywords = new string[1] { info.keywords[j] }, passType = info.passType[j], }; athenaSVC.Add(variant); } } // CreateAsset 的path参数要传 “Assets/Dir/file.postfix" 形式 // // 不能用 Application.dataPath + "/dIR/FILE.postfix" 形式 // #if UNITY_EDITOR AssetDatabase.CreateAsset(athenaSVC, "Assets/KeywordAndMultiCompile/" + svcFileName); AssetDatabase.Refresh(); #endif }
void OnGUI() { svc = (ShaderVariantCollection)EditorGUILayout.ObjectField("ShaderVariantCollection", svc, typeof(ShaderVariantCollection), false); if (svc) { if (GUILayout.Button("Add Select Shader")) { Object[] objs = Selection.objects; foreach (Object obj in objs) { Shader shader = obj as Shader; if (shader == null) { continue; } ShaderVariantCollection.ShaderVariant sv = new ShaderVariantCollection.ShaderVariant(); sv.shader = shader; svc.Add(sv); } } } }
bool CheckKeywords(Shader shader, PassType pass, string[] keywords) { bool valid = false; try { ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant( shader, pass, keywords ); valid = true; } catch (System.ArgumentException) { if (internalShaders.Contains(shader.name) && keywords.Length == 0) { valid = true; } } return(valid); }
private void OnGUI() { EditorGUILayout.BeginVertical(); if (shaderVariantCollection == null) { if (shaderVariantCollection == null) { shaderVariantCollection = new ShaderVariantCollection(); } } for (int i = 0, c = SelectedFolder.Count; i < c; i++) { SelectedFolder[i] = AssetDatabase.GetAssetPath(EditorGUILayout.ObjectField(AssetDatabase.LoadMainAssetAtPath(SelectedFolder[i]), typeof(Object))); } if (GUILayout.Button("Add")) { SelectedFolder.Add(string.Empty); } if (GUILayout.Button("Collect variants")) { Dictionary <string, List <string> > shaderKeywordSupport = new Dictionary <string, List <string> >(); Dictionary <string, UnityEngine.Rendering.PassType> shaderPassType = new Dictionary <string, UnityEngine.Rendering.PassType>(); var materials = AssetDatabase.FindAssets("t:Material", SelectedFolder.ToArray()); shaderVariantCollection.Clear(); for (int i = 0, c = materials.Length; i < c; i++) { var mat = AssetDatabase.LoadAssetAtPath <Material>(AssetDatabase.GUIDToAssetPath(materials[i])); var shader = mat.shader; //Shader shaderNew = Instantiate(shader); //shaderNew.name = "test123"; //AssetDatabase.CreateAsset(shaderNew, "Assets/shader.asset"); var shaderPath = AssetDatabase.GetAssetPath(shader); UnityEngine.Rendering.PassType passType = UnityEngine.Rendering.PassType.ForwardBase; if (shaderPath.StartsWith(builtInShaderSrcPath)) { var shaderGuid = AssetDatabase.AssetPathToGUID(shaderPath); if (!shaderKeywordSupport.ContainsKey(shaderGuid)) { shaderKeywordSupport[shaderGuid] = new List <string>(); UnityEditor.SerializedObject so = new SerializedObject(shader); var parsedForm = so.FindProperty("m_ParsedForm"); var subShaders = parsedForm.FindPropertyRelative("m_SubShaders"); var passes = subShaders.GetArrayElementAtIndex(0).FindPropertyRelative("m_Passes"); //passType= passes.GetArrayElementAtIndex(0).FindPropertyRelative("m_Type").intValue; var firstTag = passes.GetArrayElementAtIndex(0).FindPropertyRelative("m_State").FindPropertyRelative("m_Tags").FindPropertyRelative("tags"). GetArrayElementAtIndex(0); var tagIt = firstTag.GetEnumerator(); tagIt.MoveNext(); bool isLightMode = (tagIt.Current as SerializedProperty).stringValue == "LIGHTMODE"; tagIt.MoveNext(); var lightMode = (tagIt.Current as SerializedProperty).stringValue; lightMode = lightMode.ToUpper(); // Debug.Log(lightMode); if (isLightMode) { if (lightMode == "FORWARDBASE") { passType = UnityEngine.Rendering.PassType.ForwardBase; } else if (lightMode == "DEFERRED") { passType = UnityEngine.Rendering.PassType.Deferred; } else if (lightMode == "FORWARDADD") { passType = UnityEngine.Rendering.PassType.ForwardAdd; } else if (lightMode == "SHADOWCASTER") { passType = UnityEngine.Rendering.PassType.ShadowCaster; } else if (lightMode == "META") { passType = UnityEngine.Rendering.PassType.Meta; } else { passType = UnityEngine.Rendering.PassType.ForwardBase; } } else { passType = UnityEngine.Rendering.PassType.Normal; } //var passType = subShader.FindPropertyRelative("m_SubShaders").GetArrayElementAtIndex(0).GetArrayElementAtIndex(0).FindPropertyRelative("m_Type"); //if (passType != null) //{ // Debug.Log("passType:" + passType.intValue); //} var it = so.GetIterator(); while (it.Next(true)) { var prop = it; if (prop.name == "m_BuiltinKeywords") { if (prop.isArray) { // Debug.Log(prop.stringValue); var keywords = prop.stringValue.Split(" "); shaderKeywordSupport[shaderGuid].AddRange(keywords); //Debug.Log("m_BuiltinKeywords"); } } if (prop.name == "m_NonStrippedUserKeywords") { if (prop.isArray) { // Debug.Log(prop.stringValue); var keywords = prop.stringValue.Split(" "); shaderKeywordSupport[shaderGuid].AddRange(keywords); } } if (prop.name == "m_VariantsUser0") { if (prop.isArray) { for (int propIdx = 0, propC = prop.arraySize; propIdx < propC; propIdx++) { var propVariant = prop.GetArrayElementAtIndex(propIdx); if (propVariant.isArray) { for (int childPropIdx = 0, childPropC = propVariant.arraySize; childPropIdx < childPropC; childPropIdx++) { var variantName = propVariant.GetArrayElementAtIndex(childPropIdx).stringValue; // Debug.Log(variantName); shaderKeywordSupport[shaderGuid].Add(variantName); } } } } } if (prop.name == "keywordName") { // Debug.Log(prop.stringValue); shaderKeywordSupport[shaderGuid].Add(prop.stringValue); } //if (prop.name == "m_CompileInfo") //{ // Debug.Log("m_CompileInfo"); //} } shaderPassType[shaderGuid] = passType; } List <string> matKeywords = new List <string>(); for (int matIdx = 0, matc = mat.shaderKeywords.Length; matIdx < matc; matIdx++) { var shaderMacro = mat.shaderKeywords[matIdx]; if (!string.IsNullOrEmpty(shaderMacro) && shaderKeywordSupport[shaderGuid].Contains(shaderMacro)) { matKeywords.Add(shaderMacro); } } if (matKeywords.Count > 0) { matKeywords.Add("DIRECTIONAL"); } //matKeywords.Add(shaderPassType[shaderGuid].ToString()); foreach (var micro in matKeywords) { Debug.Log("$$ macro:" + micro); } ShaderVariantCollection.ShaderVariant shaderVariant = new ShaderVariantCollection.ShaderVariant( shader, shaderPassType[shaderGuid], matKeywords.ToArray() ); shaderVariantCollection.Add(shaderVariant); } } //Debug.Log(AssetDatabase.GetAssetPath(shaderVariantCollection)); if (AssetDatabase.GetAssetPath(shaderVariantCollection) != "") { AssetDatabase.SaveAssets(); } else { var filePath = UnityEditor.EditorUtility.SaveFilePanelInProject("save variant", "shaderVariantCollection", "asset", "Ok"); AssetDatabase.CreateAsset(shaderVariantCollection, filePath); } } if (GUILayout.Button("Load")) { var filePath = UnityEditor.EditorUtility.OpenFilePanelWithFilters("load variant", "Assets", new string[] { "ShaderVariantCollection", "asset" }); shaderVariantCollection = AssetDatabase.LoadAssetAtPath <ShaderVariantCollection>(filePath); } EditorGUILayout.EndVertical(); }
private void Draw(Rect windowRect) { var rect = new Rect(kMargin, kMargin, windowRect.width - kMargin * 2, EditorGUI.kSingleLineHeight); DrawSectionHeader(ref rect, "Pick shader keywords to narrow down variant list:", false); DrawKeywordsList(ref rect, m_AvailableKeywords, true); DrawSectionHeader(ref rect, "Selected keywords:", true); DrawKeywordsList(ref rect, m_SelectedKeywords, false); DrawSectionHeader(ref rect, "Shader variants with these keywords (click to select):", true); if (m_FilteredVariants.Count > 0) { int maxFilteredLength = (int)(CalcVerticalSpaceForVariants() / EditorGUI.kSingleLineHeight); // Display first N variants (don't want to display thousands of them if filter is not narrow) for (var i = 0; i < Mathf.Min(m_FilteredVariants.Count, maxFilteredLength); ++i) { var index = m_FilteredVariants[i]; var passType = (UnityEngine.Rendering.PassType)m_Data.types[index]; var wasSelected = m_SelectedVariants.Contains(index); var displayString = passType.ToString() + " " + string.Join(" ", m_Data.keywords[index]).ToLowerInvariant(); var isSelected = GUI.Toggle(rect, wasSelected, displayString, Styles.sMenuItem); rect.y += rect.height; if (isSelected && !wasSelected) { m_SelectedVariants.Add(index); } else if (!isSelected && wasSelected) { m_SelectedVariants.Remove(index); } } // show how many variants we skipped due to filter not being narrow enough if (m_FilteredVariants.Count > maxFilteredLength) { GUI.Label(rect, string.Format("[{0} more variants skipped]", m_FilteredVariants.Count - maxFilteredLength), EditorStyles.miniLabel); rect.y += rect.height; } } else { GUI.Label(rect, "No variants with these keywords"); rect.y += rect.height; } // Button to add them at the bottom of popup rect.y = windowRect.height - kMargin - kSpaceHeight - EditorGUI.kSingleLineHeight; rect.height = EditorGUI.kSingleLineHeight; // Disable button if no variants selected using (new EditorGUI.DisabledScope(m_SelectedVariants.Count == 0)) { if (GUI.Button(rect, string.Format("Add {0} selected variants", m_SelectedVariants.Count))) { // Add the selected variants Undo.RecordObject(m_Data.collection, "Add variant"); for (var i = 0; i < m_SelectedVariants.Count; ++i) { var index = m_SelectedVariants[i]; var variant = new ShaderVariantCollection.ShaderVariant(m_Data.shader, (UnityEngine.Rendering.PassType)m_Data.types[index], m_Data.keywords[index]); m_Data.collection.Add(variant); } // Close our popup Close(); GUIUtility.ExitGUI(); } } }
public static void SimpleGenShaderVariant() { //先搜集所有keyword到工具类SVC toolSVC = new ShaderVariantCollection(); var shaders = AssetDatabase.FindAssets("t:Shader", new string[] { "Assets", "Packages" }).ToList(); foreach (var shader in shaders) { ShaderVariantCollection.ShaderVariant sv = new ShaderVariantCollection.ShaderVariant(); var shaderPath = AssetDatabase.GUIDToAssetPath(shader); sv.shader = AssetDatabase.LoadAssetAtPath <Shader>(shaderPath); toolSVC.Add(sv); // allShaderNameList.Add(shaderPath); } var toolsSVCpath = "Assets/Resource/Shaders/Tools.shadervariants"; //防空 FileHelper.WriteAllText(toolsSVCpath, ""); AssetDatabase.DeleteAsset(toolsSVCpath); AssetDatabase.CreateAsset(toolSVC, toolsSVCpath); //搜索所有Mat var paths = BDApplication.GetAllRuntimeDirects().ToArray(); var assets = AssetDatabase.FindAssets("t:Prefab", paths).ToList(); var assets2 = AssetDatabase.FindAssets("t:Material", paths); assets.AddRange(assets2); List <string> allMats = new List <string>(); //GUID to assetPath for (int i = 0; i < assets.Count; i++) { var p = AssetDatabase.GUIDToAssetPath(assets[i]); //获取依赖中的mat var dependenciesPath = AssetDatabase.GetDependencies(p, true); var mats = dependenciesPath.ToList().FindAll((dp) => dp.EndsWith(".mat")); allMats.AddRange(mats); } //处理所有的 material allMats = allMats.Distinct().ToList(); float count = 1; foreach (var mat in allMats) { var obj = AssetDatabase.LoadMainAssetAtPath(mat); if (obj is Material) { var _mat = obj as Material; EditorUtility.DisplayProgressBar("处理mat", string.Format("处理:{0} - {1}", Path.GetFileName(mat), _mat.shader.name), count / allMats.Count); AddToDict(_mat); } count++; } EditorUtility.ClearProgressBar(); //所有的svc ShaderVariantCollection svc = new ShaderVariantCollection(); foreach (var item in ShaderVariantDict) { foreach (var _sv in item.Value) { svc.Add(_sv); } } AssetDatabase.DeleteAsset(ALL_SHADER_VARAINT_PATH); AssetDatabase.CreateAsset(svc, ALL_SHADER_VARAINT_PATH); AssetDatabase.Refresh(); }
/// <summary> /// 添加到Dictionary /// </summary> /// <param name="curMat"></param> static void AddToDict(Material curMat) { if (!curMat || !curMat.shader) { return; } var path = AssetDatabase.GetAssetPath(curMat.shader); if (!allShaderNameList.Contains(path)) { Debug.LogError("不存在shader:" + curMat.shader.name); Debug.Log(path); return; } ShaderData sd = null; ShaderDataDict.TryGetValue(curMat.shader.name, out sd); if (sd == null) { //一次性取出所有的 passtypes 和 keywords sd = GetShaderKeywords(curMat.shader); ShaderDataDict[curMat.shader.name] = sd; } var kwCount = sd.PassTypes.Length; if (kwCount > 2000) { if (!passShaderList.Contains(curMat.shader.name)) { Debug.LogFormat("Shader【{0}】,变体数量:{1},不建议继续分析,后续也会跳过!", curMat.shader.name, kwCount); passShaderList.Add(curMat.shader.name); } else { Debug.LogFormat("mat:{0} , shader:{1} ,keywordCount:{2}", curMat.name, curMat.shader.name, kwCount); } return; } //变体增加规则:https://blog.csdn.net/RandomXM/article/details/88642534 List <ShaderVariantCollection.ShaderVariant> svlist = null; if (!ShaderVariantDict.TryGetValue(curMat.shader.name, out svlist)) { svlist = new List <ShaderVariantCollection.ShaderVariant>(); ShaderVariantDict[curMat.shader.name] = svlist; } //求所有mat的kw for (int i = 0; i < sd.PassTypes.Length; i++) { // var pt = (PassType)sd.PassTypes[i]; ShaderVariantCollection.ShaderVariant?sv = null; try { if (curMat.shaderKeywords.Length > 0) { //变体交集 大于0 ,添加到 svcList sv = new ShaderVariantCollection.ShaderVariant(curMat.shader, pt, curMat.shaderKeywords); } else { sv = new ShaderVariantCollection.ShaderVariant(curMat.shader, pt); } } catch (Exception e) { Debug.LogErrorFormat("{0}-当前shader不存在变体(可以无视):{1}-{2}", curMat.name, pt, JsonMapper.ToJson(curMat.shaderKeywords)); continue; } //判断sv 是否存在,不存在则添加 if (sv != null) { bool isContain = false; var _sv = (ShaderVariantCollection.ShaderVariant)sv; foreach (var val in svlist) { if (val.passType == _sv.passType && System.Linq.Enumerable.SequenceEqual(val.keywords, _sv.keywords)) { isContain = true; break; } } if (!isContain) { svlist.Add(_sv); } } } }
public override void Initialize() { ReplaceOverwrittenCollections(); _tempExcludes.Clear(); if (_allowVrVariants) { _tempExcludes.AddRange(VR_KEYWORDS); } if (_allowInstancedVariants) { _tempExcludes.AddRange(INSTANCING_KEYWORDS); } foreach (var c in _whitelistedCollections) { // Load asset YAML var file = new List <string>(System.IO.File.ReadAllLines( (Application.dataPath + AssetDatabase.GetAssetPath(c)).Replace("AssetsAssets", "Assets") )); #region Pre-process to get rid of mid-list line breaks var yaml = new List <string>(); // Find shaders list int i = 0; for (; i < file.Count; ++i) { if (YamlLineHasKey(file[i], "m_Shaders")) { break; } } // Process and fill int indent = 0; for (; i < file.Count; ++i) { string f = file[i]; int myIndent = GetYamlIndent(f); if (myIndent > indent) { // If no "<key>: ", continuation of previous line if (!f.EndsWith(":") && !f.Contains(": ")) { yaml[yaml.Count - 1] += " " + f.Trim(); continue; } } yaml.Add(f); indent = myIndent; } #endregion #region Iterate over shaders for (i = 0; i < yaml.Count; ++i) { string y = yaml[i]; if (yaml[i].Contains("first:")) { string guid = GetValueFromYaml(y, "guid"); Shader s = AssetDatabase.LoadAssetAtPath <Shader>(AssetDatabase.GUIDToAssetPath(guid)); // Move to variants contents (skip current line, "second:" and "variants:") i += 3; indent = GetYamlIndent(yaml[i]); var sv = new ShaderVariantCollection.ShaderVariant(); for (; i < yaml.Count; ++i) { y = yaml[i]; // If indent changes, variants have ended if (GetYamlIndent(y) != indent) { // Outer loop will increment, so counteract i -= 1; break; } if (IsYamlLineNewEntry(y)) { // First entry will be a new entry but no variant info present yet, so skip // Builtin shaders will also be null if (sv.shader != null) { Dictionary <PassType, List <ShaderVariantCollection.ShaderVariant> > variantsByPass = null; if (!_variantsByShader.TryGetValue(sv.shader, out variantsByPass)) { variantsByPass = new Dictionary <PassType, List <ShaderVariantCollection.ShaderVariant> >(); _variantsByShader.Add(sv.shader, variantsByPass); } List <ShaderVariantCollection.ShaderVariant> variants = null; if (!variantsByPass.TryGetValue(sv.passType, out variants)) { variants = new List <ShaderVariantCollection.ShaderVariant>(); variantsByPass.Add(sv.passType, variants); } bool dupe = false; foreach (var existing in variants) { if (ShaderVariantsEqual(existing, sv)) { dupe = true; break; } } if (!dupe) { variants.Add(sv); } } sv = new ShaderVariantCollection.ShaderVariant(); sv.shader = s; } // Get contents if (YamlLineHasKey(y, "passType")) { sv.passType = (PassType)int.Parse(GetValueFromYaml(y, "passType")); } if (YamlLineHasKey(y, "keywords")) { sv.keywords = GetValuesFromYaml(y, "keywords", _tempExcludes); } } // Get final variant if (sv.shader != null) { Dictionary <PassType, List <ShaderVariantCollection.ShaderVariant> > variantsByPass = null; if (!_variantsByShader.TryGetValue(sv.shader, out variantsByPass)) { variantsByPass = new Dictionary <PassType, List <ShaderVariantCollection.ShaderVariant> >(); _variantsByShader.Add(sv.shader, variantsByPass); } List <ShaderVariantCollection.ShaderVariant> variants = null; if (!variantsByPass.TryGetValue(sv.passType, out variants)) { variants = new List <ShaderVariantCollection.ShaderVariant>(); variantsByPass.Add(sv.passType, variants); } bool dupe = false; foreach (var existing in variants) { if (ShaderVariantsEqual(existing, sv)) { dupe = true; break; } } if (!dupe) { variants.Add(sv); } } } } #endregion LogMessage(this, "Parsing ShaderVariantCollection " + c.name); // Loop over shaders foreach (var s in _variantsByShader) { string log = "Shader: " + s.Key.name; // Loop over passes foreach (var p in s.Value) { log += string.Format("\n Pass: ({1:00}){0}", p.Key, (int)p.Key); // Loop over variants for (int v = 0; v < p.Value.Count; ++v) { log += string.Format("\n Variant [{0}]:\t", v); // Loop over keywords var ks = p.Value[v].keywords; if (ks != null && ks.Length != 0) { bool first = true; foreach (var k in ks) { if (!first) { log += ", "; } log += k; first = false; } } else { log += "<no keywords>"; } } } LogMessage(this, log); } } // Merge collections if (!string.IsNullOrEmpty(_mergeToFile) && _whitelistedCollections.Count > 1) { var svc = new ShaderVariantCollection(); foreach (var a in _variantsByShader) { foreach (var b in a.Value) { foreach (var s in b.Value) { svc.Add(s); } } } try { string file = _mergeToFile + ".shadervariants"; string log = string.Format("Merged following ShaderVariantCollections into {0}:\n", file); foreach (var s in _whitelistedCollections) { log += " " + s.name + "\n"; } if (AssetDatabase.LoadAssetAtPath <ShaderVariantCollection>(file) != null) { AssetDatabase.DeleteAsset(file); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); AssetDatabase.CreateAsset(svc, file); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log(log, AssetDatabase.LoadAssetAtPath <ShaderVariantCollection>(file)); } catch (System.Exception ex) { Debug.LogError("Error merging ShaderVariantCollections. Exception follows."); throw; } } _valid = (_variantsByShader != null && _variantsByShader.Count > 0); }
static void AddToDict(Material curMat) { if (!curMat || !curMat.shader) { return; } ShaderData sd = null; ShaderDataDict.TryGetValue(curMat.shader.name, out sd); if (sd == null) { int[] passtypes = new int[] { }; string[] keywords = new string[] { }; //一次性取出所有的 passtypes 和 keywords GetShaderKeywords(curMat.shader, ref passtypes, ref keywords); sd = new ShaderData(); //kw2list var _keywords = new List <List <string> >(); foreach (var kw in keywords) { var _kws = kw.Split(' '); _keywords.Add(new List <string>(_kws)); } sd.passtypes = passtypes; sd.keywords = _keywords; ShaderDataDict[curMat.shader.name] = sd; } if (sd.passtypes.Length > 20000) { if (!passShaderList.Contains(curMat.shader.name)) { EditorUtility.DisplayDialog("警告", string.Format("Shader【{0}】,变体数量:{1},不建议继续分析,后续也会跳过!", curMat.shader.name, sd.keywords.Count), "OK"); passShaderList.Add(curMat.shader.name); } else { Debug.LogFormat("mat:{0} , shader:{1} ,keywordCount:{2}", curMat.name, curMat.shader.name, sd.passtypes.Length); } return; } //变体增加规则:https://blog.csdn.net/RandomXM/article/details/88642534 // List <ShaderVariantCollection.ShaderVariant> svlist = null; if (!ShaderVariantDict.TryGetValue(curMat.shader.name, out svlist)) { svlist = new List <ShaderVariantCollection.ShaderVariant>(); ShaderVariantDict[curMat.shader.name] = svlist; } //求所有 mat和shader kw的交集 for (int i = 0; i < sd.passtypes.Length; i++) { string[] result = new String[] {}; if (curMat.shaderKeywords.Length > 0) { result = sd.keywords[i].Intersect(curMat.shaderKeywords).ToArray(); } var pt = (PassType)sd.passtypes[i]; ShaderVariantCollection.ShaderVariant?sv = null; try { if (result.Length > 0) { //变体交集 大于0 ,添加到 svcList sv = new ShaderVariantCollection.ShaderVariant(curMat.shader, pt, result); } else { sv = new ShaderVariantCollection.ShaderVariant(curMat.shader, pt); } } catch (Exception e) { if (sd.passtypes.Length < 10000) { Debug.LogError(e); } continue; } if (sv != null) { //判断sv 是否存在 bool isContain = false; var _sv = (ShaderVariantCollection.ShaderVariant)sv; foreach (var val in svlist) { if (val.passType == _sv.passType && System.Linq.Enumerable.SequenceEqual(val.keywords, _sv.keywords)) { isContain = true; break; } } if (!isContain) { svlist.Add(_sv); } } } }
void CheckShaderVariant(ShaderVariantCollection collection, Shader source, int i, bool point = true, bool projector = false) { ShaderVariantList.Clear(); int v = i; int vc = 0; if (v >= 64) { if (!Full) { return; } ShaderVariantList.Add("FULL_ON"); v -= 64; vc++; } else { if (!LowRes) { return; } } if (v >= 32) { if (!Transparency) { return; } ShaderVariantList.Add("VTRANSPARENCY_ON"); v -= 32; vc++; } else { if (!TransparencyOff) { return; } } if (v >= 16) { if (!DensityParticles) { return; } ShaderVariantList.Add("DENSITYPARTICLES_ON"); v -= 16; vc++; } if (v >= 8) { if (!HeightFog) { return; } ShaderVariantList.Add("HEIGHTFOG_ON"); v -= 8; vc++; } else { if (!HeightFogOff) { return; } } if (v >= 4) { if (!Noise) { return; } ShaderVariantList.Add("NOISE_ON"); v -= 4; vc++; } else { if (!NoiseOff) { return; } } if (v >= 2) { if (point) { ShaderVariantList.Add("POINT_COOKIE"); vc++; } v -= 2; } if (v >= 1) { v -= 1; } else { if (!projector) { ShaderVariantList.Add("SHADOWS_OFF"); } vc++; }; string[] fv = new string[vc]; ShaderVariantList.CopyTo(fv); Material m = new Material(source); m.name = ""; EnableKeywordList(m); AssetDatabase.AddObjectToAsset(m, collection); //string final = source.name + " "; //for (int s = 0; s < fv.Length; s++) //{ // final += fv[s] + " "; //} // Debug.Log(final); ShaderVariantCollection.ShaderVariant varient = new ShaderVariantCollection.ShaderVariant(source, PassType.Normal, fv); if (!collection.Contains(varient)) { collection.Add(varient); } //if (shadows && !point && !projector) //{ // ShaderVariantList.Add("SHADOWS_NATIVE"); // string[] fv2 = new string[vc + 1]; // ShaderVariantList.CopyTo(fv2); // // ShaderVariantCollection.ShaderVariant varient2 = new ShaderVariantCollection.ShaderVariant(source, PassType.Normal, fv2); // if (!collection.Contains(varient2)) { collection.Add(varient2); } // // Material m2 = new Material(source); // EnableKeywordList(m2); // m2.name = ""; // AssetDatabase.AddObjectToAsset(m2, collection); // ShaderVariantList.RemoveAt(ShaderVariantList.Count - 1); // // //} if (SinglePassStereo) { ShaderVariantList.Add("UNITY_SINGLE_PASS_STEREO"); string[] fvssp2 = new string[vc + 1]; ShaderVariantList.CopyTo(fvssp2); ShaderVariantCollection.ShaderVariant varientSP = new ShaderVariantCollection.ShaderVariant(source, PassType.Normal, fvssp2); //Hier zit een error maar ik heb geen idee wat dus de gene die dit heeft geschreven check het! if (!collection.Contains(varientSP)) { collection.Add(varientSP); } Material m2 = new Material(source); EnableKeywordList(m2); m2.name = ""; AssetDatabase.AddObjectToAsset(m2, collection); // if (shadows && !point && !projector) // { // ShaderVariantList.Add("SHADOWS_NATIVE"); // string[] fv2 = new string[vc + 2]; // ShaderVariantList.CopyTo(fv2); // // ShaderVariantCollection.ShaderVariant varient2 = new ShaderVariantCollection.ShaderVariant(source, PassType.Normal, fv2); // if (!collection.Contains(varient2)) { collection.Add(varient2); } // // Material m3 = new Material(source); // EnableKeywordList(m3); // m3.name = ""; // AssetDatabase.AddObjectToAsset(m3, collection); // // } } }