Three.js InstancedMesh Custom Color Attribute
This article explains how to structure and apply a custom attribute
array to assign individual colors to instances within a Three.js
InstancedMesh. You will learn how to define a flat
Float32Array containing RGB values, wrap it in an
InstancedBufferAttribute, attach it to your geometry, and
configure your material to display these custom colors efficiently.
The Structure of the Color Array
To color individual instances, you must create a flat array of floating-point numbers. Since colors are typically represented by Red, Green, and Blue (RGB) channels, your array must have a size equal to the number of instances multiplied by 3.
const count = 1000; // Number of instances
const colorArray = new Float32Array(count * 3);For each instance i (from 0 to
count - 1), you fill the array with normalized RGB values
(ranging from 0.0 to 1.0):
- Red component at index
i * 3 - Green component at index
i * 3 + 1 - Blue component at index
i * 3 + 2
Implementation Step-by-Step
1. Define the Geometry and Material
Create your base geometry and a material. To tell the material to use
the colors defined in your attribute array, you must set the
vertexColors property to true.
import * as THREE from 'three';
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({
vertexColors: true
});2. Populate the Color Array
Loop through your total instance count to assign a color to each instance. In this example, we generate random colors:
const count = 500;
const colorArray = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const randomColor = new THREE.Color(Math.random(), Math.random(), Math.random());
colorArray[i * 3] = randomColor.r; // R
colorArray[i * 3 + 1] = randomColor.g; // G
colorArray[i * 3 + 2] = randomColor.b; // B
}3. Create the InstancedBufferAttribute
Wrap your raw Float32Array in a
THREE.InstancedBufferAttribute. The second argument is
3, which tells Three.js that each instance requires three
values (R, G, and B) from the array.
const colorAttribute = new THREE.InstancedBufferAttribute(colorArray, 3);4. Attach the Attribute to Geometry
Attach your color attribute to your geometry using the key name
'color'. This name is recognized by Three.js built-in
materials.
geometry.setAttribute('color', colorAttribute);5. Create the InstancedMesh
Finally, instantiate your InstancedMesh using the
modified geometry and material.
const instancedMesh = new THREE.InstancedMesh(geometry, material, count);
scene.add(instancedMesh);Updating Colors Dynamically
If you need to update the colors after rendering has started, modify
the values in the original Float32Array or access the
attribute’s array directly, and set the attribute’s
needsUpdate flag to true:
// Modify the color of the first instance to pure red
colorAttribute.setXYZ(0, 1.0, 0.0, 0.0);
// Notify Three.js to upload the new data to the GPU
colorAttribute.needsUpdate = true;