Search Unity

Fallback Off turns off shadows in surface shader

Discussion in 'Shaders' started by FuzzyQuills, Jul 17, 2014.

  1. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Hi guys, another question: I turned the fallback off, knowing i probably wouldn't need it, and... my shadows vanished. oddly, turning it back on brings back the shadows! Anyone know what's going on? My shader is a surface shader
     
  2. spraycanmansam

    spraycanmansam

    Joined:
    Nov 22, 2012
    Posts:
    254
    Can't quite remember off the top of my head but I think you need either Fallback Diffuse or VertexLit as a minimum to include the shadow collector/caster passes..
     
  3. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Really? Had no idea. Also surprised the VertexLit shader does it too.
     
  4. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Diffuse contains the FallBack of VertexLit.

    The point being that the VertexLit shader contains the shadow caster and receiver passes. Without those, the shader can't cast it receive shadows.

    So you can copy/paste those in to your shader or just add in FallBack VertexLit...
     
    spraycanmansam likes this.
  5. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    I also found you can add a separate subshader with a shadow caster pass in it. not sure if shadow collector is needed though... o_O
     
  6. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    You need it for the mesh to receive shadows.
     
  7. Nims

    Nims

    Joined:
    Nov 11, 2013
    Posts:
    86
    Very interested to see how you did that. Having to fallback on "Diffuse" for shadows makes me feel bad...really would like to know how to hook/write the passes which are needed for shadow caster/receiver.
     
  8. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    You can open up the shader source for the VertexLit shader and just rip them out.
     
  9. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Shadows require a shader to have special passes to do shadow rendering (ShadowCaster & ShadowCollector; starting with 5.0 only ShadowCaster). By default they are not generated, and fetched from a fallback instead (since for most of shaders they would be exactly the same anyway).

    If you don't want a fallback, you can tell surface shader to generate the shadow passes for you, append a " addshadow" to the #pragma surface line. http://docs.unity3d.com/Manual/SL-SurfaceShaders.html
     
    litefeel likes this.
  10. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    @Aras: Really? Had no idea! Does it work with transparent cutout shaders too? :)
     
  11. Lulucifer

    Lulucifer

    Joined:
    Jul 8, 2012
    Posts:
    358
    @Aras when does 5.0 come out
     
  12. Graph

    Graph

    Joined:
    Jun 8, 2014
    Posts:
    154
    if i may piggyback on this thread :p
    as you can see in the attached picture i'm using custom lightingModel to achieve a nice crisp cell shaded look. unfortunately tho, since i don't all "dark side" from .5 onward, the artifacts are clearly visible.
    now i've taken the shadowing passes of the vertexLit and put them into a single separate shadow to be used as fallback across the different iterations of the cell shader.
    thing is.. i think i should look inside the UnityCG.cginc file and futz around with some methods in there to get this to play together nicely.. but i'm totally lost in there, could anybody with experience on the matter give me some pointers?

    in case you're interested this is the shader version you see in the image:

    Code (CSharp):
    1.  
    2. Shader "Graph/Cell"
    3. {
    4.     Properties
    5.     {
    6.         _Color ("FilterColor", Color) = (1, 1, 1, 1)
    7.    
    8.         _MainTex ("Albedo", 2D) = "white" {}
    9.  
    10.         _Steps ("Steps", Color) = (0.95, 0.35, 0.05, 0)
    11.   }
    12.    
    13.     SubShader
    14.     {
    15.     Tags
    16.         {
    17.             "Queue" = "Geometry"
    18.             "RenderType" = "Opaque"
    19.         }
    20.  
    21.     LOD 150
    22.  
    23.     CGPROGRAM
    24.  
    25.     #pragma surface surf Cell nolightmap nodirlightmap halfasview
    26.         #pragma target 2.0
    27.  
    28.         fixed4 _Color;      
    29.         sampler2D _MainTex;
    30.         fixed4 _Steps;
    31.  
    32.  
    33.         half4 LightingCell (SurfaceOutput s, half3 lightDir, half atten)
    34.         {
    35.             #ifndef USING_DIRECTIONAL_LIGHT
    36.             lightDir = normalize(lightDir);
    37.             #endif
    38.    
    39.             half diff = ((dot(s.Normal, lightDir)) * 0.5 + 0.5) * atten;
    40.  
    41.             half4 c;
    42.             c.a = s.Alpha;
    43.  
    44.             if (diff > _Steps.r)
    45.                 c.rgb = s.Albedo * _LightColor0.rgb  * (atten*2) * 1;
    46.             else if (diff > _Steps.g)
    47.                 c.rgb = s.Albedo * _LightColor0.rgb  * (atten*2) * 0.7;
    48.             else
    49.                 c.rgb = s.Albedo * _LightColor0.rgb  * (atten*2) * 0.25;
    50.                
    51.             return c;
    52.         }
    53.  
    54.  
    55.     struct Input
    56.         {
    57.                 float2 uv_MainTex : TEXCOORD0;
    58.                 float3 viewDir;
    59.     };
    60.  
    61.  
    62.     void surf (Input IN, inout SurfaceOutput o)
    63.         {
    64.             o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * (_Color.rgb+_Color.rgb);
    65.     }
    66.  
    67.     ENDCG
    68.     }
    69.  
    70.     FallBack "Graph/Shadow"
    71. }
    72.  
    and for convenience's sake the shadow shader:


    Code (CSharp):
    1. Shader "Graph/Shadow"
    2. {
    3. SubShader
    4. {
    5.     Tags { "RenderType"="Opaque" }
    6.     LOD 80
    7.  
    8.     // Pass to render object as a shadow caster
    9.     Pass
    10.     {
    11.         Name "ShadowCaster"
    12.         Tags { "LightMode" = "ShadowCaster" }
    13.        
    14.         Fog {Mode Off}
    15.         ZWrite On ZTest LEqual Cull Off
    16.         Offset 1, 1
    17.  
    18.         CGPROGRAM
    19.         #pragma vertex vert
    20.         #pragma fragment frag
    21.         #pragma multi_compile_shadowcaster
    22.         #include "UnityCG.cginc"
    23.  
    24.         struct v2f
    25.         {
    26.             V2F_SHADOW_CASTER;
    27.         };
    28.  
    29.         v2f vert( appdata_base v )
    30.         {
    31.             v2f o;
    32.             TRANSFER_SHADOW_CASTER(o)
    33.             return o;
    34.         }
    35.  
    36.         float4 frag( v2f i ) : SV_Target
    37.         {
    38.             SHADOW_CASTER_FRAGMENT(i)
    39.         }
    40.         ENDCG
    41.     }
    42.    
    43.     // Pass to render object as a shadow collector
    44.     // note: editor needs this pass as it has a collector pass.
    45.     Pass
    46.     {
    47.         Name "ShadowCollector"
    48.         Tags { "LightMode" = "ShadowCollector" }
    49.        
    50.         Fog {Mode Off}
    51.         ZWrite On ZTest LEqual
    52.  
    53.         CGPROGRAM
    54.         #pragma vertex vert
    55.         #pragma fragment frag
    56.         #pragma multi_compile_shadowcollector
    57.  
    58.         #define SHADOW_COLLECTOR_PASS
    59.         #include "UnityCG.cginc"
    60.  
    61.         struct appdata
    62.         {
    63.             float4 vertex : POSITION;
    64.         };
    65.  
    66.         struct v2f
    67.         {
    68.             V2F_SHADOW_COLLECTOR;
    69.         };
    70.  
    71.         v2f vert (appdata v)
    72.         {
    73.             v2f o;
    74.             TRANSFER_SHADOW_COLLECTOR(o)
    75.             return o;
    76.         }
    77.  
    78.         fixed4 frag (v2f i) : SV_Target
    79.         {
    80.             SHADOW_COLLECTOR_FRAGMENT(i)
    81.         }
    82.         ENDCG
    83.     }
    84. }
    85. }
     

    Attached Files:

    kebrus likes this.
  13. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    I definitely approve the toon lighting sir! I also noticed that you are using Atten*2 in all the albedo settings. try only using it on dark areas, and see what happens!

    BTW, is shadow casting really that easy? :p Just kidding, I already sort of knew how to do that. ;) Anyway, stuff that, I will fix it up for ya! :)

    EDIT: Progress so far... well, the nice banding your shader has isn't showing. how to set the colour? BTW, shadow attenuation is going well! :)

    EDIT2: Ok, got it working. the challenge here? removing the horrid shadow attenuation... ;)
     
    Last edited: Aug 19, 2014
  14. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Here you go man, how does this look:
    ToonShaderShadowFix.png
    Here's the code BTW. give this a go in your scene!
    Code (csharp):
    1.  
    2. Shader "Graph/Cell_ShadowAttenFix"
    3. {
    4.     Properties
    5.     {
    6.         _Color ("FilterColor", Color) = (1, 1, 1, 1)
    7.         _MainTex ("Albedo", 2D) = "white" {}
    8.         _Steps ("Steps", Color) = (0.95, 0.35, 0.05, 0)
    9.   }
    10.    
    11.     SubShader
    12.     {
    13.     Tags
    14.         {
    15.             "Queue" = "Geometry"
    16.             "RenderType" = "Opaque"
    17.         }
    18.  
    19.     LOD 150
    20.  
    21.     CGPROGRAM
    22.  
    23.     #pragma surface surf Cell nolightmap nodirlightmap halfasview fullforwardshadows
    24.         #pragma target 2.0
    25.  
    26.         fixed4 _Color;      
    27.         sampler2D _MainTex;
    28.         fixed4 _Steps;
    29.  
    30.  
    31.         half4 LightingCell (SurfaceOutput s, half3 lightDir, half atten)
    32.         {
    33.             #ifndef USING_DIRECTIONAL_LIGHT
    34.             lightDir = normalize(lightDir);
    35.             #endif
    36.    
    37.             half diff = ((dot(s.Normal, lightDir)) * 0.5 + 0.5);
    38.  
    39.             half4 c;
    40.             c.a = s.Alpha;
    41.  
    42.             if (diff > _Steps.r && atten < _Steps.r)
    43.                 c.rgb = s.Albedo * _LightColor0.rgb + (s.Albedo * atten * 0.5);//
    44.               else if (diff > _Steps.r)
    45.                 c.rgb = s.Albedo * _LightColor0.rgb * 2;//
    46.             else if (diff > _Steps.g && atten < _Steps.g-0.4)
    47.                 c.rgb = s.Albedo * _LightColor0.rgb + (atten*0.5);
    48.             else if (diff > _Steps.g)
    49.                 c.rgb = s.Albedo * _LightColor0.rgb * 1;
    50.             else
    51.                 c.rgb = s.Albedo * _LightColor0.rgb * 0.5;
    52.             return c;
    53.         }
    54.  
    55.  
    56.     struct Input
    57.         {
    58.                 float2 uv_MainTex : TEXCOORD0;
    59.                 float3 viewDir;
    60.     };
    61.  
    62.  
    63.     void surf (Input IN, inout SurfaceOutput o)
    64.         {
    65.             o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * (_Color.rgb+_Color.rgb);
    66.     }
    67.  
    68.     ENDCG
    69.     }
    70.  
    71.     FallBack "Diffuse"
    72. }
    BTW, I added fullforwardshadows in case you wanted to use this with Unity Pro point light shadows. ;) The secret is (And Aras mentioned this on another thread, I am sure... :D) you can use this to enable forward rendering point shadows.

    EDIT: Also note I used the default diffuse as a fallback, feel free to include yours instead, it shouldn't break the shader. :) I also aim to produce a version that has darker shadows which will help match the darker areas.

    EDIT2: fixed a shadow attenuation bug with low-res shadows.
     
    Last edited: Aug 19, 2014
    kebrus likes this.
  15. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Here's another screen:
    ToonShaderShadowFix.png
    Also updated code, look above. it fixes the white outlines seen on low-res shadows. (again... :D)
     
    Graph likes this.
  16. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    FINAL UPDATE: Fixed weird shadow outlines completely. shadows now fade quite smoothly! :) Code in above post.
     
  17. Graph

    Graph

    Joined:
    Jun 8, 2014
    Posts:
    154
    very nice, thx a lot; this actually gave me a pretty good, new idea:
    here it is:

    Code (CSharp):
    1. Shader "Graph/Cell"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("FilterColor", Color) = (0.5, 0.5, 0.5, 1)
    6.    
    7.         _MainTex ("Albedo", 2D) = "white" {}
    8.  
    9.         _Blend ("Blend", float) = 0.04
    10.  
    11.         _Steps ("Steps", Color) = (0.86, 0.61, 0)
    12.         _Shades ("Shades", Color) = (1, 0.59, 0)
    13.   }
    14.    
    15.     SubShader
    16.     {
    17.     Tags
    18.         {
    19.             "Queue" = "Geometry"
    20.             "RenderType" = "Opaque"
    21.         }
    22.  
    23.     LOD 200
    24.     CGPROGRAM
    25.     #pragma surface surf Cell nolightmap
    26.         #pragma target 2.0
    27.         #include "methods.cginc"
    28.  
    29.         fixed4 _Color;      
    30.         sampler2D _MainTex;
    31.        
    32.        
    33.         float _Blend = 0.03;
    34.         fixed3 _Steps;
    35.         fixed3 _Shades;
    36.  
    37.  
    38.         float CellShadeSmooth (half diff, float layerBleed, int numSteps, fixed3 steps, fixed3 shades)
    39.         {
    40.             float intensity = 0.0;
    41.  
    42.             if(numSteps == 3)
    43.             {
    44.                 intensity += smoothstep(_Steps.g, _Steps.g + layerBleed, diff) * _Shades.g;
    45.                 intensity += smoothstep(_Steps.r, _Steps.r + layerBleed, diff) * (_Shades.r - _Shades.g);
    46.             }
    47.             else if(numSteps == 4)
    48.             {
    49.                 intensity += smoothstep(_Steps.b, _Steps.b + layerBleed, diff) * _Shades.b;
    50.                 intensity += smoothstep(_Steps.g, _Steps.g + layerBleed, diff) * (_Shades.g - _Shades.b);
    51.                 intensity += smoothstep(_Steps.r, _Steps.r + layerBleed, diff) * (_Shades.r - _Shades.g);
    52.             }
    53.             else if(numSteps == 2)
    54.             {
    55.                 intensity += smoothstep(_Steps.r, _Steps.r + layerBleed, diff) * _Shades.r;
    56.             }
    57.  
    58.             return intensity;
    59.         }
    60.  
    61.  
    62.         half4 LightingCell (SurfaceOutput s, half3 lightDir, half atten)
    63.         {
    64.             #ifndef USING_DIRECTIONAL_LIGHT
    65.             lightDir = normalize(lightDir);
    66.             #endif
    67.    
    68.             half diff = ((dot(s.Normal, lightDir)) * 0.5 + 0.5) * atten;
    69.  
    70.             half4 c;
    71.             c.a = s.Alpha;
    72.            
    73.             float intensity = CellShadeSmooth(diff, _Blend, 3, _Steps, _Shades);
    74.  
    75.             c.rgb = s.Albedo * _LightColor0.rgb  * (atten*2) * intensity;
    76.  
    77.             return c;
    78.         }
    79.  
    80.  
    81.     struct Input
    82.         {
    83.                 float2 uv_MainTex : TEXCOORD0;
    84.     };
    85.  
    86.     void surf (Input IN, inout SurfaceOutput o)
    87.         {
    88.              o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * (_Color.rgb + _Color.rgb);
    89.     }
    90.  
    91.     ENDCG
    92.     }
    93.     FallBack "Diffuse"
    94. }
     

    Attached Files:

    FuzzyQuills and kebrus like this.
  18. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    THAT. IS AWESOME.

    I actually see how you did it with smoothstep! well done! :)
     
  19. Graph

    Graph

    Joined:
    Jun 8, 2014
    Posts:
    154
    thx; i think i might release this as a free asset to the store "Chibi Shader", just don't know what kind of character i should make to show off the various shading "styles" we need some cloth, some skin, hair.. but maybe some metal aswell

    here's the latest iteration; i've removed the rim shading since the the outlining is quite a nice delimiter and would fight the rimming effect visually
    for the detail map supply a mainly white, tiling paper texture to give the shading a little more structure and make it look more "drawn"
    Code (CSharp):
    1. Shader "Graph/Cell"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("FilterColor", Color) = (1, 1, 1, 1)
    6.         _MainTex ("Albedo", 2D) = "white" {}
    7.  
    8.         _Blend ("Blend", Range(0, 0.1)) = 0.1
    9.         _Blend2 ("Blend2", Range(0, 0.4)) = 0.5
    10.      
    11.         _ShadeRangePower ("Range [XY] Power [ZW]", Color) = (0.9, 0.4, 1, 0.5)
    12.  
    13.         _Detail ("Paper Weight", 2D) = "white" {}
    14.  
    15.         _OutlineColor ("Outline Color", Color) = (0.117, 0.117, 0.117, 1)
    16.   }
    17.  
    18.     SubShader
    19.     {
    20.     Tags
    21.         {
    22.             "Queue" = "Geometry"
    23.             "RenderType" = "Opaque"
    24.         }
    25.  
    26.         UsePass "Graph/Outline/OUTLINE"
    27.  
    28.     LOD 200
    29.     CGPROGRAM
    30.     #pragma surface surf Cell nolightmap
    31.         #pragma target 2.0
    32.  
    33.         fixed4 _Color;    
    34.      
    35.         sampler2D _MainTex;
    36.         sampler2D _Detail;
    37.  
    38.         fixed _Blend;
    39.         fixed _Blend2;
    40.  
    41.         fixed4 _ShadeRangePower;
    42.  
    43.         half4 LightingCell (SurfaceOutput s, half3 lightDir, half atten)
    44.         {
    45.             #ifndef USING_DIRECTIONAL_LIGHT
    46.                 lightDir = normalize(lightDir);
    47.             #endif
    48.  
    49.             half diff = (dot(s.Normal, lightDir) * 0.5 + 0.5) * atten;
    50.  
    51.             fixed toonIntensity = 0;
    52.             toonIntensity += smoothstep(_ShadeRangePower.y, _ShadeRangePower.y + _Blend2, diff) * _ShadeRangePower.w;
    53.             toonIntensity += smoothstep(_ShadeRangePower.x, _ShadeRangePower.x + _Blend, diff) * (_ShadeRangePower.z - _ShadeRangePower.w);
    54.          
    55.             half4 c;
    56.             c.rgb = s.Albedo * _LightColor0.rgb  * (atten*2) * toonIntensity ;
    57.             c.a = s.Alpha;
    58.  
    59.             return c;
    60.         }
    61.  
    62.  
    63.     struct Input
    64.         {
    65.                 float2 uv_MainTex : TEXCOORD0;
    66.                 fixed4 color: Color; // vert color
    67.                 fixed4 screenPos;
    68.     };
    69.  
    70.     void surf (Input IN, inout SurfaceOutput o)
    71.         {
    72.             fixed2 screenUV = IN.screenPos.xy / IN.screenPos.w;
    73.             screenUV *= fixed2(8,6);
    74.  
    75.              o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
    76.             o.Albedo *= IN.color.rgb * _Color.rgb;
    77.             o.Albedo *= tex2D (_Detail, screenUV).rgb;
    78.     }
    79.  
    80.     ENDCG
    81.     }
    82.     //FallBack "Graph/Shadow"
    83.    FallBack "VertexLit"
    84. }
    @FuzzyQuills, you know your way around shaders well i take? (assuming that based on the indie effects)
    What would be a nice cheap way to add specular only on/in the topmost additive toonShade? can i pass data from the lightingmodel to the surface? I really would like to not have to convert this to a vert/pixel shader :p

    and here's the outline.. it's a slight modification of the standard one but i'm gonna add some PS alphaTest masking to it later so we can have that nice rough inked quickly drawn stlye


    Code (CSharp):
    1. Shader "Graph/Outline"
    2. {
    3.     Properties
    4.     {
    5.         _OutlineColor ("Outline Color", Color) = (0.117, 0.117, 0.117, 1)
    6.         //_Outline ("Outline width", Range (.002, 0.03)) = .002
    7.     }
    8.  
    9.     CGINCLUDE
    10.     #include "UnityCG.cginc"
    11.  
    12.     struct appdata
    13.     {
    14.         float4 vertex : POSITION;
    15.         float3 normal : NORMAL;
    16.     };
    17.  
    18.     struct v2f
    19.     {
    20.         float4 pos : POSITION;
    21.         float4 color : COLOR;
    22.     };
    23.  
    24.     //static uniform float _Outline = .002;
    25.     static uniform float _Outline = .003;
    26.     uniform float4 _OutlineColor;
    27.  
    28.     v2f vert(appdata v)
    29.     {
    30.         v2f o;
    31.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    32.  
    33.         float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
    34.         float2 offset = TransformViewToProjection(norm.xy);
    35.  
    36.         float distance = min(length(mul(v.vertex, _Object2World) - _WorldSpaceCameraPos.xyz), 1.25);
    37.      
    38.         o.pos.xy += (offset* distance) * o.pos.z * (_Outline );
    39.  
    40.         o.color = _OutlineColor;
    41.         return o;
    42.     }
    43.     ENDCG
    44.  
    45.     SubShader
    46.     {
    47.         Tags { "RenderType"="Opaque" }
    48.         Pass
    49.         {
    50.             Name "OUTLINE"
    51.             Tags { "LightMode" = "Always" }
    52.             Cull Front
    53.             ZWrite On
    54.             ColorMask RGB
    55.             Blend SrcAlpha OneMinusSrcAlpha
    56.  
    57.             CGPROGRAM
    58.             #pragma vertex vert
    59.             #pragma fragment frag
    60.             half4 frag(v2f i) :COLOR { return i.color; }
    61.             ENDCG
    62.         }
    63.     }
    64. }
    65.  
    and heres the one with the alphaTested outlines:

    Code (CSharp):
    1. Shader "Graph/Outline"
    2. {
    3.     Properties
    4.     {
    5.         _OutlineColor ("Outline Color", Color) = (0.117, 0.117, 0.117, 1)
    6.         //_Outline ("Outline width", Range (.002, 0.03)) = .002
    7.        
    8.         _OutlineMask ("Paper Weight", 2D) = "white" {}
    9.     }
    10.    
    11.     CGINCLUDE
    12.     #include "UnityCG.cginc"
    13.    
    14.     struct appdata
    15.     {
    16.         float4 vertex : POSITION;
    17.         float3 normal : NORMAL;
    18.         float2 uv_MainTex : TEXCOORD0;
    19.     };
    20.  
    21.     struct v2f
    22.     {
    23.         float4 pos : POSITION;
    24.         float4 color : COLOR;
    25.         float2 uv_MainTex : TEXCOORD0;
    26.     };
    27.    
    28.     //static uniform float _Outline = .002;
    29.     static uniform float _Outline = .003;
    30.     uniform float4 _OutlineColor;
    31.     sampler2D _OutlineMask;
    32.  
    33.     v2f vert(appdata v)
    34.     {
    35.         v2f o;
    36.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    37.  
    38.         float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
    39.         float2 offset = TransformViewToProjection(norm.xy);
    40.  
    41.         float distance = min(length(mul(v.vertex, _Object2World) - _WorldSpaceCameraPos.xyz), 1.5);
    42.        
    43.         o.pos.xy += (offset* distance) * o.pos.z * (_Outline );
    44.  
    45.         o.color = _OutlineColor;
    46.  
    47.         o.uv_MainTex = v.uv_MainTex;
    48.         return o;
    49.     }
    50.     ENDCG
    51.  
    52.     SubShader
    53.     {
    54.         Tags { "RenderType"="Opaque" }
    55.         Pass
    56.         {
    57.             Name "OUTLINE"
    58.             Tags { "LightMode" = "Always" }
    59.             Cull Front
    60.             ZWrite On
    61.             ColorMask RGB
    62.             //Blend SrcAlpha OneMinusSrcAlpha
    63.             AlphaTest Greater 0.5
    64.  
    65.             CGPROGRAM
    66.             #pragma vertex vert
    67.             #pragma fragment frag
    68.            
    69.             half4 frag(v2f i) : COLOR
    70.             {
    71.                 // add some PS alphaTest masking to it
    72.                 // so we can have that nice rough inked quickly drawn style
    73.  
    74.                 half4 c = i.color;
    75.                 c.a = tex2D(_OutlineMask, i.uv_MainTex).r;
    76.                 return c;
    77.             }
    78.  
    79.             ENDCG
    80.         }
    81.     }
    82. }
    83.  
    just make sure to add the _OutlineMask ("Outline Mask", 2D) = "white" {} property to the cell shader's properties and note that all red lt .5 are used to cut away at the outline
     
    Last edited: Aug 20, 2014
  20. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    @Graph: Yes, I do know my way around most shaders, in fact, I have found myself able to port HLSL and GLSL too. (But then again, that's becuase companies and organizations are always stealing ideas... ;))

    And I take it you only want the spec in the brightest shade. just calculate a specular color like... perhaps the example in the manual? Anyway, do that, but only do it in the section where you calculate the brightest shading. The example in the manual does it in the lighting model, BTW, so there's another of your questions answered! :) (No need for an extra VF shader!)

    You could also do something similar to the toon shading model in blender, it has a solid toon highlight over everything. I haven't had the chance to test your outlines yet, but interesting ideas! Who's up for SSB for 3DS-style outlines people? :D (I AM!!!)