Search Unity

Help getting outline shader to work with Single Pass Stereo VR

Discussion in 'Shaders' started by Alverik, Sep 19, 2017.

  1. Alverik

    Alverik

    Joined:
    Apr 15, 2016
    Posts:
    417
    Hi, sorry to bother you guys. Until recently, I had been using in multipass VR a certain free outline effect I found in the forums, but recently we upgraded our project to Unity 2017.1 and we switched to Single pass stereo. Problem is, the shader seem to be incompatible with Single pass Stereo (since it's basically a screen Space effect). I already talked to the author ,but he isn't very good with shaders either and was asking for help in his thread (and well, he doesn't seem to work with VR, so I can't foresee him fixing it very soon anyways...)

    Anyway, the object was becoming fully covered by the effect and the right eye had an offset. And since, I've managed to fix one or two post processing effects before, I tried to follow the reference page for SPS, wich appears in the Unity manual, but, I could't get it to work (outline seem to appear, but it's the wrong color, and it's also squashed and offset to the right).

    Sadly, I'm pretty much a noob when it comes to shader programming... So, I would greatly appreciate it if someone could point me in the right direction (since I can't really tell what's wrong with it....).

    The git repository: https://github.com/cakeslice/Outline-Effect

    If you don't want to download it, here's the shader code only (with some of the stuff I tried):

    Code (CSharp):
    1. Shader "Hidden/OutlineEffect"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6.  
    7.     }
    8.     SubShader
    9.     {
    10.         Pass
    11.         {
    12.             Tags{ "RenderType" = "Opaque" }
    13.             LOD 200
    14.             ZTest Always
    15.             ZWrite Off
    16.             Cull Off
    17.  
    18.             CGPROGRAM
    19.  
    20.             #pragma vertex vert
    21.             #pragma fragment frag
    22.             #pragma target 3.0
    23.             #include "UnityCG.cginc"
    24.  
    25.             sampler2D _MainTex;
    26.             float4 _MainTex_ST;
    27.             sampler2D _OutlineSource;
    28.  
    29.             struct v2f
    30.             {
    31.                 float4 position : SV_POSITION;
    32.                 float2 uv : TEXCOORD0;
    33.             };
    34.  
    35.             v2f vert(appdata_img v)
    36.             {
    37.                 v2f o;
    38.                 o.position = UnityObjectToClipPos(v.vertex);
    39.                 o.uv = v.texcoord;
    40.  
    41.                 return o;
    42.             }
    43.  
    44.             float _LineThicknessX;
    45.             float _LineThicknessY;
    46.             int _FlipY;
    47.             uniform float4 _MainTex_TexelSize;
    48.  
    49.             half4 frag(v2f input) : COLOR
    50.             {
    51.                 float2 uv = input.uv;
    52.                 if (_FlipY == 1)
    53.                     uv.y = uv.y;
    54.                 #if UNITY_UV_STARTS_AT_TOP
    55.                 if (_MainTex_TexelSize.y < 0)
    56.                     uv.y = 1 - uv.y;
    57.                 #endif
    58.  
    59.                 //half4 originalPixel = tex2D(_MainTex,input.uv, UnityStereoScreenSpaceUVAdjust(input.uv, _MainTex_ST));
    60.                 half4 outlineSource = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv, _MainTex_ST));
    61.  
    62.                 const float h = .95f;
    63.  
    64.                 /*
    65.                 half4 sample1 = tex2D(_OutlineSource, uv + float2(_LineThicknessX,0.0));
    66.                 half4 sample2 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX,0.0));
    67.                 half4 sample3 = tex2D(_OutlineSource, uv + float2(.0,_LineThicknessY));
    68.                 half4 sample4 = tex2D(_OutlineSource, uv + float2(.0,-_LineThicknessY));*/
    69.  
    70.                 half4 sample1 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(_LineThicknessX,0.0), _MainTex_ST));
    71.                 half4 sample2 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(-_LineThicknessX,0.0), _MainTex_ST));
    72.                 half4 sample3 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(.0,_LineThicknessY), _MainTex_ST));
    73.                 half4 sample4 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(.0,-_LineThicknessY), _MainTex_ST));
    74.  
    75.                 bool red = sample1.r > h || sample2.r > h || sample3.r > h || sample4.r > h;
    76.                 bool green = sample1.g > h || sample2.g > h || sample3.g > h || sample4.g > h;
    77.                 bool blue = sample1.b > h || sample2.b > h || sample3.b > h || sample4.b > h;
    78.            
    79.                 if ((red && blue) || (green && blue) || (red && green))
    80.                     return float4(0,0,0,0);
    81.                 else
    82.                     return outlineSource;
    83.             }
    84.  
    85.             ENDCG
    86.         }
    87.  
    88.         Pass
    89.         {
    90.             Tags { "RenderType"="Opaque" }
    91.             LOD 200
    92.             ZTest Always
    93.             ZWrite Off
    94.             Cull Off
    95.      
    96.             CGPROGRAM
    97.  
    98.             #pragma vertex vert
    99.             #pragma fragment frag
    100.             #pragma target 3.0
    101.             #include "UnityCG.cginc"
    102.  
    103.             sampler2D _MainTex;
    104.             float4 _MainTex_ST;
    105.             sampler2D _OutlineSource;
    106.  
    107.             struct v2f {
    108.                float4 position : SV_POSITION;
    109.                float2 uv : TEXCOORD0;
    110.             };
    111.      
    112.             v2f vert(appdata_img v)
    113.             {
    114.                    v2f o;
    115.                 o.position = UnityObjectToClipPos(v.vertex);
    116.                 o.uv = v.texcoord;
    117.          
    118.                    return o;
    119.             }
    120.  
    121.             float _LineThicknessX;
    122.             float _LineThicknessY;
    123.             float _LineIntensity;
    124.             half4 _LineColor1;
    125.             half4 _LineColor2;
    126.             half4 _LineColor3;
    127.             int _FlipY;
    128.             int _Dark;
    129.             float _FillAmount;
    130.             int _CornerOutlines;
    131.             uniform float4 _MainTex_TexelSize;
    132.  
    133.             half4 frag (v2f input) : COLOR
    134.             {
    135.                 float2 uv = input.uv;
    136.                 if (_FlipY == 1)
    137.                     uv.y = 1 - uv.y;
    138.                 #if UNITY_UV_STARTS_AT_TOP
    139.                     if (_MainTex_TexelSize.y < 0)
    140.                         uv.y = 1 - uv.y;
    141.                 #endif
    142.  
    143.                 half4 originalPixel = tex2D(_MainTex, UnityStereoScreenSpaceUVAdjust(input.uv, _MainTex_ST));
    144.                 half4 outlineSource = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv, _MainTex_ST));
    145.                          
    146.                 const float h = .95f;
    147.                 half4 outline = 0;
    148.                 bool hasOutline = false;
    149.  
    150.                 /*
    151.                 half4 sample1 = tex2D(_OutlineSource, uv + float2(_LineThicknessX,0.0));
    152.                 half4 sample2 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX,0.0));
    153.                 half4 sample3 = tex2D(_OutlineSource, uv + float2(.0,_LineThicknessY));
    154.                 half4 sample4 = tex2D(_OutlineSource, uv + float2(.0,-_LineThicknessY));*/
    155.  
    156.                 half4 sample1 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(_LineThicknessX,0.0), _MainTex_ST));
    157.                 half4 sample2 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(-_LineThicknessX,0.0), _MainTex_ST));
    158.                 half4 sample3 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(.0,_LineThicknessY), _MainTex_ST));
    159.                 half4 sample4 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(.0,-_LineThicknessY), _MainTex_ST));
    160.          
    161.                 bool outside = outlineSource.a < h;
    162.                 bool outsideDark = outside && _Dark;
    163.  
    164.                 if (_CornerOutlines)
    165.                 {
    166.                     // TODO: Conditional compile
    167.                     /*half4 sample5 = tex2D(_OutlineSource, uv + float2(_LineThicknessX, _LineThicknessY));
    168.                     half4 sample6 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX, -_LineThicknessY));
    169.                     half4 sample7 = tex2D(_OutlineSource, uv + float2(_LineThicknessX, -_LineThicknessY));
    170.                     half4 sample8 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX, _LineThicknessY));*/
    171.  
    172.                     half4 sample5 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(_LineThicknessX, _LineThicknessY), _MainTex_ST));
    173.                     half4 sample6 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(-_LineThicknessX, -_LineThicknessY), _MainTex_ST));
    174.                     half4 sample7 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(_LineThicknessX, -_LineThicknessY), _MainTex_ST));
    175.                     half4 sample8 = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv + float2(-_LineThicknessX, _LineThicknessY), _MainTex_ST));
    176.  
    177.                     if (sample1.r > h || sample2.r > h || sample3.r > h || sample4.r > h ||
    178.                         sample5.r > h || sample6.r > h || sample7.r > h || sample8.r > h)
    179.                     {
    180.                         outline = _LineColor1 * _LineIntensity * _LineColor1.a;
    181.                         if (outsideDark)
    182.                             originalPixel *= 1 - _LineColor1.a;
    183.                         hasOutline = true;
    184.                     }
    185.                     else if (sample1.g > h || sample2.g > h || sample3.g > h || sample4.g > h ||
    186.                         sample5.g > h || sample6.g > h || sample7.g > h || sample8.g > h)
    187.                     {
    188.                         outline = _LineColor2 * _LineIntensity * _LineColor2.a;
    189.                         if (outsideDark)
    190.                             originalPixel *= 1 - _LineColor2.a;
    191.                         hasOutline = true;
    192.                     }
    193.                     else if (sample1.b > h || sample2.b > h || sample3.b > h || sample4.b > h ||
    194.                         sample5.b > h || sample6.b > h || sample7.b > h || sample8.b > h)
    195.                     {
    196.                         outline = _LineColor3 * _LineIntensity * _LineColor3.a;
    197.                         if (outsideDark)
    198.                             originalPixel *= 1 - _LineColor3.a;
    199.                         hasOutline = true;
    200.                     }
    201.  
    202.                     if (!outside)
    203.                         outline *= _FillAmount;
    204.                 }
    205.                 else
    206.                 {
    207.                     if (sample1.r > h || sample2.r > h || sample3.r > h || sample4.r > h)
    208.                     {
    209.                         outline = _LineColor1 * _LineIntensity * _LineColor1.a;
    210.                         if (outsideDark)
    211.                             originalPixel *= 1 - _LineColor1.a;
    212.                         hasOutline = true;
    213.                     }
    214.                     else if (sample1.g > h || sample2.g > h || sample3.g > h || sample4.g > h)
    215.                     {
    216.                         outline = _LineColor2 * _LineIntensity * _LineColor2.a;
    217.                         if (outsideDark)
    218.                             originalPixel *= 1 - _LineColor2.a;
    219.                         hasOutline = true;
    220.                     }
    221.                     else if (sample1.b > h || sample2.b > h || sample3.b > h || sample4.b > h)
    222.                     {
    223.                         outline = _LineColor3 * _LineIntensity * _LineColor3.a;
    224.                         if (outsideDark)
    225.                             originalPixel *= 1 - _LineColor3.a;
    226.                         hasOutline = true;
    227.                     }
    228.  
    229.                     if (!outside)
    230.                         outline *= _FillAmount;
    231.                 }              
    232.              
    233.                 //return outlineSource;  
    234.                 if (hasOutline)
    235.                     return lerp(originalPixel + outline, outline, _FillAmount);
    236.                 else
    237.                     return originalPixel;
    238.             }
    239.      
    240.             ENDCG
    241.         }
    242.     }
    243.  
    244.     FallBack "Diffuse"
    245. }
    Code (CSharp):
    1. Shader "Hidden/OutlineBufferEffect" {
    2.     Properties
    3.     {
    4.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    5.         _Color ("Tint", Color) = (1,1,1,1)
    6.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    7.     }
    8.  
    9.     SubShader
    10.     {
    11.         Tags
    12.         {
    13.             "Queue" = "Transparent"
    14.             "IgnoreProjector" = "True"
    15.             "RenderType" = "Transparent"
    16.             "PreviewType" = "Plane"
    17.             "CanUseSpriteAtlas" = "True"
    18.         }
    19.  
    20.         // Change this stuff in OutlineEffect.cs instead!
    21.         //ZWrite Off
    22.         //Blend One OneMinusSrcAlpha
    23.         Cull [_Culling]
    24.         Lighting Off
    25.      
    26.         CGPROGRAM
    27.  
    28.         #pragma surface surf Lambert vertex:vert nofog noshadow noambient nolightmap novertexlights noshadowmask nometa //keepalpha
    29.         #pragma multi_compile _ PIXELSNAP_ON
    30.  
    31.         sampler2D _MainTex;
    32.  
    33.         fixed4 _Color;
    34.         float _OutlineAlphaCutoff;
    35.  
    36.         struct Input
    37.         {
    38.             float2 uv_MainTex;
    39.             //fixed4 color;
    40.         };
    41.  
    42.         void vert(inout appdata_full v, out Input o)
    43.         {
    44.             #if defined(PIXELSNAP_ON)
    45.             v.vertex = UnityPixelSnap(v.vertex);
    46.             #endif
    47.  
    48.             UNITY_INITIALIZE_OUTPUT(Input, o);
    49.             //o.color = v.color;
    50.         }
    51.  
    52.         void surf(Input IN, inout SurfaceOutput o)
    53.         {
    54.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex);// * IN.color;
    55.  
    56.             if (c.a < _OutlineAlphaCutoff) discard;
    57.  
    58.             float alpha = c.a * 99999999;
    59.  
    60.             o.Albedo = _Color * alpha;
    61.             o.Alpha = alpha;
    62.             o.Emission = o.Albedo;
    63.         }
    64.  
    65.         ENDCG  
    66.     }
    67.  
    68.     Fallback "Transparent/VertexLit"
    69. }
     
    Last edited: Sep 19, 2017
  2. Alverik

    Alverik

    Joined:
    Apr 15, 2016
    Posts:
    417
    Bump...
     
  3. ekergraphics

    ekergraphics

    Joined:
    Feb 22, 2017
    Posts:
    257
    I would also like to know, and I'm even having trouble finding a paid alternative.