emclick

TassellationStandardShaderGUI

Jul 18th, 2016
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.87 KB | None | 0 0
  1. using System;
  2. using UnityEngine;
  3.  
  4. namespace UnityEditor
  5. {
  6. internal class TassellationStandardShaderGUI : ShaderGUI
  7. {
  8.     private enum WorkflowMode
  9.     {
  10.         Specular,
  11.         Metallic,
  12.         Dielectric
  13.     }
  14.  
  15.     public enum BlendMode
  16.     {
  17.         Opaque,
  18.         Cutout,
  19.         Fade,       // Old school alpha-blending mode, fresnel does not affect amount of transparency
  20.         Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply
  21.     }
  22.  
  23.     private static class Styles
  24.     {
  25.         public static GUIStyle optionsButton = "PaneOptions";
  26.         public static GUIContent uvSetLabel = new GUIContent("UV Set");
  27.         public static GUIContent[] uvSetOptions = new GUIContent[] { new GUIContent("UV channel 0"), new GUIContent("UV channel 1") };
  28.  
  29.         public static string emptyTootip = "";
  30.         public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
  31.         public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
  32.         public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)");
  33.         public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)");
  34.         public static GUIContent smoothnessText = new GUIContent("Glossiness", "");
  35.         public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
  36.         public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
  37.         public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
  38.         public static GUIContent emissionText = new GUIContent("Emission", "Emission (RGB)");
  39.         public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
  40.         public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2");
  41.         public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map");
  42.  
  43.         public static GUIContent edgeLengthText = new GUIContent("Edge length", "Edge length");
  44.         public static GUIContent t_smoothnessText = new GUIContent("Smoothness", "Smoothness");
  45.        
  46.         public static string whiteSpaceString = " ";
  47.         public static string primaryMapsText = "Main Maps";
  48.         public static string secondaryMapsText = "Secondary Maps";
  49.         public static string renderingMode = "Rendering Mode";
  50.         public static GUIContent emissiveWarning = new GUIContent ("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
  51.         public static GUIContent emissiveColorWarning = new GUIContent ("Ensure emissive color is non-black for emission to have effect.");
  52.         public static readonly string[] blendNames = Enum.GetNames (typeof (BlendMode));
  53.     }
  54.  
  55.     MaterialProperty blendMode = null;
  56.     MaterialProperty albedoMap = null;
  57.     MaterialProperty albedoColor = null;
  58.     MaterialProperty alphaCutoff = null;
  59.     MaterialProperty specularMap = null;
  60.     MaterialProperty specularColor = null;
  61.     MaterialProperty metallicMap = null;
  62.     MaterialProperty metallic = null;
  63.     MaterialProperty smoothness = null;
  64.     MaterialProperty bumpScale = null;
  65.     MaterialProperty bumpMap = null;
  66.     MaterialProperty occlusionStrength = null;
  67.     MaterialProperty occlusionMap = null;
  68.     MaterialProperty heigtMapScale = null;
  69.     MaterialProperty heightMap = null;
  70.     MaterialProperty emissionColorForRendering = null;
  71.     MaterialProperty emissionMap = null;
  72.     MaterialProperty detailMask = null;
  73.     MaterialProperty detailAlbedoMap = null;
  74.     MaterialProperty detailNormalMapScale = null;
  75.     MaterialProperty detailNormalMap = null;
  76.     MaterialProperty uvSetSecondary = null;
  77.    
  78.     MaterialProperty edgeLength = null;
  79.     MaterialProperty t_smoothness = null;
  80.  
  81.     MaterialEditor m_MaterialEditor;
  82.     WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
  83.     ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, 99f, 1/99f, 3f);
  84.  
  85.     bool m_FirstTimeApply = true;
  86.  
  87.     public void FindProperties (MaterialProperty[] props)
  88.     {
  89.         blendMode = FindProperty ("_Mode", props);
  90.         albedoMap = FindProperty ("_MainTex", props);
  91.         albedoColor = FindProperty ("_Color", props);
  92.         alphaCutoff = FindProperty ("_Cutoff", props);
  93.         specularMap = FindProperty ("_SpecGlossMap", props, false);
  94.         specularColor = FindProperty ("_SpecColor", props, false);
  95.         metallicMap = FindProperty ("_MetallicGlossMap", props, false);
  96.         metallic = FindProperty ("_Metallic", props, false);
  97.         if (specularMap != null && specularColor != null)
  98.             m_WorkflowMode = WorkflowMode.Specular;
  99.         else if (metallicMap != null && metallic != null)
  100.             m_WorkflowMode = WorkflowMode.Metallic;
  101.         else
  102.             m_WorkflowMode = WorkflowMode.Dielectric;
  103.         smoothness = FindProperty ("_Glossiness", props);
  104.         bumpScale = FindProperty ("_BumpScale", props);
  105.         bumpMap = FindProperty ("_BumpMap", props);
  106.         heigtMapScale = FindProperty ("_Parallax", props);
  107.         heightMap = FindProperty("_ParallaxMap", props);
  108.         occlusionStrength = FindProperty ("_OcclusionStrength", props);
  109.         occlusionMap = FindProperty ("_OcclusionMap", props);
  110.         emissionColorForRendering = FindProperty ("_EmissionColor", props);
  111.         emissionMap = FindProperty ("_EmissionMap", props);
  112.         detailMask = FindProperty ("_DetailMask", props);
  113.         detailAlbedoMap = FindProperty ("_DetailAlbedoMap", props);
  114.         detailNormalMapScale = FindProperty ("_DetailNormalMapScale", props);
  115.         detailNormalMap = FindProperty ("_DetailNormalMap", props);
  116.         uvSetSecondary = FindProperty ("_UVSec", props);
  117.        
  118.         edgeLength = FindProperty ("_EdgeLength", props);
  119.         t_smoothness = FindProperty ("_Smoothness", props);
  120.     }
  121.  
  122.     public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] props)
  123.     {
  124.         FindProperties (props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
  125.         m_MaterialEditor = materialEditor;
  126.         Material material = materialEditor.target as Material;
  127.  
  128.         ShaderPropertiesGUI (material);
  129.  
  130.         // Make sure that needed keywords are set up if we're switching some existing
  131.         // material to a standard shader.
  132.         if (m_FirstTimeApply)
  133.         {
  134.             SetMaterialKeywords (material, m_WorkflowMode);
  135.             m_FirstTimeApply = false;
  136.         }
  137.     }
  138.  
  139.     public void ShaderPropertiesGUI (Material material)
  140.     {
  141.         // Use default labelWidth
  142.         EditorGUIUtility.labelWidth = 0f;
  143.  
  144.         // Detect any changes to the material
  145.         EditorGUI.BeginChangeCheck();
  146.         {
  147.             BlendModePopup();
  148.  
  149.             // Primary properties
  150.             GUILayout.Label (Styles.primaryMapsText, EditorStyles.boldLabel);
  151.             DoAlbedoArea(material);
  152.             DoSpecularMetallicArea();
  153.             m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
  154.             m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
  155.             m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
  156.             DoEmissionArea(material);
  157.             m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
  158.             EditorGUI.BeginChangeCheck();
  159.             m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);
  160.             if (EditorGUI.EndChangeCheck())
  161.                 emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
  162.  
  163.             m_MaterialEditor.ShaderProperty(edgeLength, Styles.edgeLengthText.text);
  164.             m_MaterialEditor.ShaderProperty(t_smoothness, Styles.t_smoothnessText.text);
  165.  
  166.             EditorGUILayout.Space();
  167.  
  168.             // Secondary properties
  169.             GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
  170.             m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
  171.             m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
  172.             m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
  173.             m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
  174.         }
  175.         if (EditorGUI.EndChangeCheck())
  176.         {
  177.             foreach (var obj in blendMode.targets)
  178.                 MaterialChanged((Material)obj, m_WorkflowMode);
  179.         }
  180.     }
  181.  
  182.     internal void DetermineWorkflow(MaterialProperty[] props)
  183.     {
  184.         if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
  185.             m_WorkflowMode = WorkflowMode.Specular;
  186.         else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
  187.             m_WorkflowMode = WorkflowMode.Metallic;
  188.         else
  189.             m_WorkflowMode = WorkflowMode.Dielectric;
  190.     }
  191.  
  192.     public override void AssignNewShaderToMaterial (Material material, Shader oldShader, Shader newShader)
  193.     {
  194.         // _Emission property is lost after assigning Standard shader to the material
  195.         // thus transfer it before assigning the new shader
  196.         if (material.HasProperty("_Emission"))
  197.         {
  198.             material.SetColor("_EmissionColor", material.GetColor("_Emission"));
  199.         }
  200.  
  201.         base.AssignNewShaderToMaterial(material, oldShader, newShader);
  202.  
  203.         if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
  204.             return;
  205.  
  206.         BlendMode blendMode = BlendMode.Opaque;
  207.         if (oldShader.name.Contains("/Transparent/Cutout/"))
  208.         {
  209.             blendMode = BlendMode.Cutout;
  210.         }
  211.         else if (oldShader.name.Contains("/Transparent/"))
  212.         {
  213.             // NOTE: legacy shaders did not provide physically based transparency
  214.             // therefore Fade mode
  215.             blendMode = BlendMode.Fade;
  216.         }
  217.         material.SetFloat("_Mode", (float)blendMode);
  218.  
  219.         DetermineWorkflow( MaterialEditor.GetMaterialProperties (new Material[] { material }) );
  220.         MaterialChanged(material, m_WorkflowMode);
  221.     }
  222.  
  223.     void BlendModePopup()
  224.     {
  225.         EditorGUI.showMixedValue = blendMode.hasMixedValue;
  226.         var mode = (BlendMode)blendMode.floatValue;
  227.  
  228.         EditorGUI.BeginChangeCheck();
  229.         mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
  230.         if (EditorGUI.EndChangeCheck())
  231.         {
  232.             m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
  233.             blendMode.floatValue = (float)mode;
  234.         }
  235.  
  236.         EditorGUI.showMixedValue = false;
  237.     }
  238.  
  239.     void DoAlbedoArea(Material material)
  240.     {
  241.         m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
  242.         if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout))
  243.         {
  244.             m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel+1);
  245.         }
  246.     }
  247.  
  248.     void DoEmissionArea(Material material)
  249.     {
  250.         float brightness = emissionColorForRendering.colorValue.maxColorComponent;
  251.         bool showHelpBox = !HasValidEmissiveKeyword(material);
  252.         bool showEmissionColorAndGIControls = brightness > 0.0f;
  253.        
  254.         bool hadEmissionTexture = emissionMap.textureValue != null;
  255.  
  256.         // Texture and HDR color controls
  257.         m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);
  258.  
  259.         // If texture was assigned and color was black set color to white
  260.         if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
  261.             emissionColorForRendering.colorValue = Color.white;
  262.  
  263.         // Dynamic Lightmapping mode
  264.         if (showEmissionColorAndGIControls)
  265.         {
  266.             bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled(emissionColorForRendering.colorValue);
  267.             EditorGUI.BeginDisabledGroup(!shouldEmissionBeEnabled);
  268.  
  269.             m_MaterialEditor.LightmapEmissionProperty (MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
  270.  
  271.             EditorGUI.EndDisabledGroup();
  272.         }
  273.  
  274.         if (showHelpBox)
  275.         {
  276.             EditorGUILayout.HelpBox(Styles.emissiveWarning.text, MessageType.Warning);
  277.         }
  278.     }
  279.  
  280.     void DoSpecularMetallicArea()
  281.     {
  282.         if (m_WorkflowMode == WorkflowMode.Specular)
  283.         {
  284.             if (specularMap.textureValue == null)
  285.                 m_MaterialEditor.TexturePropertyTwoLines(Styles.specularMapText, specularMap, specularColor, Styles.smoothnessText, smoothness);
  286.             else
  287.                 m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap);
  288.  
  289.         }
  290.         else if (m_WorkflowMode == WorkflowMode.Metallic)
  291.         {
  292.             if (metallicMap.textureValue == null)
  293.                 m_MaterialEditor.TexturePropertyTwoLines(Styles.metallicMapText, metallicMap, metallic, Styles.smoothnessText, smoothness);
  294.             else
  295.                 m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap);
  296.         }
  297.     }
  298.  
  299.     public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
  300.     {
  301.         switch (blendMode)
  302.         {
  303.             case BlendMode.Opaque:
  304.                 material.SetOverrideTag("RenderType", "");
  305.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
  306.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
  307.                 material.SetInt("_ZWrite", 1);
  308.                 material.DisableKeyword("_ALPHATEST_ON");
  309.                 material.DisableKeyword("_ALPHABLEND_ON");
  310.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
  311.                 material.renderQueue = -1;
  312.                 break;
  313.             case BlendMode.Cutout:
  314.                 material.SetOverrideTag("RenderType", "TransparentCutout");
  315.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
  316.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
  317.                 material.SetInt("_ZWrite", 1);
  318.                 material.EnableKeyword("_ALPHATEST_ON");
  319.                 material.DisableKeyword("_ALPHABLEND_ON");
  320.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
  321.                 material.renderQueue = 2450;
  322.                 break;
  323.             case BlendMode.Fade:
  324.                 material.SetOverrideTag("RenderType", "Transparent");
  325.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
  326.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
  327.                 material.SetInt("_ZWrite", 0);
  328.                 material.DisableKeyword("_ALPHATEST_ON");
  329.                 material.EnableKeyword("_ALPHABLEND_ON");
  330.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
  331.                 material.renderQueue = 3000;
  332.                 break;
  333.             case BlendMode.Transparent:
  334.                 material.SetOverrideTag("RenderType", "Transparent");
  335.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
  336.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
  337.                 material.SetInt("_ZWrite", 0);
  338.                 material.DisableKeyword("_ALPHATEST_ON");
  339.                 material.DisableKeyword("_ALPHABLEND_ON");
  340.                 material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
  341.                 material.renderQueue = 3000;
  342.                 break;
  343.         }
  344.     }
  345.    
  346.     static bool ShouldEmissionBeEnabled (Color color)
  347.     {
  348.         return color.maxColorComponent > (0.1f / 255.0f);
  349.     }
  350.  
  351.     static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
  352.     {
  353.         // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
  354.         // (MaterialProperty value might come from renderer material property block)
  355.         SetKeyword (material, "_NORMALMAP", material.GetTexture ("_BumpMap") || material.GetTexture ("_DetailNormalMap"));
  356.         if (workflowMode == WorkflowMode.Specular)
  357.             SetKeyword (material, "_SPECGLOSSMAP", material.GetTexture ("_SpecGlossMap"));
  358.         else if (workflowMode == WorkflowMode.Metallic)
  359.             SetKeyword (material, "_METALLICGLOSSMAP", material.GetTexture ("_MetallicGlossMap"));
  360.         SetKeyword (material, "_PARALLAXMAP", material.GetTexture ("_ParallaxMap"));
  361.         SetKeyword (material, "_DETAIL_MULX2", material.GetTexture ("_DetailAlbedoMap") || material.GetTexture ("_DetailNormalMap"));
  362.  
  363.         bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled (material.GetColor("_EmissionColor"));
  364.         SetKeyword (material, "_EMISSION", shouldEmissionBeEnabled);
  365.  
  366.         // Setup lightmap emissive flags
  367.         MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
  368.         if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
  369.         {
  370.             flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
  371.             if (!shouldEmissionBeEnabled)
  372.                 flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
  373.  
  374.             material.globalIlluminationFlags = flags;
  375.         }
  376.     }
  377.  
  378.     bool HasValidEmissiveKeyword (Material material)
  379.     {
  380.         // Material animation might be out of sync with the material keyword.
  381.         // So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
  382.         // (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
  383.         bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
  384.         if (!hasEmissionKeyword && ShouldEmissionBeEnabled (emissionColorForRendering.colorValue))
  385.             return false;
  386.         else
  387.             return true;
  388.     }
  389.  
  390.     static void MaterialChanged(Material material, WorkflowMode workflowMode)
  391.     {
  392.         SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
  393.  
  394.         SetMaterialKeywords(material, workflowMode);
  395.     }
  396.  
  397.     static void SetKeyword(Material m, string keyword, bool state)
  398.     {
  399.         if (state)
  400.             m.EnableKeyword (keyword);
  401.         else
  402.             m.DisableKeyword (keyword);
  403.     }
  404. }
  405.  
  406. } // namespace UnityEditor
Add Comment
Please, Sign In to add comment