Ideally, I think we'd have a system that detected the optimum shader set for your hardware, but that would requiring having a great many shaders available and a detection mechanism. Maybe we will have that at some point, but right now we're trying to optimize the current experience for the most hardware we can.
The git test branch ("go_faster") that I was playing with earlier this year did actually have basic support for that. It would detect if the hardware was SM2, SM3 or SM4 capable and set a define in the shaders. You could then add #ifdef'd features requiring better hardware support to the shaders. It makes the shaders kind of crap, due to so much code in them, but it is something that would work.
One of the main goals of the new shader code (what I had planned for 3.7) was to use a tbl type of thing which could reference different shaders for different detail levels and different hardware. You could then write clean shaders for each level of hardware support and even different detail settings (such as conditionally enabling per-pixel lighting). Obviously that isn't going to ever come from me at this point, but it's probably worth mentioning in case somebody else feels like taking a crack at it later on.
I'm not sure if not having a state sorting system is the core problem of FSO's but I'd like to think that it wouldn't hurt if we someday implemented it. Please correct me if I'm wrong, taylor.
I did some state stuff for the current shader code to try and squeak out a little bit of extra performance from it all. It was pretty basic, and didn't help a ton, but it was better than leaving it the way that it was. In my previously mentioned test branch I tried to clean things up a little bit more as well.
But the main purpose of that test branch was a proof of concept for improving rendering performance with as little code and time investment as possible. That was primarily fixing the VBO stuff to work in a remotely efficient manner. The way it was coded originally was so that each subobject of a model had it's own index buffer and VBO. That may very well be the worst possible way to implement something like that because changing those buffers is one of the most costly operations you can do. I rewrote the code a bit to use a single IBO and VBO per model, eliminating the buffer switch when rendering except for the one buffer setup when you call model_render(). On small ships like fighters the performance improvement was easily measurable, but it wasn't that big (avg. 20-40 FPS boost). On large ships with a lot of subobjects the performance improvement was massive, in some cases giving a 3x boost. And this was just in the lab, so you can imagine how better it would perform in-game when you have numerous big ships each having the performance enhancement.
And I worked on that code for about 3-4 days, so it wasn't a big time investment either. There are lots of little changes like that, and maybe a few slightly larger ones, which can be made to the current code that can really help out performance wise. Mostly just cleanup, but things like better object sorting and an early-Z pass should provide a sizable performance improvement with shaders (the old render setup is too brute force, far too many things are textured, lit and rendered without ever been seen). No massive rewrite needed.

Actually, missile and flak explosions are implemented as particles, which can't/don't give off light.
I might have been thinking about my old Xt tree then. I reworked lighting on quite a few things (like changes for subspace stuff, and various other items) but never got it working 100%. It was too many code/quality changes for the intended purpose of the code base though (ending up as 3.6.10, when it has it's original release date of June/July 2007) and I ditched the code.
Still, adding such a feature shouldn't be a big deal for someone to do.