three.js 中的 perspectiveDepthToViewZ
ref:
https://blog.csdn.net/qq_35158695/article/details/120907217
https://mynameismjp.wordpress.com/2010/09/05/position-from-depth-3/
https://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/
https://blog.csdn.net/qq_35158695/article/details/120907217
投影矩阵
P c l i p = [ 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 0 0 A B 0 0 − 1 0 ] ∗ P v i e w P_{clip} = \left[ \begin{matrix} \frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0 \\ 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0 \\ 0 & 0 & A &B \\ 0 & 0 & -1 & 0 \end{matrix} \right] * P_{view} Pclip=⎣⎢⎢⎡r−l2n0000t−b2n00r−lr+lt−bt+bA−100B0⎦⎥⎥⎤∗Pview
其中:
A
=
−
f
+
n
f
−
n
A = -\frac{f+n}{f-n}
A=−f−nf+n
B = − 2 f n f − n B= \frac{-2fn}{f-n} B=f−n−2fn
那么:
z c l i p = − ( f + n ) f − n z v i e w + − 2 f n f − n (1-1) z_{clip} = \frac{-(f+n)}{f-n} z_{view}+ \frac{-2fn}{f-n} \tag{1-1} zclip=f−n−(f+n)zview+f−n−2fn(1-1)
z = z v i e w z = z_{view} z=zview, z n d c z_{ndc} zndc有:
z n d c = − ( f + n ) f − n z + − 2 f n f − n − z = f + n + 2 f n 1 z f − n = f z + n z + 2 f n ( f − n ) z (1-2) \begin{aligned} z_{ndc} &= \frac{ \frac{-(f+n)}{f-n} z + \frac{-2fn}{f-n}} {-z} \\ &= \frac{f+n+2fn \frac{1}{z}}{f-n} \\ &= \frac{fz+nz+2fn } {(f-n)z} \\ \end{aligned} \tag{1-2} zndc=−zf−n−(f+n)z+f−n−2fn=f−nf+n+2fnz1=(f−n)zfz+nz+2fn(1-2)
2 深度纹理
深度纹理 depthBuffer 的 depth 范围是 0 ~ 1, z n d c z_{ndc} zndc范围是 -1~1
d e p t h = z n d c 1 2 + 1 2 (1-3) depth = z_{ndc} \frac{1}{2} + \frac{1}{2} \tag{1-3} depth=zndc21+21(1-3)
式子(1-2)带入到(1-3),有:
d e p t h = f z + n z + 2 f n 2 ( f − n ) z + ( f − n ) z 2 ( f − n ) z = f z + n z + 2 f n + f z − n z 2 f z − 2 n z = f z + f n f z − n z = ( n + z ) f ( f − n ) z (1-4) \begin{aligned} depth &= \frac{fz+nz+2fn } {2(f-n)z} + \frac{(f-n)z}{2(f-n)z} \\ &= \frac{fz+nz+2fn+fz-nz}{2fz-2nz} \\ &= \frac{fz+fn}{fz-nz} \\ &= \frac{(n+z)f}{(f-n)z} \end{aligned} \tag{1-4} depth=2(f−n)zfz+nz+2fn+2(f−n)z(f−n)z=2fz−2nzfz+nz+2fn+fz−nz=fz−nzfz+fn=(f−n)z(n+z)f(1-4)
z v i e w = n f d ( f − n ) − f z_{view} = \frac{nf}{d(f-n)-f} zview=d(f−n)−fnf
code
// NOTE: https://twitter.com/gonnavis/status/1377183786949959682
// 根据viewZ得到深度
float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {
return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );
}
// 根据深度信息得到 viewZ
float perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {
return ( near * far ) / ( ( far - near ) * invClipZ - far );
}
可视化深度
float readDepth( sampler2D depthSampler, vec2 coord ) {
float fragCoordZ = texture2D( depthSampler, coord ).x;
// viewZ 即渲染片段和摄影机之间的z距离
float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );
return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
}
void main() {
// readDepth() will return a linearized depth value that will be used to compute the fragment's color value
float depth = readDepth( tDepth, vUv );
gl_FragColor.rgb = 1.0 - vec3( depth ); // change this bit to invert colors
gl_FragColor.a = 1.0;
}