Search Unity

Toon Shader Working With Multiple Spotlight Shadows (Pro)

Discussion in 'Shaders' started by NateAGeek, Mar 2, 2015.

  1. NateAGeek

    NateAGeek

    Joined:
    Mar 2, 2015
    Posts:
    2
    Hello all,

    I've been working on making this toon shader from scratch. I have manage to get it to look great! However, it can't get shadows from multiple spotlights(it does work with directional), D:



    Code (CSharp):
    1. Shader "Custom/ToonShader" {
    2.     Properties {
    3.         _MainTex ("Post Image", 2D) = "white" {}
    4.         _RampTex ("Post Image", 2D) = "white" {}
    5.         _Strength ( "Additive Strength", Float ) = 1.0
    6.         _TintColor ("Tint Color", Color) = (1.0, 1.0, 1.0, 1.0)
    7.     }
    8.     SubShader {
    9.         Tags {"Queue" = "Geometry" "RenderType" = "Opaque"}
    10.         Pass {
    11.             Tags {"LightMode" = "ForwardBase"}
    12.             CGPROGRAM
    13.             #pragma multi_compile_fwdbase_fullforwardshadows
    14.             #pragma vertex vertexShaderMain
    15.             #pragma fragment fragmentShaderMain
    16.             #pragma fragmentoption ARB_precision_hint_fastest
    17.             #pragma target 3.0
    18.             #include "UnityCG.cginc"
    19.             #include "AutoLight.cginc"
    20.            
    21.             uniform sampler2D _MainTex;
    22.             uniform sampler2D _RampTex;
    23.             uniform float _Strength;
    24.             uniform float4 _LightColor0;
    25.             uniform float4 _TintColor;
    26.             uniform float _TotalRamps;
    27.            
    28.             struct vertexInput {
    29.                 float4 vertex : POSITION;
    30.                 float3 normal : NORMAL;
    31.                 float4 texcoord : TEXCOORD0;
    32.             };
    33.            
    34.             struct vertexOutput {
    35.                 float4 pos : SV_POSITION;
    36.                 float4 tex : TEXCOORD0;
    37.                 float4 posWorld : TEXCOORD1;
    38.                 float3 normalDir : TEXCOORD2;
    39.                 LIGHTING_COORDS(3,4)
    40.             };
    41.  
    42.             vertexOutput vertexShaderMain(vertexInput input) {
    43.                 vertexOutput output;
    44.                
    45.                 output.posWorld = mul(_Object2World, input.vertex);
    46.                 output.normalDir = normalize(mul(float4(input.normal, 0.0), _World2Object).xyz);
    47.                 output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
    48.                 output.tex = input.texcoord;
    49.                
    50.                 TRANSFER_VERTEX_TO_FRAGMENT(output);
    51.                
    52.                 return output;
    53.             }
    54.            
    55.             float4 fragmentShaderMain(vertexOutput o) : COLOR {
    56.                 float3 normalDir = o.normalDir;
    57.                 float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - o.posWorld.xyz);
    58.                 float atten;
    59.                 float3 lightDir;
    60.                
    61.                 if(_WorldSpaceLightPos0.w == 0.0){
    62.                     //atten = 1.0;
    63.                     lightDir = normalize(_WorldSpaceLightPos0.xyz);
    64.                 }
    65.                 else{
    66.                     float3 fragToLightSource = _WorldSpaceLightPos0 - o.posWorld.xyz;
    67.                     //atten = 1/length(fragToLightSource);
    68.                     lightDir = normalize(fragToLightSource);
    69.                 }
    70.                
    71.                 atten = LIGHT_ATTENUATION(o) * 2;
    72.                
    73.                 float3 diffuseRef = atten * _LightColor0.xyz * saturate(dot(normalDir, lightDir));
    74.                 float intensity = dot(lightDir, normalDir);
    75.                
    76.                 float3 rampColor = tex2D(_RampTex, float2(0.0, 0.0));
    77.                
    78.                 if(intensity > 0.95){
    79.                     rampColor = tex2D(_RampTex, float2(0.0, 0.0));
    80.                 }else if(intensity > 0.5){
    81.                     rampColor = tex2D(_RampTex, float2(0.25, 0.0));
    82.                 }else if(intensity > 0.25){
    83.                     rampColor = tex2D(_RampTex, float2(0.50, 0.0));
    84.                 }else{
    85.                     rampColor = tex2D(_RampTex, float2(0.75, 0.0));
    86.                 }
    87.                
    88.                 float3 lightFinal = rampColor * UNITY_LIGHTMODEL_AMBIENT.rgb;
    89.                
    90.                 return tex2D(_MainTex, o.tex) * float4(lightFinal, 1.0) * float4(diffuseRef, 1.0) * _Strength;
    91.             }
    92.             ENDCG
    93.         }
    94.         Pass {
    95.             Tags {"LightMode" = "ForwardAdd" "SHADOWSUPPORT"="true"}
    96.             Blend One One
    97.             CGPROGRAM
    98.             #pragma multi_compile_builtin
    99.             #pragma vertex vertexShaderMain
    100.             #pragma fragment fragmentShaderMain
    101.             #pragma fragmentoption ARB_precision_hint_fastest
    102.             #pragma target 3.0
    103.             #include "UnityCG.cginc"
    104.             #include "AutoLight.cginc"
    105.            
    106.             uniform sampler2D _MainTex;
    107.             uniform sampler2D _RampTex;
    108.             uniform float _Strength;
    109.             uniform float4 _LightColor0;
    110.             uniform float4 _TintColor;
    111.             uniform float _TotalRamps;
    112.            
    113.             struct vertexInput {
    114.                 float4 vertex : POSITION;
    115.                 float3 normal : NORMAL;
    116.                 float4 texcoord : TEXCOORD0;
    117.             };
    118.            
    119.             struct vertexOutput {
    120.                 float4 pos : SV_POSITION;
    121.                 float4 tex : TEXCOORD0;
    122.                 float4 posWorld : TEXCOORD1;
    123.                 float3 normalDir : TEXCOORD2;
    124.                 LIGHTING_COORDS(3,4)
    125.             };
    126.  
    127.             vertexOutput vertexShaderMain(vertexInput input) {
    128.                 vertexOutput output;
    129.                
    130.                 output.posWorld = mul(_Object2World, input.vertex);
    131.                 output.normalDir = normalize(mul(float4(input.normal, 0.0), _World2Object).xyz);
    132.                 output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
    133.                 output.tex = input.texcoord;
    134.                
    135.                 TRANSFER_VERTEX_TO_FRAGMENT(output);
    136.                
    137.                 return output;
    138.             }
    139.            
    140.             float4 fragmentShaderMain(vertexOutput o) : COLOR {
    141.                 float3 normalDir = o.normalDir;
    142.                 float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - o.posWorld.xyz);
    143.                 float atten;
    144.                 float3 lightDir;
    145.                
    146.                 if(_WorldSpaceLightPos0.w == 0.0){
    147.                     atten = 1.0;
    148.                     lightDir = normalize(_WorldSpaceLightPos0.xyz);
    149.                 }
    150.                 else{
    151.                     float3 fragToLightSource = _WorldSpaceLightPos0 - o.posWorld.xyz;
    152.                     atten = 1/length(fragToLightSource);
    153.                     lightDir = normalize(fragToLightSource);
    154.                 }
    155.                
    156.                 //atten = LIGHT_ATTENUATION(o) * 2;
    157.                
    158.                 float3 diffuseRef = atten * _LightColor0.xyz * saturate(dot(normalDir, lightDir));
    159.                 float intensity = dot(lightDir, normalDir);
    160.                
    161.                 float3 rampColor = tex2D(_RampTex, float2(0.0, 0.0));
    162.                
    163.                 if(intensity > 0.95){
    164.                     rampColor = tex2D(_RampTex, float2(0.0, 0.0));
    165.                 }else if(intensity > 0.5){
    166.                     rampColor = tex2D(_RampTex, float2(0.25, 0.0));
    167.                 }else if(intensity > 0.25){
    168.                     rampColor = tex2D(_RampTex, float2(0.50, 0.0));
    169.                 }else{
    170.                     rampColor = tex2D(_RampTex, float2(0.75, 0.0));
    171.                 }
    172.                
    173.                 float3 lightFinal = rampColor * UNITY_LIGHTMODEL_AMBIENT.rgb;
    174.                
    175.                 return tex2D(_MainTex, o.tex) * float4(lightFinal, 1.0) * float4(diffuseRef, 1.0) * _Strength;
    176.             }
    177.             ENDCG
    178.         }
    179.  
    180.     }
    181.     Fallback "VertexLit"
    182. }
    I think the issue is with my second pass... Any help or info will help!
     
  2. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    your tag ("SHADOWSUPPORT"="true") I've never seen it, does it do anything?

    I think it might be your pragmas, i usually use:
    Code (csharp):
    1. #pragma multi_compile_fwdbase
    and for the second pass
    Code (csharp):
    1. #pragma multi_compile_fwdadd
    i don't think you even need the #pragma multi_compile_builtin, thats for pixel lightmode isn't it?

    beware, i'm just suggesting, didn't test any of it. also, a good way to confirm is to create a new shader and see the "semi-compiled" code or just look at the built-in shaders

    Oh, and your fallback should be the default diffuse, because thats where the it gets the shadow caster and receiver code if i recall correctly
     
  3. NateAGeek

    NateAGeek

    Joined:
    Mar 2, 2015
    Posts:
    2
    The reason I'm using
    Code (CSharp):
    1. #pragma multi_compile_fwdbase
    is because the the TRANSFER_VERTEX_TO_FRAGMENT does not seem to work with
    Code (csharp):
    1. #pragma multi_compile_fwdadd
    #pragma multi_compile_builtin was just me trying random stuff. Also, the ("SHADOWSUPPORT"="true") thing is me just trying crap I saw in the Default Diffuse shader. I changed fall back to Diffuse, still sadly nothing...

    Thank you though!
     
  4. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    I remembered one thing. I made a toon shader myself once and the light/shadow falloff is much smaller and i couldn't see any light/shadow when i was comparing shaders but it was actually there, i just had to put the light much closer to the object to actually see it.

    Also, those two pragmas i said earlier, i use them both, i don't use fwdadd over fwdbase like you are suggesting, each for its respective pass.

    Maybe if have more time tomorrow i'll check it out, meanwhile you can always see what the default diffuse compiles to