Search Unity

Toon Multi-Decal Shader

Discussion in 'Shaders' started by KamiKaze425, Jul 11, 2014.

  1. KamiKaze425

    KamiKaze425

    Joined:
    Nov 20, 2012
    Posts:
    207
    Hey guys,
    So I'm working on a combination of the decal shader and the toony-lighted shader. However, I can have 3 sets of decals plus the main texture.
    I only need the toony effect to be on the main texture. However, if it's easier to do them all at once, that's fine too.
    Here's an example of what I have. Just that the performance sucks because of what's in the "surf" function

    Code (CSharp):
    1. Shader "Custom/ToonDecal" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (0.5,0.5,0.5,1)
    4.         _MainTex ("Base (RGB)", 2D) = "white" {}
    5.         _Ramp ("Toon Ramp (RGB)", 2D) = "gray" {}
    6.         _DecalFirst ("Face", 2D) = "black" {}
    7.         _DecalSecond ("Body", 2D) = "black" {}
    8.         _DecalThird ("Accessory", 2D) = "black" {}
    9.     }
    10.  
    11.     SubShader {
    12.         Tags { "RenderType"="Opaque" }
    13.         LOD 200
    14.        
    15. CGPROGRAM
    16. #pragma surface surf ToonRamp approxview halfasview noforwardadd
    17. sampler2D _Ramp;
    18. sampler2D _DecalFirst;
    19. sampler2D _DecalSecond;
    20. sampler2D _DecalThird;
    21.  
    22. #pragma lighting ToonRamp exclude_path:prepass approxview halfasview noforwardadd
    23.  
    24. inline fixed4 LightingToonRamp (SurfaceOutput s, fixed3 lightDir, fixed atten)
    25. {
    26.     #ifndef USING_DIRECTIONAL_LIGHT
    27.     lightDir = normalize(lightDir);
    28.     #endif
    29.    
    30.     fixed d = dot (s.Normal, lightDir)*0.5 + 0.5;
    31.     fixed3 ramp = tex2D (_Ramp, fixed2(d,d)).rgb;
    32.    
    33.     fixed4 c;
    34.     c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
    35.     c.a = 0;
    36.     return c;
    37. }
    38.  
    39. sampler2D _MainTex;
    40. fixed4 _Color;
    41.  
    42. struct Input {
    43.     fixed2 uv_MainTex : TEXCOORD0;
    44.     fixed2 uv_DecalFirst;
    45.     fixed2 uv_DecalSecond;
    46.     fixed2 uv_DecalThird;
    47. };
    48.  
    49. void surf (Input IN, inout SurfaceOutput o) {
    50.     fixed4 c = tex2D(_MainTex, IN.uv_MainTex)* _Color;
    51.     half4 decalTwo = tex2D(_DecalSecond, IN.uv_DecalSecond);
    52.     c.rgb = lerp (c.rgb, decalTwo.rgb, decalTwo.a);
    53.     half4 decalThree = tex2D(_DecalThird, IN.uv_DecalThird);
    54.     c.rgb = lerp (c.rgb, decalThree.rgb, decalThree.a);
    55.     half4 decalOne = tex2D(_DecalFirst, IN.uv_DecalFirst);
    56.     c.rgb = lerp (c.rgb, decalOne.rgb, decalOne.a);
    57.     o.Albedo = c.rgb;
    58.     o.Alpha = c.a;
    59. }
    60. ENDCG
    61.  
    62.     }
    63.  
    64.     Fallback "Diffuse"
    65. }
    66.  
    I have a very performance happy version that doesn't do the toon shading/lighting. But I'm having trouble figuring out how to add in the toon shading part...
    Code (CSharp):
    1. Pass{
    2.         SetTexture [_MainTex] {
    3.         ConstantColor[_Color]
    4.                 combine texture *constant
    5.             }
    6.             SetTexture [_DecalFirst] {
    7.                 combine texture lerp (texture) previous
    8.             }
    9.             SetTexture [_DecalSecond] {
    10.                 combine texture lerp (texture) previous
    11.             }
    12.             SetTexture [_DecalThird] {
    13.                 combine texture lerp (texture) previous
    14.             }
    15.             }

    Any help or suggestions would be greatly appreciated :D
     
  2. KamiKaze425

    KamiKaze425

    Joined:
    Nov 20, 2012
    Posts:
    207
    So I got this far with blending them. I believe that means it makes two passes now?
    But the lighting seems a bit off. Like the blended version is darker than the normal version. You can test this by setting a color such as sky blue with a bunch of decals. Then take out the pass with the texture combiners and see the sky blue change a bit.
    Code (CSharp):
    1. Shader "Custom/ToonDecal" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (0.5,0.5,0.5,1)
    4.         _MainTex ("Base (RGB)", 2D) = "white" {}
    5.         _Ramp ("Toon Ramp (RGB)", 2D) = "gray" {}
    6.         _DecalFirst ("Body", 2D) = "black" {}
    7.         _DecalSecond ("Accessory", 2D) = "black" {}
    8.         _DecalThird ("Face", 2D) = "black" {}
    9.     }
    10.  
    11.     SubShader {
    12.         Tags { "RenderType"="Opaque" }
    13.         LOD 200
    14.         Pass{
    15.  
    16.         SetTexture [_MainTex] {
    17.         ConstantColor[_Color]
    18.                 combine texture *constant
    19.             }
    20.             SetTexture [_DecalFirst] {
    21.                 combine texture lerp (texture) previous
    22.             }
    23.             SetTexture [_DecalSecond] {
    24.                 combine texture lerp (texture) previous
    25.             }
    26.             SetTexture [_DecalThird] {
    27.                 combine texture lerp (texture) previous
    28.             }
    29.             }
    30.             Blend DstColor Zero
    31.         CGPROGRAM
    32. #pragma surface surf ToonRamp approxview halfasview noforwardadd
    33. sampler2D _Ramp;
    34.  
    35. #pragma lighting ToonRamp exclude_path:prepass approxview halfasview noforwardadd
    36.  
    37. inline fixed4 LightingToonRamp (SurfaceOutput s, fixed3 lightDir, fixed atten)
    38. {
    39.     #ifndef USING_DIRECTIONAL_LIGHT
    40.     lightDir = normalize(lightDir);
    41.     #endif
    42.    
    43.     fixed d = dot (s.Normal, lightDir)*0.5 + 0.5;
    44.     fixed3 ramp = tex2D (_Ramp, fixed2(d,d)).rgb;
    45.    
    46.     fixed4 c;
    47.     c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
    48.     c.a = 0;
    49.     return c;
    50. }
    51.  
    52. sampler2D _MainTex;
    53. fixed4 _Color;
    54.  
    55. struct Input {
    56.     fixed2 uv_MainTex : TEXCOORD0;
    57. };
    58.  
    59. void surf (Input IN, inout SurfaceOutput o) {
    60.     fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
    61.     o.Albedo = c.rgb;
    62.     o.Alpha = c.a;
    63. }
    64. ENDCG
    65.  
    66.     }
    67.  
    68.     Fallback "Diffuse"
    69. }
    70.  
     
  3. KamiKaze425

    KamiKaze425

    Joined:
    Nov 20, 2012
    Posts:
    207
    So the color darkening in the second version is bugging me, so I'm resorting to the first method. Still wish there was a better way to do it.
    I did some logic that switches to simpler shaders depending on the amount of decals and circumstances, but I'd still like to optimize this one for the worst-case scenarios.