Different textures from InstancedMesh

I’m trying to solve the problem of mapping different textures in InstancedMesh using a texture atlas by shifting uv. But for some reason I don’t have any image displayed. What is the problem? I have 1 row and 6 columns in my sprite. The pictures are 48x48 each.

const materials = new ShaderMaterial({
                    uniforms: {
                        textureAtlas: { value: imageLoader.load('sprite.png'), (texture) => {
                            texture.wrapS = RepeatWrapping;
                            texture.wrapT = RepeatWrapping;
                            texture.needsUpdate = true;
                        }) },
                        atlasSize: { value: new Vector2(6, 1) } 
                    },
                    vertexShader: `
                        attribute vec2 offset;
                        varying vec2 vUv;
                
                        void main() {
                            vUv = uv / atlasSize + offset / atlasSize;
                            gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);
                        }
                    `,
                    fragmentShader: `
                        uniform sampler2D textureAtlas;
                        varying vec2 vUv;
                
                        void main() {
                            gl_FragColor = texture2D(textureAtlas, vUv);
                        }
                    `,
                });
const mesh = new InstancedMesh(imageVO.geometry, materials, item.length);
                      const offsets = [];
                      for (let i = 0; i < item.length; i++) {
                        const col = i % 6; 
                        offsets.push(col / 6, 1);
                    }
                        const offsetAttribute = new InstancedBufferAttribute(new Float32Array(offsets), 1);
                        mesh.geometry.setAttribute('offset', offsetAttribute);
                    scene.add(mesh)

Maybe, the second parameter of InstancedBufferAttribute needs to be 2, instead of 1? :thinking:

Tried it, it doesn’t work

Any chance to provide a minimal live code working example, that demonstrates the issue? jsfiddle, codepen etc.

By the way, why is it 1 instead of 0 for the second coord in the offset?
And it seems you don’t need to divide col by 6, thus it will be simply offset.push(col, 0);

And in the vertex shader, vUv will be something like this:

vUv = (uv + offset) / atlasSize;

I wrote a small example, for you: Edit fiddle - JSFiddle - Code Playground

3 Likes

Okay, I’ll try it and let you know if it works. I don’t know if it’s forbidden by the forum rules, if not, send me a private message, if it’s forbidden, I’ll just answer you here.

It’s not :slight_smile:
Feel free to write here.

2 Likes

Nice! Work it! I have the following question. I tried to search for it now, but no luck. Can you tell me how to dynamically update positions and quaternion of objects in InstancedMesh?

There are several examples with InstancedMesh, have a look at their source code: three.js examples

Ok thanks. Another question. How do I delete a certain object in InstancedMesh?

Don’t hesitate to use forum’s search :slight_smile:
You can find the stuff you’re interested in.
For example: How to show and hide an instance in instance mesh