After Far Cry we changed our early Z pass to output the pixel Z value for alpha tested and fully opaque geometry into a texture so that we could do some features in a deferred way. We started with a R16f texture format which provided good quality but was not supported on all hardware. R16G16f was very well supported but not a native format for NVidia at that time. R32f was supported on all hardware with very good quality and fast as well.
However, if hardware allows lookups into the native Z buffer then this is preferred. That allows faster rendering when generating the data (double Z write performance), less memory requirements and sometimes even better quality. However, the lookup can get a bit more complicated as the z buffer might not return the linear Z directly.
Having the z value per pixel is beneficial for several features and effects:
By using deferred techniques we decouple the geometric scene complexity from the shader. For example, the shadow mask generation before was rendering all opaque scene objects with a shadow mask shader. That shader used the interpolated position in the shadow maps to output the shadow contribution to the shadow mask. This drawcall heavy pass was replaced by a deferred pass that reconstructed the position in the shadow maps from the stored pixel depth values. Instead of the numerous draw calls for all scene objects, just a single draw call for a fullscreen quad was required.
Sample image rendered by engine.
Linear z value of GBuffer.
Shadow mask generated from GBuffer data.
SSAO generated from GBuffer data.
r_UseZPass
Toggles g-buffer pass.
Usage: r_UseZPass [0/1]
Default is 1 (on). Set to 0 to disable Z-pass. 2 to enable z-prepass for expensive materials