您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
190 行
8.5 KiB
190 行
8.5 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);
|
|
|
|
if (receiveShadowsProp != null)
|
|
{
|
|
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();
|
|
}
|
|
}
|