Assign different colors to different parts of BufferGeometry

Hello I have a BufferGeometry created using a set of vertices.
https://jsfiddle.net/eg4bhym5/2/

I want to add black color which repeats itself after certain distance. Something like this.
image

And I want to change colors rather than adding any textures as I want to add different colors. Can someone help?

Hi!
Creativity is up to you :slight_smile:
You can use a buffer attribute with colors for vertices and then use .vertexColors: THREE.VertexColors of your material.
You can use shaders to change colors along any of uv coordinates to have such stripes.

1 Like

There is also an example that demonstrates how to generate the geometry data for using vertex colors: https://threejs.org/examples/webgl_geometry_colors

2 Likes

Is that how you want it?

I got how to do it but I cannot get around a sharp change of colors though.
image

And what did you do to get this result?
Could you provide a live code example?

As sharp color transitions are needed, vertex color are not suitable IMHO.

A simpe two pixel texture with THREE.NearestFilter and THREE.RepeatWrapping is best.

Another possibility is to use mesh groups.

Why not? It works with non-indexed buffer geometry.

Because the triangles between two neighbour vertices of different colors will always be interpolated between red and white.

Sure :slight_smile:

But if you have a triangle soup (non-indexed buffer geometry), you can set the same color of vertices of triangles. One triangle is red, another one is white and so on. No interpolation.

We just don’t know how things organized in OP’s code.
All we can do is just fortune telling :slight_smile:

2 Likes

You’re right, I retract from what I said.

I still don’t know exactly what @Vimal_Rathod wants to achieve. But since its fiddle is forked by my example, you can easily add it.

The lines for the groups are only commented out in fiddle and have to be designed like this.

for ( var f = 0, p = 0; f < faceCount; f ++, p += 6) {
	
	g.addGroup( p, 6, f % 8 );
	
}

Then use multi material:

var material = [

	new THREE.MeshBasicMaterial( { color: 0x000000, side: THREE.DoubleSide} ),
	new THREE.MeshBasicMaterial( { color: 0xff0000, side: THREE.DoubleSide} ),
	new THREE.MeshBasicMaterial( { color: 0xffffff, side: THREE.DoubleSide} ),
	new THREE.MeshBasicMaterial( { color: 0x00ffff, side: THREE.DoubleSide} ),
	new THREE.MeshBasicMaterial( { color: 0x00ff00, side: THREE.DoubleSide} ),
	new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide} ),
	new THREE.MeshBasicMaterial( { color: 0x0000ff, side: THREE.DoubleSide} ),
	new THREE.MeshBasicMaterial( { color: 0xff00ff, side: THREE.DoubleSide} )
	
];

in function animate:

g.groups[ getRandomInt( faceCount - 1 ) ].materialIndex = getRandomInt( 7 );

g.groupsNeedUpdate = true; // to change materialIndex for multi material

You get what you see above in the short video. :slightly_smiling_face:


Watch now live in the collection: http://discourse.threejs.hofk.de/2019/ColorStripeChanging/ColorStripeChanging.html

20190321-1744-24511
Instead of a discussion post on vertexColors a simple example. http://discourse.threejs.hofk.de/2019/ColorStripeChanging2/ColorStripeChanging2.html

It is based on my basic example of BufferGeometry. http://discourse.threejs.hofk.de/2017/BufferGeometry/BufferGeometry.html


The whole code.

<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/assign-different-colors-to-different-parts-of-buffergeometry/6604/12 -->
<head>
	<title> ColorStripeChanging2 </title>
	<meta charset="utf-8" />
	<style>	body { margin: 0;} </style>
</head>
<body> 	
  <button type="button" id="newcolors"> new colors </button> 
</body>
<script src="../js/three.min.102.js"></script>
<script src="../js/OrbitControls.js"></script>

<script>

// @author hofk

