Creating 10,000+ Dynamic material instances in 'Blueprint'

Hello all;

I’m experimenting with a Blueprint that creates a unique texture (using ‘Substance’) for each static mesh added to the scene.

I have made a function that creates a substance graph instance with a random seed, and assigns the outputs to a dynamic material instance. The function looks like this:

For my first test, I’m calling the function like this, as part of a basic ‘Scatter’ blueprint:

In this case, there are only 10 different substance seeds, but a dynamic material instance for EVERY static mesh component. I’ve tested up to 10,000 scattered objects - so presumably 10,000 dynamic material Instances. The editor was <1 f/sec on a GeForce 775M. Obviously not usable, but I was surprised that was even possible.

Oddly, performance seems to be better when I have fewer random seeds - which would suggest that Unreal has figured out that most of the Substance outputs are identical to each other, and hasn’t created 10,000 individual texture files. That would be VERY impressive if that were true - but I can’t figure out how Unreal would do this. I tried to find the dynamic materials that had been created in the content browser (to find out how many of them there were), but they seem to be hidden.

Assuming Unreal is creating 10,000 textures from only 10 seeds, the logical workflow would be to create 10 dynamic materials (1 for each Substance seed), and then randomly pick one to assign to each Static Mesh. This would involve knowing what Dynamic Material Instances already exist - and which Substance Factory created them. It wouldn’t be too hard to do this if it was possible to re-name the Material Instances after they are created - then I could reference a DMI called something like ‘substanceA_seed8’ when I need it in future. There doesn’t seem to be any way of doing this in Blueprint - I get a whole list of DMIs called ‘DynamicMaterialInstance_4987’ etc. with no way of knowing where it came from.

I’ve therefore got a couple of Blueprint / material workflow questions, and it would be great if anyone with more knowledge than me could give some advice:

TL/DR:

>Where are dynamic material instances / textures stored? They seem to be hidden when created through a blueprint, so I can’t tell how many of them there are.

>Does Unreal do something clever to check for functionally identical textures or shaders, in order to speed up performance?

>Is it possible to rename material instances in Blueprint, or dynamically create variables I can reference in other Blueprints?

>Is 10,000+ Dynamic Material Instances completely out of the question on a modern graphics card? I’m using this for cinematics, so fps isn’t as important as it would be for other projects.

> Materials created in runtime are not ‘stored’ they are instanciated in memory. If you create the instances inside a blueprint’s construction script, they are probably stored inside the Intermediate folder somewhere, but I didn’t check that.

> When seed is lower, seed values repeat more and instances that have already been created will repeat on meshes more times, reducing the instanciation process overhead and reducing drawcalls when material+mesh are the same.

> You can’t rename variable identifiers of objects generated at runtime.

> Yes. Modern powerful Pcs can handle around 4~5000 drawcalls before starting to lag fps.
Dynamic batching can improve that CPU usage a lot, but will cost much more vram to run the game.

> I may be ulterly wrong on it all, since graphics program is not under my belt; I know little about graphics and shaders beyond common OpenGL functions :stuck_out_tongue:

If Unreal is doing that automatically… that’s awesome. Will save a ton of complication and tricky asset management.

The blueprint instructs Unreal to make a new set of texture outputs, and a new dynamic material for every single object that’s created - even if there was a single seed. I don’t WANT it to do that, but I assumed that’s how it would deal with my current blueprint.

I’ll run some more tests, but it’s always nice when a program surprises you in a good way, and not the other way around. :cool:

You can do whole thing different way (or in 2 steps).

  • first create bunch of instanced material variations lets say 100. Store them in temporary array.
  • then place meshes and pick one material from array.
  • kill array. Make all ready for next bunch of meshes + materials.

This way you do not need to worry about all that material managment.

HI,

This is very interesting. I’ve asked our developer to take a look at the post as well to see if there is any information he can provide related to Substance.

Cheers,
Wes

That would solve part of the issue, for sure. Would be even better if I could make the array permanent and public - so I could use it in other blueprints, and not start fresh each time. Do you know of a way of doing that?

That would be awesome, Wes.