I've been beating a little more on these, and am beginning to wonder if handling them in any kind of robust and performant manner would really necessitate an architectural overhaul.
The real problem with them stems from the fact that multiple entities can share the same model.
Because each entity must be in a different place, it follows that each entity can be affected by a different set of dynamic lights.
But because the same model is shared, it follows that each entity has the same lightmaps.
So, if more that one of the same model is onscreen at the same time, it means that you can't just update lightmaps in any kind of well-running manner. Instead you need to update them just before the model gets drawn, which results in lots of nasty updates of resources that are in use by the GPU at the time you try to do the update, and which means lots of pipeline stalls and slow downs.
The alternative is that the last set of lightmaps which were updated will be applied to all such models, meaning that the last such model drawn will be lit correctly and the rest won't.
Aaaarrrggggggggggghhhhh.
I'm sorely tempted to shift dynamic lighting over to attenuation maps. These bring their own complications in terms of multiple blend passes, working right with alpha surfaces, etc, but all of the other issues just go away.
Another thing is that I'd be tempted to do them in a Q3A style whereby they're just a relatively simple blend over the previous combined texture and lightmap, meaning that they wouldn't light up dark areas properly.
Quake technology is really really annoying at times.
Fortunately this is just a momentary blip on the road to D3D11, and - provided that I make the decision to go with full GPU lightmaps - all of these issues will be history.
Until then I'm thinking that I'll probably release with lightmap-based dynamic lighting of BSP models included, but with the warning that if you're playing a map where the mapper has gone nuts with them, there will be slowdowns.
Sunday, January 22, 2012
More on BSP Brush Model Lighting
Posted by
mhquake
at
11:52 PM
Subscribe to:
Post Comments (Atom)
8 comments:
Would it be possible to convert BSP models to MDL at load time? And if so would that solve anything? Just wondering..
I had thought about that a coupla years ago. For small BSP models (like ammo boxes) it would work OK; for big ones (like the cogs in ne_tower) it would suck. The small ones aren't really the ones that cause trouble (I could just as easily make an extra copy of the model for each entity that uses it too).
Problem is that MDLs just pick up a single light value which is then uniformly applied across the entire model. A model half in and half out of a light will get lit fully (or not at all, depending on if the radius crosses the origin point) by that light. Big pain.
One thing the D3D11 code can do that I haven't mentioned yet (or coded yet) is allow that kind of partial lighting of MDLs; but by then we've also resolved the BSP problem too, so it's not worth doing the conversion.
Can the tools somehow load BSP models into the map and do the lighting from there?
Possible. Doing the other way around (export the lights from the main map into a BSP) would also work.
Two immediate problems.
One is that a BSP model may be used in more than one map. So the lighting it gets for map A won't necessarily be valid for map B.
Two is that the BSP model may be used by more than one entity in a single map. So the lighting it gets for entity A won't necessarily be valid for entity B (they'll be in different positions in the map).
The only real solution there is to make a copy of the BSP model for each entity that uses it when the map loads in the engine, then add the light.exe code to the engine and relight the BSPs as part of the load process.
That would be horrible. And we're still left with the problem of: what happens if the BSP needs to move?
Broken format is broken.
Problem One is theoretically solved by telling mappers to not do that - possibly require bsp models for map A to be in a subfolder called A.
Problem Two is in principle solved the same way; have single-use bmodels and refuse to load the same bmodel for another entity. Mark bmodels by giving them a unique "name" key in their worldspawn or just a unique filename. Most bmodels are really small, so the only problem remaining is added loading time. Luckily RMQ switched to MDL for healthkits etc. so those are out of the equation at least there.
Problem Three; what if the bmodel moves. Well, yep, I don't have a solution for that except use bmodels that are pre-lit by the mapper in a neutral way (mark them in their worldspawn somehow if necessary). This isn't perfect, but overall you'd still get a gradual improvement and at least stationary bmodels would be lit correctly.
Still a huge PITA. Just trying to inch closer to a solution.
Problems 1 and 2 exist in the id1 maps though. You could just hard-code the id1 BSPs into the engine, but that intuitively feels like the wrong thing to do.
Problem 3 in theory exists for every case where problem 2 exists (problem 2 is really just a special case of problem 3) as the same bmodel in two different positions requires the same kind of handling as one that moves.
My own thought is that id themselves showed the way forward by just not using BSP for anything other than the world model in subsequent engines. With Quake it remains a legacy difficulty that needs to be dealt with, but there's no reason to make things worse.
It is a valid argument that a model format that's simple for mappers to build stuff with, but also simple to integrate into an engine, is a huge requirement. BSP goes to one extreme here, MDL to the other, and there's nothing that meets in the middle.
Having to support legacy Quake is pretty much killing any attempt to get rid of bmodel, indeed. Unless one were to drop it :^)
I do think that completely switching to models would be nice.
A sane model toolchain would be nicest of all. I just found out the round-tripping you guys need to go through. Yuck. The way I work (lots of small, incremental changes with testing after each) I'd go insane if I had to do that.
Post a Comment