using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
///
/// 扩展材质面板
///
public class CustomShaderGUI : ShaderGUI
{
MaterialEditor editor;
Object[] materials;
MaterialProperty[] properties;
bool showPresents;
// 投影模式:开启投影、裁剪投影、抖动投影、关闭投影
enum ShadowMode
{
On, Clip, Dither, Off
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
EditorGUI.BeginChangeCheck();
base.OnGUI(materialEditor, properties);
editor = materialEditor;
materials = materialEditor.targets;
this.properties = properties;
BakedEmission();
EditorGUILayout.Space();
showPresents = EditorGUILayout.Foldout(showPresents, "Presents", true);
if (showPresents)
{
OpaquePreset();
ClipPreset();
FadePreset();
TransparentPreset();
}
// 如果材质属性有被更改,检查阴影模式的设置状态
if (EditorGUI.EndChangeCheck())
{
SetShadowCasterPass();
CopyLightMappingProperties();
}
}
void CopyLightMappingProperties()
{
MaterialProperty mainTex = FindProperty("_MainTex", properties, false);
MaterialProperty baseMap = FindProperty("_BaseMap", properties, false);
if (mainTex != null && baseMap != null) {
mainTex.textureValue = baseMap.textureValue;
mainTex.textureScaleAndOffset = baseMap.textureScaleAndOffset;
}
MaterialProperty color = FindProperty("_Color", properties, false);
MaterialProperty baseColor = FindProperty("_BaseColor", properties, false);
if (color != null && baseColor != null)
{
color.colorValue = baseColor.colorValue;
}
}
///
/// 相关属性存在时可以设置关键字开关
///
///
///
///
void SetProperty(string name, string keyword, bool value)
{
if (SetProperty(name, value ? 1f : 0f))
{
SetKeyword(keyword, value);
}
}
///
/// 设置材质属性
///
///
///
///
bool SetProperty(string name, float value)
{
MaterialProperty property = FindProperty(name, properties, false);
if (property != null)
{
property.floatValue = value;
return true;
}
return false;
}
///
/// 设置关键字状态
///
///
///
void SetKeyword(string keyword, bool enabled)
{
if (enabled)
{
foreach (Material m in materials)
{
m.EnableKeyword(keyword);
}
}
else
{
foreach (Material m in materials)
{
m.DisableKeyword(keyword);
}
}
}
bool Clipping
{
set => SetProperty("_Clipping", "_CLIPPING", value);
}
bool PremultiplyAlpha
{
set => SetProperty("_PremulAlpha", "_PREMULTIPLY_ALPHA", value);
}
BlendMode SrcBlend
{
set => SetProperty("_SrcBlend", (float)value);
}
BlendMode DstBlend
{
set => SetProperty("_DstBlend", (float)value);
}
bool ZWrite
{
set => SetProperty("_ZWrite", value ? 1f : 0f);
}
RenderQueue RenderQueue
{
set
{
foreach (Material m in materials)
{
m.renderQueue = (int)value;
}
}
}
// 如果shader的预乘属性不存在,不需要显示该渲染模式的按钮
bool HasProperty(string name) => FindProperty(name, properties, false) != null;
bool HasPremultiplyAlpha => HasProperty("_PremulAlpha");
bool PresetButton(string name)
{
if (GUILayout.Button(name)) {
editor.RegisterPropertyChangeUndo(name);
return true;
}
return false;
}
///
/// 烘焙自发光
///
void BakedEmission()
{
EditorGUI.BeginChangeCheck();
editor.LightmapEmissionProperty();
if (EditorGUI.EndChangeCheck())
{
foreach (Material m in editor.targets)
{
m.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
}
}
///
/// 不透明材质默认设置
///
void OpaquePreset()
{
if (PresetButton("Opaque"))
{
Clipping = false;
PremultiplyAlpha = false;
SrcBlend = BlendMode.One;
DstBlend = BlendMode.Zero;
ZWrite = true;
RenderQueue = RenderQueue.Geometry;
}
}
///
/// 裁切材质默认设置
///
void ClipPreset()
{
if (PresetButton("Clip"))
{
Clipping = true;
PremultiplyAlpha = false;
SrcBlend = BlendMode.One;
DstBlend = BlendMode.Zero;
ZWrite = true;
RenderQueue = RenderQueue.AlphaTest;
}
}
///
/// 标准透明材质默认设置
///
void FadePreset()
{
if (PresetButton("Fade"))
{
Clipping = false;
PremultiplyAlpha = false;
SrcBlend = BlendMode.SrcAlpha;
DstBlend = BlendMode.OneMinusSrcAlpha;
ZWrite = false;
RenderQueue = RenderQueue.Transparent;
}
}
///
/// 受光正确的透明材质默认设置
///
void TransparentPreset()
{
if (HasPremultiplyAlpha && PresetButton("Transparent"))
{
Clipping = false;
PremultiplyAlpha = true;
SrcBlend = BlendMode.One;
DstBlend = BlendMode.OneMinusSrcAlpha;
ZWrite = false;
RenderQueue = RenderQueue.Transparent;
}
}
ShadowMode Shadows
{
set
{
if (SetProperty("_Shadows", (float)value))
{
SetKeyword("_SHADOWS_CLIP", value == ShadowMode.Clip);
SetKeyword("_SHADOWS_DITHER", value == ShadowMode.Dither);
}
}
}
///
/// 设置材质的ShadowCaster pass块是否启用
///
void SetShadowCasterPass()
{
MaterialProperty shadows = FindProperty("_Shadows", properties, false);
if (shadows == null || shadows.hasMixedValue)
{
return;
}
bool enabled = shadows.floatValue < (float)ShadowMode.Off;
foreach (Material m in materials)
{
m.SetShaderPassEnabled("ShadowCaster", enabled);
}
}
}