How to make same repeated texture size on differently sized instances of Box

Hello,
First I want to say that I read many topics about this on forum but didn’t found an answer that would help me achieve what I want.

I want to have textured boxes where texture is always with the same size, so in example if texture is 1m per 1m in size and I have cube with size 1 then that texture is repeated once on each face of that cube, but if I have a box with size 2 then that texture will be repeated four times on each face (2 rows, 2 cols).
This is easy to achieve with changing UV coordinates on mesh, however, I want to use mesh instances, so that would be just one parent mesh which is a cube with size 1 and then instances of that cube with different scaling. Of course we cannot change UV coordinates per instance so we can’t repeat texture with the same size regardless of scaling on instance.
I read that there are InstanceBuffers that might be used to solve this, but honestly I am very weak with shader programming hence I can’t wrap my head around this. Is this even possible to do with InstanceBuffer? If it is can you somehow point me in a direction what should I do?

Playground with example what I have now: https://playground.babylonjs.com/#20OAV9#11643

Hello!

I tried a few ways and what I found the easiest was to take advantage of the color instancedBuffer to store the scaling information of the mesh instead of a color. Then this information can be accessed using the Node Material Editor to scale the uvs of each instance: Instance Color with information | Babylon.js Playground (babylonjs.com)

I’ll also @Evgeni_Popov who probably has a better solution than this :sweat_smile:

1 Like

Hi !

I made a PG for you : https://playground.babylonjs.com/#20OAV9#11657

As @carolhmj mentioned, you have to use custom buffers for instances. I ended up using UV2 but Color buffer would work just as well

1 Like

Thanks for answers guys.
@carolhmj in your playground second box is not scaling on y properly, how can this be fixed?

@CraigFeldspar in your example only faces aligned on X are scaling texture properly, rest is stretched and that’s the problem I also faced, if you will change UV scaling for all faces then some will be distorted, can I do this per face somehow with InstanceBuffer?

Let me confirm with @Evgeni_Popov (sorry for double ping!), but I think the instanced buffers are only per instance, not per vertex per instance :thinking:

I would suggest thinInstances and stack instances of a 1x1x1 box

1 Like

@aWeirdo That’s a very good idea, I was thinking of making just instances with size 1, but thin instances will much work better. One concern I have is that I will probably need to remove/add big parts of scene when moving with camera and it says that removing/adding thin instances is slower, but perhaps not that much I should care.

I looked into node editor @carolhmj and it started to make sense for me how it works. I saw there are input mesh property called uv3/4/5/6, what are these?

One tip is if you can add/remove them in groups, it will be faster than adding/removing one by one.

About uv2/…etc, it’s a “standard” property in many computer graphics libraries/programs, they’re just “extra” uv sets that can be useful to build more complex objects: How do you manage and organize multiple UV sets and texture layers for a single model? (linkedin.com)

About the NME, I highly suggest you check out the documentation and especially the videos as they present all the features in a easy to follow manner :slight_smile: The Node Material Editor | Babylon.js Documentation (babylonjs.com)

If you are going with cubes, you can use some kind of triplanar mapping.
You can add a scale node in the node material if you need to have a special scale : https://playground.babylonjs.com/#20OAV9#11660

1 Like

If you don’t want any deformation whatever the size of each face, it’s getting a lot more complicated.

See for eg:

But it’s always very specific to a cube or a rectangle…

Hmm, what you linked there is just setting a UV for each face separately, right? I did that, it’s rather not complicated, but problem is that I can’t do that per instance.

I forgot that my textures are not all just 1x1 in size, some are 2x2 etc. I was thinking that maybe I can use thin instances per face and build boxes from these small 1x1 faces, that way I will be able to have different texture sizes. in example if there are textures 2x2 then I can create 4 different 1x1 faces that together will create one 2x2 face. Additionaly if I want to have many textures and not create separate mesh for each, then I can create texture atlas and use UV offset to have different textures using the same material? What do you think about that approach? In summary if I would have texture sizes like that: [1x1, 2x2, 4x4, 8x8] then I would need 85 different 1x1 face meshes, using texture atlas all of them would use one material. So if I would like to create 10 000 boxes (of various sizes) and each of these boxes would be on average composed by 96 (16x6) faces, so total of thin instances would be like 960 000, then I would still have just 85 draw calls, right?

Yes, that’s what @aWeirdo suggested, and I think it could be a good solution!

But do you think my numbers are reasonable? milion thin instances seems a lot, I don’t know what modern GPU can handle

That’s hard to say in the general case, I think you will have to test and see how it behaves on different GPUs.

But thin instance is the fastest way to render millions of objects, it’s a lot better than regular meshes or even mesh instances.

2 Likes