Apply different UV scale per object for same material, is that possible?

Hi there,
I come from 3D DCC environment, so what I’m asking may be simply not possible in BabylonJS…, let’s see.
So I have several objects that share the same material.
Most of them are scaled and oriented differently.
Since all of them share the same material, they also share the same texture.
So I have to scale their UVs specifically for each one of them.
OK, I come from MAYA, so in that program, UVs are just components of the object, not the material or texture.
So you have faces, edges, vertices AND UVs. And UVs can be moved and even animated.
How may I do what I need?
I thought of using triplanar textures, but I would need them to be in local space and according to this thread, that’s not possible.
Any ideas?
Thanks in advance!

That’s the same thing in Babylon.js, “uvs” are an attribute of a mesh, so each mesh has its own set of uvs.

3 Likes

Excuse me @Evgeni_Popov but my coding colleage @paleRider needs a bit more info on that because he knows how to do the UV scaling through the material, but as I understand your post, there is a way to do it on a per mesh basis.

So with the SAME material AND texture, you can have different UV scaling on different objects.

Thanks in advance for your help.

First understand about vertexData

2 Likes

Yes, but only at mesh/UV(W)s level. Not on a material/texture you create in BJS and would apply to all (or not anywhere else actually). It’s the UV’s defined on the mesh/submesh/selection that will define how the mesh (UVW) will receive the material/texture with the initial settings of this material/texture (scaling, offset and projection mode). Sure you can act on these initial settings in the material itself, but if you apply the same material to your mesh/submesh, it will of course be applied the same for all using this material/texture, according to the UVs set on the mesh.

Here’s a basic example showing this. I project a same material/texture at default scaling (1,1,1) on two identical planes which have different UVs. On the right plane, UVs are generated to fit the object in planar projection mode. On the left, plane, I have stretched my texture before generating the UVs.


2 Likes

I’ll let @paleRider see if this is usefull for us. But as far as I pseudo understand what you are doing, I guess the two planes have initial different UVs already?

1 Like

If by ‘initial,’ you mean that I did set them on the mesh before generating the export in the 3D app (here c4d) then Yes, that’s exactly what I did here.
Else, if you want to redo your UVs in BJS on an imported mesh, I believe that’s possible but you should make ready for a bit more code fiddling and start with the link provided by @JohnK To be honest, I never did this. I don’t have this need nor level of patience :grin: I’m a simple designer. I like to keep things simple and done right from the start if by any means possible of course :face_with_hand_over_mouth:

Aha, you cheated! LOL
Ok, let me explain.
In MAYA, I can deform the UVs in order to stretch the texture, that’s fine with .babylon format.
The complex thing is that the model has to be non uniformly scaled during an animation and the UVs should deform accordingly.
I’m afraid .babylon format allows for UV deformation but NOT during animation, and that’s why we need to scale the already created UVs by the scaling factor in order to achieve this (I think).
I’m not a coding guy, so I rely on what I would do on my DCC, based on my knowledge, which can be right or wrong of course.

I see. Just like that, this sounds to me like it would be something to eventually handle with a node material. But then again, I’m not an expert on this.
Though with this new information, let’s see what @JohnK has to say.
Also cc @carolhmj who might be able to find the right person to answer this question in this period of Season’s Holidays. Might require a bit of patience.

I’m already asking in other threads for other ways to accomplish this too, I hope I’m not very heavy asking.

Nah, there’s always a way and nearly always more than one.
It’s just that it’s not the best time to get the most immediate and accurate answers.
I believe you know you can also animate materials in BJS (though I still think a node material would be better and more ‘sexy’).

Please avoid that. It only creates confusion and will not make for better or faster replies. All it does is dillute the topic with bits and parts of information. As I said with just a bit of patience, I’m sure you’ll find your ‘hero’. Meanwhile, may be you could work on some other parts of the project.

I’m asking in other threads but not because I’m hurry but in order to have the topic of each focused.
Other way to do this is to use triplanar textures, but I thought it would easier to not mix topics in the same thread. Although if you understand it is the best way, a moderator may join both in one.

Nah, if it is really for two different methods, I guess it’s fine. No worries and I hope you will soon be oriented in the direction that matches your need.

The problem, as you can see here, is that NME is NOT supported in RA (we need that), so we are, esentially, fucked LOL

Hi there @JohnK and @Evgeni_Popov :

The problem here is that from this scene, where we have two boards sharing the same (PBR) material…

…in order to scale the height of, by example, the top-left board keeping the texture not-stretched…

…is mandatory to scale both, the geometry and the texture:

...
var scaling = value / _BOARD_MAX_SIZE;
_board[board].mesh.scaling.y = scaling;
_board[board].mesh.material.albedoTexture.vScale = scaling;
...

Failing to do it that way (in a trivial way, commenting the last line in the previous code) results in the stretching of the texture, that can’t “follow” the scaled geometry…

Of course, all that is causing the other board (right-bottom) showing a stretched texture once we start to “tweak” the other board, as they share the same material.

So, facing this scenario, we thought the only way to accomplish the pretended behavior was by means of triplanar PBR material, but sadly, the resulting scene can’t be exported to a GLTF, as that is not supporting triplanar at the moment and we need that GLTF to be show via AR on model-viewer.

UV animation would be another way, but it can only be done on a per-material basis level, so we could’t have there several meshes with same material.

Best regards.

You can try to update the uvs of the meshes programmatically, as Maya is doing (I assume).

For a plane it is easy:

For a generic shape it is probably much more difficult…

Hi there, @Evgeni_Popov, and thank you for your time:

As you can see in this PG, obviously the problem is that we’re in need of a triplanar-fashion approach in order to avoid stretching of textures on the YZ and XZ planes.

BJS triplanar materials are not a solution here, as that is not a GLTF-compliant feature.

Any advice of the API to access that UVs? A BJS mesh have up to six UV set, isn’t it?

If you want to update the uvs by hand for each face independently, you need to make sure that each face (triangle) has its own 3 vertices that are not shared by any other faces.

By default, a cube (created with BABYLON.MeshBuilder.CreateBox) share some vertices with multiple faces. So, you should call daCube.convertToFlatShadedMesh() to make sure each face has 3 vertices of its own.

From there, you can update the PG to compute the right uv coordinates for each vertex, depending on which face it pertains:

I have also added the scaling in Z to show it works for all axis.

Now, it is very specific to the cube. If you want to do it for other shapes it will be much more complicated (is it even possible in the general case?).

1 Like

You are not using the glTF model in Babylon.js? If you do, then you can change the material by a triplanar material after you load the glTF file?

Hi there @Evgeni_Popov:

I need a GLTF only at the end of the customization, in order to be exported for being used by model-viewer.

Best regards.