Changing the look of unity built-in shadow

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 :



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

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.

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.

I think it’s done like this:

  • Every object has two textures: one for black ink outlines, and one for coloured ink fill
  • Geometric self-shadowing is done with a stepped ramp, like wrapped Lambertian but in steps
  • Black outlines are superimposed onto the self-shadowed fill ink
  • 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.

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:

Shader "Custom/Wolf" {
	Properties {
		_Color ("Main Color", Color) = (.5,.5,.5,1)
		_SpecColor ("Specular Material Color (RGB)", Color) = (1,1,1,1)
		_OutlineColor ("Outline Color", Color) = (0,0,0,1)
		_Outline ("Outline width", Range (0.0, 0.03)) = .005
	    _ShinPower ("Shininess", Range(0,1)) = 0.5
	    _GlossPower ("Gloss", Range(0.01,1)) = 0.5
		_MainTex ("Base (RGB)", 2D) = "white" { }
		_BumpMap ("Bumpmap", 2D) = "bump" {}
		_Detail ("Detail", 2D) = "white" {}
		_SpecularTex ("Specular Map", 2D) = "gray" {}
		_RampTex ("Shading Ramp", 2D) = "white" {}
	}
	
	CGINCLUDE
    #include "UnityCG.cginc"
    
    struct appdata {
    	float4 vertex : POSITION;
    	float3 normal : NORMAL;
    };

    struct v2f {
    	float4 pos : POSITION;
   		float4 color : COLOR;
    };
    
    uniform float _Outline;
    uniform float4 _OutlineColor;
    
    v2f vert(appdata v) {
    	v2f o;
    	o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

    float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
    float2 offset = TransformViewToProjection(norm.xy);

    o.pos.xy += offset * o.pos.z * _Outline;
    o.color = _OutlineColor;
    return o;
    }
    ENDCG

	SubShader {
		Tags { "Queue" = "Geometry+10" "RenderType" = "Opaque" }
		Pass {
			Name "OUTLINE"
			Tags { "LightMode" = "Always" }
			Cull Front
			ZWrite On
			Blend SrcAlpha OneMinusSrcAlpha

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag

		half4 frag(v2f i) : COLOR {
			return i.color;
		}
		ENDCG
		}

			CGPROGRAM
			#pragma surface surf Wolf
			#pragma only_renderers d3d9
			#pragma target 3.0
			
            struct Input
			{
				float2 uv_MainTex;
				float2 uv_BumpMap;
				float3 worldNormal;
				INTERNAL_DATA
			};
			
            sampler2D _MainTex, _SpecularTex, _BumpMap, _RampTex, _Detail;
			uniform float3 _Color;
		    float _ShinPower;
	        float _GlossPower;

            inline fixed4 LightingWolf (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)
            {
                fixed3 h = normalize (lightDir + viewDir);

                fixed NdotL = dot(s.Normal, lightDir) * 0.5 + 0.5;
                fixed3 ramp = tex2D(_RampTex, float2(NdotL * atten)).rgb;

                float nh = max (0, dot (s.Normal, h));
                float spec = pow (nh, s.Gloss * 128) * s.Specular;

                fixed4 c;
                c.rgb = ((s.Albedo * _Color.rgb * ramp * _LightColor0.rgb + _LightColor0.rgb * spec * s.Specular * _SpecColor) * (atten * 2));
                return c;
            }
                
            void surf (Input IN, inout SurfaceOutput o)
            {
                o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * _Color;
                o.Albedo *= tex2D (_Detail, IN.uv_MainTex).a * 2;
                o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
                float3 specGloss = tex2D(_SpecularTex, IN.uv_MainTex).rgb;
          		o.Specular = specGloss.r * _ShinPower;
          		o.Gloss = specGloss.g * _GlossPower;
			}
			ENDCG
	}
	Fallback "Diffuse"
}

What do you guys think, could be implemented into that shader?

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).

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)

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.

– or just a custom Lighting function defined in the SS should probably cover whatever “shadow-looks” customization is needed, no?

[edit: was errroneous advice]

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.

You’re right, thanks… I forgot about these as I’ve been doing too much “1 directional light only” for too long :slight_smile:

Hmm still no luck with this, its a shame, stylized shadows can add a lot of personality to a game :frowning: