4

I've been searching the web for a while now and did not find the correct answer yet. I found the list of uniform types THREE.js uses, and I think the following code should be correct. At the last line I define an uniform array of Vector2.

uniforms: {
    "center":   { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) },
    "aspectRatio": { type: "f", value: null },
    "radius": { type: "f", value: 0.1 },
    "pointList":  { type: "v2v", value: [] },
},

In my js script I pass this array as follows. This should work too, I guess:

// Add effects
effect = new THREE.ShaderPass( THREE.MetaBalls2D );
effect.renderToScreen = true;
effect.uniforms[ 'aspectRatio' ].value = window.innerWidth/window.innerHeight;
effect.uniforms[ 'pointList' ].value = pointList //is an array of THREE.Vector2;
composer.addPass( effect );

My question now is, how do I access this uniform variable (pointList in this case) from the fragmentshader?

2 Answers 2

8

You should know what is the max size that your array should be, so say you have an array:

var myVec2Array = [
    new THREE.Vector2(),
    new THREE.Vector2(),
    new THREE.Vector2(),
    ...
]

you can do something along these lines, when you initialize a shader:

var myShader = new THREE.ShaderMaterial({
    uniforms:{
        _myVec2UniformArray:{
            type:'v2v',
            value:myVec2Array
        }
    },
    vertexShader: 
        '#define ARRAYMAX '+ myVec2Array.length +'\n' + myVertexShader
}

In myVertexShader you would init:

uniform vec2 _myVec2UniformArray[ARRAYMAX];

You don't have to populate the array, but you can expose ARRAYMAX in js, and use it to manage the array on both ends.

Sign up to request clarification or add additional context in comments.

3 Comments

question @pailhead - with this setup, would it be possible to send an updated _myVec2UniformArray uniform with a different size array? Would it work as long as that new array size is less than the ARRAYMAX?
i think glsl wont let you resize and array, not sure exactly what the impact of this is, but you can pass another uniform and break before hitting MAX_whatever?
Thanks a lot. That tricks save me ! Just a question, could you initialize an array with define ? Like that: #define array '+ myVec2Array +'\n' + myVertexShader ?
2

I would initialise it with some vectors just in case:

"pointList":  { type: "v2v", value: [ new THREE.Vector2(), new THREE.Vector2() ] },

I think this is what you need to add to your shader:

uniform vec2 pointList[2];

Also, if you want to avoid Vector2s you can use 2fv as uniform type:

"pointList":  { type: "2fv", value: [ 1, 0,  0, 1 ] }

3 Comments

Thank you @mrdoob for the answer. So, if I understand it correctly, you only can initialize the array if you know the size upfront? Could you pass the number of points via an int and initialize it like this: uniform vec2 pointList[size];? Because that would be what I need. I want to pass the size from javascript to my shader.
I think you could do something like "#define maxv2s 10\n" + yourGlslShader; and then uniform vec2 myv2array[maxv2s] this way you could define this shader from js. You can't dynamically scale the array, I think.
2fv seems pretty interesting, i didn't know about it before!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.