three.js 深度不完全解读

发布时间 2023-10-24 14:58:48作者: 安安静静的码农

three.js 深度不完全解读

一、深度值的获取

1、方法1: FBO的深度附件

深度信息通过渲染管线中的深度缓冲区(depth buffer)来计算和存储。缓冲区用于存储每个像素点的深度值。
在渲染过程中,渲染器会根据每个像素点的深度值来确定最终像素的可见性和着色。

const target = new THREE.WebGLRenderTarget();
target.depthTexture = new THREE.DepthTexture();

renderer.setRenderTarget(target);
renderer.render()

// 深度值: target.depthTexture, 近(0)~远(1)

2、方法2: 深度材质

scene.overrideMaterial = new THREE.MeshDepthMaterial()
const target = new THREE.WebGLRenderTarget();

renderer.setRenderTarget(target)
renderer.render();

// 深度值: target.texture, 近(1)~远(0)

原理:

// @vertex
vHighPrecisionZW = gl_Position.zw;
// @fragement
// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.
float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;

#if DEPTH_PACKING == 3200
  gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );
#elif DEPTH_PACKING == 3201
  gl_FragColor = packDepthToRGBA( fragCoordZ );
#endif

方法3: 利用 gl_FragCoord

float depth = gl_FragCoord.z / gl_FragCoord.w;

二、深度值的压缩和解压

压缩类型(DEPTH_PACKING):

export const BasicDepthPacking = 3200;
export const RGBADepthPacking = 3201;
vec4 packDepthToRGBA( const in float v ) {
  vec4 r = vec4( fract( v * PackFactors ), v );
  r.yzw -= r.xyz * ShiftRight8; // tidy overflow
  return r * PackUpscale;
}

float unpackRGToDepth( const in highp vec2 v ) {
  return unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );
}

三、深度值的相关转换

深度转viewZ

float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {
  // maps perspective depth in [ 0, 1 ] to viewZ
  return ( near * far ) / ( ( far - near ) * depth - far );
}