using System; using UnityEngine.Scripting.APIUpdating; namespace UnityEngine.Rendering { /// /// Material quality flags. /// [Flags] [MovedFrom("Utilities")] public enum MaterialQuality { /// Low Material Quality. Low = 1 << 0, /// Medium Material Quality. Medium = 1 << 1, /// High Material Quality. High = 1 << 2 } /// /// Material Quality utility class. /// [MovedFrom("Utilities")] public static class MaterialQualityUtilities { /// /// Keywords strings for Material Quality levels. /// public static string[] KeywordNames = { "MATERIAL_QUALITY_LOW", "MATERIAL_QUALITY_MEDIUM", "MATERIAL_QUALITY_HIGH", }; /// /// String representation of the MaterialQuality enum. /// public static string[] EnumNames = Enum.GetNames(typeof(MaterialQuality)); /// /// Keywords for Material Quality levels. /// public static ShaderKeyword[] Keywords = { new ShaderKeyword(KeywordNames[0]), new ShaderKeyword(KeywordNames[1]), new ShaderKeyword(KeywordNames[2]), }; /// /// Returns the highest available quality level in a MaterialQuality bitfield. /// /// Input MaterialQuality bitfield. /// The highest available quality level. public static MaterialQuality GetHighestQuality(this MaterialQuality levels) { for (var i = Keywords.Length - 1; i >= 0; --i) { var level = (MaterialQuality)(1 << i); if ((levels & level) != 0) return level; } return 0; } /// /// Returns the closest available quality level in a MaterialQuality bitfield. /// /// Available MaterialQuality bitfield. /// Input MaterialQuality level. /// The closest available quality level. public static MaterialQuality GetClosestQuality(this MaterialQuality availableLevels, MaterialQuality requestedLevel) { // Special fallback when there are no available quality levels. Needs to match in the shader stripping code if (availableLevels == 0) return MaterialQuality.Low; // First we want to find the closest available quality level below the requested one. int requestedLevelIndex = ToFirstIndex(requestedLevel); MaterialQuality chosenQuality = (MaterialQuality)0; for (int i = requestedLevelIndex; i >= 0; --i) { var level = FromIndex(i); if ((level & availableLevels) != 0) { chosenQuality = level; break; } } if (chosenQuality != 0) return chosenQuality; // If none is found then we fallback to the closest above. for (var i = requestedLevelIndex + 1; i < Keywords.Length; ++i) { var level = FromIndex(i); var diff = Math.Abs(requestedLevel - level); if ((level & availableLevels) != 0) { chosenQuality = level; break; } } Debug.Assert(chosenQuality != 0); return chosenQuality; } /// /// Set the global keyword for the provided MaterialQuality. /// /// MaterialQuality level to set the keyword for. public static void SetGlobalShaderKeywords(this MaterialQuality level) { for (var i = 0; i < KeywordNames.Length; ++i) { if ((level & (MaterialQuality)(1 << i)) != 0) Shader.EnableKeyword(KeywordNames[i]); else Shader.DisableKeyword(KeywordNames[i]); } } /// /// Set the global keyword for the provided MaterialQuality. /// /// MaterialQuality level to set the keyword for. /// Command Buffer used to setup the keyword. public static void SetGlobalShaderKeywords(this MaterialQuality level, CommandBuffer cmd) { for (var i = 0; i < KeywordNames.Length; ++i) { if ((level & (MaterialQuality)(1 << i)) != 0) cmd.EnableShaderKeyword(KeywordNames[i]); else cmd.DisableShaderKeyword(KeywordNames[i]); } } /// /// Returns the index (in the MaterialQuality enum) of the first available level. /// /// MaterialQuality bitfield. /// The index of the first available level. public static int ToFirstIndex(this MaterialQuality level) { for (var i = 0; i < KeywordNames.Length; ++i) { if ((level & (MaterialQuality)(1 << i)) != 0) return i; } return -1; } /// /// Returns the enum equivalent of the index in the MaterialQuality enum list. /// /// Index of the material quality. /// The equivalent enum. public static MaterialQuality FromIndex(int index) => (MaterialQuality)(1 << index); } }