Get local position in surface shader

Is there any way to get the local position (relative to the mesh) on the surface shader?

This is part of my code:

fixed4 _Color;
fixed4 _ReflectColor;
half _Shininess;
fixed _DrawLimit;

struct Input {
	float2 uv_MainTex;
	float3 worldRefl;
	float3 worldPos;
};

void surf (Input IN, inout SurfaceOutput o) {
	clip(IN.worldPos.z - _DrawLimit);
	
	fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
	fixed4 c = tex * _Color;
	o.Albedo = c.rgb;
	o.Gloss = tex.a;
				
	o.Specular = _Shininess;
	
	fixed4 reflcol = texCUBE (_Cube, IN.worldRefl);
	reflcol *= tex.a;
	o.Emission = reflcol.rgb * _ReflectColor.rgb;
	o.Alpha = reflcol.a * _ReflectColor.a;								
}

Instead of using worldPos I need the local position. I can’t find a way to get it in the docs, at least here:

Untested, but here’s an idea.

First, add a member to your Input structure:

struct Input {
  float2 uv_MainTex;
  float3 localPos;
};

Then add a vertex modifier function that populates the localPos member with the vertex information from appdata:

#pragma surface surf Lambert vertex:vert
  
void vert (inout appdata_full v, out Input o) {
  UNITY_INITIALIZE_OUTPUT(Input,o);
  o.localPos = v.vertex.xyz;
}

Now in your surf function you should be able to access IN.localPos as:

void surf (Input IN, inout SurfaceOutput o) {
    // Do something with IN.localPos....
}

In fact I just discovered that we don’t need the vert and we could do it only in surf with:

float3 localPos = IN.worldPos -  mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz;

Don’t forget to declare worldPos in Input:

struct Input {
   /// [....]
   float3 worldPos;
 };
float3 localPos = IN.worldPos -  mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz;

when we use this, it will cause problems with rotation.

float3 localPos = mul(unity_WorldToObject, float4(IN.worldPos, 1.0)).xyz;

this works perfectly for me