Showing multiple textures on the same model

Hi everyone !

I’m still working on my product configurator (Kitchen knifes) and I need some advice/tips !
Coding isn’t really a problem for me, even though I haven’t tried making my own shaders (scary stuff haha).
But 3D modelling is a whole new world for me, and I’m pretty sure I’m not going in the right direction.

I have a 3D model of a kitchen knife, with a mesh for the blade, and another for the handle. So a pretty simple 3D object! But my blade has to look metallic, show a brand logo, and should also be able to show another drawing on it (a personnalisation option, could be a picture, another logo, text, whatever…).

I tried several things in blender which seem to work :

  • 3 uv maps, blade + logo + drawing
  • 2 uv maps, blade + drawing, and the logo is another mesh, a plane shrinkwrapped on the blade.


But once in Playcanvas, I can’t manage to get the same result!
I can only use 2 UVs, and the result is a bit weird (the drawing has an impact on the metallic material, even though the UV for the drawing doesn’t cover the whole blade).
And the shrinkwrapped plane has lost it’s transparency.

My first guess is that I’m not using the right techniques for this :smiley:
Does someone have an idea on how to manage it?

Thanks in advance!

maybe this would work for you?

1 Like

Hi @TonyLGC,

I think you are getting close! Indeed in PlayCanvas and in general in most realtime 3D engines you have two UV coordinate sets to work with.

In your case the way I would approach that would be:

  1. Split the knife in two nodes in Blender, one for the metallic surface and one for wooden handler. Use UV0 (first UV set) for each node to unwrap.

When importing that in PlayCanvas you will get two material slots (mesh instances) for your model, so you can assign a unique material for each surface.

  1. For the logo you can use a detail texture, no need for a plane surface/polygons for that (you can get z fighting from a distance). You can use the UV1 channel to get the position right and then in code set the detail channel for your metal material to your logo image. It will blend correctly without affecting or getting affected by metalness. For on detail maps here:

https://developer.playcanvas.com/en/api/pc.StandardMaterial.html#diffuseDetailMap

1 Like

Thanks guys! I’m going to look at all these and keep this post update ASAP :smiley:

Hi again everyone :wink:

I looked at the engraving example and it looks a bit hard for me right now, but I’m going to try the DiffuseDetailMap (Detail Diffuse Map?).
Right now I have my metal material with no main DiffuseMap, and UV1 with a decoration. So if I understand it well, I can put my logo on the blade with the DiffuseDetailMap on UV1?

I also searched for examples in other product customizers and I found this one that is interesting.
In this one, their logo blends with the decoration (leaving a border around the logo). They can rotate the texture, that makes me wonder if they first generate an image outside of their 3D engine, mixing the decoration and logo (in a html canvas perhaps?), and only then they put it as texture on their 3D model.

Is that a crazy and heavy processing idea? :stuck_out_tongue:

I already use something like that. An user can send his own picture, I load it in a canvas, change the pixels so it becomes transparent and greyscale, and set it as a DiffuseMap. It works OK as long as you send a PNG.

Some gifs !
The exemple configurator I found
diane

My work so far (you can try it also here but it might not work 24/24 because I regulary break everything haha, and don’t mind the mess in the code, I should will clean it up)
playcanvas

2 Likes

Hey everyone again!

I tried playing around with the DiffuseDetailMap
Here is the test project I use : PlayCanvas 3D HTML5 Game Engine

This is what I have in Blender (don’t look at the handle, it’s a crap UV map haha)

And in Playcanvas. That’s not far away! Thanks @Leonidas for the tip :slight_smile:

Some problems I need some help with :
I need to invert the Alpha. For this example I did it myself first manually on the texture.
I searched a bit and it looks like I’ll have to use a custom shader?

Also I have a glitch on the logo, that disappears if I zoom on it.

image

I suspect it won’t happen if I use the inverted Alpha, could that be it?

edit: nevermind, it happens with the normal Alpha too.
image

