Generally, this behavior of TransformVector material expression is unintended. It should provide proper per-instance transform when used in vertex shader. It can be filed as bug report in a relative section.
For a workaround ou might want to try using custom node like that:
With the following code:
#if USE_INSTANCING
return mul(InputVector,(MaterialFloat3x3)Parameters.InstanceLocalToWorld);
#else
return mul(InputVector,GetLocalToWorld3x3());
#endif
Again, it needs to be passed through vertex interpolator, otherwise compile error will be thrown.
##I’m trying to get local normal per instanced static mesh in the material.
I’ve managed to get position, orientation and scale using the Object* nodes and passing them through VertexInterpolator, so they’re calculated in the vertex shader. The only one that didn’t work was the ObjectOrientation node. But I can get the same result by passing a (0,0,1) vector to a TransformVector(Local to World) and then to the VertexInterpolator.
But no matter what I do, I can’t get any vector transformed from World to Local space nor Tangent to Local. See the setup below:
For standard Static Meshes, it works with any of the TransformVector nodes connected. For instanced, though, it doesn’t work either way!
Here’s an example:
The left cylinder is an instanced mesh and the right one is a standard StaticMeshActor. Both using the same material. The StaticMeshActor (right) correctly displays its local normals, displaying as blue what would be its top side. But the instanced one doesn’t, fading to blue on its world space top faces.
How can I do it? I’m almost thinking this is a bug.
Thank you so much!!! You’re awesome! From one of your previous posts in other question, I supposed it had to be some custom code, but I had no Idea what the existing functions and properties were.
Since it was from world to local, I had to invert the Matrix and Vector positions, but it’s working!! 
Thanks again! And here’s the inverted multiplication for the next one who tries it:
#if USE_INSTANCING
return mul((MaterialFloat3x3)Parameters.InstanceLocalToWorld, Vector);
#else
return mul(GetLocalToWorld3x3(), Vector);
#endif
I ran into the same problem two years later but a new node called “pre-skinned local position” has been added and work
Is this still working in UE5? I mean, I think there is no USE_INSTANCING anymore