How do I adjust shader tint based on normal/face orientation?

Using a very handy shader reference from, I adapted the solution to be used with flat shading/colours. I am new to shaders, so the solution is likely far from optimal, but available below.

This gets me mostly to the effect I am after, but as this shader is used on mesh that has faces strictly orient flat or vertical (like stairs), I have been trying to apply a darker tint to the vertical faces to achieve a pseudo-shadow effect.

I have struggled to learn how shaders can adapt to face orientation, and failed attempts result in an “invalid” pink shader that I’m failing to resolve. Any help is much appreciated, thank you.

Shader "TintedHeight" {

     _MainTex ("Base (RGB)", 2D) = "white" {}
     _HeightMin ("Height Min", Float) = -1
     _HeightMax ("Height Max", Float) = 1
     _ColorMin ("Tint Color At Min", Color) = (0,0,0,1)
     _ColorMax ("Tint Color At Max", Color) = (1,1,1,1)
    SubShader {
        Pass {


            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            float _HeightMax;
            float _HeightMin;
            fixed4 _ColorMin;
            fixed4 _ColorMax;

            struct Input
	       float3 worldPos;

            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;

            v2f vert (appdata_base v)
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
             	float3 worldPos = mul (unity_ObjectToWorld, v.vertex).xyz;
                float h = (_HeightMax - worldPos.y) / (_HeightMax - _HeightMin);
                o.color = lerp (_ColorMax.rgba, _ColorMin.rgba, h);
                return o;	

            fixed4 frag (v2f i) : SV_Target
                return fixed4 (i.color, 1);


I see that you are using the vertex position in your computation. This will adjust the color based upon the vertex location, rather than the face’s direction. I suspect you want to use v.normal, which is a vector that defines the direction the face is pointing.

This page has an example, scroll down a bit to the “visualizing normals” section.