Passing array to TSL function

Hello everyone, very excited by TSL, but this problem is driving me crazy. Hopefully it’s a relatively simple solution.

I’m working from the procedural terrain TSL example.

But I want to generate terrain by passing an array to material.positionNode = Fn( () => {
Then at some point in there I will set position.y.addAssign( myArray.element(z*x) );

I’ve tried const myArray = uniform(getRndIntegerArray(100));
// where the function returns an array of ints, or an array of floats. Just to have dummy data

This gives Uncaught ReferenceError: myArray is not defined

Though there’s no issue if I, for example say const myNumber = uniform(1.0 );

What am I missing?

Thanks in advance

B

If you need a uniform array, use uniformArray(). E.g.

const tintColors = uniformArray( [
	new Color( 1, 0, 0 ),
	new Color( 0, 1, 0 ),
	new Color( 0, 0, 1 )
], 'color' );

If the array data are constants and don’t have to be uniforms, you have to wait until the following PR is merged:

2 Likes

Thank you very much for the fast reply @Mugen87

The array is just a way to pass the elevation (y-value) of a real-world map, which will be copied for each vertex in the terrain map. So they’re just regular Ints or Floats.

So, like this? var myArray = uniformArray([1,2,3], 'number');

I still get an endless Uncaught ReferenceError: myArray is not defined

I could well be mangling the declaration of myArray…

B

Here is the (simplified) code I’m using with success.

//regular JS array of numbers (float)
const currentMap = [ 0.1, 0.2, 0.3 ]; 

//no need to specify type
const cm = uniformArray( currentMap );

//node
const myNode = Fn(() => {

	//retrieve the value within a loop
	Loop( { type: 'int', start: int( 0 ), end: int( 3 ), condition: '<' }, ( { i } ) => {
		const elem = float( cm.element(i) );
	} );

})();

Thank you @Oxyn that was very helpful.

However, I must still be doing something wrong. I’ve updated my code but now I just get a blank screen. No errors. But no plane either.

Here’s what I’m doing, does anything jump out as an obvious rookey error?:

function tsl(){
	const myArray = getRndIntegerArray(10);
	const myNum = uniform(1.0);
	const uniform_array = uniformArray(myArray);
	const arraySize =  uniform(myArray.length);
  	const geometry =  new THREE.PlaneGeometry( 10, 10, 10, 10 );
	var material = new THREE.MeshStandardNodeMaterial( { color: 0xFF0000 } );
				
	material.positionNode = Fn( () => {
	var position = positionLocal.xyz.toVar();

	//retrieve the value within a loop
	Loop( { type: 'int', start: int( 0 ), end: int(arraySize), condition: '<=' }, ( { i } ) => {
		const v = float( uniform_array.element(i) );
		position.y.assign( v);
	} );
	
	return position;

} )();

If I console log the mesh.geometry.attributes.position I get:

Do you mind share a live example that shows what you are doing? three.js dev template - module - JSFiddle - Code Playground

In any event, if you have a height value per vertex, you would not use a loop to access the array values. Do it with vertexIndex.

position.y.assign( uniform_array.element( vertexIndex ) );

Thank you again @Mugen87.

Fiddle: three.js dev template - module - JSFiddle - Code Playground

I’ll try to get vertexIndex to work.
B

It seems you have not saved your modifications of the fiddle.

Apologies, now saved! three.js dev template - module - JSFiddle - Code Playground

If you want to apply a height per vertex, you can also use the following approach: three.js dev template - module - JSFiddle - Code Playground

The idea is to make use of bufferAttribute() and represent you height data as an additional buffer attribute.

3 Likes

Amazing! Such a clean solution. Thanks very much @Mugen87
B

1 Like