How do I setUniform for an array of a custom struct?

I have a shader with this struct defined in it:

struct LightInputData
{
  vec3 worldPos;
  vec3 color;
  vec3 falloff;
};

and it has this uniform variable:

uniform LightInputData uPointLights[8];

How can I set this uniform in my sketch.js? I know that setUniform is the way to go when setting floats and vec3s and stuff, but I can’t seem to get this one to work. It is possible that I’m making some other mistake that’s preventing it from looking right, but I want to ask here before I bang my head on the wall much longer.

1 Like

it seems like not straightforward to access uniform structs

so I doubt it’s supported in p5.js. In any case it might be helpful if you share an example code :slight_smile:

3 Likes

EDIT: Uh oh, I may have spoken too soon. It works fine… in the trivial case with just one light in the array. I can’t get it to work with two lights yet. I’ll keep poking at it and I’ll update this again when I have a solution.

EDIT AGAIN: Okay I fixed it, it was a goof on my part elsewhere in my sketch, and I can confirm that my solution does indeed work with a dynamic number of point lights (up to my shader’s arbitrary maximum).

Thank you so much! That link contained just the answer I was looking for. For posterity, I have a uniform array of LightInputData in my fragment shader, like this:

struct LightInputData
{
  vec3 worldPos;
  vec3 color;
  vec3 falloff;
};

uniform LightInputData uPointLights[MAX_POINT_LIGHT_COUNT];

and I want to use setUniform to send data from my sketch to this array. The correct way to do it is to access each named field in the struct individually, by name, within the array, like this:

phong.setUniform("uPointLights[0].worldPos", pointLight.WorldPosArray);
phong.setUniform("uPointLights[0].color", pointLight.ColorArray);
phong.setUniform("uPointLights[0].falloff", pointLight.FalloffArray);

…and so on for each element in the array. My solution for doing it with the array of lights I have in my sketch is to loop like this (and this does seem to work):

for (let i = 0; i < pointLightCount; ++i)
{
  let pointLight = pointLights[i];
  
  phong.setUniform(`uPointLights[${i}].worldPos`, pointLight.WorldPosArray);
  phong.setUniform(`uPointLights[${i}].color`, pointLight.ColorArray);
  phong.setUniform(`uPointLights[${i}].falloff`, pointLight.FalloffArray);
}
3 Likes