Each instance can have its own matrix, and that matrix can represent (or be decomposed into) three things: position, rotation, and scale. Making some additions to the earlier example from Ducks in a row anyone?,
const count = 5;
const spacing = 5;
const mesh = new THREE.InstancedMesh( geometry, material, count );
const dummy = new THREE.Object3D();
for ( let i = 0; i < count; i++ ) {
for ( let j = 0; j < count; j++ ) {
dummy.position.set( i * spacing, j * spacing, 0 );
dummy.rotation.y = 2 * Math.PI * Math.random();
dummy.scale.multiplyScalar( Math.random() );
mesh.setMatrixAt( i * count + j, dummy.matrix );
}
}
mesh.instanceMatrix.needsUpdate = true;
scene.add( mesh );
In this case we are setting the position/rotation/scale of the dummy object for convenience, and then taking the matrix derived from those properties and assigning it to the instance.