MeshStandardMaterial, per Texture Tiling

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:

  1. 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)
  2. No offset/rotation support
  3. Maybe some overhead for the shader.replace calls
  4. 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

1 Like