//#if UNITY_EDITOR using System; using UnityEngine; using UnityEditor; class LayaPBRSpecularGUI : ShaderGUI { public enum RenderMode { /**渲染状态_不透明。*/ Opaque = 0, /**渲染状态_透明测试。*/ Cutout = 1, /**渲染状态_透明混合_菲涅尔不影响透明度。*/ Fade = 2, /**渲染状态_透明混合_物理上看似合理的透明。*/ Transparent = 3, /**渲染状态_自定义。*/ Custom = 4 } public enum SrcBlendMode { //Blend factor is (0, 0, 0, 0). Zero = 0, //Blend factor is (1, 1, 1, 1). One = 1, //Blend factor is (Rd, Gd, Bd, Ad). DstColor = 2, //Blend factor is (Rs, Gs, Bs, As). SrcColor = 3, //Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad). OneMinusDstColor = 4, //Blend factor is (As, As, As, As). SrcAlpha = 5, //Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As). OneMinusSrcColor = 6, //Blend factor is (Ad, Ad, Ad, Ad). DstAlpha = 7, //Blend factor is (1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad). OneMinusDstAlpha = 8, //Blend factor is (f, f, f, 1); where f = min(As, 1 - Ad). SrcAlphaSaturate = 9, //Blend factor is (1 - As, 1 - As, 1 - As, 1 - As). OneMinusSrcAlpha = 10 } public enum DstBlendMode { //Blend factor is (0, 0, 0, 0). Zero = 0, //Blend factor is (1, 1, 1, 1). One = 1, //Blend factor is (Rd, Gd, Bd, Ad). DstColor = 2, //Blend factor is (Rs, Gs, Bs, As). SrcColor = 3, //Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad). OneMinusDstColor = 4, //Blend factor is (As, As, As, As). SrcAlpha = 5, //Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As). OneMinusSrcColor = 6, //Blend factor is (Ad, Ad, Ad, Ad). DstAlpha = 7, //Blend factor is (1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad). OneMinusDstAlpha = 8, //Blend factor is (f, f, f, 1); where f = min(As, 1 - Ad). SrcAlphaSaturate = 9, //Blend factor is (1 - As, 1 - As, 1 - As, 1 - As). OneMinusSrcAlpha = 10 } public enum CullMode { CULL_NONE = 0, CULL_FRONT = 1, CULL_BACK = 2, } public enum DepthWrite { OFF = 0, ON = 1 } public enum DepthTest { OFF = 0, Never = 1, LESS = 2, EQUAL = 3, LEQUAL = 4, GREATER = 5, NOTEQUAL = 6, GEQUAL = 7, ALWAYS = 8 } public enum RenderQueue { //Opaque geometry uses this queue. Geometry = 2000, //Alpha tested geometry uses this queue. AlphaTest = 2450, //This render queue is rendered after Geometry and AlphaTest, in back-to-front order. Transparent = 3000, } public enum SmoothnessTextureChannelMode { Specular_Alpha = 0, Albedo_Alpha = 1 } MaterialProperty diffuseTexture = null; MaterialProperty diffuseColor = null; MaterialProperty specularColor = null; MaterialProperty specularTexture = null; MaterialProperty smoothness = null; MaterialProperty smoothnessScale = null; MaterialProperty smoothnessTextureChannel = null; MaterialProperty normalTexture = null; MaterialProperty normalScale = null; MaterialProperty parallaxTexture = null; MaterialProperty parallaxScale = null; MaterialProperty occlusionTexture = null; MaterialProperty occlusionStrength = null; MaterialProperty reflection = null; MaterialProperty emission = null; MaterialProperty emissionTexture = null; MaterialProperty emissionColor = null; MaterialProperty cullMode = null; MaterialProperty renderMode = null; MaterialProperty alphaTest = null; MaterialProperty alphaCutoff = null; MaterialProperty alphaBlend = null; MaterialProperty srcBlendMode = null; MaterialProperty dstBlendMode = null; MaterialProperty depthWrite = null; MaterialProperty depthTest = null; MaterialEditor m_MaterialEditor; bool m_FirstTimeApply = true; public void FindProperties(MaterialProperty[] props) { diffuseTexture = FindProperty("_MainTex", props); diffuseColor = FindProperty("_Color", props); specularColor = FindProperty("_SpecColor", props); specularTexture = FindProperty("_SpecGlossMap", props); smoothness = FindProperty("_Glossiness", props); smoothnessScale = FindProperty("_GlossMapScale", props); smoothnessTextureChannel = FindProperty("_SmoothnessTextureChannel", props); occlusionTexture = FindProperty("_OcclusionMap", props); occlusionStrength = FindProperty("_OcclusionStrength", props); normalTexture = FindProperty("_BumpMap", props); normalScale = FindProperty("_BumpScale", props); parallaxTexture = FindProperty("_ParallaxMap", props); parallaxScale = FindProperty("_Parallax", props); reflection = FindProperty("_Reflection", props); emission = FindProperty("_EnableEmission", props); emissionTexture = FindProperty("_EmissionMap", props); emissionColor = FindProperty("_EmissionColor", props); renderMode = FindProperty("_Mode", props); cullMode = FindProperty("_Cull", props); alphaTest = FindProperty("_AlphaTest", props, false); alphaCutoff = FindProperty("_Cutoff", props, false); alphaBlend = FindProperty("_AlphaBlend", props, false); srcBlendMode = FindProperty("_SrcBlend", props); dstBlendMode = FindProperty("_DstBlend", props); depthWrite = FindProperty("_ZWrite", props); depthTest = FindProperty("_ZTest", props); } public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) { // render the default gui FindProperties(props); m_MaterialEditor = materialEditor; Material material = materialEditor.target as Material; if (m_FirstTimeApply) { onChangeRender(material, (RenderMode)material.GetFloat("_Mode")); m_FirstTimeApply = false; } ShaderPropertiesGUI(material); } public void ShaderPropertiesGUI(Material material) { // Use default labelWidth EditorGUIUtility.labelWidth = 0f; // Detect any changes to the material EditorGUI.BeginChangeCheck(); { //renderMode GUILayout.BeginHorizontal(); GUILayout.Label(Styles.renderModeText, GUILayout.Width(120)); var mode = (RenderMode)renderMode.floatValue; mode = (RenderMode)EditorGUILayout.Popup((int)mode, Styles.renderModeNames); GUILayout.EndHorizontal(); //Primary properties GUILayout.Label(Styles.PrimaryText, EditorStyles.boldLabel); //Diffuse m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, diffuseTexture, diffuseColor); //specular bool hasSpecularMap = false; hasSpecularMap = specularTexture.textureValue != null; m_MaterialEditor.TexturePropertySingleLine(Styles.specularText, specularTexture, hasSpecularMap ? null : specularColor); //smoothness //m_MaterialEditor.ShaderProperty(smoothness, Styles.smoothnessText, MaterialEditor.kMiniTextureFieldLabelIndentLevel); bool showSmoothnessScale = hasSpecularMap; int smoothnessChannel = (int)smoothnessTextureChannel.floatValue; if (smoothnessChannel == (int)SmoothnessTextureChannelMode.Albedo_Alpha) { showSmoothnessScale = true; } int indentation = 2; // align with labels of texture properties m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation); //smoothnessTextureChannel GUILayout.BeginHorizontal(); GUILayout.Label("", GUILayout.Width(26)); GUILayout.Label(Styles.smoothnessTextureChannelText, GUILayout.Width(120)); var smoothMode = (SmoothnessTextureChannelMode)smoothnessTextureChannel.floatValue; smoothMode = (SmoothnessTextureChannelMode)EditorGUILayout.Popup((int)smoothMode, Styles.smoothnessTextureChannelModeNames); GUILayout.EndHorizontal(); //mormal bool hasNormalTexture = false; hasNormalTexture = normalTexture.textureValue != null; m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, normalTexture, hasNormalTexture ? normalScale : null); //parallax bool hasparallaxTexture = false; hasparallaxTexture = parallaxTexture.textureValue != null; m_MaterialEditor.TexturePropertySingleLine(Styles.parallaxText, parallaxTexture, hasparallaxTexture ? parallaxScale : null); //occlusion bool hasOcclusion = false; hasOcclusion = occlusionTexture.textureValue != null; m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionTexture, hasOcclusion ? occlusionStrength : null); //reflection m_MaterialEditor.ShaderProperty(reflection, Styles.reflectionText); //emission m_MaterialEditor.ShaderProperty(emission, Styles.emissionText); if (emission.floatValue == 1) { m_MaterialEditor.TexturePropertySingleLine(Styles.emissionMapText, emissionTexture, emissionColor); } //scaleAndOffset m_MaterialEditor.TextureScaleOffsetProperty(diffuseTexture); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); //Advanced properties GUILayout.Label(Styles.AdvancedText, EditorStyles.boldLabel); //alphaTest m_MaterialEditor.ShaderProperty(alphaTest, Styles.alphaTest); if (alphaTest.floatValue == 1) { m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1); } //alphaBlend m_MaterialEditor.ShaderProperty(alphaBlend, Styles.alphaBlendText); var dstMode = (DstBlendMode)dstBlendMode.floatValue; var srcMode = (SrcBlendMode)srcBlendMode.floatValue; if (alphaBlend.floatValue == 1) { GUILayout.BeginHorizontal(); GUILayout.Label("", GUILayout.Width(20)); srcMode = (SrcBlendMode)EditorGUILayout.Popup((int)srcMode, Styles.srcBlendNames); dstMode = (DstBlendMode)EditorGUILayout.Popup((int)dstMode, Styles.dstBlendNames); GUILayout.EndHorizontal(); } //depthWrite GUILayout.BeginHorizontal(); GUILayout.Label(Styles.depthWriteText, GUILayout.Width(120)); var depthW = (DepthWrite)depthWrite.floatValue; depthW = (DepthWrite)EditorGUILayout.Popup((int)depthW, Styles.depthWriteNames); GUILayout.EndHorizontal(); //depthTest GUILayout.BeginHorizontal(); GUILayout.Label(Styles.depthTestText, GUILayout.Width(120)); var depthT = (DepthTest)depthTest.floatValue; depthT = (DepthTest)EditorGUILayout.Popup((int)depthT, Styles.depthTestNames); GUILayout.EndHorizontal(); //cullMode GUILayout.BeginHorizontal(); GUILayout.Label(Styles.cullModeText, GUILayout.Width(120)); var cull = (CullMode)cullMode.floatValue; cull = (CullMode)EditorGUILayout.Popup((int)cull, Styles.cullModeNames); GUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode"); //renderMode renderMode.floatValue = (float)mode; onChangeRender(material, (RenderMode)material.GetFloat("_Mode")); //smoothnessTextureChannel smoothnessTextureChannel.floatValue = (float)smoothMode; material.SetInt("_SmoothnessTextureChannel", (int)smoothMode); if (smoothnessTextureChannel.floatValue == 1) { material.EnableKeyword("Smoothness_DiffuseTexture_Alpha"); } else { material.DisableKeyword("Smoothness_DiffuseTexture_Alpha"); } //cullMode cullMode.floatValue = (float)cull; material.SetInt("_Cull", (int)cull); if ((RenderMode)material.GetFloat("_Mode") == RenderMode.Custom) { //alphaTest if (alphaTest.floatValue == 1) { material.EnableKeyword("EnableAlphaCutoff"); material.EnableKeyword("_ALPHATEST_ON"); } else { material.DisableKeyword("EnableAlphaCutoff"); material.DisableKeyword("_ALPHATEST_ON"); } //alphaBlend if (alphaBlend.floatValue == 1) { srcBlendMode.floatValue = (float)srcMode; dstBlendMode.floatValue = (float)dstMode; material.SetInt("_SrcBlend", (int)srcMode); material.SetInt("_DstBlend", (int)dstMode); material.EnableKeyword("_ALPHABLEND_ON"); material.SetInt("_AlphaBlend", 1); } else { material.DisableKeyword("_ALPHABLEND_ON"); material.SetInt("_AlphaBlend", 0); material.SetInt("_SrcBlend", (int)1); material.SetInt("_DstBlend", (int)0); } //depthWrite depthWrite.floatValue = (float)depthW; material.SetInt("_ZWrite", (int)depthW); //depthTest depthTest.floatValue = (float)depthT; material.SetInt("_ZTest", (int)depthT); } if (parallaxTexture.textureValue != null) { material.EnableKeyword("ParallaxTexture"); } else { material.DisableKeyword("ParallaxTexture"); } if (specularTexture.textureValue != null) { material.EnableKeyword("SpecularTexture"); } else { material.DisableKeyword("SpecularTexture"); } if (reflection.floatValue == 1) { material.EnableKeyword("EnableReflection"); } else { material.DisableKeyword("EnableReflection"); } if (emission.floatValue == 1) { material.EnableKeyword("EnableEmission"); } else { material.DisableKeyword("EnableEmission"); } } } m_MaterialEditor.RenderQueueField(); } public void onChangeRender(Material material, RenderMode mode) { switch (mode) { case RenderMode.Opaque: material.SetInt("_Mode", 0); material.SetInt("_AlphaTest", 0); material.SetInt("_AlphaBlend", 0); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.SetInt("_ZTest", 4); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("ALPHAPREMULTIPLY_ON"); material.DisableKeyword("EnableAlphaCutoff"); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; break; case RenderMode.Cutout: material.SetInt("_Mode", 1); material.SetInt("_AlphaTest", 1); material.SetInt("_AlphaBlend", 0); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.SetInt("_ZTest", 4); material.EnableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("ALPHAPREMULTIPLY_ON"); material.EnableKeyword("EnableAlphaCutoff"); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest; break; case RenderMode.Fade: material.SetInt("_Mode", 2); material.SetInt("_AlphaTest", 0); material.SetInt("_AlphaBlend", 1); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.SetInt("_ZTest", 4); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("ALPHAPREMULTIPLY_ON"); material.DisableKeyword("EnableAlphaCutoff"); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; break; case RenderMode.Transparent: material.SetInt("_Mode", 3); material.SetInt("_AlphaTest", 0); material.SetInt("_AlphaBlend", 1); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.SetInt("_ZTest", 4); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.EnableKeyword("ALPHAPREMULTIPLY_ON"); material.DisableKeyword("EnableAlphaCutoff"); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; break; case RenderMode.Custom: material.SetInt("_Mode", 4); material.renderQueue = material.GetInt("_RenderQueue"); break; default: material.SetInt("_Mode", 0); material.SetInt("_AlphaTest", 0); material.SetInt("_AlphaBlend", 0); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.SetInt("_ZTest", 4); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("ALPHAPREMULTIPLY_ON"); material.DisableKeyword("EnableAlphaCutoff"); material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; break; } } public static class Styles { public static GUIStyle optionsButton = "PaneOptions"; public static GUIContent uvSetLabel = new GUIContent("UV Set"); public static GUIContent[] uvSetOptions = new GUIContent[] { new GUIContent("UV channel 0"), new GUIContent("UV channel 1") }; public static string emptyTootip = ""; public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)"); public static GUIContent specularText = new GUIContent("Specular", "Specular (RGB) and Transparency (A)"); public static GUIContent specularShininessText = new GUIContent("Shininess", "Specular Range"); public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness"); public static GUIContent smoothnessScaleText = new GUIContent("Smoothness Scale", "Smoothness scale factor"); public static GUIContent smoothnessTextureChannelText = new GUIContent("Source", "Smoothness texture and channel"); public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map"); public static GUIContent parallaxText = new GUIContent("Parallax Map", "Parallax Map"); public static GUIContent occlusionText = new GUIContent("Occlusion Map", "Occlusion"); public static GUIContent reflectionText = new GUIContent("Enable Reflection", "Enable Reflection"); public static GUIContent emissionText = new GUIContent("Enable Emission", "Enable Emission"); public static GUIContent emissionMapText = new GUIContent("Emission", "Emission"); public static GUIContent cullModeText = new GUIContent("Cull", "CullMode"); public static GUIContent renderModeText = new GUIContent("RenderMode", "RenderMode"); public static GUIContent alphaTest = new GUIContent("AlphaTest", "AlphaTest"); public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff"); public static GUIContent alphaBlendText = new GUIContent("AlphaBlend", "AlphaBlend"); public static GUIContent depthWriteText = new GUIContent("DepthWrite", "DepthWrite"); public static GUIContent depthTestText = new GUIContent("DepthTest", "DepthTest"); public static string whiteSpaceString = " "; public static string PrimaryText = "Primary Properties"; public static string AdvancedText = "Advanced Properties"; public static readonly string[] srcBlendNames = Enum.GetNames(typeof(SrcBlendMode)); public static readonly string[] dstBlendNames = Enum.GetNames(typeof(DstBlendMode)); public static readonly string[] renderModeNames = Enum.GetNames(typeof(RenderMode)); public static readonly string[] cullModeNames = Enum.GetNames(typeof(CullMode)); public static readonly string[] depthWriteNames = Enum.GetNames(typeof(DepthWrite)); public static readonly string[] depthTestNames = Enum.GetNames(typeof(DepthTest)); public static readonly string[] smoothnessTextureChannelModeNames = Enum.GetNames(typeof(SmoothnessTextureChannelMode)); } } //#endif