Threejs: assign different colors to each vertex in a geometry

36,634

Solution 1

It has to be geometry.vertexColors instead of geometry.colors (push a colour per vertex).

And the material:

material = new THREE.MeshBasicMaterial({ vertexColors: THREE.VertexColors });

Solution 2

I'm using version 71. Lee's answer probably still works, but seemed very convoluted.

Here's the simplest example I could do of making a Mesh with individual colors assigned to each vertex:

var geometry = new THREE.Geometry();

// Make the simplest shape possible: a triangle.
geometry.vertices.push(
    new THREE.Vector3(-10,  10, 0),
    new THREE.Vector3(-10, -10, 0),
    new THREE.Vector3( 10, -10, 0)
);

// Note that I'm assigning the face to a variable
// I'm not just shoving it into the geometry.
var face = new THREE.Face3(0, 1, 2);

// Assign the colors to the vertices of the face.
face.vertexColors[0] = new THREE.Color(0xff0000); // red
face.vertexColors[1] = new THREE.Color(0x00ff00); // green
face.vertexColors[2] = new THREE.Color(0x0000ff); // blue

// Now the face gets added to the geometry.
geometry.faces.push(face);

// Using this material is important.
var material = new THREE.MeshBasicMaterial({vertexColors: THREE.VertexColors});

var mesh = new THREE.Mesh(geometry, material);

Hopefully this answer is less terrifying looking.

It kind of sucks that the colors are assigned to the vertices of the face instead of the vertices of the geometry, as this means you'll have to set them repeatedly. Personally, I'm just going to have a layer on top of Three.js so that I can assign colors to geometry instead.

Solution 3

This code should work for three.js v49, creating an RGB color cube.

(Related to How to change face color in Three.js)

// this material causes a mesh to use colors assigned to vertices
var vertexColorMaterial = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors } );

var color, point, face, numberOfSides, vertexIndex;

// faces are indexed using characters
var faceIndices = [ 'a', 'b', 'c', 'd' ];

var size = 100;
var cubeGeometry = new THREE.CubeGeometry( size, size, size );

// first, assign colors to vertices as desired
for ( var i = 0; i < cubeGeometry.vertices.length; i++ ) 
{
    point = cubeGeometry.vertices[ i ];
    color = new THREE.Color( 0xffffff );
    color.setRGB( 0.5 + point.x / size, 0.5 + point.y / size, 0.5 + point.z / size );
    cubeGeometry.colors[i] = color; // use this array for convenience
}

// copy the colors to corresponding positions 
//     in each face's vertexColors array.
for ( var i = 0; i < cubeGeometry.faces.length; i++ ) 
{
    face = cubeGeometry.faces[ i ];
    numberOfSides = ( face instanceof THREE.Face3 ) ? 3 : 4;
    for( var j = 0; j < numberOfSides; j++ ) 
    {
        vertexIndex = face[ faceIndices[ j ] ];
        face.vertexColors[ j ] = cubeGeometry.colors[ vertexIndex ];
    }
}

cube = new THREE.Mesh( cubeGeometry, vertexColorMaterial );
Share:
36,634
Stefan Ramson
Author by

Stefan Ramson

PhD student at software architecture group. Doing research on programming language design, declarative programming and interactive programming. Designs board and video games.

Updated on July 09, 2022

Comments

  • Stefan Ramson
    Stefan Ramson almost 2 years

    I want to do picking via IdMapping in Three.js

    Because of performance issues I only have one huge geometry, computed like this:

    for (var i = 0; i < numberOfVertices; i += 9) {
      p1  = new THREE.Vector3(graphData.triangles.vertices[i+0], graphData.triangles.vertices[i+1], graphData.triangles.vertices[i+2]);
      p2  = new THREE.Vector3(graphData.triangles.vertices[i+3], graphData.triangles.vertices[i+4], graphData.triangles.vertices[i+5]);
      p3  = new THREE.Vector3(graphData.triangles.vertices[i+6], graphData.triangles.vertices[i+7], graphData.triangles.vertices[i+8]);
      geometry.vertices.push(new THREE.Vertex( p1.clone() ));
      geometry.vertices.push(new THREE.Vertex( p2.clone() ));
      geometry.vertices.push(new THREE.Vertex( p3.clone() ));
      geometry.faces.push( new THREE.Face3( i/3, i/3+1, i/3+2 ) );
    
      // i want to do something like this:
      geometry.colors.push(new THREE.Color(0xFF0000));
      geometry.colors.push(new THREE.Color(0xFF0000));
      geometry.colors.push(new THREE.Color(0xFF0000)); 
    }
    
    geometry.computeFaceNormals();
    var material = new THREE.MeshBasicMaterial({});
    
    var triangles = new THREE.Mesh( geometry, material );
    scene.add(triangles);
    

    How can I assign different colors to each vertex in my geometry?

  • Stefan Ramson
    Stefan Ramson about 12 years
    At least for me I could only set .vertexColors on the faces of my geometry, like geometry.faces[0].vertexColors[0] = ..
  • sole
    sole about 12 years
    It might have changed in the latest version of three. Which revision are you using?
  • Stefan Ramson
    Stefan Ramson about 12 years
    i use the ?current? Version r49
  • Stemkoski
    Stemkoski almost 12 years
    for which version of three.js does the code from this answer work?
  • sole
    sole over 11 years
    Lee Stemkoski, it was for the current version at that time. Not sure which one it was, just check the change log? :-)
  • Peter Ehrlich
    Peter Ehrlich about 10 years
    Note that geometry.colorsNeedUpdate = true is necessary if changing an existing geometry.
  • MrTrustworthy
    MrTrustworthy over 8 years
    That's the only working way for Three.js r73 I could find on stackoverflow. One note though: You can also prepare an array of 3 Colors beforehand and pass it to the Face3 constructor as 5th argument instead of assigning the face.vertexColors[x] directly.
  • Sphinxxx
    Sphinxxx almost 8 years
    @MrTrustworthy - A third option is to assign that array after you create the face: face.vertexColors = [new THREE.Color(0xff0000), new THREE.Color(0x00ff00), new THREE.Color(0x0000ff)];