Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Material Local Space and Instanced Static Meshes

Hi people. I'm working with materials on Instanced Static Meshes and I'm noticing that when transforming positions to Local Space in the Material Editor (I'm specifically using the ObjectPivotPoint node), I always get the pivot point for the Instanced Static Mesh component (or the actor that owns it, not sure), but not each instance's pivot point. I'm doing cylindrical billboarding around the local X axis using World Position Offset, which works wonders on separate meshes. But on lots of instanced mesh sheets, which as well are segments of a lightning bolt, I'm always getting the same location for the pivot point. And since I need a reference of the camera location respect of the object space, this leads to incorrect behaviour. And the local X axis i'm getting is wrong also.

Help is appreciated.

Product Version: UE 4.12
more ▼

asked Aug 14 '16 at 09:58 PM in Rendering

avatar image

49 3 4 11

(comments are locked)
10|2000 characters needed characters left

2 answers: sort voted first

I've taken a look at MaterialTemplate.USF, and it appears that TransformLocalVectorToWorld should return you per instance transformed position, but only if used in vertex frequency shader. and only if used with instanced meshes or particles. So to get what you need, you would have to use either (0,0,0) hooked up to TransformPosition(Local to Absolute World) or ObjectPosition node. They would have to be connected to two custom UVs slots. Then you can retrive the data in pixel shader by TextureCoordinate node. There might be a better solution, but this is what comes as obvious answer.

more ▼

answered Aug 17 '16 at 02:13 PM

avatar image

7.7k 129 29 289

avatar image vle07 Oct 12 '16 at 08:44 AM

I'm having difficulty following your steps to get the per instance transformed position. Do you think you could provide a screenshot of the nodes (or a more detailed step by step procedure)? Thanks!

avatar image Deathrey Oct 12 '16 at 10:05 AM

alt text

avatar image vle07 Oct 12 '16 at 08:06 PM

Thank you! It works perfectly. (In case someone can't find the customized UV connections on the main material node, they can be added by clicking on the main material node and setting the number of customized UVs in the details panel)

Do you have any good resources that explain conceptually what the material editor is doing? For example, like how you knew that nodes connected to a customized UV slot would be executed in a vertex frequency shader. Did you just figure it out by looking at the MaterialTemplate.USF? The UE4 wiki is great for beginners, but it really doesn't go into depth.

avatar image Deathrey Oct 12 '16 at 09:32 PM

Material editor is just transferring nodes into HLSL code and combining that with MaterialTemplate.USF to get actual final shader code.

I also faced the task of getting per-instance position once, and my journey through docs went nowhere, and answerhub was suggesting that it was not possible. Not being able to get per-instance position seemed more than strange for me and I went on with checking compiled and MaterialTemplate.usf in particular. Inside the file on line 523 I found what I was looking for. I don't actually think that this is documented anywhere.

If that was of any help for you, please, toss me a vote or something. It would slightly facilitate my road to a forum badge :)

avatar image Ninjin May 02 '17 at 09:38 PM

Can you also set this up if you want the local position of each vertex of each instance? Not sure if I understand Customized UV, but I tried to put the World Position Offset calculations into UV0 and UV1 (masked out RG into UV0 and GB into UV1). Then I used 2 TexCoords and plugged them into World Position Offset, sadly no luck :3 It seems like Absolute World Position won't execute on the Vertex Shader.

avatar image AJQuick Oct 01 '17 at 02:09 PM

I'd be curious to know about this too. I am attempting to do vertex animation on instance meshes and I would like to apply a "yaw" offset to the vertices of each instance in local instance space. "TransformVector" appears to simply transform to component space, which is incorrect. I am working strictly in the vertex shader btw.

(comments are locked)
10|2000 characters needed characters left

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 :

     // 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

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):

     Interpolants.PerInstanceParams = Intermediates.PerInstanceParams;
     //our new code:
     Interpolants.InstanceOrigin = Input.InstanceOrigin ;
     Interpolants.InstanceTransform1= Input.InstanceTransform1;
     Interpolants.InstanceTransform2= Input.InstanceTransform2;
     Interpolants.InstanceTransform3= Input.InstanceTransform3;

3.After that go to "struct FMaterialPixelParameters" in MaterialTemplate.usf and also look for #if USE_INSTANCING and change it too:

     half4 PerInstanceParams;
     //our new code:
     float3 InstanceLocalPosition;
     float4x4 InstanceLocalToWorld;

4.go to LocalVertexFactory.usf to function "FMaterialPixelParameters GetMaterialPixelParameters(FVertexFactoryInterpolantsVSToPS Interpolants," Again look for #if USE_INSTANCING and change it to the following code:

     Result.PerInstanceParams = Interpolants.PerInstanceParams;
     //our new code:
     Result.InstanceLocalToWorld = mul(GetInstanceTransform(Interpolants), Primitive.LocalToWorld);

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)
     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));
         return float4x4(

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)
         return mul(InLocalVector, (MaterialFloat3x3)Parameters.InstanceLocalToWorld);
         return mul(InLocalVector, GetLocalToWorld3x3());

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)
         return Parameters.InstanceLocalToWorld[3].xyz;
         return Primitive.ObjectWorldPositionAndRadius.xyz;

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).

more ▼

answered Jun 21 '17 at 09:14 AM

avatar image

16 1 2 5

avatar image rohanbabuam Nov 08 '18 at 07:49 PM

Hi, Is it possible to access the 'ObjectPositionWS' node from PostProcess material?

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question