BK52
BK52

Reputation: 934

Three.js - BufferGeometry - Change color of every line

In this example, all lines are drawn with same color. I try to change color of every line. I made these changes.

Define attribute

  const colors = new Float32Array(MAX_POINTS * 3);
  geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));

Change material

const material = new THREE.LineBasicMaterial({ vertexColors: true });

In the update function change colors

   ...
for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) {
    UpdateColor();
    colors[Cindex++] = rgb[0];
    colors[Cindex++] = rgb[1];
    colors[Cindex++] = rgb[2];
    
    positions[ index ++ ] = x;
    positions[ index ++ ] = y;
    positions[ index ++ ] = z;

    x += ( Math.random() - 0.5 ) * 30;
    y += ( Math.random() - 0.5 ) * 30;
    z += ( Math.random() - 0.5 ) * 30;
}

In animate() added this line.

 line.geometry.attributes.color.needsUpdate = true;

My changes is here.

Only a few line changes color. It is not working what i want. How can i do this?

Upvotes: 2

Views: 1344

Answers (1)

prisoner849
prisoner849

Reputation: 17596

Use LineSegments with a non-indexed buffer geometry, and vertexColors: true in the material:

body{
  overflow: hidden;
  margin: 0;
}
<script type="module">
import * as THREE from 'https://cdn.skypack.dev/[email protected]';

let renderer, scene, camera;

let line;
const MAX_POINTS = 500;
let drawCount;
let prevPoint = new THREE.Vector3();
let currPoint = new THREE.Vector3();
let color = new THREE.Color();

init();
animate();

function init() {

    // info
    const info = document.createElement( 'div' );
    info.style.position = 'absolute';
    info.style.top = '30px';
    info.style.width = '100%';
    info.style.textAlign = 'center';
    info.style.color = '#fff';
    info.style.fontWeight = 'bold';
    info.style.backgroundColor = 'transparent';
    info.style.zIndex = '1';
    info.style.fontFamily = 'Monospace';
    info.innerHTML = "three.js animataed LineSegments using non-indexed BufferGeometry";
    document.body.appendChild( info );

    // renderer
    renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
  //renderer.setClearColor( 0x7f7f7f);
    document.body.appendChild( renderer.domElement );

    // scene
    scene = new THREE.Scene();

    // camera
    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.set( 0, 0, 1000 );

    // geometry
    const geometry = new THREE.BufferGeometry();

    // attributes
    const positions = new Float32Array( MAX_POINTS * 3 * 2); // 3 vertices per point
    geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
  const colors = new Float32Array( MAX_POINTS * 3 * 2);
  geometry.setAttribute( 'color', new THREE.BufferAttribute( colors, 3) );

    // drawcalls
    drawCount = 2; // draw the first 2 points, only
    geometry.setDrawRange( 0, drawCount );

    // material
    const material = new THREE.LineBasicMaterial( { vertexColors: true } );

    // line
    line = new THREE.LineSegments( geometry,  material );
    scene.add( line );

    // update positions
    updatePositions();

}

// update positions
function updatePositions() {

    const positions = line.geometry.attributes.position;
  const colors = line.geometry.attributes.color;

    let x, y, z;
    prevPoint.set(0, 0, 0);
  currPoint.set(0, 0, 0);

    for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) {
        
    positions.setXYZ(i * 2, prevPoint.x, prevPoint.y, prevPoint.z);
        currPoint.random().subScalar(0.5).multiplyScalar(30).add(prevPoint);
    positions.setXYZ((i * 2) + 1, currPoint.x, currPoint.y, currPoint.z);
    prevPoint.copy(currPoint);
    
    color.set(Math.random() * 0xffffff);
    colors.setXYZ(i * 2, color.r, color.g, color.b);
    colors.setXYZ(i * 2 + 1, color.r, color.g, color.b);

    }
  
  positions.needsUpdate = true;
  colors.needsUpdate = true;

}

// render
function render() {

    renderer.render( scene, camera );

}

// animate
function animate() {

    requestAnimationFrame( animate );

    drawCount = ( drawCount + 2 ) % (MAX_POINTS * 2);

    line.geometry.setDrawRange( 0, drawCount );

    if ( drawCount === 0 ) {

        // periodically, generate new data

        updatePositions();


    }

    render();

}

</script>

Upvotes: 2

Related Questions