Search Unity

Transparency/Outline Shader: How to display front texture

Discussion in 'Shaders' started by kittik, Jun 22, 2018.

  1. kittik

    kittik

    Joined:
    Mar 6, 2015
    Posts:
    483
    I am inexperienced with creating/modifying Shaders, but have managed to create a handful of effects.

    After merging an Outline Shader, with a 'See-Through Objects' Shader I am trying to change the current shader from this:



    Where the Outline Color displays

    To this:



    Where the Object closest to the camera is displayed, but the Outline of the far object is still displayed

    My code is as follows

    Code (shader):
    1. Shader "Kittik/AlwaysVisibleOutline"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.         _OutlineColor("Outline color", Color) = (0,0,0,1)
    7.         _OutlineWidth("Outline width", Range(1.08, 1.165)) = 1.08
    8.     }
    9.     SubShader
    10.     {
    11.         Tags { "Queue"="Transparent" }
    12.         LOD 100
    13.  
    14.         Pass
    15.         {
    16.             Cull Off
    17.             ZWrite Off
    18.  
    19.             ZTest Always
    20.  
    21.             CGPROGRAM
    22.             #pragma vertex vert
    23.             #pragma fragment frag
    24.  
    25.             #include "UnityCG.cginc"
    26.  
    27.             struct appdata
    28.             {
    29.                 float4 vertex : POSITION;
    30.             };
    31.  
    32.             struct v2f
    33.             {
    34.                 float4 vertex : SV_POSITION;
    35.             };
    36.  
    37.             float _OutlineWidth;
    38.             float4 _OutlineColor;
    39.  
    40.             v2f vert (appdata v)
    41.             {
    42.                 v.vertex.xzy *= _OutlineWidth;
    43.  
    44.                 v2f o;
    45.                 o.vertex = UnityObjectToClipPos(v.vertex);
    46.  
    47.                 return o;
    48.             }
    49.            
    50.             fixed4 frag (v2f i) : SV_Target
    51.             {
    52.                 return _OutlineColor;
    53.             }
    54.  
    55.             ENDCG
    56.         }
    57.  
    58.         Pass
    59.         {
    60.             CGPROGRAM
    61.             #pragma vertex vert
    62.             #pragma fragment frag
    63.  
    64.             #include "UnityCG.cginc"
    65.  
    66.             struct appdata
    67.             {
    68.                 float4 vertex : POSITION;
    69.                 float2 uv : TEXCOORD0;
    70.             };
    71.  
    72.             struct v2f
    73.             {
    74.                 float2 uv : TEXCOORD0;
    75.                 float4 vertex : SV_POSITION;
    76.             };
    77.  
    78.             sampler2D _MainTex;
    79.             float4 _MainTex_ST;
    80.            
    81.             v2f vert (appdata v)
    82.             {
    83.                 v2f o;
    84.                 o.vertex = UnityObjectToClipPos(v.vertex);
    85.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    86.  
    87.                 return o;
    88.             }
    89.            
    90.             fixed4 frag (v2f i) : SV_Target
    91.             {
    92.                 // sample the texture
    93.                 fixed4 col = tex2D(_MainTex, i.uv);
    94.  
    95.                 return col;
    96.             }
    97.             ENDCG
    98.         }
    99.     }
    100. }

    Help would be appreciated, as would an explanation would also be, as I am trying to learn how to create interesting/effective shaders.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,694
    The usual solution to this problem is to render the object(s) you want to have an outline to another buffer, run an edge detection shader on that, and render the results on top of the final image as a post process image effect.

    Like this:
    https://forum.unity.com/threads/free-open-source-outline-effect.314362/

    However you can also do something similar with stencils. The trick is to render the object three times. Once normally. Once with ZTest Always, ColorMask 0, and writing to the stencil mask. And once with the outline pass that tests against the stencil from the previous pass and only render where it did not.