I ran into the same problem.I am using instanced meshes and I needed to do local to world transform in the material pixelshader(not vertex shader) but the transform node is not supported in the PS when using instancing. However I found out you can fairly easily modify the USF files to include that functionality without having to change anything in the engine’s c++ code (you will also be able to access instance position this way in the PS). I simply added the needed matrix stuff to LocalVertexFactory.usf, MaterialTemplate.usf and LocalVertexFactory.usf and made it possible to access this stuff from the pixel/fragment shader in the material editor.
The following steps work for UE 4.14:
In these files (LocalVertexFactoryCommon.usf, MaterialTemplate.usf and LocalVertexFactory.usf) you just need to look for the “USE_INSTANCING” defines. I did the following changes
(please backup the files before you make any changes to them!):
1.Change following in “struct FVertexFactoryInterpolantsVSToPS” in LocalVertexFactoryCommon.usf :
#if USE_INSTANCING
// x = per-instance random, y = per-instance fade out amount, z = hide/show flag, w dither fade cutoff
float4 PerInstanceParams : COLOR1;
//our new code:
float4 InstanceOrigin : COLOR2; // per-instance random in w
half4 InstanceTransform1 : COLOR3; // hitproxy.r + 256 * selected in .w
half4 InstanceTransform2 : COLOR4; // hitproxy.g in .w
half4 InstanceTransform3 : COLOR5; // hitproxy.b in .w
#endif
2.Now in LocalVertexFactors.usf go to function “FVertexFactoryInterpolantsVSToPS VertexFactoryGetInterpolantsVSToPS(FVertexFactoryInput Input,”
Look for #if USE_INSTANCING. Here we copy the Instance Transform data to the Interpolants(so that they are copied to the pixelshader):
#if USE_INSTANCING
Interpolants.PerInstanceParams = Intermediates.PerInstanceParams;
//our new code:
Interpolants.InstanceOrigin = Input.InstanceOrigin ;
Interpolants.InstanceTransform1= Input.InstanceTransform1;
Interpolants.InstanceTransform2= Input.InstanceTransform2;
Interpolants.InstanceTransform3= Input.InstanceTransform3;
#endif
3.After that go to “struct FMaterialPixelParameters” in MaterialTemplate.usf and also look for #if USE_INSTANCING and change it too:
#if USE_INSTANCING
half4 PerInstanceParams;
//our new code:
float3 InstanceLocalPosition;
float4x4 InstanceLocalToWorld;
#endif
4.go to LocalVertexFactory.usf to function “FMaterialPixelParameters GetMaterialPixelParameters(FVertexFactoryInterpolantsVSToPS Interpolants,”
Again look for #if USE_INSTANCING and change it to the following code:
#if USE_INSTANCING
Result.PerInstanceParams = Interpolants.PerInstanceParams;
//our new code:
Result.InstanceLocalToWorld = mul(GetInstanceTransform(Interpolants), Primitive.LocalToWorld);
#endif
5.Now we must add an entire new function “GetInstanceTransform”. So in LocalVertexFactory.usf look for the other GetInstanceTransform functions
and just paste the following function somewhere there:
float4x4 GetInstanceTransform(FVertexFactoryInterpolantsVSToPS Input)
{
#if !USE_INSTANCING_EMULATED
return float4x4(
float4(Input.InstanceTransform1.xyz, 0.0f),
float4(Input.InstanceTransform2.xyz, 0.0f),
float4(Input.InstanceTransform3.xyz, 0.0f),
float4(Input.InstanceOrigin.xyz, 1.0f));
#else
return float4x4(
float4(1,0,0,0),
float4(0,1,0,0),
float4(0,0,1,0),
float4(0,0,0,1));
#endif
}
6.Finally in MaterialTemplate.usf we need to change the function “MaterialFloat3 TransformLocalVectorToWorld(FMaterialPixelParameters”
which will allow us to use this transform node in the pixelfragment part of the material editor:
/** Transforms a vector from local space to world space (PS version) */
MaterialFloat3 TransformLocalVectorToWorld(FMaterialPixelParameters Parameters,MaterialFloat3 InLocalVector)
{
#if USE_INSTANCING
return mul(InLocalVector, (MaterialFloat3x3)Parameters.InstanceLocalToWorld);
#else
return mul(InLocalVector, GetLocalToWorld3x3());
#endif
}
7.Now if you want to get instance object position in the PS too you can do that by modifying “float3 GetObjectWorldPosition(FMaterialPixelParameters Parameters)” in MaterialTemplate.usf
/** Return the object's position in world space */
float3 GetObjectWorldPosition(FMaterialPixelParameters Parameters)
{
#if USE_INSTANCING
return Parameters.InstanceLocalToWorld[3].xyz;
#else
return Primitive.ObjectWorldPositionAndRadius.xyz;
#endif
}
That’s all that is needed. If you need access to other transform functions in the PS you might have to change one of the functions in MaterialTemplate.usf too
but change only those that have (FMaterialPixelParameters Parameters).