You need an additional buffer attribute for storing original colors of instances.
var instanceColorsBase = new Float32Array(instanceColors.length);
instanceColorsBase.set(instanceColors);
geometry.setAttribute( 'instanceColor', new THREE.InstancedBufferAttribute( new Float32Array( instanceColors ), 3 ) );
geometry.setAttribute( 'instanceColorBase', new THREE.BufferAttribute(new Float32Array( instanceColorsBase ), 3 ) );
instanceColorBase
is the attribute you restore instanceColor
from.
Also you need to remember instanceId
of previous raycast, so it’s prevInstanceId
.
And a color of highlighting: var highlightColor = new THREE.Color("yellow");
Then, when you check intersection:
if (instanceId != prevInstanceId) {
setInstanceColor(instanceId, true);
setInstanceColor(prevInstanceId, false);
prevInstanceId = instanceId;
}
Where setInstanceColor()
is:
function setInstanceColor(instanceId, isHighlighting){
if (instanceId == -1) return;
mesh.geometry.attributes.instanceColor.setXYZ(
instanceId,
isHighlighting ? highlightColor.r : mesh.geometry.attributes.instanceColorBase.getX(instanceId),
isHighlighting ? highlightColor.g : mesh.geometry.attributes.instanceColorBase.getY(instanceId),
isHighlighting ? highlightColor.b : mesh.geometry.attributes.instanceColorBase.getZ(instanceId)
);
mesh.geometry.attributes.instanceColor.needsUpdate = true;
}
Means, when isHighlighting
is true
, then we get the color data of highlightColor
, otherwise, we restore it from the instanceColorBase
attribute.
Made it from the scratch at midnight, so this solution can be optimized and improved