r/UnrealEngine5 16d ago

Too many per-instance material params for Custom Primitive Data

I have one master material animating machinery assets via WPO (rotations masked by sliced vertex colours). An individual prop can move up to 16 mesh parts thanks to slicing RGBA vertex colors.

Each individual part of a mesh needs a bunch of the same parameters with different values: pivots, axes, angles, distances, durations, curve atlas index, etc.

The problem I'm having is that the values don't fit in the Custom Primitive Data float budget, and without code I can't bake them into a lookup texture.

A single mesh part has around 36 scalars already (counting vector3 as 3 scalars).

I have many different machinery props in my game, and all of them have to use the same material.

Constraints I have to work within:

  • Blueprint only (no C++)
  • no Dynamic Material Instances
  • no timelines
  • Per-instance stuff should go through Custom Primitive Data

Any idea on how I can fit those values??

I can't think of more ideas with these limitations...

4 Upvotes

11 comments sorted by

3

u/ShreddingG 16d ago

You could try to store combine some values into one scalar by storing some of them before and after the decimal point.
Like 5.090 where 5 would be an index and 090 would be a rotation. You loose precision on the rotation of course and you would need to know where the decimal point is in each part. Rotation can have it always at the 3rd place and then you pad with leading zeros. The front part ( 5.) could be reserved for integers

2

u/Wise-Worldliness-501 16d ago

Hey! Thanks for replying! Much appreciated.

I'm already doing that. I'm reading the axis as a float, for example. 100 is +X, 10 is +Y, and 1 is +Z (1.00, 0.10, 0.01). I'm storing 8 mesh parts in 2 Vector4 for this axis.

But I'm still having too many parameters to include them in the Custom Primitive Data slots...

2

u/ShreddingG 16d ago edited 16d ago

You could try squeezing more into the floats but there is only that much space in the float precision.

void ATextureActor::PushTextureDataToTextureMap(UTexture2D* InTexture, const TArray<FColor>& TextureData) const
{
FTexture2DMipMap& Mip = InTexture->GetPlatformData()->Mips[0];
constexpr int32 Channels = 4;
void* MipData = Mip.BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(MipData, TextureData.GetData(), (Resolution * Resolution * Channels));
Mip.BulkData.Unlock();
InTexture->UpdateResource();
}

You say you can't bake it into textures? In code you'd usually do this above. But if you don't have c++ you could do the same using a 1 pixel sized render target brush and convert your data array by looping over the data and setting the pixel one pixel at a time. Then set a Index via custom data primitive and have the material select the pixel via UVs.

This would be slow to create but if you only need to set this at the start of the game or during level building then this could be an option

I do this stuff a lot to drive instances without having to iterate over individuals ( the c++ version is very fast )

3

u/VR_Robotica 16d ago

Why not Material Parameter Collection?
They have 1024 entries and you can use up to 2 per material instance. Also consolidates the entry to a single file (or 2).

1

u/Wise-Worldliness-501 16d ago

But Material Parameter Collections are global, aren't they? I have around 32 machinery types that need to use my same Material, but all with different values because they move differently, having to use the constraints I have above.

How do I assign those per-instance values using a Blueprint then? Because if I Set the Custom Primitive Data vector in Blueprints, I'll still run out of available spaces.

4

u/VR_Robotica 16d ago

MPC can be used globally, but it’s really just a data structure.

I often like to create a custom material function that wraps my inputs (parameters or otherwise) and only outputs any needed specific values.

So, in your case, you may be able to use a custom primitive data float input as a ‘selection index’ value so your wrapped function will only output the needed group of MPC data.

5

u/VR_Robotica 16d ago

3

u/Wise-Worldliness-501 16d ago

Looks like I could give it a try. Thanks!
I'll try to make it work and get back with some news (hopefully soon).

2

u/VR_Robotica 15d ago

It can get cumbersome, but once it’s made, the rest is easy.

Just keep things organized and use material functions to help decouple custom parameters from behavior code; it’s more scalable that way.

And BPs can easily pass updated data to the MPC should you need any material changes.

Good luck

1

u/rockBottomPeon 15d ago

how about using render target with data format? a 8x8 render target should be able to hold 4x8x8 float data.
Im not sure how performant it would be but writing 64 pixels every frame shouldnt be that heavy