Of late I've been of a mind to do some of the 'eye candy' I want to get working in Dominium, for special effects et al. I've lond had in mind a solution for the 'multiple light source' problem, especially with shaders in mind.
Now, I know about deferred rendering, and static/dynamic light-mapping, and so on - and hence the title of this journal entry I have little time to work on my pet project, and have to work with what a) I have and b) is attainable realistically in short bursts of development.
So, 'polylux' is my system for allowing multiple light sources, per object (in fact, per material/mesh). It works with the gl_LightSource state parameters, and hence is typically limited to 8 simultaneous light sources. I chose this route as a 'starter', but it'll probably also be a comfortable base line going forward - until the demand for more rears its ugly head.
It works by abstracting the 'data' for a light away from the actual OpenGL 'light' - so I can have hundreds (theoretically unlimited) light sources whizzing around the scene, being animated and so on. But, when it comes to render time, only the 8 most 'important' light sources are considered by the shader when its used to render the model itself.
As it's 'per material' (and there is always only ever one multi-stage material for any particular mesh in the 666 engine) then that means a single model could be lit by far more light sources if it's authored in the right way. ie. a single model with 4 meshes, could be 'lit' by 4 x 8 lights, with each mesh being lit by its nearest 'most important' light sources.
A simple geometry pass is used to determine the nearest lights that could possibly contribute light to a mesh, and light sources can be prioritised to always be included (i.e. the sun). Directional lights are more important than beam lights, beam lights more important than spot lights, spot lights more important than point lights. Larger light-sources are also then weighed in the balance, as a single huge point source (explosion) would then supercede a beam, or even a directional light.
As Dominium is a free flight space sim, all the lights will exist as 'colliders' within the collision octree, and thus I can leverage off that system to determine which light caster volumes interact with a models 'light receiver' volume. So initially there is a broad-phase pass to remove light-sources which do not contribute light, followed by a narrow-phase pass of direct collision testing, and finally a sorting/prioritisation cull which reduces the number of sources down to 8 at most for a given mesh.
I could support more than 8 of course, by simply providing an array of light source data to the shader directly, and bypassing the OpenGL state objects. But ultimately, the limit will be how many times the GPU can process light contributions to a single pixel. I may experiment with that later as time permits.
The shader aspect is fairly simple - it simply loops over 8 lights, and checks if a light is enabled or not before computing the contribution with the appropriate shader code for that light type. With shader branching concerns, that's probably a false optimisation - but I'm not at the 'make it optimal' stage yet anyway. Eventually there would be 8 variants of the shader, one for each additional active light source and other possible tweaks as they arise.
So - what use? Explosions (as mentioned), weapon effects, huge ship-slicing energy beams, engine effects, sunlight, reflected planetary light, reflected ring-system light, glows from nebula's, pretty much anything luminous really!
Anyway, enough waffle - enjoy the video, hopefully!...