Can I remove the tangent basis interpolators from a surface shader?

I’m attempting to write a surface shader with three Input struct parameters, that also writes to o.Normal, and I get the “Too many texture interpolators would be used for ForwardBase pass” error. Looking at the compiled shader contents, I see the struct it’s creating:

struct v2f_surf {
  float4 pos : SV_POSITION;
  float2 pack0 : TEXCOORD0;
  float3 viewDir : TEXCOORD1;
  fixed3 TtoW0 : TEXCOORD2;
  fixed3 TtoW1 : TEXCOORD3;
  fixed3 TtoW2 : TEXCOORD4;
  fixed3 lightDir : TEXCOORD5;
  fixed3 vlight : TEXCOORD6;
  LIGHTING_COORDS(7,8)
};

The TtoW* interpolators appear to be added automatically when my surface shader writes to o.Normal, presumably for use by bumpmaps. I don’t need them (my normal calculations are based on something else); is there a way to tell the surface shader compiler not to include them?

None that i know of. Have you tried just deleting them and use the resulting vertex - fragment shader? should work.

Okay, actually, after some more experimenting I would expand my question a little bit: is there a way to force surface shader operations to happen in world space, even if I write to o.Normal? It appears that a number of things suddenly start happening in tangent space when I write to the normal, which isn’t what I want in this case.

You could bypass writing to o.Normal and write to your own custom struct.

o.CustomNormal or something like that?

Sorry, I didn’t specify: the ‘o’ in o.Normal is the SurfaceOutput struct used by the surface shader. I believe that means I need to write to it for interaction with the rest of the lighting system. (unless I do as Chickenlord suggests and do everything myself…I don’t like it, because it’s now a pain to maintain this shader in the future, but it may be the only way to do what I want)

The lighting system will work just fine if you don’t write to o.Normal - the tangent basis just won’t be called up (which appears to be the result you’re after).

Maybe I’m missing something here, but, no, that doesn’t work as I want. I do need to write the per-pixel normal in the surface shader; writing to o.CustomNormal or something results in compile errors, because the standard SurfaceOutput struct doesn’t include it.

Here’s the relevant bit of the surface shader I’m working with.

#pragma surface surf alpha noforwardadd nolightmap

void surf (Input IN, inout SurfaceOutput o) {
	half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			
	float interpolant = saturate(1-c.a);

	o.Normal = normalize(lerp(IN.worldNormal, IN.viewDir, interpolant));

	o.Albedo = c.rgb;
	o.Emission = CubemapAmbient(half4(o.Albedo, 1), o.Normal);
			
	o.Alpha = c.a;
}

Yeah, sure it doesn’t. But you could define your own one, then copy over the lighting function from the Lighting.cginc and rename all functions SurfaceOutputs. Thats it. it maybe possible though, that deferred rednering doesn’t like it, but i haven’t tried.