Designating lights to light sources? GLSL

So, I was browsing around the forum and doing some experimenting. Apparently the gl_LightSource[i] assigns the lights you create in your scene in a reverse chronological order. That means that gl_LightSource[0] is the latest created light.

However this causes a lot of inconveniences when you are creating a level. If I make two rooms with different light sources I’d like to model the first one without having to decide on which light goes where before making the next room. However I’d have to update my script everytime I add a new light.

Is there any way to change how the lights are designated to gl_LightSource[i]?

Also is there a limit on how many light sources you can have?

i think that you can use a uniform variable for light position or other properties in your shader, and pass the light you want to shader

oh, I was thinking of that. but it seems inefficient. I assume that every render the engine will set the light ONCE. but if I set it with a script it’ll set it for every object that I render which is kind of redundant?

not sure if that is how it works but that’s what I’d assume.

but then assumptions never get you anywhere :slight_smile:

Ok, this is an old thread, but I’m trying to do the same thing…

it seems that the light indices aren’t quite as simple as reverse chronological order as they are also “per layer”

I’ve tried to dynamically recognize them in the fragment shader with this code (taken from the glsl orange book) and then call the appropriate function to calculate the lighting contribution of each light.

//clear the light intensity accumulators
vec4 amb = vec4(0.0);
vec4 diff = vec4(0.0);
vec4 spec = vec4(0.0);

//loop through enabled lights computing the contribution from each
for (int i = 0; i < numEnabledLights; i++)
    if (isLightEnabled(i) == true)
        if (gl_LightSource[i].position.w == 0.0)
            DirectionalLight(i, normal, amb, diff, spec);
        else if (gl_LightSource[i].spotCutoff == 180.0)
            PointLight(i, eye, ecPosition3, normal, amb, diff, spec);
            SpotLight(i, eye, ecPosition3, normal, amb, diff, spec);

This works fine, and I thought “great”

I’ve been building a whole shader library based on this for a project.

the trouble is it only works “most” of the time.

Under certain indiscenable circumstances it seems to just stop working and not find any lights… sometimes when I use it on a new scene it “just works”, sometimes it just “makes up” a default light that bears no relation to those in the scene…

when it works I can chop and change the lights, add them, delete them, change their type/colours etc

when it doesn’t work nothing I do makes any difference.

When I use it on my “live scene” for my project, it just seems to get junk for the lights…

I don’t currently have a corrupt file I can share here…

anyone else had any success with this type of approach?

Would this work for you? Maybe this isn’t what you are looking for, but it returns the name of all the lights in a scene.

import GameLogic as g

lamp = g.getCurrentScene().getLightList()[0]
pos = lamp.getPosition()

… I would have to iterate through all the lights, build one array for position, one for type? or does this script build the arrays?

How could I pass those to GLSL? is it possible to pass an array?

I still don’t understand why the first approach only works sometimes…

I would go with what Zahaghi suggested… using uniform variables. You can assign a property to the light objects and have a python and GLSL script that looks for them or something… I would assign the light via a uniform variable… so if I wanted to add a light etc then I could just change the property value of a light. I wouldn’t do all the programming only in the GLSL script.

It should be possible to pass arrays etc. there are a few types of variables you might be able to use.

I guess that’d be more robust, but could get quite a lot more complicated from a script point of view… although ultimately more controllable

I’ve noticed that doing it in the shader, blender will assign the lights to the geometry taking the layers into account ie if the shader is set to have three lights I can have three lights on each layer and the geometry on those layers is lit by the lights on their layer…

…which was nice!

Doing it Zaghaghis way would allow me to change the number of lights per layer though and would probably be more efficient…

The problems I encountered with it not working “sometimes” were due to other things in the scene not being set up properly (some geometry without a material goes black when dynamically lit when I put my shader in the scene, even though the shader is not set to affect those objects… It’s all or nothing then… that’s ok as I plan to use GLSL for everything ultimately.

I must get to grips with the assignment part of the custom shaders in python though, then I could pass flags for “prelit”, “two sided”,“1bit alpha” “8bit alpha” or “environment mapped” and just have one shader library file…