您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

186 行
8.4 KiB

using System;
using UnityEditor;
using UnityEngine;
public abstract class LightweightShaderGUI : ShaderGUI
{
public enum SurfaceType
{
Opaque,
Transparent
}
public enum BlendMode
{
Alpha, // Old school alpha-blending mode, fresnel does not affect amount of transparency
Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply
Additive,
Multiply
}
private static class Styles
{
public static string renderingOptionsLabel = "Rendering Options";
public static string surfaceType = "Surface Type";
public static string blendingMode = "Blending Mode";
public static GUIContent twoSidedText = new GUIContent("Two Sided", "Render front and back faces");
public static GUIContent alphaClipText = new GUIContent("Alpha Clip", "Enable Alpha Clip");
public static GUIContent alphaClipThresholdText = new GUIContent("Clip Threshold", "Threshold for alpha clip");
public static GUIContent receiveShadowText = new GUIContent("Receive Shadows", "Enables this material to receive shadows if there is at least one shadow casting light affecting it.");
public static readonly string[] surfaceNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
}
protected MaterialEditor m_MaterialEditor;
protected MaterialProperty surfaceTypeProp;
protected MaterialProperty blendModeProp;
protected MaterialProperty cullingProp;
protected MaterialProperty alphaClipProp;
protected MaterialProperty alphaCutoffProp;
protected MaterialProperty receiveShadowsProp;
private bool m_FirstTimeApply = true;
public abstract void MaterialChanged(Material material);
public virtual void FindProperties(MaterialProperty[] properties)
{
surfaceTypeProp = FindProperty("_Surface", properties);
blendModeProp = FindProperty("_Blend", properties);
cullingProp = FindProperty("_Cull", properties);
alphaClipProp = FindProperty("_AlphaClip", properties);
alphaCutoffProp = FindProperty("_Cutoff", properties);
receiveShadowsProp = FindProperty("_ReceiveShadows", properties, false);
}
public virtual void ShaderPropertiesGUI(Material material)
{
DoPopup(Styles.surfaceType, surfaceTypeProp, Styles.surfaceNames);
if ((SurfaceType)material.GetFloat("_Surface") == SurfaceType.Transparent)
DoPopup(Styles.blendingMode, blendModeProp, Styles.blendNames);
EditorGUI.BeginChangeCheck();
bool twoSidedEnabled = EditorGUILayout.Toggle(Styles.twoSidedText, cullingProp.floatValue == 0);
if (EditorGUI.EndChangeCheck())
cullingProp.floatValue = twoSidedEnabled ? 0 : 2;
EditorGUI.BeginChangeCheck();
bool alphaClipEnabled = EditorGUILayout.Toggle(Styles.alphaClipText, alphaClipProp.floatValue == 1);
if (EditorGUI.EndChangeCheck())
alphaClipProp.floatValue = alphaClipEnabled ? 1 : 0;
if (alphaClipProp.floatValue == 1)
m_MaterialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
EditorGUI.BeginChangeCheck();
bool receiveShadows = EditorGUILayout.Toggle(Styles.receiveShadowText, receiveShadowsProp.floatValue == 1.0f);
if (EditorGUI.EndChangeCheck())
receiveShadowsProp.floatValue = receiveShadows ? 1.0f : 0.0f;
EditorGUILayout.Space();
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
// Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
// material to a lightweight shader.
if (m_FirstTimeApply)
{
MaterialChanged(material);
m_FirstTimeApply = false;
}
ShaderPropertiesGUI(material);
}
public static void SetupMaterialBlendMode(Material material)
{
bool alphaClip = material.GetFloat("_AlphaClip") == 1;
if (alphaClip)
material.EnableKeyword("_ALPHATEST_ON");
else
material.DisableKeyword("_ALPHATEST_ON");
SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface");
if (surfaceType == SurfaceType.Opaque)
{
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
material.SetShaderPassEnabled("ShadowCaster", true);
}
else
{
BlendMode blendMode = (BlendMode)material.GetFloat("_Blend");
switch (blendMode)
{
case BlendMode.Alpha:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
material.SetShaderPassEnabled("ShadowCaster", false);
break;
case BlendMode.Premultiply:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
material.SetShaderPassEnabled("ShadowCaster", false);
break;
case BlendMode.Additive:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
material.SetShaderPassEnabled("ShadowCaster", false);
break;
case BlendMode.Multiply:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
material.SetShaderPassEnabled("ShadowCaster", false);
break;
}
}
}
protected void DoPopup(string label, MaterialProperty property, string[] options)
{
EditorGUI.showMixedValue = property.hasMixedValue;
var mode = property.floatValue;
EditorGUI.BeginChangeCheck();
mode = EditorGUILayout.Popup(label, (int)mode, options);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo(label);
property.floatValue = (float)mode;
}
EditorGUI.showMixedValue = false;
}
protected void DoMaterialRenderingOptions()
{
EditorGUILayout.Space();
GUILayout.Label(Styles.renderingOptionsLabel, EditorStyles.boldLabel);
m_MaterialEditor.EnableInstancingField();
m_MaterialEditor.DoubleSidedGIField();
}
}