154 lines
5.8 KiB
C#
154 lines
5.8 KiB
C#
// 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);
|
||
}
|
||
}
|