How to get instanced mesh local normal in material

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!! :smiley:

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

1 Like