Since noone gave a clear formula, I sat down with a piece of paper, and came up with this.
// -------------------------------
// n: distance to near clip plane
// f: distance to far clip plane
// z: value in depth buffer
// -------------------------------
double convertZ(double n, double f, double z)
{
// Convert Z from [0, 1] to [-1, 1]
double wz = (2.0 * z) - 1.0;
double a = -(f - n) / (2.0 * f * n);
double b = (f + n) / (2.0 * f * n);
return -1.0 / (wz * a + b);
}
Tried it some times, and it seems to give OK results. You can try using gluUnProject, with an identity modelview matrix. Something like this.
double p[3];
gluUnProject(x, y, z, mv, pr, vp, p+0, p+1, p+2);
x and y can be anything, as long as z is the value from the depth buffer.
mv is the modelview matrix, and should be the indentity.
pr is the projection matrix, and should be the one you get from glPerspective/glFrustum.
vp is the viewport, can be anything, but keep it valid, so the viewport transform doesn’t mess up.
p[2] will hold the result you are after, and if you are lucky, convertZ() should give you the same result.