Search Unity

adding Shadow to a curved shader

Discussion in 'Shaders' started by ryanchan, Aug 18, 2015.

  1. ryanchan

    ryanchan

    Joined:
    Jul 22, 2015
    Posts:
    11
    Hi everyone, I read some tutorials about how to add shadow to vertex/fragment shader (e.g. adding-shadows-to-a-unity-vertexfragment-shader-in-7-easy-steps), but it seems not working at all. Please take a look, thanks a lot

    Code (CSharp):
    1. Shader "Custom/ToonCurved" {
    2.       Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.         _QOffset ("Offset", Vector) = (0,0,0,0)
    5.         _Dist ("Distance", Float) = 100.0
    6.         _Alpha ("Alpha", Range(0.0,1.0)) = 1.0
    7.         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
    8.         _Outline ("Outline width", Range (.002, 0.03)) = .005
    9.         _Color ("Main Color", Color) = (0.5,0.5,0.5,1)
    10.     }
    11.     SubShader {
    12.         Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    13.         Tags {"LightMode" = "ForwardBase"}
    14.         LOD 100
    15.  
    16.         Pass
    17.         {
    18.             Name "OUTLINE"
    19.             Cull Front
    20.             ZWrite On
    21.             ColorMask RGB
    22.             Blend SrcAlpha OneMinusSrcAlpha
    23.             CGPROGRAM
    24.             #pragma vertex vert
    25.             #pragma fragment frag
    26.             #include "UnityCG.cginc"
    27.             sampler2D _MainTex;
    28.             float4 _QOffset;
    29.             float _Dist;
    30.             float _Alpha;
    31.             uniform float4 _MainTex_ST;
    32.             uniform float _Outline;
    33.             uniform float4 _OutlineColor;
    34.      
    35.             struct v2f {
    36.                 float4 pos : SV_POSITION;
    37.                 fixed4 color : COLOR;
    38.             };
    39.        
    40.             struct appdata {
    41.                 float4 vertex : POSITION;
    42.                 float3 normal : NORMAL;
    43.             };
    44.             v2f vert (appdata v)
    45.             {
    46.                 v2f o;
    47.                 float4 vPos = mul (UNITY_MATRIX_MV, v.vertex);
    48.                 float zOff = vPos.z/_Dist;
    49.                 vPos += _QOffset*zOff*zOff;
    50.            
    51.                 o.pos = mul (UNITY_MATRIX_P, vPos);
    52.          
    53.                 float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
    54.                 float2 offset = TransformViewToProjection(norm.xy);
    55.            
    56.                 o.pos.xy += offset * o.pos.z * _Outline;
    57.                 o.color = _OutlineColor;
    58.                 UNITY_TRANSFER_FOG(o,o.pos);
    59.                 return o;
    60.             }
    61.             half4 frag (v2f i) : COLOR
    62.             {
    63.                 UNITY_APPLY_FOG(i.fogCoord, i.color);
    64.                 return i.color;
    65.             }
    66.             ENDCG
    67.         }
    68.    
    69.    
    70.          // Normal pass
    71.         Pass
    72.         {
    73.             CGPROGRAM
    74.             #pragma vertex vert
    75.             #pragma fragment frag
    76.             #include "UnityCG.cginc"
    77.             #pragma multi_compile_fwdbase
    78.             #include "AutoLight.cginc"
    79.             sampler2D _MainTex;
    80.             float4 _QOffset;
    81.             float _Dist;
    82.             float _Alpha;
    83.             uniform float4 _MainTex_ST;
    84.             uniform float _Outline;
    85.             uniform float4 _OutlineColor;
    86.             struct v2f
    87.             {
    88.                 float4 pos : SV_POSITION;
    89.                 float2 uv : TEXCOORD0;
    90.                 fixed4 color : COLOR;
    91.                 LIGHTING_COORDS(0,1)
    92.             };
    93.             v2f vert(appdata_base v)
    94.             {
    95.                 v2f o;
    96.                 float4 vPos = mul(UNITY_MATRIX_MV, v.vertex);
    97.                 float zOff = vPos.z / _Dist;
    98.                 vPos += _QOffset*zOff*zOff;
    99.                 o.pos = mul(UNITY_MATRIX_P, vPos);
    100.                 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    101.                 o.color = _OutlineColor;
    102.                 UNITY_TRANSFER_FOG(o,o.pos);
    103.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    104.                 return o;
    105.             }
    106.             fixed4 frag(v2f i) : COLOR
    107.             {
    108.                 float attenuation = LIGHT_ATTENUATION(i);
    109.                 return tex2D(_MainTex, i.uv) * float4(1,1,1,_Alpha) * attenuation;
    110.             }
    111.             ENDCG
    112.         }
    113.  
    114.     }
    115.     Fallback "VertexLit"
    116. }
     
  2. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,051
    What is not working? What are you expecting it to do? Is it giving errors or just not doing what you want?
     
  3. ryanchan

    ryanchan

    Joined:
    Jul 22, 2015
    Posts:
    11
    It just have no shadow
     
  4. WhiskyJoe

    WhiskyJoe

    Joined:
    Aug 21, 2012
    Posts:
    143
    From your other thread...

    Could be multiple things:
    • Tags {"LightMode"="ForwardBase"} is a Pass Tag and should be used in a pass, not the subshader.
    • LIGHTING_COORDS(0,1) - you're using 0 for your uv coordinates. use 1 and 2 instead.
    • Are shadows enabled? (see Quality Settings)
    • Are you using a directional light? (other light sources require a different Light mode and #pragma multi_compile_fwdadd instead of #pragma multi_compile_fwdbase)
    Could be any or all of these things.

    You can probably also save yourself a lot of trouble by just using a surface shader with the outline pass added to get shadows.
     
  5. ryanchan

    ryanchan

    Joined:
    Jul 22, 2015
    Posts:
    11
    Thanks for the replies!



    Now I got the shadow but the position is not match becoz the shader is curved.
    Should I modify the receive shadow part or any other suggestion?

    Code (CSharp):
    1. Shader "MyToon/Toon-Fragment" {
    2.     Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.         _Ramp ("Ramp Texture", 2D) = "white" {}
    5.         _Outline ("Outline", Range(0,1)) = 0.1
    6.         _QOffset ("Offset", Vector) = (0,0,0,0)
    7.         _Dist ("Distance", Float) = 100.0
    8.     }
    9.     SubShader {
    10.         Tags { "RenderType"="Opaque" }
    11.         LOD 200
    12.  
    13.         Pass {
    14.             Tags { "LightMode"="ForwardBase" }
    15.              
    16.             Cull Front
    17.             Lighting Off
    18.             ZWrite On
    19.  
    20.             CGPROGRAM
    21.            
    22.             #pragma vertex vert
    23.             #pragma fragment frag
    24.            
    25.             #pragma multi_compile_fwdbase
    26.  
    27.             #include "UnityCG.cginc"
    28.              
    29.             float _Outline;
    30.             float4 _QOffset;
    31.             float _Dist;
    32.  
    33.             struct a2v
    34.             {
    35.                 float4 vertex : POSITION;
    36.                 float3 normal : NORMAL;
    37.             };  
    38.  
    39.             struct v2f
    40.             {
    41.                 float4 pos : POSITION;
    42.             };
    43.  
    44.             v2f vert (a2v v)
    45.             {
    46.                 v2f o;
    47.  
    48.                 float4 pos = mul( UNITY_MATRIX_MV, v.vertex);  
    49.                 float zOff = pos.z/_Dist;
    50.                 pos += _QOffset*zOff*zOff;
    51.                 float3 normal = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
    52.                 normal.z = -0.5;
    53.                 pos = pos + float4(normalize(normal),0) * _Outline;
    54.                 o.pos = mul(UNITY_MATRIX_P, pos);
    55.                  
    56.                 return o;
    57.             }
    58.  
    59.             float4 frag(v2f i) : COLOR  
    60.             {  
    61.                 return float4(0, 0, 0, 1);                
    62.             }  
    63.  
    64.             ENDCG
    65.         }
    66.          
    67.         Pass {
    68.             Tags { "LightMode"="ForwardBase" }
    69.              
    70.             Cull Back  
    71.             Lighting On
    72.  
    73.             CGPROGRAM
    74.             #pragma vertex vert
    75.             #pragma fragment frag
    76.            
    77.             #pragma multi_compile_fwdbase
    78.             #include "UnityCG.cginc"
    79.             #include "Lighting.cginc"
    80.             #include "AutoLight.cginc"
    81.             #include "UnityShaderVariables.cginc"
    82.              
    83.  
    84.             sampler2D _MainTex;
    85.             sampler2D _Ramp;
    86.            
    87.             float4 _QOffset;
    88.             float _Dist;
    89.  
    90.             float4 _MainTex_ST;
    91.  
    92.             float _Tooniness;
    93.  
    94.             struct a2v
    95.             {
    96.                 float4 vertex : POSITION;
    97.                 float3 normal : NORMAL;
    98.                 float4 texcoord : TEXCOORD0;
    99.                 float4 tangent : TANGENT;
    100.             };  
    101.  
    102.             struct v2f
    103.             {
    104.                 float4 pos : POSITION;
    105.                 float2 uv : TEXCOORD0;
    106.                 float3 normal : TEXCOORD1;
    107.                 LIGHTING_COORDS(2,3)
    108.             };
    109.              
    110.             v2f vert (a2v v)
    111.             {
    112.                 v2f o;
    113.  
    114.                 //Transform the vertex to projection space
    115.                 float4 vPos = mul(UNITY_MATRIX_MV, v.vertex);
    116.                 float zOff = vPos.z / _Dist;
    117.                 vPos += _QOffset*zOff*zOff;
    118.                 o.pos = mul(UNITY_MATRIX_P, vPos);
    119.                 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    120.                 o.normal = mul((float3x3)_Object2World, SCALED_NORMAL);
    121.                 //Get the UV coordinates
    122.                  
    123.                 // pass lighting information to pixel shader
    124.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    125.                 return o;
    126.             }
    127.              
    128.             float4 frag(v2f i) : COLOR  
    129.             {  
    130.                 //Get the color of the pixel from the texture
    131.                 float4 c = tex2D (_MainTex, i.uv);  
    132.                 //Merge the colours
    133.  
    134.                 //Based on the ambient light
    135.                 float3 lightColor = UNITY_LIGHTMODEL_AMBIENT.xyz;
    136.  
    137.                 //Work out this distance of the light
    138.                 float atten = LIGHT_ATTENUATION(i);
    139.                 //Angle to the light
    140.                 float diff = dot (normalize(i.normal), normalize(_WorldSpaceLightPos0.xyz));  
    141.                 diff = diff * 0.5 + 0.5;  
    142.                 //Perform our toon light mapping  
    143.                 diff = tex2D(_Ramp, float2(diff, 0.5));
    144.                 //Update the colour
    145.                 lightColor += _LightColor0.rgb * (diff * atten);  
    146.                 //Product the final color
    147.                 c.rgb = lightColor * c.rgb * 2;
    148.                 return c;  
    149.  
    150.             }  
    151.  
    152.             ENDCG
    153.         }
    154.        
    155.     }
    156.     FallBack "Diffuse"      
    157. }  
     
  6. FuzzyShan

    FuzzyShan

    Joined:
    Jul 30, 2012
    Posts:
    182
    I am a shader noob, but hopefully what I am thinking is on the right track...atten is your light shadow information, if your diffuse texture actually has some sort of proces(curving, or pixel scroll or something), you can't just use diffuse * atten, that ofcourse will bend the shadows why not use some kind of additive operation.
     
  7. WhiskyJoe

    WhiskyJoe

    Joined:
    Aug 21, 2012
    Posts:
    143
    The problem lies in the shadow pass. In your curved shader, you modify the vertex positions with a specific offset, but the shadowcaster/receiver passes are done with the normal vertex position (your vertex positions are not saved when altered in the vertex shader).

    Someone on this forum ha the same problem some time ago, I'm pretty sure you can find it somewhere if you search for it. In theory, you can add an adjusted shadowcaster/receiver pass with the adjusted vertex positions, but I think there were some issues with it, not sure.