Saturday, September 10, 2011

GPU Lightmap Updating - Thoughts and Experiences

I've completed the slight diversion into GPU lightmap updating (I actually completed it a week ago but had to disappear for a short while) with some quite interesting results.

The overall verdict is that it's not going to be immediately viable but will definitely be something that it will be worth revisiting at some point in the future. It was also worth doing now to satisfy my own curiosity on the matter.

Animated lightstyles. The speed hit was initially a little too much but I was able to claw some back with use of some shader branching, and it now runs at some 80% to 90% of the speed of the old way in ID1 timedemos. On DirectQ's current target hardware you would need to do quite a bit of sorting and multiple passes to avoid the need for shader branching, which might (I don't know and right now I don't think it's worth investing the extra time to find out) wipe out any potential performance gains from not having to re-upload textures.

An interesting potential tradeoff emerged from this - if I was to drop use of coloured light then performance shoots up. In this case a lightmap animation is just one texture lookup and a dotproduct (with coloured light it's up to 4 texture lookups, shader branching, and some multiplies and adds).

Overbright lighting just came out naturally from it (in fact disabling overbrighting would reduce performance due to extra shader instructions), but it didn't do much to reduce the "stair step" effect.

For dynamic lights I just went for a fairly crude and brute force approach - assuming that every surface is potentially dynamically lit and using a "default dynamic light" with radius 0 for cases where a surface is not lit in reality. The intention here was to guage the effect rather than to measure a speed gain - doing it right would involve more code restructuring than I was prepared to do right now.

Two options were available - evaluating dynamic lights per-vertex or per-pixel. Per-vertex was much faster for sure - almost "for free" in fact - but the quality drop off (even with smooth shading used) was just unacceptable. Per-pixel dropped performance to about one-third (expected but not to that degree) and looked beautiful, but then a strange thing happened.

A beautiful perfectly circular dynamic light just created a huge visual discontinuity with Quake's original jaggy low-res lightmaps. Kinda like when you mix high-res replacement textures with low-res originals - it just doesn't look right. And ultimately visual consistency is more important than increased prettiness in one area only, so the overall effect is actually detrimental to the look and feel of the game.

Regarding performance there are quite obvious things that can be done to bring dynamic lights up, but like I said before the code restructuring required was something that I was unwilling to undertake right now. If I ever come back to this idea that will probably change, but for now I'm happy enough to park it.

There are a few other things I need to follow up on, so more later.

No comments: