Best way to pass lights to a shader?

I’m working on a custom deferred rendering system (seems like a bandwagon nowadays, haha). I’m pretty much finished up with the whole thing as far as my own personal needs go, but I have one last thing I’m trying to improve. Right now, here’s how I pass my lights into the shader:
-create an image that is 4px wide by number of lights long.
-first column is light positions, second is color, third is various attributes (range, spotlight stuff, fade), fourth is direction (for spots and directional lights)
However, this means for each light I have at least 2 texture lookups. For a single light it’s not so bad, but right now I can barely push 100 lights without a drop in framerate (80FPS on an ooold HD6670 1GB). As I intend for this to run on a decent range of hardware, I was hoping to find a more efficient way to input the light data. I know jME naturally passes in the g_LightList or something like that, but I have no idea how to use this, nor can I figure anything out from the other shaders. I also don’t know if I can hijack this to input the data I need, as I know it’s probably rooted deeeeep in the jME render code.
So, do any of the experienced shader people have any input here? Should I change my approach to something else, or is there a more efficient way to do what I’m trying to do? Thanks in advance!

Also, the hub has been incredibly slow recently. It often takes up to 3 minutes for a page to load. I know there’s a dedicated forum for website problems, I just don’t feel like waiting 10 minutes to post that it’s been slow haha. I’m relatively certain it’s not on my end, as everything else loads pretty swiftly (and I should hope so, this internet plan is not cheap). Probably just extra traffic or something.

Maybe try to choose an limited amount of lights, that are most close to the camera and pass them just as parameters? I don’t know the parameters of your 3D world, but if you indeed make it for your personal needs, then maybe it’s good idea to not make it too flexible? I did so in my custom shadow renderer.

Are you planning to going public this code?

Take a look at:
its outdated and stuff, but was able to run with around 3k lights on my old setup.
Maybee you can salvage the code for passing the lights.

So what I’m gathering here is this:
Create a separate viewport for the lights, pass in diffuse, depth, normals, other things, and attach the lights as geometries to this viewport’s scene. Then each different kind of light has its own type of material that rendered the light as needed, then adds effect by settings the viewport’s material to additive blend? It’s kind of the opposite approach to mine. Instead of one single render pass with a loop for all the lights, it’s a single pass for each light. Probably a ways more efficient than my approach as well. Thanks!

As far as I understand your approach, it requires evaluating every light for each pixel of screen. Yes, it is in single shader, but still huge iteration. Normal approach for deferred rendering is to try to limit light influence radius by drawing light geometries, avoiding processing out-of-range lights entirely.

Additionally, think how this is going to work with shadows. Non-shadowcasting lights have very limited usability. But even for that, I would probably use instancing rather than pass information by texture.

This scene:
[video]Deferred lighting experiments - YouTube
has 400 lights. It renders in 6ms per frame without shadows, 70ms per frame with shadows and I have not really looked into optimalization yet (but there is a limit what can be done for shadowcasting case, given cost for framebuffer binds for shadow render).

@abies Yes, you’re correct. I changed my approach to follow the light geometries and it is definitely much more efficient. As far as shadows go, I’m not too worried about implementing them with my directional and spot lights, but with the point lights it’ll be much harder. I was hoping to find some lightweight method for doing point shadows, but as shadows are one of the most complex parts of realtime rendering, it’s not easy.