Re the geeks3d formula, looking at it a bit, it doesn’t feel right. Plug in z_win=1 and you do get 1, but plug in z_win=0 and you just get a mess (not 0, which you’d expect).
…but I would like to know how does the “non-linearisation” (and thus the linearisation) work and not just implement it anyway.)
Is there a place in the OpenGL documentation where the z calculation is written down?
Sure. You know what the PROJECTION transform is, right? Takes eye-space to clip-space. Do the perspective divide and you have NDC-space. Then just scale and shift that and you have window-space.
The main thing you need is the PROJECTION transform. Look at Appendix F in the Red Book:
At the bottom of the page are the perspective and orthographic projection matricies. All you need are the bottom two rows to compute z_clip and w_clip from z_eye (w_eye == 1). Then just divide z_clip/w_clip, and you have z_ndc. Then shift and scale that -1…1 value into 0…1 (*.5+.5, assuming glDepthRange 0,1) to get window-space Z. You can write all this out. It’s not complex. That’ll give you an expression that defines z_win in terms of z_eye. This defines the normal Z transform, and what you call “non-linearizing” it.
Then given z_win, you want to “re-linearize” it. So you want something like z_eye, but in 0…1 range. In other words you want to take the previous equation, solve for z_eye in terms of z_win, then plug that into (-z_eye-n)/(f-n) to get a linear-in-eye-space 0…1 Z value in terms of the window-space Z value.