// BlendUnlitShaderGUI.cs // Custom Material Inspector for Soullies/BlendUnlit // Drives the GPU Blend equation based on the user-selected Blend Mode. using UnityEditor; using UnityEngine; using UnityEngine.Rendering; public class BlendUnlitShaderGUI : ShaderGUI { // ------------------------------------------------------------------------- // Blend mode definitions // ------------------------------------------------------------------------- enum BlendMode { Alpha = 0, // SrcAlpha, OneMinusSrcAlpha – standard transparency Additive = 1, // SrcAlpha, One – additive / glow, black = invisible Multiply = 2, // DstColor, Zero – darkens below Premultiplied = 3, // One, OneMinusSrcAlpha – pre-multiplied alpha / HDR } static readonly string[] BlendModeNames = { "Alpha (SrcAlpha, 1-SrcAlpha)", "Additive (SrcAlpha, One)", "Multiply (DstColor, Zero)", "Premultiplied (One, 1-SrcAlpha)", }; // Src / Dst for each BlendMode entry static readonly (UnityEngine.Rendering.BlendMode src, UnityEngine.Rendering.BlendMode dst)[] BlendEquations = { (UnityEngine.Rendering.BlendMode.SrcAlpha, UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha), // Alpha (UnityEngine.Rendering.BlendMode.SrcAlpha, UnityEngine.Rendering.BlendMode.One), // Additive (UnityEngine.Rendering.BlendMode.DstColor, UnityEngine.Rendering.BlendMode.Zero), // Multiply (UnityEngine.Rendering.BlendMode.One, UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha), // Premultiplied }; // ------------------------------------------------------------------------- // GUI // ------------------------------------------------------------------------- public override void OnGUI(MaterialEditor editor, MaterialProperty[] props) { Material mat = editor.target as Material; EditorGUI.BeginChangeCheck(); // Draw all standard properties EXCEPT our hidden blend props foreach (var prop in props) { // Hide internal blend-equation float props from inspector if (prop.name == "_SrcBlendRGB" || prop.name == "_DstBlendRGB") continue; // Replace the raw _BlendMode float with our friendly enum popup if (prop.name == "_BlendMode") { EditorGUILayout.Space(4); DrawBlendModePopup(editor, mat, prop); EditorGUILayout.Space(4); continue; } editor.ShaderProperty(prop, prop.displayName); } if (EditorGUI.EndChangeCheck()) { // Apply blend equations to all selected materials foreach (Object obj in editor.targets) { ApplyBlendMode((Material)obj); } } EditorGUILayout.Space(8); editor.RenderQueueField(); editor.EnableInstancingField(); editor.DoubleSidedGIField(); } // ------------------------------------------------------------------------- // Helpers // ------------------------------------------------------------------------- static void DrawBlendModePopup(MaterialEditor editor, Material mat, MaterialProperty prop) { int current = (int)prop.floatValue; current = Mathf.Clamp(current, 0, BlendModeNames.Length - 1); EditorGUI.BeginChangeCheck(); int selected = EditorGUILayout.Popup("Blend Mode", current, BlendModeNames); if (EditorGUI.EndChangeCheck()) { editor.RegisterPropertyChangeUndo("Blend Mode"); prop.floatValue = selected; } } static void ApplyBlendMode(Material mat) { int index = Mathf.Clamp((int)mat.GetFloat("_BlendMode"), 0, BlendEquations.Length - 1); BlendMode mode = (BlendMode)index; // Disable all keyword variants, then enable the correct one mat.DisableKeyword("_BLENDMODE_ALPHA"); mat.DisableKeyword("_BLENDMODE_ADDITIVE"); mat.DisableKeyword("_BLENDMODE_MULTIPLY"); mat.DisableKeyword("_BLENDMODE_PREMULTIPLIED"); switch (mode) { case BlendMode.Alpha: mat.EnableKeyword("_BLENDMODE_ALPHA"); break; case BlendMode.Additive: mat.EnableKeyword("_BLENDMODE_ADDITIVE"); break; case BlendMode.Multiply: mat.EnableKeyword("_BLENDMODE_MULTIPLY"); break; case BlendMode.Premultiplied: mat.EnableKeyword("_BLENDMODE_PREMULTIPLIED"); break; } // Write the actual Blend equation floats that the Shader reads var (src, dst) = BlendEquations[index]; mat.SetFloat("_SrcBlendRGB", (float)src); mat.SetFloat("_DstBlendRGB", (float)dst); // Adjust RenderQueue hint for Multiply mode // (Multiply should typically not write ZBuffer and renders as transparent) if (mode == BlendMode.Multiply) { mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; } else { // Keep queue at Transparent for all other modes (default) if (mat.renderQueue < (int)UnityEngine.Rendering.RenderQueue.Transparent) mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; } EditorUtility.SetDirty(mat); } // Called when the Shader is assigned to a material for the first time public override void AssignNewShaderToMaterial(Material mat, Shader oldShader, Shader newShader) { base.AssignNewShaderToMaterial(mat, oldShader, newShader); ApplyBlendMode(mat); } }