Actually, the output Z value is usually quite sensible. If your near field is 0, then the output Z is exactly the Z depth in camera space. As Zn grows, there is an increasing amount of bias, in that values at Zn will be 0, but values at Zf will still be Zf, so there's a "stretching" of this space. This is for non-infinite projection matrices, as seen here:
http://msdn2.microsoft.com/en-us/library/bb206260(VS.85).aspx
As you can see, you can easily un-warp the value by adding (Zn*Zf/(Zf-Zn)) and then multiplying by ((Zf-Zn)/Zf), which gives you the world-space distance along the Z depth radius from the camera.
Another common value to use is the Z value of the output of the WORLDVIEW matrix.
A third common value to use is the vertex value of the output of the WORLD matrix, and dot it with the world-space camera forward vector.
A fourth common value to use is the plain vertex value, dotted with the object-space camera forward vector.
All of these will give you basically the same value : world space Z depth distance. Unfortunately, this will cause some warping of fog at the edges of the screen -- basically, something will be less in fog when at the edge of the screen, than when in the center of the screen. Unless you are horribly shader limited, I would suggest using radial fog, where you actually use the distance calculation.
Jon Watte, Direct3D MVP
Tweets, occasionallykW X-port 3ds Max .X exporter
kW Animation source code