document.getElementById( "newcolors" ).onclick = newcolors;

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.set( 5, -18, 30 );
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x111111, 1 );	
var container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement ); 
var controls = new THREE.OrbitControls( camera, renderer.domElement );

var clock = new THREE.Clock( );

var stripCount = 24;

var stripWidth = 1;
var stripHeight = 12;
var centerX = stripCount * stripWidth / 2;
var centerY = stripHeight / 2;

var faceCount = stripCount * 2;

// use THREE.VertexColors
var material = new THREE.MeshBasicMaterial( { side: THREE.DoubleSide,  vertexColors: THREE.VertexColors, wireframe: false } );

var g = new THREE.BufferGeometry( ); // non indexed BufferGeometry

g.positions = new Float32Array( faceCount * 9 ); // 'triangle soup'
g.addAttribute( 'position', new THREE.BufferAttribute( g.positions, 3 ) );
g.colors = new Float32Array( faceCount * 9 );
g.addAttribute( 'color', new THREE.BufferAttribute( g.colors, 3 ) );

for ( var i = 0, j = 0; i < stripCount; i ++, j += 18 ) { 

	// left face
		
	g.positions[ j ]     = i * stripWidth - centerX;
	g.positions[ j + 1 ] = 0 - centerY;
	g.positions[ j + 2 ] = 8 * Math.sin(  Math.PI * i / 25 );
	
	g.positions[ j + 3 ] = ( i + 1 ) * stripWidth - centerX;
	g.positions[ j + 4 ] = stripHeight - centerY;
	g.positions[ j + 5 ] = 8 * Math.sin(  Math.PI * ( i + 1 ) / 25 );
	
	g.positions[ j + 6 ] = i * stripWidth - centerX;
	g.positions[ j + 7 ] = stripHeight - centerY;
	g.positions[ j + 8 ] = 8 * Math.sin(  Math.PI * i / 25 );
	
	// right face
	
	g.positions[ j +  9 ] = i * stripWidth - centerX;
	g.positions[ j + 10 ] = 0 - centerY;
	g.positions[ j + 11 ] = 8 * Math.sin(  Math.PI * i / 25 );
						   
	g.positions[ j + 12 ] = ( i + 1 ) * stripWidth - centerX;
	g.positions[ j + 13 ] = 0 - centerY;
	g.positions[ j + 14 ] = 8 * Math.sin(  Math.PI * ( i + 1 ) / 25 );
						   
	g.positions[ j + 15 ] = ( i + 1 ) * stripWidth - centerX;
	g.positions[ j + 16 ] = stripHeight - centerY;
	g.positions[ j + 17 ] = 8 * Math.sin(  Math.PI * ( i + 1 ) / 25 );
	
}

var mesh = new THREE.Mesh( g, material );
scene.add( mesh );

var t1 = 0;
var t2;

var c8;
var c = [];

newcolors( );

animate();

//..................................

function animate() {
	
	t2 = clock.getElapsedTime ( ); 

	requestAnimationFrame( animate );	
	renderer.render( scene, camera );
	
	if ( t2 - t1 > 0.4 ) {
		
		for ( var i = 0, j = 0; i < stripCount; i ++, j += 18 ) {
			
			c8 = getRandomInt( 7 ) * 3;
			
			for ( k = 0; k < 18; k ++ ) {   // apply color
				
				g.colors[ j + k ] = c[ k % 3 + c8 ];
				
			}

		}
		
		t1 = t2;
		
	}
	
	g.attributes.color.needsUpdate = true;
		
	controls.update();
	
}

function getRandomInt( max ) {

  return Math.floor( Math.random( ) * Math.floor( max ) );
  
}

function newcolors( ) {
	
	c = [];

	for ( var i = 0; i < 8; i ++  ) {  // random colors
	
		c.push( Math.random( ), Math.random( ), Math.random( ) );
		
	}
	
}

</script>

</html>
2 Likes

Really thanks for the info @hofk and others. I got how to do that using your example thanks to that.