Rim lighting

This shader uses the difference between the view direction and the polygon surface normal to add additional color offset to the surface.

Rim lighting

Shader

Shader "Shaders/Material/RimLight" {
  Properties {
    _MainTex ("Albedo (RGB)", 2D) = "white" {}
    _Color ("Color", Color) = (1, 1, 1, 1)
    _Rim ("Rim", Range(0,1)) = 0.1
  }
  SubShader {
    Tags { "RenderType" = "Opaque" }
    CGPROGRAM
    #pragma surface surf Standard

    sampler2D _MainTex;
    float4 _Color;
    float _Rim;
    #define RIM (1.0 - _Rim)

    struct Input {
        float2 uv_MainTex;
        float3 worldNormal;
        float3 viewDir;
    };

    void surf (Input IN, inout SurfaceOutputStandard o) {

      // Calculate the angle between normal and view direction
      float diff = 1.0 - dot(IN.worldNormal, IN.viewDir);

      // Cut off the diff to the rim size using the RIM value.
      diff = step(RIM, diff) * diff;

      // Smooth value
      float value = step(RIM, diff) * (diff - RIM) / RIM;

      // Sample texture and add rim color
      float3 rgb = tex2D(_MainTex, IN.uv_MainTex).rgb;
      o.Albedo = float3(value) * _Color + rgb;
    }
    ENDCG
  }
  FallBack "Diffuse"
}

Shader Notes

Notice that initially the value of step(RIM, diff) * diff will be in the range [1:RIM]; although this works, if the value of RIM is high, the falloff at the edge of the rim lighting is extremely harsh.

To fix this, the value is scaled into the range [1:0] using:

float value = step(RIM, diff) * (diff - RIM) / RIM;

This makes the transition from the rim color to the original texture smoother.