How to write unlit surface shader?

Ive written a clipping unlit surface shader for something Im working on. It works great except that I get that annoying “shader wants normals” error. I don’t use the normals. How can I tell shaderlab that they aren’t necessary for this shader?

Code is below for reference

Shader "Custom/ClippingUnlitTransparent" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_cliprect ("Clip Rectangle", Vector) = (-1,-1,-1,-1) 
		
	}
	SubShader {
		Lighting Off
		AlphaTest Greater 0.5
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Unlit 
		#include "UnityCG.cginc" 
		
		half4 LightingUnlit (SurfaceOutput s, half3 lightDir, half atten) {
          half4 c;
          c.rgb = s.Albedo;
          c.a = s.Alpha;
          return c;
        }

		sampler2D _MainTex;
		float4 _cliprect;
		

		struct Input {
          float2 uv_MainTex;
          float4 screenPos;
        };

		void surf (Input IN, inout SurfaceOutput o) {
			float2 screenPosition = IN.screenPos.xy / IN.screenPos.w;
			screenPosition.y = 1.0 - screenPosition.y;
    		screenPosition.xy = screenPosition.xy * _ScreenParams.xy;
			
			if ((screenPosition.x>=_cliprect[0])&&
			    (screenPosition.x<=_cliprect[2])&&
			    (screenPosition.y>=_cliprect[1])&&
			    (screenPosition.y<=_cliprect[3]))
			{
				half4 c = tex2D (_MainTex, IN.uv_MainTex);
				o.Albedo = c.rgb;
				o.Alpha = c.a;
			}  else{
				o.Albedo = float3(0,0,0);
				o.Alpha = 0;
			}
			
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

You can also create a no lighting shader function.

#pragma surface surf NoLighting

fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, fixed atten)
    {
    	fixed4 c;
    	c.rgb = s.Albedo; 
    	c.a = s.Alpha;
    	return c;
    }

just FYI, I found that the s.Albedo value in the lighting shader function was at double the correct intensity. i.e.
//c.rgb = s.Albedo; //should be: c.rgb = s.Albedo*0.5f;

try to disable all lighting method listed there.

also, best way to write shader that doesn’t interact with lighting is to make a vertex/fragment shader, not surface.

also, in your shader you really interact with lighting - try to light your model by more than 1 light source and you’ll show over-lighting effect. so you can just ignore light function (return;) and write color to emission in frag method or use amient color instead.

In addition to use a NoLighting shader function, you might also like to add noforwardadd, so that point lights do not affect the albedo. The Emission control ignores forward add passes, so that is a workaround that accomplishes the same thing, except the additional pass still takes place with 0s in the Albedo, resulting in 0 in the additive output.

Better to just skip it entirely!

For anyone else that comes across this problem and is trying to make this work, the best solution that I found was to add a “noambient” pragma to @FlyingOstriche’s solution. This makes it so that the lighting function uses just the base colors as intended

#pragma surface surf NoLighting noambient

and

fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, fixed atten) {
			return fixed4(s.Albedo, s.Alpha);
		}

This should provide a good look for an unlit material. The reason that the colors were blown out in earlier solutions was because the ambient light was being added to the final output after the lighting function. “noforwardadd” could also be used, though I doubt its very necessary.

And for GPU Instanced Unlit this is working pretty good for me… able to change 1000s of colors on the fly:

Shader "Unlit/InstancedUnLit"
{
	Properties
	{
		_Color ("Color", color) = (1,1,1,1)
		_MainTex ("Texture", 2D) = "white" {}
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;

			UNITY_INSTANCING_BUFFER_START(Props)
			UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
			UNITY_INSTANCING_BUFFER_END(Props)
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// sample the texture
				fixed4 col = tex2D(_MainTex, i.uv) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
}