Hello everyone,
I recently faced the necessity of applying different tile (Repeat) to Texture(s) on the same MeshStandardMaterial.
Digging a bit it seems that there is no native support for this use-case in threejs so I decided to follow a DIY approach.
I would like to share what I created to help people in the same situation, and also to collect feedback on potential drawback of my approach, or suggestions for improvements.
Here the specific usecase I had to solve:
https://metaverso.info/demo/multi-tile/?editorMode=1&file=A.glb
(Click on the model to open material’s settings)
To make that model as lite as possible I decided to use a png with alpha as diffuse map (map) in order to create all the holes in the frame.
ThreeJs standard approach makes mandatory to also create 1:1 normal, metalness and roughness maps, making glb itself too heavy.
So i created a piece of code that modify the MeshStandardMaterial using the onBeforeCompile moethod. I did some tests and seems to perform correctly also with different combinations of maps:
Here some examples:
https://metaverso.info/demo/multi-tile/?editorMode=1&file=DamagedHelmet.glb
https://metaverso.info/demo/multi-tile/?editorMode=1&file=DamagedHelmet_NO_ALBEDO_NO_METALROUGH.glb
https://metaverso.info/demo/multi-tile/?editorMode=1&file=DamagedHelmet_NO_NORM.glb
This approach seems to be not invasive from a “code flow” point of view and allows the correct visualization of GLTF that uses the KHR_texture_transform extension (only for the scale, ofcourse).
There are some limitations:
- The tile value is bound to the Texture.repeat value, meaning that if 2 maps share the same texture they also share the tile (metalroughness in GLTF for example)
- No offset/rotation support
- Maybe some overhead for the shader.replace calls
- Supports only map, normalMap, metalnessMap, roughnessMap and emissiveMap (AO, LIGHTMAP, ALPHA still share vUv2 with 1:1 tile)
n) … ?
Here the link to the code:
https://metaverso.info/demo/multi-tile/CustomTiles.ts
Is written in typescript.
Example of Typescript usage:
import { addSupportForCustomTiles } from "path/to/CustomTiles.ts";
...
addSupportForCustomTiles(mesh.material);
Example of use with GLTFLoader:
gltfLoader.load(src, (gltf) => {
gltf.scene.traverse((obj) => {
if (obj instanceof Mesh){
addSupportForCustomTiles(mesh.material);
}
});
});
Looking forward for feedbacks, Thanks.
Cosimo