gl_FragCoord.z が線形かどうかはまだわかりません。
が線形かどうかgl_FragCoord.z
は、射影行列に依存します。正射投影gl_FragCoord.z
は線形ですが、透視投影は線形ではありません。
一般に、深さ (gl_FragCoord.z
およびgl_FragDepth
) は次のように計算されます ( GLSL gl_FragCoord.z の計算と gl_FragDepth の設定を参照)。
float ndc_depth = clip_space_pos.z / clip_space_pos.w;
float depth = (((farZ-nearZ) * ndc_depth) + nearZ + farZ) / 2.0;
射影行列は、シーンの 3D ポイントからビューポートの 2D ポイントへのマッピングを表します。目空間からクリップ空間に変換し、クリップ空間の座標をクリップ座標のw成分で除算することにより、正規化されたデバイス座標 (NDC) に変換します。
正投影
Orthographic Projection では、目空間の座標は正規化されたデバイス座標に線形にマッピングされます。

正投影行列:
r = right, l = left, b = bottom, t = top, n = near, f = far
2/(r-l) 0 0 0
0 2/(t-b) 0 0
0 0 -2/(f-n) 0
-(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
Orthographic Projection では、Z コンポーネントは次の線形関数によって計算されます。
z_ndc = z_eye * -2/(f-n) - (f+n)/(f-n)

透視投影
透視投影では、投影行列は、ピンホール カメラから見た世界の 3D ポイントからビューポートの 2D ポイントへのマッピングを表します。
カメラ錐台 (切頭ピラミッド) の眼球座標は、立方体 (正規化されたデバイス座標) にマップされます。

透視投影行列:
r = right, l = left, b = bottom, t = top, n = near, f = far
2*n/(r-l) 0 0 0
0 2*n/(t-b) 0 0
(r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1
0 0 -2*f*n/(f-n) 0
透視投影では、Z コンポーネントは有理関数によって計算されます。
z_ndc = ( -z_eye * (f+n)/(f-n) - 2*f*n/(f-n) ) / -z_eye

深度バッファ
正規化されたデバイス座標は (-1,-1,-1) から (1,1,1) の範囲にあるため、Z 座標は深度バッファーの範囲 [0,1] にマップする必要があります。
depth = (z_ndc + 1) / 2
それが線形でない場合、ワールド空間で線形化する方法は?
深度バッファーの深度を元の Z 座標に変換するには、投影 (正射投影または透視投影)、およびニア プレーンとファー プレーンを知る必要があります。
正投影
n = near, f = far
z_eye = depth * (f-n) + n;
透視投影
n = near, f = far
z_ndc = 2.0 * depth - 1.0;
z_eye = 2.0 * n * f / (f + n - z_ndc * (f - n));
透視投影行列がわかっている場合、これは次のように実行できます。
A = prj_mat[2][2]
B = prj_mat[3][2]
z_eye = B / (A + z_ndc)
への回答も参照してください
ビュースペースの深さの値とndc xyを指定してビュースペースの位置を回復する方法