I need to create the illusion of movement of a spaceship by moving the texture offset of a starfield background image. The camera and starfield image keep track of the spaceship as it moves and I am using a APaperSpriteActor to display the background image, however I am unable to figure out how I change the background texture UV offset at runtime (there is a UPaperSprite::GetSourceUV() method, but no equivalent Set method).
I’m sure I could get this working by using Material, but then I am unsure how to present the material as a flat image (perhaps using a plane?).
Customized UVs change the same UVs Texture Samples use, but once for each vertex instead of each pixel. As Texture Samples use the coordinate index 0 by default, customizing UV0 already alters the default textures coordinate.
Changing the coordinates Scalar Parameters in Blueprint:
Personally I would use something called Material Parameter Collection to change these values. This is much cheaper than what has been proposed and is more flexible.
Just create a material paramter collection in your editor and use material parameter nodes in your material. Then, inside some blueprint you simply update the values in a tick event and you are good to go. I am not at a PC until monday so I cant give you a screenshot. Sorry for that.
Thanks to RVillani and NoobsDeSroobs, this is now working ([Animated GIF; 47.2MB][1]).
I basically used the set-up suggested by RVillani, exposing UOffset and VOffset as parameters and then using a Material Instance for the starfield material.
The base C++ CameraActor class does the movement:
FVector Position = GetActorLocation();
FVector Diff = Position - LastPosition;
LastPosition = Position;
if (StarfieldMID) {
float UOffset, VOffset;
if (StarfieldMID->GetScalarParameterValue(TEXT("UOffset"), UOffset) &&
StarfieldMID->GetScalarParameterValue(TEXT("VOffset"), VOffset)) {
UOffset += Diff.X * UVOffsetScale;
VOffset -= Diff.Z * UVOffsetScale;
StarfieldMID->SetScalarParameterValue(TEXT("UOffset"), UOffset);
StarfieldMID->SetScalarParameterValue(TEXT("VOffset"), VOffset);
} else {
UE_LOG(LogGame, Error, TEXT("[%s] Failed to get U/V offset parameter values"), *GetName());
}
}
and the blueprint-subclass creates the Material Instance Dynamic in the BeginPlay event and passes it to the base class:
I don’t think using a Material Parameter Collection was at all straight forward and I didn’t see what advantage it gave me over a material instance as I will be adding a total of 3 textures to the starfield to give a parallax effect and MPCs seem to be global, unless I have misunderstood their use? Thanks anyway for the suggestion.
MPCs are global, indeed, and if you’d like to synchronize the effect across multiple materials, it would be really useful.
Nice catch on creating the Dynamic Material Instance on BeginPlay. I always do that, but I messed up when making the example for you XD Glad you saw that!
Sorry about waking up an old post but I was looking for something similar for some hours now, and I found on another post something which could be useful in that case and without using MPC, dynamic material and blueprints, only a node in the Material editor.
So, i’m posting it here, just in case someone was in the same case as me and arrive on this post while asking google “offset UV UE4” or “moving dynamically UV in UE4” etc…
And here is my saver : The node “Panner”.
You have to put the pin out of the “TexCoords” in the “Panner” and then “TextureSample”. Easy and less cost than dynamic material apparently ! =)
It also exists another node named “Rotator” to rotate these UVs in real-time.
For the sake of completeness, since we discussed some optimization techniques in this thread, and it seems to still get some views, I also want to mention Custom Primitive Data (CPD) parameters.
If you want multiple meshes to have their UVs manipulated differently, in which case you won’t use Material Parameter Collections, CPD allows you to do that without preventing the engine from auto-batching your meshes into a single draw call, so it’s good for performance.
If your textures different per mesh, they won’t be auto-instanced. Dynamic instancing only works when rendering the same mesh with the same material (no dynamic instances) multiple times. CPD is a way to have different values for that material on each mesh, while keeping their materials the exact same.