Search Unity

  1. Unity 2019.4 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  3. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

adding an outline to Unity 5 standard shader

Discussion in 'Shaders' started by Sortasoft, Dec 19, 2014.

  1. Sortasoft

    Sortasoft

    Joined:
    Feb 24, 2009
    Posts:
    59
    Is it possible to add an outline to the new Unity 5 standard shader? Any suggestions on how to go about doing so?
     
    Alstev likes this.
  2. KyleStaves

    KyleStaves

    Joined:
    Nov 4, 2009
    Posts:
    820
    Bump, would love to know if anyone has done this
     
  3. JRascall

    JRascall

    Joined:
    Dec 23, 2012
    Posts:
    1
    This would be greatly appreciated if anyone has figured it out.
     
  4. sballew7

    sballew7

    Joined:
    Sep 3, 2013
    Posts:
    64
    Trying this as well, but haven't had any luck.
     
  5. grahnzz

    grahnzz

    Joined:
    May 7, 2013
    Posts:
    46
  6. rev087

    rev087

    Joined:
    Oct 3, 2013
    Posts:
    11
    I'm NOT a graphics developer, and I just barely understand how surface / vert and frag shaders even work, let alone PBR.

    That said, I did manage to hack together a modified version of the Standard shader to include an outline, that "seem to work" in Forward rendering (breaks in other rendering paths).

    It's based on the additional pass with normal extrusion method, which works best for somewhat rounded meshes (acute angles expose the weakness in this method: it leaves gaps between the extruded faces).



    Search for "Outline" to see comments in the code, where I marked the modifications I did to the Standard shader. Also, you can uncomment a line to get the "see through" effect, where the filled silhouette is rendered on top of other things occluding the object.

    Another limitation is that the Standard shader comes with a sweet custom editor, but it's marked as "internal" so I can't extend it, and I haven't yet attempted recreating it from scratch. The workaround is to comment it (second-to-last line) to use the default shader editor that exposes the new "Outline Extrusion" and "Outline Color" settings, or uncomment it to use the custom editor for the Standard shader and access the _Outline and _OutColor attributes via code (with GetComponent<Renderer>().material.SetFloat("_Outline", ...) and GetComponent<Renderer>().material.SetColor("_OutColor", ...)

    Here's my little frankenstein of a shader:

    Code (CSharp):
    1. Shader "Standard Outlined"
    2. {
    3.     Properties
    4.     {
    5.         [LM_Albedo] [LM_Transparency] _Color("Color", Color) = (1,1,1,1)  
    6.         [LM_MasterTilingOffset] [LM_Albedo] _MainTex("Albedo", 2D) = "white" {}
    7.      
    8.         [LM_TransparencyCutOff] _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
    9.  
    10.         [LM_Glossiness] _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
    11.         [LM_Metallic] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
    12.         [LM_Metallic] [LM_Glossiness] _MetallicGlossMap("Metallic", 2D) = "white" {}
    13.  
    14.          _BumpScale("Scale", Float) = 1.0
    15.         [LM_NormalMap] _BumpMap("Normal Map", 2D) = "bump" {}
    16.  
    17.         _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
    18.         _ParallaxMap ("Height Map", 2D) = "black" {}
    19.  
    20.         _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
    21.         _OcclusionMap("Occlusion", 2D) = "white" {}
    22.  
    23.         [LM_Emission] _EmissionColor("Color", Color) = (0,0,0)
    24.         [LM_Emission] _EmissionMap("Emission", 2D) = "white" {}
    25.      
    26.         _DetailMask("Detail Mask", 2D) = "white" {}
    27.  
    28.         _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
    29.         _DetailNormalMapScale("Scale", Float) = 1.0
    30.         _DetailNormalMap("Normal Map", 2D) = "bump" {}
    31.  
    32.         [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
    33.  
    34.         // UI-only data
    35.         [KeywordEnum(None, Realtime, Baked)]  _Lightmapping ("GI", Int) = 1
    36.         [HideInInspector] _EmissionScaleUI("Scale", Float) = 0.0
    37.         [HideInInspector] _EmissionColorUI("Color", Color) = (1,1,1)
    38.  
    39.         // Blending state
    40.         [HideInInspector] _Mode ("__mode", Float) = 0.0
    41.         [HideInInspector] _SrcBlend ("__src", Float) = 1.0
    42.         [HideInInspector] _DstBlend ("__dst", Float) = 0.0
    43.         [HideInInspector] _ZWrite ("__zw", Float) = 1.0
    44.  
    45.         // Outline
    46.         _Outline ("Outline Extrusion", Range(-1,1)) = 0.05
    47.         _OutColor ("Outline Color", Color) = (1,1,1,1)
    48.     }
    49.  
    50.     CGINCLUDE
    51.         //@TODO: should this be pulled into a shader_feature, to be able to turn it off?
    52.         #define _GLOSSYENV 1
    53.         #define UNITY_SETUP_BRDF_INPUT MetallicSetup
    54.     ENDCG
    55.  
    56.     SubShader
    57.     {
    58.         Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
    59.         LOD 300
    60.  
    61.         // Outline addition starts here
    62.         Cull Off
    63.         ZWrite Off
    64.         //ZTest Always // Uncomment for "see through"
    65.  
    66.         CGPROGRAM
    67.             #pragma surface surf Solid vertex:vert
    68.             struct Input {
    69.                 float4 color : COLOR;
    70.             };
    71.  
    72.             fixed4 _OutColor;
    73.             float _Outline;
    74.  
    75.         fixed4 LightingSolid (SurfaceOutput s, half3 lightDir, half atten) {
    76.         return _OutColor;
    77.         }
    78.  
    79.             void vert (inout appdata_full v) {
    80.                 v.vertex.xyz += v.normal * _Outline;
    81.             }
    82.  
    83.             void surf (Input IN, inout SurfaceOutput o) {
    84.                 o.Albedo = _OutColor.rgb;
    85.             }
    86.         ENDCG
    87.  
    88.         Cull Back
    89.         ZWrite On  
    90.         ZTest LEqual
    91.         // Outline addition ends here
    92.  
    93.         // ------------------------------------------------------------------
    94.         //  Base forward pass (directional light, emission, lightmaps, ...)
    95.         Pass
    96.         {
    97.             Name "FORWARD"
    98.             Tags { "LightMode" = "ForwardBase" }
    99.  
    100.             Blend [_SrcBlend] [_DstBlend]
    101.             ZWrite [_ZWrite]
    102.  
    103.             CGPROGRAM
    104.             #pragma target 3.0
    105.             // TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    106.             #pragma exclude_renderers gles
    107.          
    108.             // -------------------------------------
    109.                  
    110.             #pragma shader_feature _NORMALMAP
    111.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    112.             #pragma shader_feature _EMISSION
    113.             //ALWAYS ON shader_feature _GLOSSYENV
    114.             #pragma shader_feature _METALLICGLOSSMAP
    115.             #pragma shader_feature ___ _DETAIL_MULX2
    116.             #pragma shader_feature _PARALLAXMAP
    117.          
    118.             #pragma multi_compile_fwdbase
    119.             #pragma multi_compile_fog
    120.              
    121.             #pragma vertex vertForwardBase
    122.             #pragma fragment fragForwardBase
    123.  
    124.             #include "UnityStandardCore.cginc"
    125.  
    126.             ENDCG
    127.         }
    128.         // ------------------------------------------------------------------
    129.         //  Additive forward pass (one light per pass)
    130.         Pass
    131.         {
    132.             Name "FORWARD_DELTA"
    133.             Tags { "LightMode" = "ForwardAdd" }
    134.             Blend [_SrcBlend] One
    135.             Fog { Color (0,0,0,0) } // in additive pass fog should be black
    136.             ZWrite Off
    137.             ZTest LEqual
    138.  
    139.             CGPROGRAM
    140.             #pragma target 3.0
    141.             // GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    142.             #pragma exclude_renderers gles
    143.  
    144.             // -------------------------------------
    145.  
    146.          
    147.             #pragma shader_feature _NORMALMAP
    148.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    149.             #pragma shader_feature _METALLICGLOSSMAP
    150.             #pragma shader_feature ___ _DETAIL_MULX2
    151.             #pragma shader_feature _PARALLAXMAP
    152.          
    153.             #pragma multi_compile_fwdadd_fullshadows
    154.             #pragma multi_compile_fog
    155.          
    156.             #pragma vertex vertForwardAdd
    157.             #pragma fragment fragForwardAdd
    158.  
    159.             #include "UnityStandardCore.cginc"
    160.  
    161.             ENDCG
    162.         }
    163.         // ------------------------------------------------------------------
    164.         //  Shadow rendering pass
    165.         Pass {
    166.             Name "ShadowCaster"
    167.             Tags { "LightMode" = "ShadowCaster" }
    168.          
    169.             ZWrite On ZTest LEqual
    170.  
    171.             CGPROGRAM
    172.             #pragma target 3.0
    173.             // TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    174.             #pragma exclude_renderers gles
    175.          
    176.             // -------------------------------------
    177.  
    178.  
    179.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    180.             #pragma multi_compile_shadowcaster
    181.  
    182.             #pragma vertex vertShadowCaster
    183.             #pragma fragment fragShadowCaster
    184.  
    185.             #include "UnityStandardShadow.cginc"
    186.  
    187.             ENDCG
    188.         }
    189.         // ------------------------------------------------------------------
    190.         //  Deferred pass
    191.         Pass
    192.         {
    193.             Name "DEFERRED"
    194.             Tags { "LightMode" = "Deferred" }
    195.  
    196.             CGPROGRAM
    197.             #pragma target 3.0
    198.             // TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    199.             #pragma exclude_renderers nomrt gles
    200.          
    201.  
    202.             // -------------------------------------
    203.  
    204.             #pragma shader_feature _NORMALMAP
    205.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    206.             #pragma shader_feature _EMISSION
    207.             //ALWAYS ON shader_feature _GLOSSYENV
    208.             #pragma shader_feature _METALLICGLOSSMAP
    209.             #pragma shader_feature ___ _DETAIL_MULX2
    210.             #pragma shader_feature _PARALLAXMAP
    211.  
    212.             #pragma multi_compile ___ UNITY_HDR_ON
    213.             #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
    214.             #pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
    215.             #pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
    216.          
    217.             #pragma vertex vertDeferred
    218.             #pragma fragment fragDeferred
    219.  
    220.             #include "UnityStandardCore.cginc"
    221.  
    222.             ENDCG
    223.         }
    224.  
    225.         // ------------------------------------------------------------------
    226.         // Extracts information for lightmapping, GI (emission, albedo, ...)
    227.         // This pass it not used during regular rendering.
    228.         Pass
    229.         {
    230.             Name "META"
    231.             Tags { "LightMode"="Meta" }
    232.  
    233.             Cull Off
    234.  
    235.             CGPROGRAM
    236.             #pragma vertex vert_meta
    237.             #pragma fragment frag_meta
    238.  
    239.             #pragma shader_feature _EMISSION
    240.             #pragma shader_feature _METALLICGLOSSMAP
    241.             #pragma shader_feature ___ _DETAIL_MULX2
    242.  
    243.             #include "UnityStandardMeta.cginc"
    244.             ENDCG
    245.         }
    246.     }
    247.  
    248.     SubShader
    249.     {
    250.         Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
    251.         LOD 150
    252.  
    253.         // ------------------------------------------------------------------
    254.         //  Base forward pass (directional light, emission, lightmaps, ...)
    255.         Pass
    256.         {
    257.             Name "FORWARD"
    258.             Tags { "LightMode" = "ForwardBase" }
    259.  
    260.             Blend [_SrcBlend] [_DstBlend]
    261.             ZWrite [_ZWrite]
    262.  
    263.             CGPROGRAM
    264.             #pragma target 2.0
    265.          
    266.             #pragma shader_feature _NORMALMAP
    267.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    268.             #pragma shader_feature _EMISSION
    269.             // ALWAYS ON shader_feature _GLOSSYENV
    270.             #pragma shader_feature _METALLICGLOSSMAP
    271.             #pragma shader_feature ___ _DETAIL_MULX2
    272.             // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
    273.  
    274.             #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
    275.  
    276.             #pragma multi_compile_fwdbase
    277.             #pragma multi_compile_fog
    278.  
    279.             #pragma vertex vertForwardBase
    280.             #pragma fragment fragForwardBase
    281.  
    282.             #include "UnityStandardCore.cginc"
    283.  
    284.             ENDCG
    285.         }
    286.         // ------------------------------------------------------------------
    287.         //  Additive forward pass (one light per pass)
    288.         Pass
    289.         {
    290.             Name "FORWARD_DELTA"
    291.             Tags { "LightMode" = "ForwardAdd" }
    292.             Blend [_SrcBlend] One
    293.             Fog { Color (0,0,0,0) } // in additive pass fog should be black
    294.             ZWrite Off
    295.             ZTest LEqual
    296.          
    297.             CGPROGRAM
    298.             #pragma target 2.0
    299.  
    300.             #pragma shader_feature _NORMALMAP
    301.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    302.             #pragma shader_feature _METALLICGLOSSMAP
    303.             #pragma shader_feature ___ _DETAIL_MULX2
    304.             // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
    305.             #pragma skip_variants SHADOWS_SOFT
    306.          
    307.             #pragma multi_compile_fwdadd_fullshadows
    308.             #pragma multi_compile_fog
    309.          
    310.             #pragma vertex vertForwardAdd
    311.             #pragma fragment fragForwardAdd
    312.  
    313.             #include "UnityStandardCore.cginc"
    314.  
    315.             ENDCG
    316.         }
    317.         // ------------------------------------------------------------------
    318.         //  Shadow rendering pass
    319.         Pass {
    320.             Name "ShadowCaster"
    321.             Tags { "LightMode" = "ShadowCaster" }
    322.          
    323.             ZWrite On ZTest LEqual
    324.  
    325.             CGPROGRAM
    326.             #pragma target 2.0
    327.  
    328.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    329.             #pragma skip_variants SHADOWS_SOFT
    330.             #pragma multi_compile_shadowcaster
    331.  
    332.             #pragma vertex vertShadowCaster
    333.             #pragma fragment fragShadowCaster
    334.  
    335.             #include "UnityStandardShadow.cginc"
    336.  
    337.             ENDCG
    338.         }
    339.  
    340.         // ------------------------------------------------------------------
    341.         // Extracts information for lightmapping, GI (emission, albedo, ...)
    342.         // This pass it not used during regular rendering.
    343.         Pass
    344.         {
    345.             Name "META"
    346.             Tags { "LightMode"="Meta" }
    347.  
    348.             Cull Off
    349.  
    350.             CGPROGRAM
    351.             #pragma vertex vert_meta
    352.             #pragma fragment frag_meta
    353.  
    354.             #pragma shader_feature _EMISSION
    355.             #pragma shader_feature _METALLICGLOSSMAP
    356.             #pragma shader_feature ___ _DETAIL_MULX2
    357.  
    358.             #include "UnityStandardMeta.cginc"
    359.             ENDCG
    360.         }
    361.     }
    362.  
    363.     FallBack "VertexLit"
    364.     //CustomEditor "StandardShaderGUI"
    365. }
    366.  
     
    itsharshdeep likes this.
  7. rev087

    rev087

    Joined:
    Oct 3, 2013
    Posts:
    11
    The method above works for me, but it's a very poor solution. Ideally, an outline should be done in Screen space instead of World space, so we could get rid of the acute angle gaps, and more importantly, set the width of the outline in pixels.

    If anyone has any idea to improve the method I describe in the post above, or could ELI5 a way to implement a screen-space outline, I would really, REALLY appreciate it :)
     
  8. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    Hey!
    I hope you guys will see this.
    As I also wanted to add an outline to the standard shader, i had it working by adding the code from the "ToonBasicOutline" shader like this :

    Code (CSharp):
    1. Shader "Standard (Outlined)" {
    2.  
    3.         Properties
    4.     {
    5.         _Color("Color", Color) = (1,1,1,1)
    6.         _MainTex("Albedo", 2D) = "white" {}
    7.  
    8.         _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
    9.  
    10.         _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
    11.         [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
    12.         _MetallicGlossMap("Metallic", 2D) = "white" {}
    13.  
    14.         _BumpScale("Scale", Float) = 1.0
    15.         _BumpMap("Normal Map", 2D) = "bump" {}
    16.  
    17.         _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
    18.         _ParallaxMap ("Height Map", 2D) = "black" {}
    19.  
    20.         _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
    21.         _OcclusionMap("Occlusion", 2D) = "white" {}
    22.  
    23.         _EmissionColor("Color", Color) = (0,0,0)
    24.         _EmissionMap("Emission", 2D) = "white" {}
    25.  
    26.         _DetailMask("Detail Mask", 2D) = "white" {}
    27.  
    28.         _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
    29.         _DetailNormalMapScale("Scale", Float) = 1.0
    30.         _DetailNormalMap("Normal Map", 2D) = "bump" {}
    31.  
    32.         [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
    33.  
    34.         // UI-only data
    35.         [HideInInspector] _EmissionScaleUI("Scale", Float) = 0.0
    36.         [HideInInspector] _EmissionColorUI("Color", Color) = (1,1,1)
    37.  
    38.         // Blending state
    39.         [HideInInspector] _Mode ("__mode", Float) = 0.0
    40.         [HideInInspector] _SrcBlend ("__src", Float) = 1.0
    41.         [HideInInspector] _DstBlend ("__dst", Float) = 0.0
    42.         [HideInInspector] _ZWrite ("__zw", Float) = 1.0
    43.  
    44.         // -------------------------
    45.         // Added Outline properties
    46.         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
    47.         _Outline ("Outline width", Range (.002, 0.03)) = .005
    48.         // -------------------------
    49.     }
    50.  
    51.     CGINCLUDE
    52.         #define UNITY_SETUP_BRDF_INPUT MetallicSetup
    53.     ENDCG
    54.  
    55. /////////////////////////////////////////////////////////////////////////////////////////////
    56.  
    57.     SubShader
    58.     {
    59.         Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
    60.         LOD 300
    61.  
    62.         // ----------------------
    63.         // Start of Outline adding
    64.    
    65.         CGINCLUDE
    66.         #include "UnityCG.cginc"
    67.      
    68.         struct appdata {
    69.             float4 vertex : POSITION;
    70.             float3 normal : NORMAL;
    71.         };
    72.      
    73.         struct v2f {
    74.             float4 pos : SV_POSITION;
    75.             UNITY_FOG_COORDS(0)
    76.             fixed4 color : COLOR;
    77.         };
    78.      
    79.         uniform float _Outline;
    80.         uniform float4 _OutlineColor;
    81.      
    82.         v2f vert(appdata v) {
    83.             // just make a copy of incoming vertex data but scaled according to normal direction
    84.             v2f o;
    85.             o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    86.  
    87.             float3 norm   = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
    88.             float2 offset = TransformViewToProjection(norm.xy);
    89.  
    90.             o.pos.xy += offset * o.pos.z * _Outline;
    91.             o.color = _OutlineColor;
    92.             UNITY_TRANSFER_FOG(o,o.pos);
    93.             return o;
    94.         }
    95.         ENDCG      
    96.  
    97.         Pass {
    98.             Name "OUTLINE"
    99.             Tags { "LightMode" = "Always" }
    100.             Cull Front
    101.             ZWrite On
    102.             ColorMask RGB
    103.             Blend SrcAlpha OneMinusSrcAlpha
    104.  
    105.             CGPROGRAM
    106.             #pragma vertex vert
    107.             #pragma fragment frag
    108.             #pragma multi_compile_fog
    109.             fixed4 frag(v2f i) : SV_Target
    110.             {
    111.                 UNITY_APPLY_FOG(i.fogCoord, i.color);
    112.                 return i.color;
    113.             }
    114.             ENDCG
    115.         }
    116.  
    117.         // End of Outline adding
    118.         // ----------------------
    119.  
    120.  
    121.         // ------------------------------------------------------------------
    122.         //  Base forward pass (directional light, emission, lightmaps, ...)
    123.         Pass
    124.         {
    125.             Name "FORWARD"
    126.             Tags { "LightMode" = "ForwardBase" }
    127.  
    128.             Blend [_SrcBlend] [_DstBlend]
    129.             ZWrite [_ZWrite]
    130.  
    131.             CGPROGRAM
    132.             #pragma target 3.0
    133.             // TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    134.             #pragma exclude_renderers gles
    135.            
    136.             // -------------------------------------
    137.                    
    138.             #pragma shader_feature _NORMALMAP
    139.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    140.             #pragma shader_feature _EMISSION
    141.             #pragma shader_feature _METALLICGLOSSMAP
    142.             #pragma shader_feature ___ _DETAIL_MULX2
    143.             #pragma shader_feature _PARALLAXMAP
    144.            
    145.             #pragma multi_compile_fwdbase
    146.             #pragma multi_compile_fog
    147.                
    148.             #pragma vertex vertForwardBase
    149.             #pragma fragment fragForwardBase
    150.  
    151.             #include "UnityStandardCore.cginc"
    152.  
    153.             ENDCG
    154.         }
    155.         // ------------------------------------------------------------------
    156.         //  Additive forward pass (one light per pass)
    157.         Pass
    158.         {
    159.             Name "FORWARD_DELTA"
    160.             Tags { "LightMode" = "ForwardAdd" }
    161.             Blend [_SrcBlend] One
    162.             Fog { Color (0,0,0,0) } // in additive pass fog should be black
    163.             ZWrite Off
    164.             ZTest LEqual
    165.  
    166.             CGPROGRAM
    167.             #pragma target 3.0
    168.             // GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    169.             #pragma exclude_renderers gles
    170.  
    171.             // -------------------------------------
    172.  
    173.            
    174.             #pragma shader_feature _NORMALMAP
    175.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    176.             #pragma shader_feature _METALLICGLOSSMAP
    177.             #pragma shader_feature ___ _DETAIL_MULX2
    178.             #pragma shader_feature _PARALLAXMAP
    179.            
    180.             #pragma multi_compile_fwdadd_fullshadows
    181.             #pragma multi_compile_fog
    182.            
    183.             #pragma vertex vertForwardAdd
    184.             #pragma fragment fragForwardAdd
    185.  
    186.             #include "UnityStandardCore.cginc"
    187.  
    188.             ENDCG
    189.         }
    190.         // ------------------------------------------------------------------
    191.         //  Shadow rendering pass
    192.         Pass {
    193.             Name "ShadowCaster"
    194.             Tags { "LightMode" = "ShadowCaster" }
    195.            
    196.             ZWrite On ZTest LEqual
    197.  
    198.             CGPROGRAM
    199.             #pragma target 3.0
    200.             // TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    201.             #pragma exclude_renderers gles
    202.            
    203.             // -------------------------------------
    204.  
    205.  
    206.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    207.             #pragma multi_compile_shadowcaster
    208.  
    209.             #pragma vertex vertShadowCaster
    210.             #pragma fragment fragShadowCaster
    211.  
    212.             #include "UnityStandardShadow.cginc"
    213.  
    214.             ENDCG
    215.         }
    216.         // ------------------------------------------------------------------
    217.         //  Deferred pass
    218.         Pass
    219.         {
    220.             Name "DEFERRED"
    221.             Tags { "LightMode" = "Deferred" }
    222.  
    223.             CGPROGRAM
    224.             #pragma target 3.0
    225.             // TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    226.             #pragma exclude_renderers nomrt gles
    227.            
    228.  
    229.             // -------------------------------------
    230.  
    231.             #pragma shader_feature _NORMALMAP
    232.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    233.             #pragma shader_feature _EMISSION
    234.             #pragma shader_feature _METALLICGLOSSMAP
    235.             #pragma shader_feature ___ _DETAIL_MULX2
    236.             #pragma shader_feature _PARALLAXMAP
    237.  
    238.             #pragma multi_compile ___ UNITY_HDR_ON
    239.             #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
    240.             #pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
    241.             #pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
    242.            
    243.             #pragma vertex vertDeferred
    244.             #pragma fragment fragDeferred
    245.  
    246.             #include "UnityStandardCore.cginc"
    247.  
    248.             ENDCG
    249.         }
    250.  
    251.         // ------------------------------------------------------------------
    252.         // Extracts information for lightmapping, GI (emission, albedo, ...)
    253.         // This pass it not used during regular rendering.
    254.         Pass
    255.         {
    256.             Name "META"
    257.             Tags { "LightMode"="Meta" }
    258.  
    259.             Cull Off
    260.  
    261.             CGPROGRAM
    262.             #pragma vertex vert_meta
    263.             #pragma fragment frag_meta
    264.  
    265.             #pragma shader_feature _EMISSION
    266.             #pragma shader_feature _METALLICGLOSSMAP
    267.             #pragma shader_feature ___ _DETAIL_MULX2
    268.  
    269.             #include "UnityStandardMeta.cginc"
    270.             ENDCG
    271.         }
    272.     }
    273.  
    274.     SubShader
    275.     {
    276.         Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
    277.         LOD 150
    278.  
    279.         // ------------------------------------------------------------------
    280.         //  Base forward pass (directional light, emission, lightmaps, ...)
    281.         Pass
    282.         {
    283.             Name "FORWARD"
    284.             Tags { "LightMode" = "ForwardBase" }
    285.  
    286.             Blend [_SrcBlend] [_DstBlend]
    287.             ZWrite [_ZWrite]
    288.  
    289.             CGPROGRAM
    290.             #pragma target 2.0
    291.            
    292.             #pragma shader_feature _NORMALMAP
    293.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    294.             #pragma shader_feature _EMISSION
    295.             #pragma shader_feature _METALLICGLOSSMAP
    296.             #pragma shader_feature ___ _DETAIL_MULX2
    297.             // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
    298.  
    299.             #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
    300.  
    301.             #pragma multi_compile_fwdbase
    302.             #pragma multi_compile_fog
    303.    
    304.             #pragma vertex vertForwardBase
    305.             #pragma fragment fragForwardBase
    306.  
    307.             #include "UnityStandardCore.cginc"
    308.  
    309.             ENDCG
    310.         }
    311.         // ------------------------------------------------------------------
    312.         //  Additive forward pass (one light per pass)
    313.         Pass
    314.         {
    315.             Name "FORWARD_DELTA"
    316.             Tags { "LightMode" = "ForwardAdd" }
    317.             Blend [_SrcBlend] One
    318.             Fog { Color (0,0,0,0) } // in additive pass fog should be black
    319.             ZWrite Off
    320.             ZTest LEqual
    321.            
    322.             CGPROGRAM
    323.             #pragma target 2.0
    324.  
    325.             #pragma shader_feature _NORMALMAP
    326.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    327.             #pragma shader_feature _METALLICGLOSSMAP
    328.             #pragma shader_feature ___ _DETAIL_MULX2
    329.             // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
    330.             #pragma skip_variants SHADOWS_SOFT
    331.            
    332.             #pragma multi_compile_fwdadd_fullshadows
    333.             #pragma multi_compile_fog
    334.            
    335.             #pragma vertex vertForwardAdd
    336.             #pragma fragment fragForwardAdd
    337.  
    338.             #include "UnityStandardCore.cginc"
    339.  
    340.             ENDCG
    341.         }
    342.         // ------------------------------------------------------------------
    343.         //  Shadow rendering pass
    344.         Pass {
    345.             Name "ShadowCaster"
    346.             Tags { "LightMode" = "ShadowCaster" }
    347.            
    348.             ZWrite On ZTest LEqual
    349.  
    350.             CGPROGRAM
    351.             #pragma target 2.0
    352.  
    353.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    354.             #pragma skip_variants SHADOWS_SOFT
    355.             #pragma multi_compile_shadowcaster
    356.  
    357.             #pragma vertex vertShadowCaster
    358.             #pragma fragment fragShadowCaster
    359.  
    360.             #include "UnityStandardShadow.cginc"
    361.  
    362.             ENDCG
    363.         }
    364.  
    365.         // ------------------------------------------------------------------
    366.         // Extracts information for lightmapping, GI (emission, albedo, ...)
    367.         // This pass it not used during regular rendering.
    368.         Pass
    369.         {
    370.             Name "META"
    371.             Tags { "LightMode"="Meta" }
    372.  
    373.             Cull Off
    374.  
    375.             CGPROGRAM
    376.             #pragma vertex vert_meta
    377.             #pragma fragment frag_meta
    378.  
    379.             #pragma shader_feature _EMISSION
    380.             #pragma shader_feature _METALLICGLOSSMAP
    381.             #pragma shader_feature ___ _DETAIL_MULX2
    382.  
    383.             #include "UnityStandardMeta.cginc"
    384.             ENDCG
    385.         }
    386.     }
    387.  
    388.     FallBack "Standard"
    389.     CustomEditor "CustomStandardShaderGUI"
    390. }
    391.  
    Here's the shader where I modified it (the rest is unchanged so I didn't copy it all here).

    And as you said, rev087, you can't see the new properties in the inspector because of the custom editor made for the standard shader.
    So I copied the "StandardShaderGUI.cs" script and modified it to add the Outline properties.

    Here's what i got now :

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. namespace UnityEditor
    5. {
    6.     internal class CustomStandardShaderGUI : 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("Smoothness", "");
    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 string whiteSpaceString = " ";
    44.         public static string primaryMapsText = "Main Maps";
    45.         public static string secondaryMapsText = "Secondary Maps";
    46.         public static string renderingMode = "Rendering Mode";
    47.         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.");
    48.         public static GUIContent emissiveColorWarning = new GUIContent ("Ensure emissive color is non-black for emission to have effect.");
    49.         public static readonly string[] blendNames = Enum.GetNames (typeof (BlendMode));
    50.     }
    51.  
    52.     MaterialProperty blendMode = null;
    53.     MaterialProperty albedoMap = null;
    54.     MaterialProperty albedoColor = null;
    55.     MaterialProperty alphaCutoff = null;
    56.     MaterialProperty specularMap = null;
    57.     MaterialProperty specularColor = null;
    58.     MaterialProperty metallicMap = null;
    59.     MaterialProperty metallic = null;
    60.     MaterialProperty smoothness = null;
    61.     MaterialProperty bumpScale = null;
    62.     MaterialProperty bumpMap = null;
    63.     MaterialProperty occlusionStrength = null;
    64.     MaterialProperty occlusionMap = null;
    65.     MaterialProperty heigtMapScale = null;
    66.     MaterialProperty heightMap = null;
    67.     MaterialProperty emissionScaleUI = null;
    68.     MaterialProperty emissionColorUI = null;
    69.     MaterialProperty emissionColorForRendering = null;
    70.     MaterialProperty emissionMap = null;
    71.     MaterialProperty detailMask = null;
    72.     MaterialProperty detailAlbedoMap = null;
    73.     MaterialProperty detailNormalMapScale = null;
    74.     MaterialProperty detailNormalMap = null;
    75.     MaterialProperty uvSetSecondary = null;
    76.     // Outline Add ------------------------------------------------------- //
    77.     MaterialProperty _OutlineColor = null;
    78.     MaterialProperty _Outline = null;
    79.  
    80.     MaterialEditor m_MaterialEditor;
    81.     WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
    82.  
    83.     bool m_FirstTimeApply = true;
    84.  
    85.     public void FindProperties (MaterialProperty[] props)
    86.     {
    87.         blendMode = FindProperty ("_Mode", props);
    88.         albedoMap = FindProperty ("_MainTex", props);
    89.         albedoColor = FindProperty ("_Color", props);
    90.         alphaCutoff = FindProperty ("_Cutoff", props);
    91.         specularMap = FindProperty ("_SpecGlossMap", props, false);
    92.         specularColor = FindProperty ("_SpecColor", props, false);
    93.         metallicMap = FindProperty ("_MetallicGlossMap", props, false);
    94.         metallic = FindProperty ("_Metallic", props, false);
    95.         if (specularMap != null && specularColor != null)
    96.             m_WorkflowMode = WorkflowMode.Specular;
    97.         else if (metallicMap != null && metallic != null)
    98.             m_WorkflowMode = WorkflowMode.Metallic;
    99.         else
    100.             m_WorkflowMode = WorkflowMode.Dielectric;
    101.         smoothness = FindProperty ("_Glossiness", props);
    102.         bumpScale = FindProperty ("_BumpScale", props);
    103.         bumpMap = FindProperty ("_BumpMap", props);
    104.         heigtMapScale = FindProperty ("_Parallax", props);
    105.         heightMap = FindProperty("_ParallaxMap", props);
    106.         occlusionStrength = FindProperty ("_OcclusionStrength", props);
    107.         occlusionMap = FindProperty ("_OcclusionMap", props);
    108.         emissionScaleUI = FindProperty ("_EmissionScaleUI", props);
    109.         emissionColorUI = FindProperty ("_EmissionColorUI", 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.         // Outline Add ------------------------------------------------------- //
    118.         _OutlineColor = FindProperty ("_OutlineColor", props);
    119.         _Outline = FindProperty ("_Outline", 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.             EditorGUILayout.Space();
    164.  
    165.             // Secondary properties
    166.             GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
    167.             m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
    168.             m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
    169.             m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
    170.             m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
    171.  
    172.             EditorGUILayout.Space();
    173.  
    174.             // Outline properties --------------------------------------------------- //
    175.             GUILayout.Label ("Outline Properties", EditorStyles.boldLabel);
    176.             m_MaterialEditor.ColorProperty (_OutlineColor, "Outline Color");
    177.             m_MaterialEditor.FloatProperty (_Outline, "Outline Width");
    178.         }
    179.         if (EditorGUI.EndChangeCheck())
    180.         {
    181.             foreach (var obj in blendMode.targets)
    182.                 MaterialChanged((Material)obj, m_WorkflowMode);
    183.         }
    184.     }
    185.  
    186.     internal void DetermineWorkflow(MaterialProperty[] props)
    187.     {
    188.         if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
    189.             m_WorkflowMode = WorkflowMode.Specular;
    190.         else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
    191.             m_WorkflowMode = WorkflowMode.Metallic;
    192.         else
    193.             m_WorkflowMode = WorkflowMode.Dielectric;
    194.     }
    195.  
    196.     public override void AssignNewShaderToMaterial (Material material, Shader oldShader, Shader newShader)
    197.     {
    198.         base.AssignNewShaderToMaterial(material, oldShader, newShader);
    199.  
    200.         if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
    201.             return;
    202.  
    203.         BlendMode blendMode = BlendMode.Opaque;
    204.         if (oldShader.name.Contains("/Transparent/Cutout/"))
    205.         {
    206.             blendMode = BlendMode.Cutout;
    207.         }
    208.         else if (oldShader.name.Contains("/Transparent/"))
    209.         {
    210.             // NOTE: legacy shaders did not provide physically based transparency
    211.             // therefore Fade mode
    212.             blendMode = BlendMode.Fade;
    213.         }
    214.         material.SetFloat("_Mode", (float)blendMode);
    215.  
    216.         //DetermineWorkflow( ShaderUtil.GetMaterialProperties(new Material[] { material }) );
    217.         MaterialChanged(material, m_WorkflowMode);
    218.     }
    219.  
    220.     void BlendModePopup()
    221.     {
    222.         EditorGUI.showMixedValue = blendMode.hasMixedValue;
    223.         var mode = (BlendMode)blendMode.floatValue;
    224.  
    225.         EditorGUI.BeginChangeCheck();
    226.         mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
    227.         if (EditorGUI.EndChangeCheck())
    228.         {
    229.             m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
    230.             blendMode.floatValue = (float)mode;
    231.         }
    232.  
    233.         EditorGUI.showMixedValue = false;
    234.     }
    235.  
    236.     void DoAlbedoArea(Material material)
    237.     {
    238.         m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
    239.         if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout))
    240.         {
    241.             m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel+1);
    242.         }
    243.     }
    244.  
    245.     void DoEmissionArea(Material material)
    246.     {
    247.         bool showEmissionColorAndGIControls = emissionScaleUI.floatValue > 0f;
    248.         bool hadEmissionTexture = emissionMap.textureValue != null;
    249.  
    250.         // Do controls
    251.         m_MaterialEditor.TexturePropertySingleLine(Styles.emissionText, emissionMap, showEmissionColorAndGIControls ? emissionColorUI : null, emissionScaleUI);
    252.  
    253.         // Set default emissionScaleUI if texture was assigned
    254.         if (emissionMap.textureValue != null && !hadEmissionTexture && emissionScaleUI.floatValue <= 0f)
    255.             emissionScaleUI.floatValue = 1.0f;
    256.  
    257.         // Dynamic Lightmapping mode
    258.         if (showEmissionColorAndGIControls)
    259.         {
    260.             bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled(EvalFinalEmissionColor(material));
    261.             EditorGUI.BeginDisabledGroup(!shouldEmissionBeEnabled);
    262.  
    263.             m_MaterialEditor.LightmapEmissionProperty (MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
    264.  
    265.             EditorGUI.EndDisabledGroup();
    266.         }
    267.  
    268.         if (!HasValidEmissiveKeyword(material))
    269.         {
    270.             EditorGUILayout.HelpBox(Styles.emissiveWarning.text, MessageType.Warning);
    271.         }
    272.  
    273.     }
    274.  
    275.     void DoSpecularMetallicArea()
    276.     {
    277.         if (m_WorkflowMode == WorkflowMode.Specular)
    278.         {
    279.             if (specularMap.textureValue == null)
    280.                 m_MaterialEditor.TexturePropertyTwoLines(Styles.specularMapText, specularMap, specularColor, Styles.smoothnessText, smoothness);
    281.             else
    282.                 m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap);
    283.  
    284.         }
    285.         else if (m_WorkflowMode == WorkflowMode.Metallic)
    286.         {
    287.             if (metallicMap.textureValue == null)
    288.                 m_MaterialEditor.TexturePropertyTwoLines(Styles.metallicMapText, metallicMap, metallic, Styles.smoothnessText, smoothness);
    289.             else
    290.                 m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap);
    291.         }
    292.     }
    293.  
    294.     public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
    295.     {
    296.         switch (blendMode)
    297.         {
    298.             case BlendMode.Opaque:
    299.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    300.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
    301.                 material.SetInt("_ZWrite", 1);
    302.                 material.DisableKeyword("_ALPHATEST_ON");
    303.                 material.DisableKeyword("_ALPHABLEND_ON");
    304.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    305.                 material.renderQueue = -1;
    306.                 break;
    307.             case BlendMode.Cutout:
    308.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    309.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
    310.                 material.SetInt("_ZWrite", 1);
    311.                 material.EnableKeyword("_ALPHATEST_ON");
    312.                 material.DisableKeyword("_ALPHABLEND_ON");
    313.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    314.                 material.renderQueue = 2450;
    315.                 break;
    316.             case BlendMode.Fade:
    317.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
    318.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    319.                 material.SetInt("_ZWrite", 0);
    320.                 material.DisableKeyword("_ALPHATEST_ON");
    321.                 material.EnableKeyword("_ALPHABLEND_ON");
    322.                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    323.                 material.renderQueue = 3000;
    324.                 break;
    325.             case BlendMode.Transparent:
    326.                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
    327.                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    328.                 material.SetInt("_ZWrite", 0);
    329.                 material.DisableKeyword("_ALPHATEST_ON");
    330.                 material.DisableKeyword("_ALPHABLEND_ON");
    331.                 material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
    332.                 material.renderQueue = 3000;
    333.                 break;
    334.         }
    335.     }
    336.  
    337.     // Calculate final HDR _EmissionColor (gamma space) from _EmissionColorUI (LDR, gamma) & _EmissionScaleUI (gamma)
    338.     static Color EvalFinalEmissionColor(Material material)
    339.     {
    340.         return material.GetColor("_EmissionColorUI") * material.GetFloat("_EmissionScaleUI");
    341.     }
    342.  
    343.     static bool ShouldEmissionBeEnabled (Color color)
    344.     {
    345.         return color.grayscale > (0.1f / 255.0f);
    346.     }
    347.  
    348.     static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
    349.     {
    350.         // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
    351.         // (MaterialProperty value might come from renderer material property block)
    352.         SetKeyword (material, "_NORMALMAP", material.GetTexture ("_BumpMap") || material.GetTexture ("_DetailNormalMap"));
    353.         if (workflowMode == WorkflowMode.Specular)
    354.             SetKeyword (material, "_SPECGLOSSMAP", material.GetTexture ("_SpecGlossMap"));
    355.         else if (workflowMode == WorkflowMode.Metallic)
    356.             SetKeyword (material, "_METALLICGLOSSMAP", material.GetTexture ("_MetallicGlossMap"));
    357.         SetKeyword (material, "_PARALLAXMAP", material.GetTexture ("_ParallaxMap"));
    358.         SetKeyword (material, "_DETAIL_MULX2", material.GetTexture ("_DetailAlbedoMap") || material.GetTexture ("_DetailNormalMap"));
    359.  
    360.         bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled (material.GetColor("_EmissionColor"));
    361.         SetKeyword (material, "_EMISSION", shouldEmissionBeEnabled);
    362.  
    363.         // Setup lightmap emissive flags
    364.         MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
    365.         if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
    366.         {
    367.             flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
    368.             if (!shouldEmissionBeEnabled)
    369.                 flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
    370.  
    371.             material.globalIlluminationFlags = flags;
    372.         }
    373.     }
    374.  
    375.     bool HasValidEmissiveKeyword (Material material)
    376.     {
    377.         // Material animation might be out of sync with the material keyword.
    378.         // 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.
    379.         // (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
    380.         bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
    381.         if (!hasEmissionKeyword && ShouldEmissionBeEnabled (emissionColorForRendering.colorValue))
    382.             return false;
    383.         else
    384.             return true;
    385.     }
    386.  
    387.     static void MaterialChanged(Material material, WorkflowMode workflowMode)
    388.     {
    389.         // Clamp EmissionScale to always positive
    390.         if (material.GetFloat("_EmissionScaleUI") < 0.0f)
    391.             material.SetFloat("_EmissionScaleUI", 0.0f);
    392.  
    393.         // Apply combined emission value
    394.         Color emissionColorOut = EvalFinalEmissionColor (material);
    395.         material.SetColor("_EmissionColor", emissionColorOut);
    396.  
    397.         // Handle Blending modes
    398.         SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
    399.  
    400.         SetMaterialKeywords(material, workflowMode);
    401.     }
    402.  
    403.     static void SetKeyword(Material m, string keyword, bool state)
    404.     {
    405.         if (state)
    406.             m.EnableKeyword (keyword);
    407.         else
    408.             m.DisableKeyword (keyword);
    409.     }
    410. }
    411.  
    412. } // namespace UnityEditor
    413.  
    You can just copy and paste it in a new CS file, this will work (there are just a few added lines, might not be worth the scroll ^^).

    After this, you need to change the last line of your modified Standard shader (the shader, not the .cs file) to this :
    Code (CSharp):
    1.     CustomEditor "CustomStandardShaderGUI"
    Change your material's shader to the new "Standard (Outlined)" shader and this is it! The default Outline width is set to 0.005. I recommend you to keep it like this as I find it good but you can still try to set it differently (just don't go too high as this will not work as intended).

    Also, the "ToonBasicOutline" shader included in Unity may not be the best outline shader, but it's the best I could find. If you find another one, please let me know!
     
    Last edited: May 13, 2015
    inthedarkgames and asdzxcv777 like this.
  9. vladk

    vladk

    Joined:
    Jul 10, 2008
    Posts:
    159
    Hey, are you sure you pasted the full code of a shader? It looks like it missing some parts in the end.
     
  10. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    No, as I said this is from Unity's Standard shader, I pasted only the part I changed.

    You can get it here : https://unity3d.com/get-unity/download/archive in the Built in shaders.
    I think I'll just edit it to paste the full shader, will be easier.

    EDIT : Done, you can just copy/paste it in a new shader file now.
     
    Andres Fernandez likes this.
  11. sballew7

    sballew7

    Joined:
    Sep 3, 2013
    Posts:
    64
    Very cool. Thanks for sharing, MingJ.
     
  12. Andres Fernandez

    Andres Fernandez

    Joined:
    Feb 4, 2013
    Posts:
    56
    Yeah, thanks for sharing. Good stuff. Is it possible to make it work on WebGL?
     
  13. rev087

    rev087

    Joined:
    Oct 3, 2013
    Posts:
    11
    Nice work MingJ, much easier to work with than what I had.
     
    MingJ likes this.
  14. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    I didn't try it, but I guess it should be.
     
  15. Andres Fernandez

    Andres Fernandez

    Joined:
    Feb 4, 2013
    Posts:
    56
    Then I must have done something wrong because I can't make it work in WebGL :p It does work great in editor, but not in build.
     
  16. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    Are you in deferred rendering mode ? For an unknown reason outlines don't seem to work on deferred mode (on build). I have the same issue on Android. Even Unity's 'Toon' shader doesn't work. I'm not really experienced with shaders so I can't understand why...
    Try to use forward mode instead and see if it works.
     
    Last edited: May 19, 2015
    Andres Fernandez likes this.
  17. Andres Fernandez

    Andres Fernandez

    Joined:
    Feb 4, 2013
    Posts:
    56
    I believe I've tried both forward and deferred, but I'll check again (just in case I missed forward) and post the result.
     
  18. TSRajesh

    TSRajesh

    Joined:
    Jun 19, 2013
    Posts:
    32
    I Apologize if this question is too trivial or obvious.. But How do I compile / import this modified shader into Unity 5?
     
  19. MingJ

    MingJ

    Joined:
    May 13, 2015
    Posts:
    12
    You just have to create a new shader in your project and replace its content by the code I pasted above.
     
  20. antislash

    antislash

    Joined:
    Apr 23, 2015
    Posts:
    646
    i think it's also possible simply by writing a surface shader with 2 "dirty passes " meaning 2 CGPROGRAM blocks
    the first one with a vertex function that extrudes vertexes along normals, full red, and the second rendering original geometry....

    here is a draft...

    Code (CSharp):
    1. Shader "Custom/victor_outline" {
    2.    Properties {
    3.         _MainColor ("Diffuse Color", Color) = (1,1,1,1)
    4.         _MainTex ("Base layer (RGB)", 2D) = "white" {}
    5.  
    6.         _Dist ("Shift", Range(-1, 1)) = 0
    7.     }
    8.  
    9.     SubShader {
    10.  
    11.         /// first pass
    12.      
    13.         Tags { "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    14.         LOD 200
    15.         Blend SrcAlpha OneMinusSrcAlpha
    16.         Lighting On
    17.         ZWrite On
    18.         ZTest LEqual
    19.         cull Front
    20.         CGPROGRAM
    21.  
    22.         #pragma surface surf StandardSpecular fullforwardshadows addshadow alphatest:_Cutoff vertex:vert
    23.         #pragma target 3.0
    24.         #include "UnityCG.cginc"
    25.  
    26.  
    27.         float4 _MainColor;
    28.         float _Dist;
    29.  
    30.      
    31.         struct Input {
    32.             float2 uv_MainTex;
    33.         };
    34.      
    35.         void vert (inout appdata_full v) {
    36.             v.vertex.xyz += float3(v.normal.xyz)*_Dist;    
    37.         }
    38.      
    39.         void surf (Input i, inout SurfaceOutputStandardSpecular o) {
    40.             o.Emission = _MainColor.rgb;  // main albedo color
    41.             o.Specular =0;
    42.             o.Smoothness = 0;
    43.             o.Alpha = 1;
    44.             ///////////////
    45.         }
    46.         ENDCG
    47.         //// end first pass
    48.      
    49.         /// second pass
    50.  
    51.         Tags { "IgnoreProjector"="True" "RenderType"="Opaque"}
    52.         Blend SrcAlpha OneMinusSrcAlpha
    53.         Lighting On
    54.         ZWrite On
    55.         Cull Off
    56.  
    57.  
    58.         CGPROGRAM
    59.      
    60.         #pragma surface surf StandardSpecular fullforwardshadows addshadow alphatest:_Cutoff
    61.         #pragma target 3.0
    62.         #include "UnityCG.cginc"
    63.  
    64.          sampler2D _MainTex;
    65.  
    66.      
    67.         struct Input {
    68.             float2 uv_MainTex;
    69.             float3 norm :  TEXCOORD1;
    70.         };
    71.      
    72.         void surf (Input i, inout SurfaceOutputStandardSpecular o) {
    73.  
    74.             // Main Albedo
    75.             fixed4 tex = tex2D (_MainTex, i.uv_MainTex);
    76.             o.Albedo = tex.rgb;  // main albedo
    77.             o.Specular = 0;
    78.             o.Smoothness = 0;
    79.             o.Alpha = tex.a;
    80.         }
    81.         ENDCG
    82.         // end first pass
    83.  
    84.   } //subshader
    85. }//shader
     
    Last edited: Jun 15, 2015
    MaxPirat likes this.
  21. TSRajesh

    TSRajesh

    Joined:
    Jun 19, 2013
    Posts:
    32
    Sweet! Thank You!
     
  22. Onsterion

    Onsterion

    Joined:
    Feb 21, 2014
    Posts:
    211
    do you find a solution for WebGL?
     
  23. Disky

    Disky

    Joined:
    Dec 11, 2015
    Posts:
    1
    Is it possible to make this shader work with Deffered camera settings and Opaque-rendering mode on the material?
     
    yano_123 and StaffanEk like this.
  24. FusRoDahh

    FusRoDahh

    Joined:
    Jan 20, 2015
    Posts:
    21
    +1 for the shader & script. Saved countless hours on understanding how to extend standard shader itself. Thank you very much!
     
  25. Iteki

    Iteki

    Joined:
    Jun 14, 2016
    Posts:
    1