Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Changing the look of unity built-in shadow

Discussion in 'Shaders' started by Padawan, May 15, 2014.

  1. Padawan

    Padawan

    Joined:
    Mar 20, 2014
    Posts:
    2
    Hi, there!
    Could someone help me out/explain, how to make a shadow look like in the game "The Wolf Among Us" or something similar.
    Is there a way to make it?
    Here is some picture to see what i 'm talkin' about :
    $wolfamongus_big2.png
    $1.png
    $2.png

    If it's impossible then the one named 2.png (the last one) is possible or neither?
    Any help is appreciated! :)
     
  2. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    It's not entirely clear from the image, but after looking at a playthrough of the game, it looks like for all fragments in the shadow, they remove any black outline that would normally be there, and switch the rest of the fragments to black (or any other arbitrary color you'd choose).

    That means you have to get access to the raw shadow values (without the lighting data), which is a bit different for Forward and Deferred Lighting.
    Modifying shadows for Deferred Lighting is something I posted about here.
    Getting access to the data in forward Lighting mode is something you can read more about in this thread.
     
  3. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I think it's really simple - just the shader for shadow pass doesn't draw shadow where normal .y is a certain value. Or even simpler, use alpha information for non transparent floor textures to not draw shadow there, seems like a pretty deliberate aesthetic effect.
     
  4. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    I think it's done like this:

    1. Every object has two textures: one for black ink outlines, and one for coloured ink fill
    2. Geometric self-shadowing is done with a stepped ramp, like wrapped Lambertian but in steps
    3. Black outlines are superimposed onto the self-shadowed fill ink
    4. Fragments that are in realtime cast shadow have their black ink inverted

    It might even be possible to do this with surface shaders, but that's an exercise left to the reader.
     
  5. Padawan

    Padawan

    Joined:
    Mar 20, 2014
    Posts:
    2
    Thanks for all the info so far guys!
    hippocoder's tip would work how just wanted it. Just another question can it be implemented in this shader a got it only needs to take into count the _Detail because i use that for the ink texture.
    Here is the shader:
    Code (csharp):
    1. Shader "Custom/Wolf" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (.5,.5,.5,1)
    4.         _SpecColor ("Specular Material Color (RGB)", Color) = (1,1,1,1)
    5.         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
    6.         _Outline ("Outline width", Range (0.0, 0.03)) = .005
    7.         _ShinPower ("Shininess", Range(0,1)) = 0.5
    8.         _GlossPower ("Gloss", Range(0.01,1)) = 0.5
    9.         _MainTex ("Base (RGB)", 2D) = "white" { }
    10.         _BumpMap ("Bumpmap", 2D) = "bump" {}
    11.         _Detail ("Detail", 2D) = "white" {}
    12.         _SpecularTex ("Specular Map", 2D) = "gray" {}
    13.         _RampTex ("Shading Ramp", 2D) = "white" {}
    14.     }
    15.    
    16.     CGINCLUDE
    17.     #include "UnityCG.cginc"
    18.    
    19.     struct appdata {
    20.         float4 vertex : POSITION;
    21.         float3 normal : NORMAL;
    22.     };
    23.  
    24.     struct v2f {
    25.         float4 pos : POSITION;
    26.         float4 color : COLOR;
    27.     };
    28.    
    29.     uniform float _Outline;
    30.     uniform float4 _OutlineColor;
    31.    
    32.     v2f vert(appdata v) {
    33.         v2f o;
    34.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    35.  
    36.     float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
    37.     float2 offset = TransformViewToProjection(norm.xy);
    38.  
    39.     o.pos.xy += offset * o.pos.z * _Outline;
    40.     o.color = _OutlineColor;
    41.     return o;
    42.     }
    43.     ENDCG
    44.  
    45.     SubShader {
    46.         Tags { "Queue" = "Geometry+10" "RenderType" = "Opaque" }
    47.         Pass {
    48.             Name "OUTLINE"
    49.             Tags { "LightMode" = "Always" }
    50.             Cull Front
    51.             ZWrite On
    52.             Blend SrcAlpha OneMinusSrcAlpha
    53.  
    54.         CGPROGRAM
    55.         #pragma vertex vert
    56.         #pragma fragment frag
    57.  
    58.         half4 frag(v2f i) : COLOR {
    59.             return i.color;
    60.         }
    61.         ENDCG
    62.         }
    63.  
    64.             CGPROGRAM
    65.             #pragma surface surf Wolf
    66.             #pragma only_renderers d3d9
    67.             #pragma target 3.0
    68.            
    69.             struct Input
    70.             {
    71.                 float2 uv_MainTex;
    72.                 float2 uv_BumpMap;
    73.                 float3 worldNormal;
    74.                 INTERNAL_DATA
    75.             };
    76.            
    77.             sampler2D _MainTex, _SpecularTex, _BumpMap, _RampTex, _Detail;
    78.             uniform float3 _Color;
    79.             float _ShinPower;
    80.             float _GlossPower;
    81.  
    82.             inline fixed4 LightingWolf (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)
    83.             {
    84.                 fixed3 h = normalize (lightDir + viewDir);
    85.  
    86.                 fixed NdotL = dot(s.Normal, lightDir) * 0.5 + 0.5;
    87.                 fixed3 ramp = tex2D(_RampTex, float2(NdotL * atten)).rgb;
    88.  
    89.                 float nh = max (0, dot (s.Normal, h));
    90.                 float spec = pow (nh, s.Gloss * 128) * s.Specular;
    91.  
    92.                 fixed4 c;
    93.                 c.rgb = ((s.Albedo * _Color.rgb * ramp * _LightColor0.rgb + _LightColor0.rgb * spec * s.Specular * _SpecColor) * (atten * 2));
    94.                 return c;
    95.             }
    96.                
    97.             void surf (Input IN, inout SurfaceOutput o)
    98.             {
    99.                 o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * _Color;
    100.                 o.Albedo *= tex2D (_Detail, IN.uv_MainTex).a * 2;
    101.                 o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    102.                 float3 specGloss = tex2D(_SpecularTex, IN.uv_MainTex).rgb;
    103.                 o.Specular = specGloss.r * _ShinPower;
    104.                 o.Gloss = specGloss.g * _GlossPower;
    105.             }
    106.             ENDCG
    107.     }
    108.     Fallback "Diffuse"
    109. }
    What do you guys think, could be implemented into that shader?
     
  6. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    How would that remove the outlines?

    Surface shaders apply shadows at the same time as the lights, but you want to modify the way the shadow is applied, so you should create a custom vertex/fragment shader (although you can probably re-use a lot of the code here).
     
  7. neroziros

    neroziros

    Joined:
    Aug 25, 2012
    Posts:
    129
    Did you manage to accomplish this? I am looking for a similar effect but still no luck. In my case, I want the shadows to be fully black regardless of there being multiple lights in the scene. (Currently, even though the shadows are fully black with one light, once there are more the shadows are lighted up)
     
  8. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,863
    According to the images, the shadow texture is blended in such way that any black on the underlying surface is inverted and thats it.

    normal.y wont work on walls.
     
  9. metaleap

    metaleap

    Joined:
    Oct 3, 2012
    Posts:
    589
    -- or just a custom Lighting function defined in the SS should probably cover whatever "shadow-looks" customization is needed, no?
     
  10. metaleap

    metaleap

    Joined:
    Oct 3, 2012
    Posts:
    589
    [edit: was errroneous advice]
     
    Last edited: May 29, 2014
  11. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    No, lighting functions don't sample the shadows, they just apply the lights. Their attenuation parameter value also includes things like distance from a spotlight, and cookies.
     
  12. metaleap

    metaleap

    Joined:
    Oct 3, 2012
    Posts:
    589
    You're right, thanks.. I forgot about these as I've been doing too much "1 directional light only" for too long :)
     
  13. neroziros

    neroziros

    Joined:
    Aug 25, 2012
    Posts:
    129
    Hmm still no luck with this, its a shame, stylized shadows can add a lot of personality to a game :(