If I add more space around the logo, it still happens but with a further camera:
image

1 Like

Is the logo a separate texture? If so, is the texture set to clamp on the UV?

1 Like

Hi yaustar, thanks for the reply

Yup it’s a seperate texture
This is the original I have to use :


This is my inverted one for the test :

Both the logo and the “decor” texture are clamped.

The decor can also have the same problem, like here :
image
As long as the drawing gets close to the border (without even toughing it), it happens.

@mvaligursky may have a better idea. Would it be possible to setup a small repro project to look at?

Thanks for looking :smiley:
Here is my test project : PlayCanvas 3D HTML5 Game Engine

Hmm looks like to be mip map related. If I disable mip maps on the texture, the lines disappear. This does explain why it doesn’t show when you are close up to the model before :thinking:

1 Like

Oh indeed :slight_smile:
But it still happens on this one, with mipmap disabled :

clamp mode just means that the edge pixels are used outside of the 0…1 range on the UV coordinates. If you want transparent outside, you need 1 pixel transparent border around the texture.

1 Like

Hi mvaligursky, thanks for the reply!

Unfortunately, adding a transparent border didn’t change much.
I remade my UV maps in order to avoid a maximum of zooming in, used black & white textures with a nice (white) border because I couldn’t find how to invert an alpha texture, and now the glitch appears really far away.
So now I limited the distance of the camera and I think that will do it for now haha : test_couteau - PLAYCANVAS

image

Also, while playing with DiffuseDetailMap, I found … DiffuseMapRotation, and now I feel stupid, this answers one of my previous questions :stuck_out_tongue:

the DiffuseMapRotation is pretty recent thing I believe, and I suspect it wasn’t there when you asked :slight_smile:

When you have a transparent / white or whatever you need border, and turn off mipmaps on those textures, you should not have any leaking pixels. But if you have mipmaps, the story is more complicated, as mipmaps are created by averaging pixels and your edges are no longer full transparent.

You could likely fix it up by modifying mimap data directly (if not compressed), or perhaps you could write a shader (chunk) which tests if u or v coordinate is outside of 0…1 range and simply return fully transparent pixel.

But perhaps not using mipmaps is acceptable simple solution?
Limiting distance as you currently do is tricky … as it might work on some devices, but a distance would need to be different on lower DPI devices, as mipmaps will kick in a lot sooner.

1 Like

I’ll disable the mipmaps, for a product configurator the distance to the object is always more or less the same :slight_smile:
Thanks for the help guys !
A V1 of my project should come out soon :ok_hand:

3 Likes

Hi !

Any way of changing the pivot point of the diffuseMapRotation setting? :stuck_out_tongue:
If I’m correct, it looks like the pivot is the upper left corner.


playcanvas

@slimbuck Do you know much about the UV rotate on materials?

1 Like

You can do a manual rotation of the UVs, the bellow function takes in a center(Vec2) of rotation, an amount of rotation(float), the mesh(mesh) you want to translate the uvs of and the UV channel(int)

You will have to do some translation of the rotation from radians to degrees or what ever you want to use as rotator, but this should get you started on doing it manually.

RotateUv.prototype.rotateUV = function(center, rotation, mesh, channel){
    uvs = [];
    mesh.getUvs(channel, uvs);
    
    for(var i = 0; i < uvs.length; i += 2){
        uvs[i] -= center.x;
        uvs[i+1] -= center.y;
        
        var x = uvs[i];
        var y = uvs[i+1];
        
        uvs[i] = x * Math.cos(rotation) - y * Math.sin(rotation);
        uvs[i+1] = x * Math.sin(rotation) + y * Math.cos(rotation);
    
        uvs[i] += center.x;
        uvs[i+1] += center.y;
    }
    
    
    mesh.setUvs(channel, uvs);
    mesh.update();

};

Rotation

Example:
https://playcanvas.com/project/842212/overview/rotation

3 Likes

Oooh thats looks perfect, will look at it ASAP :slight_smile: Thanks !

1 Like