6
\$\begingroup\$

I want to render an arbitrary number of lights in my fragment shader. I do not understand how you can properly pass them into the shader though. For example, I want something like this:

uniform int numberOfLights;

struct PerLight
{
    vec4 position;
    vec4 intensity;
}

uniform Lights
{
    vec4 ambientIntensity;
    float lightAttenuation;
    PerLight lights[numberOfLights];
} Lgt;

I've only seen documentation and examples use 'numberOfLights' as a constant and I cant get above to work so I am guessing you cant have a dynamicly sized struct in glsl.

So, how are you supposed to pass any given number of lights to the shader?

\$\endgroup\$

1 Answer 1

6
\$\begingroup\$

You're not supposed to pass an arbitrary number of lights to a shader because it won't work, as you've discovered. This isn't just a software or API limitation; this is a hardware limitation - each light must fit in GPU register space, of which there is a limited amount (increasing all the time, but still a hard limit). Adding together the contributation for each light would also cause you to hit limits on GPU instruction counts (not so relevant any more, but it used to be a big deal in the earlier days of shaders).

So, the main limit is register space, this limit will vary across different hardware generations, and therefore you can't just specify an arbitrary number of lights. You need to find an alternative solution.

One method may be to sum individual light contributions across multiple passes - Doom 3 did this, with one pass per light, and it worked well enough there. On more modern hardware you could sum lights in groups of 2, 4, 8 or whatever, which would get the number of passes down.

Another method might be to use a deferred renderer instead (Google for info).

Finally, and if you know that you're never going to exceed a certain number of lights, you can just specify your own hard limit.

\$\endgroup\$
3
  • \$\begingroup\$ With tile based deferred rendering you could handle even more lights than grouping 2, 4, 8 or whatever lights together. \$\endgroup\$
    – danijar
    Commented Apr 14, 2013 at 21:05
  • \$\begingroup\$ Absolutely, which is why a deferred renderer was a separate option. With a forward renderer you'd need to be more careful - many of the lights in a given group of e.g. 16 may not contribute anything at all and you'd just be wasting cycles on them by having such a large grouping. There are other solutions to that problem, of course. \$\endgroup\$ Commented Apr 14, 2013 at 21:10
  • \$\begingroup\$ I will give deferred rendering a look. Is there any sites in particular you would recommend? \$\endgroup\$ Commented Apr 14, 2013 at 21:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .