Search Unity

Custom shader

Discussion in 'Shaders' started by GameDevRick, Nov 6, 2017.

  1. GameDevRick

    GameDevRick

    Joined:
    Oct 8, 2011
    Posts:
    269
    I would like to add an alpha channel or opacity slider to the Detail Albedo secondary map, but I don't
    know which property it would be associated with when calling FindProperty(). I am adding a line after
    this one in the standard shader:

    Code (CSharp):
    1. detailAlbedoMap = FindProperty("_DetailAlbedoMap", props);
    That new line should find the opacity or alpha channel property so I can set it to a slider with ranges.
    Something like this?:

    Code (CSharp):
    1. detailAlbedoMap = FindProperty("_DetailAlbedoMapAlpha", props);
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Where are you calling FindProperty from? There's some context missing here.

    If you're making a custom drawer for a material, there's a special API to do that.
     
  3. GameDevRick

    GameDevRick

    Joined:
    Oct 8, 2011
    Posts:
    269
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Right, so that's a copy of some built-in material editor?

    First of all, you'll need to also draw the detailMaskAlpha. Do it in the same place/way as the detailAlbedoMap is drawn.
    Then, make sure your copy of the editor script is in an Editor folder.
    Then, have your custom shader reference your editor script. In the bottom of the shader file, there's a line that references which editor to use. Replace that with your own editor.

    That should work.
     
  5. GameDevRick

    GameDevRick

    Joined:
    Oct 8, 2011
    Posts:
    269
    Ya.. that's where I am with this I think.Yes, it is a copy of the standard shader.
    I think I need to know what the name of the property is for the alpha on this line:

    https://gyazo.com/9466ea5c57542cc62de457aa76378f4c

    I will post the entire shader so you can see why it isn't working.
    Note that the custom editor code is in the editor folder and it works with the shader fine.
    Also note that any additions or changes I made to the shader are commented with // CUSTOM for ease of searching.

    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. using System;
    4. using UnityEngine;
    5.  
    6. namespace UnityEditor
    7. {
    8.     internal class CustomStandardShaderGUI : ShaderGUI
    9.     {
    10.         private enum WorkflowMode
    11.         {
    12.             Specular,
    13.             Metallic,
    14.             Dielectric
    15.         }
    16.  
    17.         public enum BlendMode
    18.         {
    19.             Opaque,
    20.             Cutout,
    21.             Fade,   // Old school alpha-blending mode, fresnel does not affect amount of transparency
    22.             Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply
    23.         }
    24.  
    25.         public enum SmoothnessMapChannel
    26.         {
    27.             SpecularMetallicAlpha,
    28.             AlbedoAlpha,
    29.         }
    30.  
    31.         private static class Styles
    32.         {
    33.             public static GUIContent uvSetLabel = new GUIContent("UV Set");
    34.  
    35.             public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
    36.             public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
    37.             public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)");
    38.             public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)");
    39.             public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness value");
    40.             public static GUIContent smoothnessScaleText = new GUIContent("Smoothness", "Smoothness scale factor");
    41.             public static GUIContent smoothnessMapChannelText = new GUIContent("Source", "Smoothness texture and channel");
    42.             public static GUIContent highlightsText = new GUIContent("Specular Highlights", "Specular Highlights");
    43.             public static GUIContent reflectionsText = new GUIContent("Reflections", "Glossy Reflections");
    44.             public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
    45.             public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
    46.             public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
    47.             public static GUIContent emissionText = new GUIContent("Color", "Emission (RGB)");
    48.             public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
    49.             public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2");
    50.  
    51.             // CUSTOM
    52.             public static GUIContent detailAlphaText = new GUIContent("Detail Alpha", "Alpha channel for setting opacity");
    53.  
    54.             public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map");
    55.  
    56.             public static string primaryMapsText = "Main Maps";
    57.             public static string secondaryMapsText = "Secondary Maps";
    58.             public static string forwardText = "Forward Rendering Options";
    59.             public static string renderingMode = "Rendering Mode";
    60.             public static string advancedText = "Advanced Options";
    61.             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.");
    62.             public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
    63.         }
    64.  
    65.         MaterialProperty blendMode = null;
    66.         MaterialProperty albedoMap = null;
    67.         MaterialProperty albedoColor = null;
    68.         MaterialProperty alphaCutoff = null;
    69.         MaterialProperty specularMap = null;
    70.         MaterialProperty specularColor = null;
    71.         MaterialProperty metallicMap = null;
    72.         MaterialProperty metallic = null;
    73.         MaterialProperty smoothness = null;
    74.         MaterialProperty smoothnessScale = null;
    75.         MaterialProperty smoothnessMapChannel = null;
    76.         MaterialProperty highlights = null;
    77.         MaterialProperty reflections = null;
    78.         MaterialProperty bumpScale = null;
    79.         MaterialProperty bumpMap = null;
    80.         MaterialProperty occlusionStrength = null;
    81.         MaterialProperty occlusionMap = null;
    82.         MaterialProperty heigtMapScale = null;
    83.         MaterialProperty heightMap = null;
    84.         MaterialProperty emissionColorForRendering = null;
    85.         MaterialProperty emissionMap = null;
    86.         MaterialProperty detailMask = null;
    87.  
    88.         // CUSTOM
    89.         MaterialProperty detailMaskAlpha = null;
    90.  
    91.         MaterialProperty detailAlbedoMap = null;
    92.         MaterialProperty detailNormalMapScale = null;
    93.         MaterialProperty detailNormalMap = null;
    94.         MaterialProperty uvSetSecondary = null;
    95.  
    96.         MaterialEditor m_MaterialEditor;
    97.         WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
    98.         private const float kMaxfp16 = 65536f; // Clamp to a value that fits into fp16.
    99.         ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, kMaxfp16, 1 / kMaxfp16, 3f);
    100.  
    101.         bool m_FirstTimeApply = true;
    102.  
    103.         public void FindProperties(MaterialProperty[] props)
    104.         {
    105.             blendMode = FindProperty("_Mode", props);
    106.             albedoMap = FindProperty("_MainTex", props);
    107.             albedoColor = FindProperty("_Color", props);
    108.             alphaCutoff = FindProperty("_Cutoff", props);
    109.             specularMap = FindProperty("_SpecGlossMap", props, false);
    110.             specularColor = FindProperty("_SpecColor", props, false);
    111.             metallicMap = FindProperty("_MetallicGlossMap", props, false);
    112.             metallic = FindProperty("_Metallic", props, false);
    113.             if (specularMap != null && specularColor != null)
    114.                 m_WorkflowMode = WorkflowMode.Specular;
    115.             else if (metallicMap != null && metallic != null)
    116.                 m_WorkflowMode = WorkflowMode.Metallic;
    117.             else
    118.                 m_WorkflowMode = WorkflowMode.Dielectric;
    119.             smoothness = FindProperty("_Glossiness", props);
    120.             smoothnessScale = FindProperty("_GlossMapScale", props, false);
    121.             smoothnessMapChannel = FindProperty("_SmoothnessTextureChannel", props, false);
    122.             highlights = FindProperty("_SpecularHighlights", props, false);
    123.             reflections = FindProperty("_GlossyReflections", props, false);
    124.             bumpScale = FindProperty("_BumpScale", props);
    125.             bumpMap = FindProperty("_BumpMap", props);
    126.             heigtMapScale = FindProperty("_Parallax", props);
    127.             heightMap = FindProperty("_ParallaxMap", props);
    128.             occlusionStrength = FindProperty("_OcclusionStrength", props);
    129.             occlusionMap = FindProperty("_OcclusionMap", props);
    130.             emissionColorForRendering = FindProperty("_EmissionColor", props);
    131.             emissionMap = FindProperty("_EmissionMap", props);
    132.             detailMask = FindProperty("_DetailMask", props);
    133.             detailAlbedoMap = FindProperty("_DetailAlbedoMap", props);
    134.  
    135.             // CUSTOM - This is the property that I want to make into a range to control the opacity
    136.             detailMaskAlpha = FindProperty("_DetailMaskAlpha", props);
    137.  
    138.             detailNormalMapScale = FindProperty("_DetailNormalMapScale", props);
    139.             detailNormalMap = FindProperty("_DetailNormalMap", props);
    140.             uvSetSecondary = FindProperty("_UVSec", props);
    141.         }
    142.  
    143.         public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    144.         {
    145.             FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
    146.             m_MaterialEditor = materialEditor;
    147.             Material material = materialEditor.target as Material;
    148.  
    149.             // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
    150.             // material to a standard shader.
    151.             // Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071)
    152.             if (m_FirstTimeApply)
    153.             {
    154.                 MaterialChanged(material, m_WorkflowMode);
    155.                 m_FirstTimeApply = false;
    156.             }
    157.  
    158.             ShaderPropertiesGUI(material);
    159.         }
    160.  
    161.         // SHADER PROPERTIES GUI
    162.         public void ShaderPropertiesGUI(Material material)
    163.         {
    164.             // Use default labelWidth
    165.             EditorGUIUtility.labelWidth = 0f;
    166.  
    167.             // Detect any changes to the material
    168.             EditorGUI.BeginChangeCheck();
    169.             {
    170.                 BlendModePopup();
    171.  
    172.                 // Primary properties
    173.                 GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);
    174.                 DoAlbedoArea(material);
    175.                 DoSpecularMetallicArea();
    176.                 m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
    177.                 m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
    178.                 m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
    179.                 m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
    180.  
    181.                 DoEmissionArea(material);
    182.                 EditorGUI.BeginChangeCheck();
    183.                 m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);
    184.                 if (EditorGUI.EndChangeCheck())
    185.                     emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
    186.  
    187.                 EditorGUILayout.Space();
    188.  
    189.                 // Secondary properties
    190.                 GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
    191.                 m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
    192.  
    193.                 // CUSTOM
    194.                 m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlphaText, detailMaskAlpha);
    195.  
    196.                 m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
    197.  
    198.                 m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
    199.                 m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
    200.  
    201.                 // Third properties
    202.                 GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel);
    203.                 if (highlights != null)
    204.                     m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);
    205.                 if (reflections != null)
    206.                     m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);
    207.             }
    208.             if (EditorGUI.EndChangeCheck())
    209.             {
    210.                 foreach (var obj in blendMode.targets)
    211.                     MaterialChanged((Material)obj, m_WorkflowMode);
    212.             }
    213.  
    214.             EditorGUILayout.Space();
    215.  
    216.             // NB renderqueue editor is not shown on purpose: we want to override it based on blend mode
    217.             GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);
    218.             m_MaterialEditor.EnableInstancingField();
    219.             m_MaterialEditor.DoubleSidedGIField();
    220.         }
    221.  
    222.         internal void DetermineWorkflow(MaterialProperty[] props)
    223.         {
    224.             if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
    225.                 m_WorkflowMode = WorkflowMode.Specular;
    226.             else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
    227.                 m_WorkflowMode = WorkflowMode.Metallic;
    228.             else
    229.                 m_WorkflowMode = WorkflowMode.Dielectric;
    230.         }
    231.  
    232.         public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
    233.         {
    234.             // _Emission property is lost after assigning Standard shader to the material
    235.             // thus transfer it before assigning the new shader
    236.             if (material.HasProperty("_Emission"))
    237.             {
    238.                 material.SetColor("_EmissionColor", material.GetColor("_Emission"));
    239.             }
    240.  
    241.             base.AssignNewShaderToMaterial(material, oldShader, newShader);
    242.  
    243.             if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
    244.             {
    245.                 SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
    246.                 return;
    247.             }
    248.  
    249.             BlendMode blendMode = BlendMode.Opaque;
    250.             if (oldShader.name.Contains("/Transparent/Cutout/"))
    251.             {
    252.                 blendMode = BlendMode.Cutout;
    253.             }
    254.             else if (oldShader.name.Contains("/Transparent/"))
    255.             {
    256.                 // NOTE: legacy shaders did not provide physically based transparency
    257.                 // therefore Fade mode
    258.                 blendMode = BlendMode.Fade;
    259.             }
    260.             material.SetFloat("_Mode", (float)blendMode);
    261.  
    262.             DetermineWorkflow(MaterialEditor.GetMaterialProperties(new Material[] { material }));
    263.             MaterialChanged(material, m_WorkflowMode);
    264.         }
    265.  
    266.         void BlendModePopup()
    267.         {
    268.             EditorGUI.showMixedValue = blendMode.hasMixedValue;
    269.             var mode = (BlendMode)blendMode.floatValue;
    270.  
    271.             EditorGUI.BeginChangeCheck();
    272.             mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
    273.             if (EditorGUI.EndChangeCheck())
    274.             {
    275.                 m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
    276.                 blendMode.floatValue = (float)mode;
    277.             }
    278.  
    279.             EditorGUI.showMixedValue = false;
    280.         }
    281.  
    282.         void DoAlbedoArea(Material material)
    283.         {
    284.             m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
    285.             if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout))
    286.             {
    287.                 m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
    288.             }
    289.         }
    290.  
    291.         void DoEmissionArea(Material material)
    292.         {
    293.             // Emission for GI?
    294.             if (m_MaterialEditor.EmissionEnabledProperty())
    295.             {
    296.                 bool hadEmissionTexture = emissionMap.textureValue != null;
    297.  
    298.                 // Texture and HDR color controls
    299.                 m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);
    300.  
    301.                 // If texture was assigned and color was black set color to white
    302.                 float brightness = emissionColorForRendering.colorValue.maxColorComponent;
    303.                 if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
    304.                     emissionColorForRendering.colorValue = Color.white;
    305.  
    306.                 // change the GI flag and fix it up with emissive as black if necessary
    307.                 m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);
    308.             }
    309.         }
    310.  
    311.         void DoSpecularMetallicArea()
    312.         {
    313.             bool hasGlossMap = false;
    314.             if (m_WorkflowMode == WorkflowMode.Specular)
    315.             {
    316.                 hasGlossMap = specularMap.textureValue != null;
    317.                 m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor);
    318.             }
    319.             else if (m_WorkflowMode == WorkflowMode.Metallic)
    320.             {
    321.                 hasGlossMap = metallicMap.textureValue != null;
    322.                 m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic);
    323.             }
    324.  
    325.             bool showSmoothnessScale = hasGlossMap;
    326.             if (smoothnessMapChannel != null)
    327.             {
    328.                 int smoothnessChannel = (int)smoothnessMapChannel.floatValue;
    329.                 if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha)
    330.                     showSmoothnessScale = true;
    331.             }
    332.  
    333.             int indentation = 2; // align with labels of texture properties
    334.             m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation);
    335.  
    336.             ++indentation;
    337.             if (smoothnessMapChannel != null)
    338.                 m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation);
    339.         }
    340.  
    341.         public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
    342.         {
    343.             switch (blendMode)
    344.             {
    345.                 case BlendMode.Opaque:
    346.                     material.SetOverrideTag("RenderType", "");
    347.                     material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    348.                     material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
    349.                     material.SetInt("_ZWrite", 1);
    350.                     material.DisableKeyword("_ALPHATEST_ON");
    351.                     material.DisableKeyword("_ALPHABLEND_ON");
    352.                     material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    353.                     material.renderQueue = -1;
    354.                     break;
    355.                 case BlendMode.Cutout:
    356.                     material.SetOverrideTag("RenderType", "TransparentCutout");
    357.                     material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    358.                     material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
    359.                     material.SetInt("_ZWrite", 1);
    360.                     material.EnableKeyword("_ALPHATEST_ON");
    361.                     material.DisableKeyword("_ALPHABLEND_ON");
    362.                     material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    363.                     material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
    364.                     break;
    365.                 case BlendMode.Fade:
    366.                     material.SetOverrideTag("RenderType", "Transparent");
    367.                     material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
    368.                     material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    369.                     material.SetInt("_ZWrite", 0);
    370.                     material.DisableKeyword("_ALPHATEST_ON");
    371.                     material.EnableKeyword("_ALPHABLEND_ON");
    372.                     material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    373.                     material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
    374.                     break;
    375.                 case BlendMode.Transparent:
    376.                     material.SetOverrideTag("RenderType", "Transparent");
    377.                     material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    378.                     material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    379.                     material.SetInt("_ZWrite", 0);
    380.                     material.DisableKeyword("_ALPHATEST_ON");
    381.                     material.DisableKeyword("_ALPHABLEND_ON");
    382.                     material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
    383.                     material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
    384.                     break;
    385.             }
    386.         }
    387.  
    388.         static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)
    389.         {
    390.             int ch = (int)material.GetFloat("_SmoothnessTextureChannel");
    391.             if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)
    392.                 return SmoothnessMapChannel.AlbedoAlpha;
    393.             else
    394.                 return SmoothnessMapChannel.SpecularMetallicAlpha;
    395.         }
    396.  
    397.         static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
    398.         {
    399.             // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
    400.             // (MaterialProperty value might come from renderer material property block)
    401.             SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap"));
    402.             if (workflowMode == WorkflowMode.Specular)
    403.                 SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap"));
    404.             else if (workflowMode == WorkflowMode.Metallic)
    405.                 SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap"));
    406.             SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
    407.             SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap"));
    408.  
    409.             // A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect
    410.             // or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.
    411.             // The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.
    412.             MaterialEditor.FixupEmissiveFlag(material);
    413.             bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
    414.             SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
    415.  
    416.             if (material.HasProperty("_SmoothnessTextureChannel"))
    417.             {
    418.                 SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha);
    419.             }
    420.         }
    421.  
    422.         static void MaterialChanged(Material material, WorkflowMode workflowMode)
    423.         {
    424.             SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
    425.  
    426.             SetMaterialKeywords(material, workflowMode);
    427.         }
    428.  
    429.         static void SetKeyword(Material m, string keyword, bool state)
    430.         {
    431.             if (state)
    432.                 m.EnableKeyword(keyword);
    433.             else
    434.                 m.DisableKeyword(keyword);
    435.         }
    436.     }
    437. } // namespace UnityEditor
    438.  
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    That's not a shader. That's an editor for a shader. Have you written an edited version of the standard shader? Just writing an editor isn't going to get you very far.

    Or are you trying to add a drawer for a property that already exists in the standard shader, but isn't exposed?
     
  7. GameDevRick

    GameDevRick

    Joined:
    Oct 8, 2011
    Posts:
    269
    Ah ya.. I'm sorry.. I modified the shader too:

    "are you trying to add a drawer for a property that already exists in the standard shader, but isn't exposed?"
    I can't answer that question because I don't fully get what's going on in there. I don't quite understand
    how the shader and editor code are working together and how to access the alpha property yet.

    Here is the shader:

    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. Shader "CustomStandardShader"
    4. {
    5.     Properties
    6.     {
    7.         _Color("Color", Color) = (1,1,1,1)
    8.         _MainTex("Albedo", 2D) = "white" {}
    9.  
    10.         _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
    11.  
    12.         _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
    13.         _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
    14.         [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
    15.  
    16.         [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
    17.         _MetallicGlossMap("Metallic", 2D) = "white" {}
    18.  
    19.         [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
    20.         [ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
    21.  
    22.         _BumpScale("Scale", Float) = 1.0
    23.         _BumpMap("Normal Map", 2D) = "bump" {}
    24.  
    25.         _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
    26.         _ParallaxMap ("Height Map", 2D) = "black" {}
    27.  
    28.         _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
    29.         _OcclusionMap("Occlusion", 2D) = "white" {}
    30.  
    31.         _EmissionColor("Color", Color) = (0,0,0)
    32.         _EmissionMap("Emission", 2D) = "white" {}
    33.  
    34.         _DetailMask("Detail Mask", 2D) = "white" {}
    35.  
    36.         _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
    37.  
    38.         // CUSTOM This was an attempt at the slider, but I think it is drawing the texture property
    39.         // and I don't know how to make it only the alpha value. I don't really understand how this
    40.         // is working with the custom editor. This is my first attempt at shader modding.
    41.         // _DetailAlbedoMapAlpha("Alpha", Range(0.0, 1.0)) = 1.0
    42.  
    43.         _DetailNormalMapScale("Scale", Float) = 1.0
    44.         _DetailNormalMap("Normal Map", 2D) = "bump" {}
    45.  
    46.         [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
    47.  
    48.  
    49.         // Blending state
    50.         [HideInInspector] _Mode ("__mode", Float) = 0.0
    51.         [HideInInspector] _SrcBlend ("__src", Float) = 1.0
    52.         [HideInInspector] _DstBlend ("__dst", Float) = 0.0
    53.         [HideInInspector] _ZWrite ("__zw", Float) = 1.0
    54.     }
    55.  
    56.     CGINCLUDE
    57.         #define UNITY_SETUP_BRDF_INPUT MetallicSetup
    58.     ENDCG
    59.  
    60.     SubShader
    61.     {
    62.         Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
    63.         LOD 300
    64.  
    65.  
    66.         // ------------------------------------------------------------------
    67.         //  Base forward pass (directional light, emission, lightmaps, ...)
    68.         Pass
    69.         {
    70.             Name "FORWARD"
    71.             Tags { "LightMode" = "ForwardBase" }
    72.  
    73.             Blend [_SrcBlend] [_DstBlend]
    74.             ZWrite [_ZWrite]
    75.  
    76.             CGPROGRAM
    77.             #pragma target 3.0
    78.  
    79.             // -------------------------------------
    80.  
    81.             #pragma shader_feature _NORMALMAP
    82.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    83.             #pragma shader_feature _EMISSION
    84.             #pragma shader_feature _METALLICGLOSSMAP
    85.             #pragma shader_feature ___ _DETAIL_MULX2
    86.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    87.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    88.             #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
    89.             #pragma shader_feature _PARALLAXMAP
    90.  
    91.             #pragma multi_compile_fwdbase
    92.             #pragma multi_compile_fog
    93.             #pragma multi_compile_instancing
    94.             // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes.
    95.             //#pragma multi_compile _ LOD_FADE_CROSSFADE
    96.  
    97.             #pragma vertex vertBase
    98.             #pragma fragment fragBase
    99.             #include "UnityStandardCoreForward.cginc"
    100.  
    101.             ENDCG
    102.         }
    103.         // ------------------------------------------------------------------
    104.         //  Additive forward pass (one light per pass)
    105.         Pass
    106.         {
    107.             Name "FORWARD_DELTA"
    108.             Tags { "LightMode" = "ForwardAdd" }
    109.             Blend [_SrcBlend] One
    110.             Fog { Color (0,0,0,0) } // in additive pass fog should be black
    111.             ZWrite Off
    112.             ZTest LEqual
    113.  
    114.             CGPROGRAM
    115.             #pragma target 3.0
    116.  
    117.             // -------------------------------------
    118.  
    119.  
    120.             #pragma shader_feature _NORMALMAP
    121.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    122.             #pragma shader_feature _METALLICGLOSSMAP
    123.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    124.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    125.             #pragma shader_feature ___ _DETAIL_MULX2
    126.             #pragma shader_feature _PARALLAXMAP
    127.  
    128.             #pragma multi_compile_fwdadd_fullshadows
    129.             #pragma multi_compile_fog
    130.             // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes.
    131.             //#pragma multi_compile _ LOD_FADE_CROSSFADE
    132.  
    133.             #pragma vertex vertAdd
    134.             #pragma fragment fragAdd
    135.             #include "UnityStandardCoreForward.cginc"
    136.  
    137.             ENDCG
    138.         }
    139.         // ------------------------------------------------------------------
    140.         //  Shadow rendering pass
    141.         Pass {
    142.             Name "ShadowCaster"
    143.             Tags { "LightMode" = "ShadowCaster" }
    144.  
    145.             ZWrite On ZTest LEqual
    146.  
    147.             CGPROGRAM
    148.             #pragma target 3.0
    149.  
    150.             // -------------------------------------
    151.  
    152.  
    153.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    154.             #pragma shader_feature _METALLICGLOSSMAP
    155.             #pragma shader_feature _PARALLAXMAP
    156.             #pragma multi_compile_shadowcaster
    157.             #pragma multi_compile_instancing
    158.             // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes.
    159.             //#pragma multi_compile _ LOD_FADE_CROSSFADE
    160.  
    161.             #pragma vertex vertShadowCaster
    162.             #pragma fragment fragShadowCaster
    163.  
    164.             #include "UnityStandardShadow.cginc"
    165.  
    166.             ENDCG
    167.         }
    168.         // ------------------------------------------------------------------
    169.         //  Deferred pass
    170.         Pass
    171.         {
    172.             Name "DEFERRED"
    173.             Tags { "LightMode" = "Deferred" }
    174.  
    175.             CGPROGRAM
    176.             #pragma target 3.0
    177.             #pragma exclude_renderers nomrt
    178.  
    179.  
    180.             // -------------------------------------
    181.  
    182.             #pragma shader_feature _NORMALMAP
    183.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    184.             #pragma shader_feature _EMISSION
    185.             #pragma shader_feature _METALLICGLOSSMAP
    186.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    187.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    188.             #pragma shader_feature ___ _DETAIL_MULX2
    189.             #pragma shader_feature _PARALLAXMAP
    190.  
    191.             #pragma multi_compile_prepassfinal
    192.             #pragma multi_compile_instancing
    193.             // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes.
    194.             //#pragma multi_compile _ LOD_FADE_CROSSFADE
    195.  
    196.             #pragma vertex vertDeferred
    197.             #pragma fragment fragDeferred
    198.  
    199.             #include "UnityStandardCore.cginc"
    200.  
    201.             ENDCG
    202.         }
    203.  
    204.         // ------------------------------------------------------------------
    205.         // Extracts information for lightmapping, GI (emission, albedo, ...)
    206.         // This pass it not used during regular rendering.
    207.         Pass
    208.         {
    209.             Name "META"
    210.             Tags { "LightMode"="Meta" }
    211.  
    212.             Cull Off
    213.  
    214.             CGPROGRAM
    215.             #pragma vertex vert_meta
    216.             #pragma fragment frag_meta
    217.  
    218.             #pragma shader_feature _EMISSION
    219.             #pragma shader_feature _METALLICGLOSSMAP
    220.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    221.             #pragma shader_feature ___ _DETAIL_MULX2
    222.             #pragma shader_feature EDITOR_VISUALIZATION
    223.  
    224.             #include "UnityStandardMeta.cginc"
    225.             ENDCG
    226.         }
    227.     }
    228.  
    229.     SubShader
    230.     {
    231.         Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
    232.         LOD 150
    233.  
    234.         // ------------------------------------------------------------------
    235.         //  Base forward pass (directional light, emission, lightmaps, ...)
    236.         Pass
    237.         {
    238.             Name "FORWARD"
    239.             Tags { "LightMode" = "ForwardBase" }
    240.  
    241.             Blend [_SrcBlend] [_DstBlend]
    242.             ZWrite [_ZWrite]
    243.  
    244.             CGPROGRAM
    245.             #pragma target 2.0
    246.  
    247.             #pragma shader_feature _NORMALMAP
    248.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    249.             #pragma shader_feature _EMISSION
    250.             #pragma shader_feature _METALLICGLOSSMAP
    251.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    252.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    253.             #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
    254.             // SM2.0: NOT SUPPORTED shader_feature ___ _DETAIL_MULX2
    255.             // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
    256.  
    257.             #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED
    258.  
    259.             #pragma multi_compile_fwdbase
    260.             #pragma multi_compile_fog
    261.  
    262.             #pragma vertex vertBase
    263.             #pragma fragment fragBase
    264.             #include "UnityStandardCoreForward.cginc"
    265.  
    266.             ENDCG
    267.         }
    268.         // ------------------------------------------------------------------
    269.         //  Additive forward pass (one light per pass)
    270.         Pass
    271.         {
    272.             Name "FORWARD_DELTA"
    273.             Tags { "LightMode" = "ForwardAdd" }
    274.             Blend [_SrcBlend] One
    275.             Fog { Color (0,0,0,0) } // in additive pass fog should be black
    276.             ZWrite Off
    277.             ZTest LEqual
    278.  
    279.             CGPROGRAM
    280.             #pragma target 2.0
    281.  
    282.             #pragma shader_feature _NORMALMAP
    283.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    284.             #pragma shader_feature _METALLICGLOSSMAP
    285.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    286.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    287.             #pragma shader_feature ___ _DETAIL_MULX2
    288.             // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
    289.             #pragma skip_variants SHADOWS_SOFT
    290.  
    291.             #pragma multi_compile_fwdadd_fullshadows
    292.             #pragma multi_compile_fog
    293.  
    294.             #pragma vertex vertAdd
    295.             #pragma fragment fragAdd
    296.             #include "UnityStandardCoreForward.cginc"
    297.  
    298.             ENDCG
    299.         }
    300.         // ------------------------------------------------------------------
    301.         //  Shadow rendering pass
    302.         Pass {
    303.             Name "ShadowCaster"
    304.             Tags { "LightMode" = "ShadowCaster" }
    305.  
    306.             ZWrite On ZTest LEqual
    307.  
    308.             CGPROGRAM
    309.             #pragma target 2.0
    310.  
    311.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    312.             #pragma shader_feature _METALLICGLOSSMAP
    313.             #pragma skip_variants SHADOWS_SOFT
    314.             #pragma multi_compile_shadowcaster
    315.  
    316.             #pragma vertex vertShadowCaster
    317.             #pragma fragment fragShadowCaster
    318.  
    319.             #include "UnityStandardShadow.cginc"
    320.  
    321.             ENDCG
    322.         }
    323.  
    324.         // ------------------------------------------------------------------
    325.         // Extracts information for lightmapping, GI (emission, albedo, ...)
    326.         // This pass it not used during regular rendering.
    327.         Pass
    328.         {
    329.             Name "META"
    330.             Tags { "LightMode"="Meta" }
    331.  
    332.             Cull Off
    333.  
    334.             CGPROGRAM
    335.             #pragma vertex vert_meta
    336.             #pragma fragment frag_meta
    337.  
    338.             #pragma shader_feature _EMISSION
    339.             #pragma shader_feature _METALLICGLOSSMAP
    340.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    341.             #pragma shader_feature ___ _DETAIL_MULX2
    342.             #pragma shader_feature EDITOR_VISUALIZATION
    343.  
    344.             #include "UnityStandardMeta.cginc"
    345.             ENDCG
    346.         }
    347.     }
    348.  
    349.  
    350.     FallBack "VertexLit"
    351.     CustomEditor "CustomStandardShaderGUI"
    352. }
    353.  
     
  8. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Right.

    So first of all, the names have to match. So in your shader, you have:

    Code (csharp):
    1. _DetailAlbedoMapAlpha("Alpha", Range(0.0, 1.0)) = 1.0
    So when you get that property in your editor, you have to use the same name:

    Code (csharp):
    1. // CUSTOM - This is the property that I want to make into a range to control the opacity
    2. detailMaskAlpha = FindProperty("_DetailAlbedoMapAlpha", props);
    Then, when drawing it, you can't use TexturePropertySingleLine. That method is for Textures (as the name implies), but you're drawing a float. Checking the other sliders (like the Metallic and Smoothness sliders), they use ShaderProperty, which is a generic property drawer, so you can use that:

    Code (csharp):
    1. m_MaterialEditor.ShaderProperty(detailMaskAlpha, Styles.detailAlphaText);
    All that put together draws the thing correctly.



    Now, you actually have to change the shader to use you custom masking. This is a bit more involved, as the detail albedo map isn't used directly in the standard shader, but instead in a .cginc file.

    So on line 99 in your shader, you have:
    Code (csharp):
    1. #include "UnityStandardCoreForward.cginc"
    That means "copy-paste everything in the file UnityStandardCoreForward.cginc in here". So your line 99 is repalced by an entire file.

    Similarly, in UnityStandardCoreForward.cginc, the file UnityStandardCore.cginc is included. And from that file, UnityStandardInput.cginc is included. In that file, _DetailAlbedoMap is actually sampled and applied to the material:

    So in order to apply your alpha slider, you'll have to replace all of those files with your custom ones, and have those reference each other. After that, you'll need to figure out how to actually apply your alpha value.


    Final detail: Shaders are already pretty complex, and the Standard shader is probably the most complex shader that exists in Unity. After all of the #includes have resolved, it's probably thousands of lines long. So don't be too discouraged if this is a bit over your head.

    @Eric5h5 or @hippocoder, maybe move this thread into the shader subforum?
     
  9. GameDevRick

    GameDevRick

    Joined:
    Oct 8, 2011
    Posts:
    269
    Thank you very much Baste!
    The custom property drawer is drawing correctly, but your hint at the complexity of the shader is spot on.
    It may be proving to be too cumbersome to locate and modify the alpha property within the cginc files.
    I am looking into using Shader Forge as a way to set up custom property drawers, but I am not familiar
    with it yet and I don't know if that is possible.