Multiple Lightsources?

Hi,

I wonder what is the best way to support multiple lightsources in a shader without knowing the exact number at the time of writing?

Of course, I could always compute all 8 OpenGL Lightsources in my Shader but this would be very slow and would result in wrong results when there are less lightsources present.

I thought about a uniform parameter to pass to the shader but this won´t work, even on ShaderModel 3 Hardware.

So which way should I go?

Case

I don’t know what you are trying to achieve over here, but on pre-SM3.0 capable hardware you usually had to process one light at a time. On SM3.0 hardware i have read some nVidia paper suggesting 4 lights per-shader. Infact, nVidia ported FarCry’s lighting shaders to SM3.0 and they did lighting in batches of upto 4 lights per-pass.

When you try to send the number of lights as uniform, what exactly happens???

One idea is to use different shaders for each separate light count - 1, 2, 3, …

When I send the number of lights as uniforms, I get a compile error in my Fragment Programm (Shader Model 3 Hardware!):

error C5043: profile requires index expression to be compile-time constant

When trying to do something like that in my vertex program, I get another error:

error C5025: lvalue in assignment too complex

Any ideas? Always computing 4 Lightsources is pretty slow, at least for some shaders.

what graphics card do you use? and driver version?

… and what were the exact shader sources producing the errors?

error C5043: profile requires index expression to be compile-time constant

Are you using the default light source uniforms? Last time I tried using them, ATI drivers had a lot of problems. I remember the following giving the same compiler error:

void f(int i)
{
    array[i] = something;
}

f(0);

One way to get around that problem is by using macros.

The way I have been doing this is by including bools at the top of my shader like this:

light0active
light1active
.
.
.

up to some maximum number of lights. Then I use conditionals to process the contribution from all the active lights. It is probably bad to have the conditionals, but it works.

The other way I would like to try (but haven’t yet) is to make a lighting ShaderObject which would just compute lighting and store it in variables such as diffuse, specular, and indirect. Then I would link this to all my ShaderObjects that compute material properties using the already computed lighting data.

So every time I change my lighting environment I would compile the lighting ShaderObject once and link it to all my material ShaderObjects. For this to actually work well, it relies on linking being very fast. I don’t know if this is the case, though. I have even heard that some shader compilers just concatenate shader strings and then compile them all at once, effectively linking before compiling. Anyone have anymore information on this?

Originally posted by mogumbo:
Anyone have anymore information on this?
I’ve been doing this for all my shaders. I have created a library of “utility” shader objects (lighting, shadows, fog, skinning, parallax, etc) that I compile and link as needed to get a final shader program.

AFAIK, ATI has been compiling before linking since their first implementation, whereas NV added support for this recently (Forceware 80+).

Unfortunately, the NV implementation is currently buggy. It works the first time, but as soon as you try to link a program containing a shader object that has already been linked with another program, the link fails (with an obscure, internal error). I have reported this, but the bug is still present with the latest official drivers.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.