123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // Licensed under the MIT License.
- using System;
- using UnityEditor;
- using UnityEngine;
- using UnityEngine.Rendering;
- using Object = UnityEngine.Object;
- /// <summary>
- /// A custom base shader inspector for ShadowSDK shaders.
- /// </summary>
- public abstract class ShadowShaderGUI : ShaderGUI {
- protected enum RenderingMode {
- Opaque,
- TransparentCutout,
- Transparent,
- PremultipliedTransparent,
- Additive,
- Custom
- }
- protected enum CustomRenderingMode {
- Opaque,
- TransparentCutout,
- Transparent
- }
- protected enum DepthWrite {
- Off,
- On
- }
- protected static class BaseStyles {
- public static string renderingOptionsTitle = "Rendering Options";
- public static string advancedOptionsTitle = "Advanced Options";
- public static string renderTypeName = "RenderType";
- public static string renderingModeName = "_Mode";
- public static string customRenderingModeName = "_CustomMode";
- public static string sourceBlendName = "_SrcBlend";
- public static string destinationBlendName = "_DstBlend";
- public static string blendOperationName = "_BlendOp";
- public static string depthTestName = "_ZTest";
- public static string depthWriteName = "_ZWrite";
- public static string depthOffsetFactorName = "_ZOffsetFactor";
- public static string depthOffsetUnitsName = "_ZOffsetUnits";
- public static string colorWriteMaskName = "_ColorWriteMask";
- public static string cullModeName = "_CullMode";
- public static string renderQueueOverrideName = "_RenderQueueOverride";
- public static string alphaTestOnName = "_ALPHATEST_ON";
- public static string alphaBlendOnName = "_ALPHABLEND_ON";
- public static readonly string[] renderingModeNames = Enum.GetNames(typeof(RenderingMode));
- public static readonly string[] customRenderingModeNames = Enum.GetNames(typeof(CustomRenderingMode));
- public static readonly string[] depthWriteNames = Enum.GetNames(typeof(DepthWrite));
- public static GUIContent sourceBlend = new GUIContent("Source Blend", "Blend Mode of Newly Calculated Color");
- public static GUIContent destinationBlend = new GUIContent("Destination Blend", "Blend Mode of Existing Color");
- public static GUIContent blendOperation = new GUIContent("Blend Operation", "Operation for Blending New Color With Existing Color");
- public static GUIContent depthTest = new GUIContent("Depth Test", "How Should Depth Testing Be Performed.");
- public static GUIContent depthWrite = new GUIContent("Depth Write", "Controls Whether Pixels From This Material Are Written to the Depth Buffer");
- public static GUIContent depthOffsetFactor = new GUIContent("Depth Offset Factor", "Scales the Maximum Z Slope, with Respect to X or Y of the Polygon");
- public static GUIContent depthOffsetUnits = new GUIContent("Depth Offset Units", "Scales the Minimum Resolvable Depth Buffer Value");
- public static GUIContent colorWriteMask = new GUIContent("Color Write Mask", "Color Channel Writing Mask");
- public static GUIContent cullMode = new GUIContent("Cull Mode", "Triangle Culling Mode");
- public static GUIContent renderQueueOverride = new GUIContent("Render Queue Override", "Manually Override the Render Queue");
- }
- protected bool initialized;
- protected MaterialProperty renderingMode;
- protected MaterialProperty customRenderingMode;
- protected MaterialProperty sourceBlend;
- protected MaterialProperty destinationBlend;
- protected MaterialProperty blendOperation;
- protected MaterialProperty depthTest;
- protected MaterialProperty depthWrite;
- protected MaterialProperty depthOffsetFactor;
- protected MaterialProperty depthOffsetUnits;
- protected MaterialProperty colorWriteMask;
- protected MaterialProperty cullMode;
- protected MaterialProperty renderQueueOverride;
- protected const string LegacyShadersPath = "Legacy Shaders/";
- protected const string TransparentShadersPath = "/Transparent/";
- protected const string TransparentCutoutShadersPath = "/Transparent/Cutout/";
- public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) {
- Material material = (Material)materialEditor.target;
- FindProperties(props);
- Initialize(material);
- RenderingModeOptions(materialEditor);
- }
- protected virtual void FindProperties(MaterialProperty[] props) {
- renderingMode = FindProperty(BaseStyles.renderingModeName, props);
- customRenderingMode = FindProperty(BaseStyles.customRenderingModeName, props);
- sourceBlend = FindProperty(BaseStyles.sourceBlendName, props);
- destinationBlend = FindProperty(BaseStyles.destinationBlendName, props);
- blendOperation = FindProperty(BaseStyles.blendOperationName, props);
- depthTest = FindProperty(BaseStyles.depthTestName, props);
- depthWrite = FindProperty(BaseStyles.depthWriteName, props);
- depthOffsetFactor = FindProperty(BaseStyles.depthOffsetFactorName, props);
- depthOffsetUnits = FindProperty(BaseStyles.depthOffsetUnitsName, props);
- colorWriteMask = FindProperty(BaseStyles.colorWriteMaskName, props);
- cullMode = FindProperty(BaseStyles.cullModeName, props);
- renderQueueOverride = FindProperty(BaseStyles.renderQueueOverrideName, props);
- }
- protected void Initialize(Material material) {
- if(!initialized) {
- MaterialChanged(material);
- initialized = true;
- }
- }
- protected virtual void MaterialChanged(Material material) {
- SetupMaterialWithRenderingMode(material,
- (RenderingMode)renderingMode.floatValue,
- (CustomRenderingMode)customRenderingMode.floatValue,
- (int)renderQueueOverride.floatValue);
- }
- protected void RenderingModeOptions(MaterialEditor materialEditor) {
- EditorGUI.BeginChangeCheck();
- EditorGUI.showMixedValue = renderingMode.hasMixedValue;
- RenderingMode mode = (RenderingMode)renderingMode.floatValue;
- EditorGUI.BeginChangeCheck();
- mode = (RenderingMode)EditorGUILayout.Popup(renderingMode.displayName, (int)mode, BaseStyles.renderingModeNames);
- if(EditorGUI.EndChangeCheck()) {
- materialEditor.RegisterPropertyChangeUndo(renderingMode.displayName);
- renderingMode.floatValue = (float)mode;
- Object[] targets = renderingMode.targets;
- foreach(Object target in targets) {
- MaterialChanged((Material)target);
- }
- }
- EditorGUI.showMixedValue = false;
- if((RenderingMode)renderingMode.floatValue == RenderingMode.Custom) {
- EditorGUI.indentLevel += 2;
- customRenderingMode.floatValue = EditorGUILayout.Popup(customRenderingMode.displayName, (int)customRenderingMode.floatValue, BaseStyles.customRenderingModeNames);
- materialEditor.ShaderProperty(sourceBlend, BaseStyles.sourceBlend);
- materialEditor.ShaderProperty(destinationBlend, BaseStyles.destinationBlend);
- materialEditor.ShaderProperty(blendOperation, BaseStyles.blendOperation);
- materialEditor.ShaderProperty(depthTest, BaseStyles.depthTest);
- depthWrite.floatValue = EditorGUILayout.Popup(depthWrite.displayName, (int)depthWrite.floatValue, BaseStyles.depthWriteNames);
- materialEditor.ShaderProperty(depthOffsetFactor, BaseStyles.depthOffsetFactor);
- materialEditor.ShaderProperty(depthOffsetUnits, BaseStyles.depthOffsetUnits);
- materialEditor.ShaderProperty(colorWriteMask, BaseStyles.colorWriteMask);
- EditorGUI.indentLevel -= 2;
- }
- if(!PropertyEnabled(depthWrite)) {
- }
- materialEditor.ShaderProperty(cullMode, BaseStyles.cullMode);
- }
- protected static void SetupMaterialWithRenderingMode(Material material, RenderingMode mode, CustomRenderingMode customMode, int renderQueueOverride) {
- // If we aren't switching to Custom, then set default values for all RenderingMode types. Otherwise keep whatever user had before
- if(mode != RenderingMode.Custom) {
- material.SetInt(BaseStyles.blendOperationName, (int)BlendOp.Add);
- material.SetInt(BaseStyles.depthTestName, (int)CompareFunction.LessEqual);
- material.SetFloat(BaseStyles.depthOffsetFactorName, 0.0f);
- material.SetFloat(BaseStyles.depthOffsetUnitsName, 0.0f);
- material.SetInt(BaseStyles.colorWriteMaskName, (int)ColorWriteMask.All);
- }
- switch(mode) {
- case RenderingMode.Opaque: {
- material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Opaque]);
- material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Opaque);
- material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
- material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.Zero);
- material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.On);
- material.DisableKeyword(BaseStyles.alphaTestOnName);
- material.DisableKeyword(BaseStyles.alphaBlendOnName);
- material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Geometry;
- }
- break;
- case RenderingMode.TransparentCutout: {
- material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.TransparentCutout]);
- material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.TransparentCutout);
- material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
- material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.Zero);
- material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.On);
- material.EnableKeyword(BaseStyles.alphaTestOnName);
- material.DisableKeyword(BaseStyles.alphaBlendOnName);
- material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.AlphaTest;
- }
- break;
- case RenderingMode.Transparent: {
- material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Transparent]);
- material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Transparent);
- material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.SrcAlpha);
- material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.OneMinusSrcAlpha);
- material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
- material.DisableKeyword(BaseStyles.alphaTestOnName);
- material.EnableKeyword(BaseStyles.alphaBlendOnName);
- material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
- }
- break;
- case RenderingMode.PremultipliedTransparent: {
- material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Transparent]);
- material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Transparent);
- material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
- material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.OneMinusSrcAlpha);
- material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
- material.DisableKeyword(BaseStyles.alphaTestOnName);
- material.EnableKeyword(BaseStyles.alphaBlendOnName);
- material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
- }
- break;
- case RenderingMode.Additive: {
- material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Transparent]);
- material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Transparent);
- material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
- material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.One);
- material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
- material.DisableKeyword(BaseStyles.alphaTestOnName);
- material.EnableKeyword(BaseStyles.alphaBlendOnName);
- material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
- }
- break;
- case RenderingMode.Custom: {
- material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.customRenderingModeNames[(int)customMode]);
- // _SrcBlend, _DstBlend, _BlendOp, _ZTest, _ZWrite, _ColorWriteMask are controlled by UI.
- switch(customMode) {
- case CustomRenderingMode.Opaque: {
- material.DisableKeyword(BaseStyles.alphaTestOnName);
- material.DisableKeyword(BaseStyles.alphaBlendOnName);
- }
- break;
- case CustomRenderingMode.TransparentCutout: {
- material.EnableKeyword(BaseStyles.alphaTestOnName);
- material.DisableKeyword(BaseStyles.alphaBlendOnName);
- }
- break;
- case CustomRenderingMode.Transparent: {
- material.DisableKeyword(BaseStyles.alphaTestOnName);
- material.EnableKeyword(BaseStyles.alphaBlendOnName);
- }
- break;
- }
- material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : material.renderQueue;
- }
- break;
- }
- }
- /// <summary>
- /// Check whether shader feature is enabled
- /// </summary>
- /// <param name="property">float property to check against</param>
- /// <returns>false if 0.0f, true otherwise</returns>
- protected static bool PropertyEnabled(MaterialProperty property) {
- return !property.floatValue.Equals(0.0f);
- }
- /// <summary>
- /// Get the value of a given float property for a material
- /// </summary>
- /// <param name="material">material to check</param>
- /// <param name="propertyName">name of property against material</param>
- /// <returns>if has property, then value of that property for current material, null otherwise</returns>
- protected static float? GetFloatProperty(Material material, string propertyName) {
- if(material.HasProperty(propertyName)) {
- return material.GetFloat(propertyName);
- }
- return null;
- }
- /// <summary>
- /// Get the value of a given vector property for a material
- /// </summary>
- /// <param name="material">material to check</param>
- /// <param name="propertyName">name of property against material</param>
- /// <returns>if has property, then value of that property for current material, null otherwise</returns>
- protected static Vector4? GetVectorProperty(Material material, string propertyName) {
- if(material.HasProperty(propertyName)) {
- return material.GetVector(propertyName);
- }
- return null;
- }
- /// <summary>
- /// Get the value of a given color property for a material
- /// </summary>
- /// <param name="material">material to check</param>
- /// <param name="propertyName">name of property against material</param>
- /// <returns>if has property, then value of that property for current material, null otherwise</returns>
- protected static Color? GetColorProperty(Material material, string propertyName) {
- if(material.HasProperty(propertyName)) {
- return material.GetColor(propertyName);
- }
- return null;
- }
- /// <summary>
- /// Sets the shader feature controlled by keyword and property name parameters active or inactive
- /// </summary>
- /// <param name="material">Material to modify</param>
- /// <param name="keywordName">Keyword of shader feature</param>
- /// <param name="propertyName">Associated property name for shader feature</param>
- /// <param name="propertyValue">float to be treated as a boolean flag for setting shader feature active or inactive</param>
- protected static void SetShaderFeatureActive(Material material, string keywordName, string propertyName, float? propertyValue) {
- if(propertyValue.HasValue) {
- if(keywordName != null) {
- if(!propertyValue.Value.Equals(0.0f)) {
- material.EnableKeyword(keywordName);
- } else {
- material.DisableKeyword(keywordName);
- }
- }
- material.SetFloat(propertyName, propertyValue.Value);
- }
- }
- /// <summary>
- /// Sets vector property against associated material
- /// </summary>
- /// <param name="material">material to control</param>
- /// <param name="propertyName">name of property to set</param>
- /// <param name="propertyValue">value of property to set</param>
- protected static void SetVectorProperty(Material material, string propertyName, Vector4? propertyValue) {
- if(propertyValue.HasValue) {
- material.SetVector(propertyName, propertyValue.Value);
- }
- }
- /// <summary>
- /// Set color property against associated material
- /// </summary>
- /// <param name="material">material to control</param>
- /// <param name="propertyName">name of property to set</param>
- /// <param name="propertyValue">value of property to set</param>
- protected static void SetColorProperty(Material material, string propertyName, Color? propertyValue) {
- if(propertyValue.HasValue) {
- material.SetColor(propertyName, propertyValue.Value);
- }
- }
- }
|