Why setColorAt in InstancedMesh not working?

I have a plane made of >10k squares and I want only the individual squares to change color that I hover my mouse above after click. But setColorAt isnt working.

let plane
let intersects
let color = new THREE.Color();

const geometry = new THREE.BoxGeometry(1, 1, .1);


//using instance method
function createInstancePlane(){
  const material = new THREE.MeshBasicMaterial({
    color: 0xffff00,
    transparent: true,
    opacity: 1,
  });
  plane = new THREE.InstancedMesh(geometry, material, 11856);
  scene.add(plane);

  //dummy
  const dummy = new THREE.Object3D();

  let mm = 0;

  for (let i = 0; i < 152; i++) {
    for (let j = 0; j < 78; j++) {
      dummy.position.x = i - 76;
      dummy.position.y = j - 39;
      dummy.position.z = 0;

      dummy.updateMatrix();
      plane.setMatrixAt(mm, dummy.matrix);
      mm++;
    }
  }
}
createInstancePlane()
console.log(plane)

//RAYCASTER
const rayCaster = new THREE.Raycaster();

let mouse = new Vector2();
window.addEventListener("mousemove", (e) => {
  mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
});


let funcWhileMouseMove = () => {
  rayCaster.setFromCamera(mouse, camera);
  intersects = rayCaster.intersectObject(plane);
  for (let obj of intersects) {
    console.log(obj.instanceId)
    plane.setColorAt(obj.instanceId, color.set(0xff0000)); //THIS NOT WORKING
    plane.instanceColor.needsUpdate = true;
  }
};

//TICK FUNCTION
function tick() {
  stats.begin();

  //RAYCASTER obj test
  window.addEventListener("mouseup", () => {
    window.removeEventListener("mousemove", funcWhileMouseMove);
    setTimeout(() => {
      plane.material.color.set("pink");
    }, 1000);

  });

  window.addEventListener("mousedown", () => {
    window.addEventListener("mousemove", funcWhileMouseMove);
  });
  stats.end();

  window.requestAnimationFrame(tick);
}
tick();

I get the desired plane made of >10k squares and when I click and move mouse I get instanceId too, but color stays the same.

The color attribute for an instanced mesh is created when you first use setColorAt(), it’s not created by default like instance matrix.

Make sure you call setColorAt at least once before rendering for the first time, if you do it after, the color attribute will be missing and the call will not have any effect.

how to do that?

plane = new THREE.InstancedMesh(geometry, material, 11856);
plane.setColorAt(0, new THREE.Color()); // add this line
2 Likes

thanks man, it works