ObjSpaceLightDir appears to be zero - LightMode is ForwardBase

Hello! I’m currently writing a Unity shader to replicate a setup for a particular form of stylized lighting we have working in Blender. I’ve written a lot of shaders in the past outside of Unity (GLSL/HLSL) and what I seem to be struggling with is getting Unity to feed information into the shader; seems there’s a lot of preconditions which need to be met and I’m sure I’m just missing one.

With “o.lightDir = abs(normalize(ObjSpaceLightDir(v.vertex)));” uncommented I would expect to see the object colored with the normal to the most influential light, but it’s just black. I’ve seen in the past people getting a zero from ObjSpaceLightDir when LightMode is not ForwardBase, but I believe I have configured that correctly. Do recent Unity versions have any other things I need to change for this to work?

Shader is as follows:

Shader "Custom/Inked"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 lightDir : TEXCOORD1;
            };

            fixed4 _Color;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);

                // This works perfectly.
                // o.lightDir = v.normal;

                // This just gives me a black object.
                //o.lightDir = abs(normalize(ObjSpaceLightDir(v.vertex)));

                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                return fixed4(i.lightDir, 1);
            }
            ENDCG
        }
    }
}

It looks perfectly fine to me in Unity 2020.1.15f1 - keep in mind that you are debugging lightDir directly and not any kind of lighting function, so your object will just be a uniform colour. Modifying the code slightly (just passing the vertex normal and doing a basic lighting op) gives me this result;

Shader "Custom/Inked"
{
	Properties
	{
		_Color ("Color", Color) = (1,1,1,1)
	}
		SubShader
	{
		Tags { "RenderType" = "Opaque" }

		Pass
		{
			Tags { "LightMode" = "ForwardBase" }
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
				float3 lightDir : TEXCOORD0;
				float3 normal : TEXCOORD1;
			};

			fixed4 _Color;

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos (v.vertex);
				o.lightDir = abs (normalize (ObjSpaceLightDir (v.vertex)));
				o.normal = v.normal;
				return o;
			}

			fixed4 frag (v2f i) : SV_Target
			{
				return max (0, dot (i.normal, i.lightDir));
			}
			ENDCG
		}
	}
}


If you’re going to be writing a lit shader however, it’s probably going to be a much better idea to use surface shaders;

Yeah, I started from there and found that the object was black. Slowly stripped it back to find the source of the problem and it seems that this vector is always 0. I’m still seeing black so it must be something external to the shader, that at least narrows it down thanks!

I’m looking to avoid a surface shader as it’s a non-photorealistic style being employed which we’ve currently built using nodes in Blender.