Customise UVs per instance with Instanced Static Meshes

All instances of an Instanced Static Mesh Component must share the same material and mesh. Is it possible, however, to customise the rendering of the material on the instance in any way other than using the PerInstanceRandom and PerInstanceFadeAmountconstants?

To be more specific, I have a texture map that contains a number of different textures. I’d like to access the UV attributes applied to the instanced mesh so that I could render different textures on different instances through the same material. Is this possible at all?

For reference, and to clarify what I’m after, it seems that Unity supports something called MaterialPropertyBlocks, which allows you to pass custom data to the instances and access that data in the shader.

Thanks in advance for any information!

This is a bit simplified, but still a more detailed explanation of what I’m after:

I’m building a turn based strategy game (not totally unlike the example project), and I want to procedurally generate the environment. The game world will consist of objects, most of which will have a very simple mesh (e.g. a piece of wall). For these I’d like to re-use the mesh and simply render a different texture based on the type of wall to get the performance I need. To give you a ballpark figure I expect that a single level might include tens or even hundreds of thousands of these objects.

I can’t use different materials for different instances, but I think it should be possible to create a texture atlas and simply sample different parts of that per instance to achieve the same effect. The problem is that I can’t pass any custom information to the instance that I could then reference in the material to determine which part of the atlas to sample.

The Turn Based Strategy example project also uses a texture atlas to render different floor tiles, but uses the PerInstanceRandom constant to simply pick a random one. This isn’t really good enough for me.

I think you’ve already answered this pointing me to the engine code that I might have to customise to achieve this, but surely there has to be another way?

I don’t think you can add your own data to Per Instance parameters without modifying the engine, however, it should be relatively trivial to do, You should take a look at LocalVertexFactory.usf and InstancedStaticMesh.cpp.

However, if you do not want to dive into the code, you could describe the effect, you are trying to achieve. There might be a simple workaround for that.

Ah, after some time trying to wrap my head around this, I think I finally understand why UE works the way it does: because of the different LOD models. Because of this the vertex buffers have to be dynamically created, which makes them directly inaccessible.

I wonder if there is a solution that involves just extending the ISMC rather than having to change the engine core itself…

Passing unique UVs for every instance to get textures from atlas is probably good way to go.
Yeah, for your purpose you should be able to create new class, extending ISMC, but sadly that is outside of what I can help with. I did not do much coding for UE4.

Perhaps, you would get more qualified assistance by posting in programming section of the forums or answerhub.

I’ve posted this to the forums: Extending Instanced Static Mesh Component for texture atlas support - C++ - Epic Developer Community Forums

I’ll keep an eye on the thread. Quite interested myself. Thanks.

I was able to achieve this by modifying InstancedStaticMesh source code to accept user-defined float instead of random float.

My modifications are described here: [https://markdownshare.com/view/a4b04e89-83bc-48bd-8ec5-229ab407f275][1]

Add Instance blueprint node now accepts an additional parameter:

131213-addinstance.png

And you can access this parameter in the material with PerInstanceRandom:

You can use any float value, but I noticed heavy glitches when the fractional component is zero. I am not sure why this happens, but I seemingly solved this by adding 0.5 to the integer before passing it to the instance and using floor operation to get the integer back in the material.

I used this to generate Minecraft-like voxel terrain. Here, grass, dirt, tree trunks and leaves all use the same quad mesh in a single Instanced Static Mesh for each 8x8 chunk of voxels (tall grass uses a separate mesh).

Thank you so much for this, it looks amazing! Will have a closer look ASAP :slight_smile:

Hey, I couldn’t manage to implement what you’re suggesting, would you be able to show what the code is supposed to look like?

Did you find that you still had performance benefits of instanced static meshes?

do you think this could be done in a plugin instead? that way it would more easily survive engine updates and multiple people in a team (especially the artsy types) won’t have to make sure they get the same changes etc, but i can’t figure out how to inherit from the ISMC stuff in a plugin and then e.g. use that functionality both directly and in a HISMC (since that depends on the original code) :confused:

This would great as a plugin if not a new feature of ISMC. I managed to get it working by editing modifying 4.20 source. But will need to get latest version at some point.

Would you have any instructions on how to modify the source? I think Terzalo’s instructions are outdated and don’t apply to the latest engine versions. Thanks!

Actually, I’ve managed to get it to work in 4.21 by modifying the source code as well. I had to pad the structure containing the instance data or I’d get serialization errors, but everything else was fairly straight-forward.

I took a stab at creating a plugin, but from what I can tell, it’s actually impossible with the way Epic has designed the UInstancedStaticMeshComponent class and its interaction with other parts of the engine. You need to extend UInstancedStaticMeshComponent to get it correctly work with lightmaps, physics, etc, but then you can’t override necessary functions like BuildRenderData (since it’s not a virtual function).

yeah i looked at the source and tried to figure out if/how it could be made a plugin but it seems so lowlevel intertwined with the rendering code etc you can’t just copy it (also horrible idea because upgradeability) but i also saw no way to extend it in a plugin and have the engine actually use that then. which is a bit sad, i mean it’s such a straightforward feature, why isn’t it in the engine already, they literally only need to add a single boolean per instance to turn the PRNG off and expose the “random” value (probably better to also rename it then :P).

For making unique instances I admit it’s very interesting way. I also want to make many instances to move or change slightly but in current implementation of ISM I cannot.

Even if for unique shapes it’s great idea I would rather stay with custom static mesh when generating voxels.
It is possible to pass custom vertex value for each triangle which makes material setup very easy and flexible.
I can read unique RGBA values for all faces I create.

So yeah in the end I am not even using all values but only A: FColor color = FColor(255, 255, 255, i); and only values 0-6 from it so 249 values are unused :D