I’m creating a game which is full of characters that are just a basic spheres. Each sphere has it’s own color, and a texture applied. Since there will be 100s of “characters” with around 20 textures that need to dynamically change, I wish to instance them.
How can this be accomplished, if possible? Would I need to create a separate instance for each texture?
Using mesh.setColorAt( i, color );
works for color, but is there an offset
option for the texture, or something similar?
Creating the characters as a separate object, I achieve this via offsetting the texture
// my object
this.face = Math.floor( Math.random( ) * 16 );
this.texture = textures['faces-atlas'].clone( ); // 2048x2048 texture atlas comprised of 512x512 textures (4x4)
this.texture.center.x = 0;
this.texture.center.y = 0;
this.texture.offset.x = 0.25 * ( this.face % 4 );
this.texture.offset.y = 0.25 * Math.floor( this.face/4 );
this.geometry = new THREE.SphereGeometry( this.size/2, 32, 16 );
this.material = new THREE.MeshToonMaterial( {
color: this.color,
map: this.texture,
gradientMap: this.toonTexture
} );
this.material.onBeforeCompile = ( shader ) => {
const custom_map_fragment = THREE.ShaderChunk.map_fragment.replace(
`diffuseColor *= sampledDiffuseColor;`,
`diffuseColor = vec4( mix( diffuse, sampledDiffuseColor.rgb, sampledDiffuseColor.a ), opacity );`
);
shader.fragmentShader = shader.fragmentShader.replace( '#include <map_fragment>', custom_map_fragment );
};
this.object = new THREE.Mesh( this.geometry, this.material ); // need this 'object' instanced & change each texture dynamically
The point of InstancedMeshes is to have duplicates of exactly the same material-geometry combinations - you cannot swap material parameters between the instances (InstancedMesh does allow for some customization in terms of color passed independently, but that won’t help much for textures.)
If that’s a viable option, you can create a texture atlas (ie. all character texture options bundled up into a single image), and then pass that as the texture for instanced meshes - but you’ll need a custom shader for that, so that you can pick specific subregion of that texture atlas based on gl_InstanceID.
3 Likes
Hi mjurczyk, thanks for the reply!
Yep I’m using a single image for all the textures, I got that far reading upon it, I just don’t know the method used of picking the specific subregion
You can use an instanced buffer attribute with an indices of texture chunks, or with pre-computed UVs per instance.
For example, I used the first approach (with texture chunk indices)
Demo:
JSFiddle
5 Likes
Hey prisoner, perfect thank you!
1 Like
Hi, thank you very much for this post which greatly helps !
Then, how do you update dynamically the index ? I’m brand new to shaders and InstancedMeshes and struggle with this…
thank you for your reply !
Thank you very much for this solution !
I struggle to have a different texture per face of each box… Do you know how to manage this ?
Instanced buffer attributes will help 
Demo: Log in - JSFiddle - Code Playground
4 Likes
Hi @prisoner849 ,
Fantastic ! You’re the best…
Thank you very much for your invaluable help, it saves my project !
Your working demo helps me understand better how textured shaders work, and it’s a must have to work with three.js
have a nice day and nice weekend !
1 Like
FYI: this link is not public
Ha, true. You have to be logged in. Funny 
I don’t know why JSFiddle behaves this way nowadays.
1 Like