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:
mrdoob:dev
← sunag:dev-array-2
opened 01:02AM - 23 Jan 25 UTC
Closes https://github.com/mrdoob/three.js/issues/30097
**Description**
The… implementation has two types of declarations `array( [ ...nodes ] )` and `array( 'type', count )`. Both are compatible with `.toConst()` and `.toVar()` and have been updated in parse. `TempNode` has also been updated to automatically generate cache if `.toVar()` is not used.
```js
// style 1 - constants
const a = array( [ vec3(), vec3() ] );
// style 1 - runtime values
const b = array( [ uniform( 1 ), a.element( 0 ).x ] );
// style 2 - constants
const c = array( 'vec3', 2 );
// style 3 - constants / runtime values
const d = vec3( 0, 0, 1 ).toArray( 2 ); // the result will be: [ vec3( 0, 0, 1 ), vec3( 0, 0, 1 ) ]
// .toVar() and assigns
const e = array( [ vec3(), vec3() ] ).toVar();
e.element( 0 ).assign( vec3() );
// .toConst()
const f = array( [ vec3(), vec3() ] ).toConst();
const v = f.element( 0 );
```
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
Oxyn
January 23, 2025, 9:09am
4
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 ) );
It seems you have not saved your modifications of the fiddle.
Mugen87
January 24, 2025, 2:48pm
11
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