Hi, I am attempting to build a 3d product preview. The user is able to customize the appearance of the product using a web editor. This means that I must generate textures on the fly using canvas.
The texture on these products will cover most, if not all of the entire product surface (blankets, socks, mugs, phone cases etc.).
The user is able to customize both a background pattern and a foreground image.
The background pattern is created by the user by adding elements, changing their position, scaling them etc. (imagine a UI similar to Canva)
In the example below, the foreground image is the dog, the background pattern is the donut pattern in the back.
The foreground image behaves more like a large decal, where it’s placement can vary. However, I decided against Decal Geometry due to the possible stretching arising from projection. (I imagine that a decal wrapped around a mug, where the decal’s width is larger than the mug’s diameter will produce significant stretching).
Instead I decided in favor of layering two meshes on top of another, one for the background pattern and one for the foreground image.
This is where my concern arises: How do I deal with UV unwrapping?
Given a product with a complex 3d model, I can expect the UV unwrapping to generate a UV map with islands, warped segments etc.
However, the canvas I will generate will be a simple flat tile, oblivious to the UV map.
This will result in my background and foreground image being stretched and skewed, right?
How do I avoid this?
I’m not sure about the UV unwrapping, but for composing two images, a far better approach would be to (re)draw the foreground image on the desired position on an offscreen canvas copy of the background pattern, then paste the mixed image on the final, visible canvas and apply as texture to the mesh.
In other words:
create background image.
copy to offscreen background canvas.
create foreground image,
draw over the offscreen background canvas at the desired position.
copy the now mixed offscreen canvas to the visible canvas.
apply as texture to the mesh.
A high res canvas will make no artifacts and no aliasing (2k-4k)
Usually Three.js handles textures well, you might just have to experiment with position, scale and rotation in order to apply successfully the texture to your model, assuming the model doesn’t have any flaws.
I decided against having a single texture because that way I forgo the advantage of having a repeating background image.
I didn’t make this clear in my post above, but the background will be a repeating tile.
If I have two meshes, each with its own material and texture, I can set RepeatWrapping on the background texture and position the foreground texture in the right position using texture offset.
Have you tried to use multiple materials? It’s definitely feasible, although personally I haven’t tried to use the repeating function to just one of them, but I think it should work. Just search here for multiple materials, and on stackoverflow.
Also, with two meshes you might have z-buffer issues (artifacts) due to the very close proximity of the two.