How to access an `uniformArray` element using a `Node` object?

Hi there, everyone. :wave:
I’m quite new to Three.js and even more in TSL.

I just started developing a digital version of a famous board game to get some confidence in Three.js; I immediately started using WebGPU even though -from what I understand- it’s still considered “experimental” in order to build confidence in a future-proof tool.

That said… I was going to open this as a bug report but then I found a better way to handle this…
But the question remains, hoping it can be useful to someone else…

I was trying to implement a SpriteMap / TileMap component to be used as the main board in my game; this way I can have a single texture with all the tiles I need and I can compose it as needed, from time to time.
To do this, I imagined the following shaders…

// Vertex shader:
//
varying vec2 vUv;

void main() {
    vUv = uv;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// Fragment shader
//
uniform sampler2D map;

uniform vec2 tiles;
uniform vec2 indexes[TILES_COUNT];

varying vec2 vUv;

void main() {
    vec2 size = 1.0 / tiles;    
    vec2 tileIndex = floor(vUv / size);

    int index = int(tileIndex.y * tiles.x + tileIndex.x);
    vec2 offset = indexes[index];

    vec2 tileUv = mod(vUv, size) + (offset * size);

    gl_FragColor = texture2D(map, tileUv);
}

… so I tried to replicate it using TSL as follows:

const tiles = vec2(new Vector2(TILES_X, TILES_Y));
const size = div(1, tiles);

const indexes = uniformArray(new Array<Vector2>(TILES_COUNT));

for (const yIndex of range(TILES_Y))
{
    for (const xIndex of range(TILES_X))
    {
        const index = (yIndex * TILES_X) + xIndex;

        indexes.array[index] = new Vector2(0, 0);
    }
}

const colorNode = Fn((builder: WGSLNodeBuilder) =>
{
    const tileIndex = uv().div(size).floor();

    const index = tileIndex.y.mul(tiles.x).add(tileIndex.x);
    const offset = indexes.element(index.toInt());

    const tileUv = uv().mod(size)
        .add(offset.mul(size));

    return texture(map, tileUv);
});

… but indexes.element isn’t compatible with Node objects: it only accepts number values.

Is it a design choice not to support this kind of use of an uniformArray or it’s something that’s still missing?

Thanks. :upside_down_face:

.element() definitely supports node values.

Try colorNode = Fn( (…) => {…} )();

Mmmh… :thinking:
So it must be a typing problem… Is there a missing overloading definition?

src/game/components/board.ts:87:42 - error TS2345: Argument of type 'ShaderNodeObject<OperatorNode>' is not assignable to parameter of type 'number'.

87         const offset = indexes.element(index.toInt());
                                          ~~~~~~~~~~~~~

Have you tried adding the () to the end of your Fn() ?

Actually, it’s doesn’t matter at all in TypeScript.

In any case, yes…
And it works as intended.

myMaterial.colorNode = colorNode();

… but the TypeScript error is still there.

The typescript definitions need fixing. It should be any or number | Node as far as I can tell. The upstream Three.js project contains both uses of number and node parameters.

You might want to submit a PR to that project.
(I have never used type script).