Monday, March 29, 2010

The Trouble with Fog

One of the things that was broken for me (although apparently not for some others) in DirectQ 1.8.2 was fog. I didn't get round to even investigating it prior to release but I have done so now.

I had suspected that the cause was somehow hardware related, and it's bad news.

It seems as though Shader Model 3 or above removes the built-in fixed functionality fog. So hardware that supports SM3 or higher (and this is everything from the GeForce 6 series - or equivalent - and upwards) is no longer required to support fog render states in hardware. Doesn't matter if you compile your shaders to SM2, or even if you don't use shaders at all, it's the model supported by the hardware that is the deciding factor here. A lot of this probably depends on the vendor; one of mine supports per-vertex fog (which will break on the water and sky shaders) but not per-pixel, and it seems that even that can't be relied on going forward.

Now, this is not a problem for OpenGL: fog is in the spec and therefore fog shall be supported, even if it means a software fallback or a wacky blend to get it. But D3D doesn't work that way. D3D exposes the raw bones of the hardware and nothing more; despite being COM and OOP it actually is a much lower level API than OpenGL.

None of this is definitive and I'm still doing the research, but there is plenty of info to support it and the only thing lacking is official confirmation.

Next comes the bit where I consider my options. Assuming that the non-support of fog turns out to be true, here's what they look like.

The first and easiest is to just drop fog entirely, at least for now. There is potential to come back to it when the renderer goes through a few more evolutions and possibly implements everything in vertex shaders (which D3D - oddly enough - does support in software if required - they would even run on a Voodoo 2).

The next option is to implement one of those hacky workarounds I mentioned, possibly blending everything with a cubemap for a fake fog effect (I believe DarkPlaces does something like this). Gouraud shaded polygons could also get it, but the pain and suffering involved in that approach means it's not something I'd undertake lightly.

The final option is to hack together something that works with fixed per-vertex fog for everything aside from water and sky, which would have fog calculated in their shaders instead, and no guarantee that it would be invariant with fixed or even continue to work in the future. Not an option in other words.

On balance I'm inclining towards option 1. Transitioning everything to vertex shaders is definitely on the cards for 1.9, so the requirements to support it will be there. (Did I mention that D3D vertex shaders would even work on a Voodoo 2? I probably should just in case I give the idea that I'm locking people out here.) The other options just involve creating a mess that would then have to be extracted.

Better to not have a feature (at least in the short term) than to have one that kinda works half the time but can't even be relied on.

2 comments:

austenite said...

My 2 cents:

Had a look at the fog feature when it did work, but turned it off, as it wasn't a feature of the original game.

Won't miss it if you decide to leave it out.

Keep up the great work on DirectQ -- the gameplay seems to getting faster and smoother with every release.

Jonathan said...

Thanks very much! xfire has built-in game video recording which didn't work with qrack but doesn't seem to work with mhquake either. For qrack I thought it was because xfire didn't support opengl recording but now that it doesn't work with mhquake I am stumped. any idea? I want to record lots of ctf game recorded gameplay videos and post them online (xfire system is nice).