If you're going for an "unlimited" number of lights, I'd set up a vector of point lights in C++. Something like std::vector<PointLightData>, with PointLightData being a struct holding the data for each light. You can add or remove lights from it, and update the contents whenever you want. You'd then pass the data of this vector to the shader storage buffer object each frame, with a glBufferData call. Because the array in GLSL is unsized, there's no hard limit to how many point lights you can add, except for hardware limitations (which I doubt you'll reach). As long as the SSBO is backed by data uploaded in C++ from glBufferData(), it's all valid. Some C++ pseudo-code would go something like this:
struct PointLight
{
vec3 position;
// whatever other data you want
};
std::vector<PointLight> scenePointLights;
void mainLoop()
{
updatePointLights(); // do whatever logic like physics
uploadPointLightData(); // call glBufferData() with the data from scenePointLights
renderScene();
}
An the GLSL pseudo:
struct PointLight
{
vec3 position;
// whatever other data
};
layout(std430, binding = 0) buffer pointLights
{
PointLight pointLightData[]; // scenePointLights.data()
};
uniform int numPointLights; // scenePointLights.size()
void main()
{
for (int i = 0; i < numPointLights; i ++)
{
PointLight p = pointLights.pointLightData[i];
// Do whatever lighting code
}
}
This is obviously a little simplified, but it's the basic idea on how to do it. I'd suggest doing a bit of Googling to figure out exactly how all of these work, though. The link I posted earlier shows a few more examples, too.