Shader Material - Uniform Object Array

Hi babyloniens,

I’m trying to use Uniform Object Array in a custom fragment shader, I made a playground to illustrate :

I want to render cliping planes with colors :

As you can see in the playground it works great with one plane. Now I want the same rendering with any number of planes.

Now when I switch the value of nbPlanesMax (line 20) to more than 2 it does not work anymore. I tried to debug with Spector and I can see the color is not correctly set :

I tried so many things :p, any lead would be great, what am I missing ?

expand out your loop maybe?

Im not really sure about your code or what its doing but you could do a loop over your shaderstring to essentually take this part:

for(int i = 0; i < nbColorPlanes; i++) {
        float distanceToPlane =  dot(, colorPlanes.planes[i] + colorPlanes.planes[i].plane.w;
        if(abs(distanceToPlane) < 0.1) {
            color = colorPlanes.planes[i].color;

and instead of doing the loop in the shader, make a look with regualar javascript and add multiple copies of that loop for the nbColorPlanes count.

so it would look like
for(int i=0; i < nbColorPlanes; i++){
shaderString +=
float distanceToPlane = dot(, colorPlanes.planes[int(${i})] + colorPlanes.planes[int(${i})].plane.w; if(abs(distanceToPlane) < 0.1) { color = colorPlanes.planes[int(${i})].color; } }

I did not really take the time to fix it up but that is the general idea. Stay away from dynamic loops in glsl.

You have to give the right parameters to addUniform:

1 Like

Hi @Pryme8 !

Do you mean I should recreate a Shader Material from a dynamic string each time the user create a new plane ? The playground I did was just to explain the problem but my use case is more complex (user could update the plane position for example) and I think it could be complicated to implement, but definitely doable I need to make some tests thanks for the idea !

Thank you so much @Evgeni_Popov !

So the problem was the line 109

uniformBuffer.addUniform('colorPlanes', 4, uniformArray.length / 4)

I don’t understand why 4 is the correct argument, can you explain ? Maybe I could make a PR ? for the doc :

4 is because the size of an element is 4 floats (vec4). As the total size (in floats) is size * arraySize, arraySize must be equal to uniformArray.length / 4 to have a final array of uniformArray.length floats.

1 and uniformArray.length is not valid because the addUniform method would think you want to make an array of float and would add some padding after each float (3 float padding).

These rules applies to arrays, but you could also use the non-array form of the method by passing 0 for arraySize. In that case, you can use updateUniform (instead of updateUniformArray) to set the data:

In this case, the code is taking your data “as is” and don’t add any padding.