How to change texture/color per object instance in InstancedMesh

Hello,
Please forgive my noobness, i am somewhat new to all this…

Using latest r111 InstancedMesh, referencing the example webgl_instancing_raycast
in the example, i have simply replaced the below:

	var geometry = new THREE.BoxBufferGeometry( .5, .5, .5, 1, 1, 1 );
	var material = new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'textures/square-outline-textured.png' ) } );

which now draws cubes with the given texture…
my dilemma is: how to control color / texture of individual instances?! i am hoping this new InstancedMesh class makes this easy somehow? :see_no_evil:

Instancing is a more advanced approach recently being easier to start with with InstancedMesh, to add any more individual attributes you need to add a InstancedBufferAttribute to the geometry which instead controlling the attributes of a vertex, will be the attribute per instance, for example a individual color per instance.

For textures this requires more work depending on your case, if you have many different textures you would have to pack them into a texture atlas or texture array, replacing the line in the code sampling from the texture.

Anyway for more individual control you have to patch the material with a onBeforeCompile callback or you might take a look at this plugin i made to make patching easier.

1 Like

@Fyrestar
Can I use instanced buffer attributes with THREE.InstancedMesh()?
I thought it relates to THREE.InstancedBufferGeometry().
But if so, would be cool to see any example with instanced attributes and instanced mesh.

2 Likes

@Hayawen here’s an example coloring each sphere individually using THREE.InstancedMesh and the plugin to patch the material to use the new attribute. (scroll to the bottom of the code)

It works without being based on THREE.InstancedBufferGeometry

3 Likes

This new example shows how you can enhance InstancedMesh with additional instanced attributes:

https://raw.githack.com/mrdoob/three.js/dev/examples/webgl_instancing_scatter.html

4 Likes

Ok, this works very nicely for color…

But texture seems much more complicated… especially if each side of box has different texture too! :scream:

1 Like

Since then, using of THREE.InstancedMesh() seems even more semantically correct :slight_smile:
Cool to see such hybrid examples.
@Fyrestar @Mugen87 Thanks! :+1:

1 Like

Not really, you just need to have 6 values per instance and store some ID in a regular attribute buffer to identify the side.

1 Like

“store some ID in a regular attribute buffer to identify the side”

i’m not sure i understand this part…!

Since you want to have 6 different textures on every instance, you have 6 values you store the texture index for each side, but in the shader you need to know which side it is in, which of those 6 values you will use to pick the texture from the texture atlas or array.

So you need to have an id attribute storing a side index for every 2 faces vertices of a side. You might have thought it is similar to a regular cube, using a different material for every side, but for instancing you need to use one shader. Since you said you’re new to all this it might be better to study more examples first as this is a little too complicated for beginners.

1 Like

Hmm, ok, how about this… if InstancedMesh is given an array of 6 materials instead of just 1 material, the cube will display each texture on 1 face accordingly…
i am wondering can this be used somehow to know which face is being painted in the call? is it possible to know maybe which material it’s using and override based on that?

Ok this gives me an idea after having posted this… i can probably do this giving each material a special onBeforeCompile! ^^ gonna try that!

1 Like

If you want every cube have a different combination of textures on the sides it needs to be done per-instance.

ok, i think my only problem now is that i don’t know which part of the fragementShader exactly to replace with the code to apply my specific texture:

gl_FragColor = texture2D(textures[0], vUv );

i tried to replace #include <map_fragment> part, but that didn’t go too well :smiley:

ok, here’s what i’ve managed to do so far…
the codepen below should display 6 different textures on each side of the cubes… but only for ONE side i am overriding the onBeforeUpdate function…
However, i am getting a very weird problem where only the 1st texture i replace works ok, 2nd and 3rd seem to always overlap with original?!

2 Likes

that’s interesting… I just ran the code above on my android phone and it works ok! just messes up on desktop Chrome!
any ideas? :smile:

If anybody runs into this overlapping texture issue in the future, I was able to solve it here:

1 Like