Search Unity

Help Optimising Toon Shader

Discussion in 'Shaders' started by RichHurst, Aug 25, 2013.

  1. RichHurst

    RichHurst

    Joined:
    Jul 25, 2013
    Posts:
    30
    Hi All,

    I'm wondering if someone could help me...

    I'm currently using one the brilliant Toony Gooch shaders from Jean Moreno as a basis, but wanted to customise it slightly to have a consistent outline. Currently I am achieving this with the following code, but I don't know much about shaders and I am pretty sure this isn't very optimised. Could anyone tell me if I can do this more efficiently?

    Code (csharp):
    1. Shader "Toony Gooch/Toony Gooch Outline"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,1)
    6.    
    7.         _MainTex ("Base (RGB)", 2D) = "white" {}
    8.         _Ramp ("Toon Ramp (RGB)", 2D) = "gray" {}
    9.        
    10.         _SColor ("Shadow Color", Color) = (0.0,0.0,0.0,1)
    11.         _LColor ("Highlight Color", Color) = (0.5,0.5,0.5,1)
    12.         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
    13.         _Outline ("Outline width", Range (.002, 0.03)) = .005      
    14.     }
    15.  
    16.     SubShader
    17.     {
    18.         Tags { "RenderType"="Opaque" } 
    19.                            
    20.         LOD 200
    21. CGPROGRAM
    22.  
    23.         #pragma surface surf ToonRamp
    24.        
    25.         sampler2D _MainTex;
    26.         sampler2D _Ramp;
    27.         float4 _LColor;
    28.         float4 _SColor;
    29.         float4 _Color;
    30.        
    31.         // custom lighting function that uses a texture ramp based
    32.         // on angle between light direction and normal
    33.        
    34.         #pragma lighting ToonRamp exclude_path:prepass
    35.         inline half4 LightingToonRamp (SurfaceOutput s, half3 lightDir, half atten)
    36.         {
    37.             #ifndef USING_DIRECTIONAL_LIGHT
    38.             lightDir = normalize(lightDir);
    39.             #endif
    40.            
    41.             //Calculate N . L
    42.             half d = dot (s.Normal, lightDir)*0.5 + 0.5;
    43.             //Basic toon shading
    44.             half3 ramp = tex2D(_Ramp, float2(d,d)).rgb;
    45.             //Gooch shading
    46.             ramp = lerp(_SColor,_LColor,ramp);
    47.            
    48.             half4 c;
    49.             c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
    50.             c.a = 0;
    51.            
    52.             return c;
    53.         }
    54.                
    55.        
    56.         struct Input
    57.         {
    58.             float2 uv_MainTex : TEXCOORD0;
    59.         };
    60.        
    61.         void surf (Input IN, inout SurfaceOutput o)
    62.         {
    63.             half4 c = tex2D(_MainTex, IN.uv_MainTex);
    64.            
    65.             o.Albedo = c.rgb * _Color.rgb;
    66.             o.Alpha = c.a;
    67.         }      
    68.            
    69.  
    70. ENDCG
    71.  
    72.  
    73.         Pass {
    74.          
    75.             Cull Front
    76.             Lighting Off
    77.          
    78.         CGPROGRAM
    79.             #pragma vertex vert
    80.             #pragma fragment frag
    81.          
    82.             #include "UnityCG.cginc"
    83.             struct a2v
    84.             {
    85.                 float4 vertex : POSITION;
    86.                 float3 normal : NORMAL;
    87.             };
    88.          
    89.             struct v2f
    90.             {
    91.                 float4 pos : POSITION;
    92.             };
    93.          
    94.             float _Outline;
    95.          
    96.             v2f vert (a2v v)
    97.             {
    98.                 v2f o;
    99.                 o.pos = mul( UNITY_MATRIX_MVP, v.vertex + (float4(v.normal,0) * _Outline));
    100.                 return o;
    101.             }
    102.          
    103.             float4 frag (v2f IN) : COLOR
    104.             {
    105.                 return float(0);
    106.             }
    107.          
    108.             ENDCG
    109.          
    110.         }          
    111.     }
    112.  
    113.    
    114.     Fallback "Toon/Lighted"
    115. }

    Any help would be much appreciated.

    Thanks

    Rich
     
  2. Lulucifer

    Lulucifer

    Joined:
    Jul 8, 2012
    Posts:
    358
    I cant see any thing to help make this more effecient,
    but i think you could do more to make the outline looks better
     
  3. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    how does the ramp texture look? You could compute it procedurally.
     
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    It's actually really inefficient, it's a surface shader for a start.
     
  5. RichHurst

    RichHurst

    Joined:
    Jul 25, 2013
    Posts:
    30
    Ok, first of all, thanks for the responses...

    Lulucifer - Thanks, but I'm pretty happy with the effect at the moment, just want to speed it up as its for a mobile game.

    Dolkar - It's just the standard ramp texture that comes with the asset... Have you got any pointers for where I could find out how I could compute it procedurally?

    Hippocoder - You are probably correct, but it achieves the effect I want... Do you have any suggestions how I could create this same effect more efficiently?

    To be honest, I was thinking it probably doesn't need to calculate the light either as the light doesn't move in my scene and its a 2d based game, I tried to implement this but couldn't get the right look using a constant value for the lightDir. I calculated a vector 3 that took the light's position, took that away from the game objects position and divided it by the distance, but this didn't produce the same effect. Like I said, I've got little / no knowledge of shader programming so any help would be great.

    Thanks once again...