首页
/ three.js DepthTexture 深度纹理 API 详解:将渲染深度自动写入纹理

three.js DepthTexture 深度纹理 API 详解:将渲染深度自动写入纹理

2026-09-06 18:13:50作者:傅爽业Veleda

DepthTexture 是 three.js 中一类特殊的纹理:它不保存颜色数据,而是在渲染过程中自动把片元的深度信息写入其中,供阴影映射、屏幕空间环境光遮蔽(SSAO)、延迟渲染、WebXR 深度感知等需要"可采样的深度缓冲"的场景使用。本文以官方文档 DepthTexture.html 为主体,结合仓库 v0.185.0 的源码与示例,完整讲解其构造参数、属性语义、内部实现与实战用法,读完你可以在自己的渲染管线中正确地创建并挂载深度纹理。

DepthTexture 是什么

类定义摘要写得很简洁:"This class can be used to automatically save the depth information of a rendering into a texture."(本类可用来在渲染时自动把深度信息保存进一张纹理)。

与普通 Texture 最大的差异在于:DepthTexture 不依赖来自 CPU 端的像素数据(image/Canvas/ImageBitmap),它的 image 只是一个描述符对象 { width, height, depth }。真正的深度数据来自 GPU 端深度缓冲区的回读——渲染器在把场景渲染到某个渲染目标时,如果该目标绑定了 DepthTexture,就会把深度缓冲直接写入这张纹理,供后续着色阶段采样。

其继承链为 EventDispatcher → Texture → DepthTexture,即它复用 Texture 基类 的绝大多数字段与生命周期,仅在基类之上重写了少量默认值并增加了深度相关属性。

类继承与源码定位

实现位于 src/textures/DepthTexture.js,完整类体非常精简(约 100 行)。核心构造函数(第 28 行)如下:

constructor( width, height, type = UnsignedIntType, mapping, wrapS, wrapT,
             magFilter = NearestFilter, minFilter = NearestFilter, anisotropy,
             format = DepthFormat, depth = 1 ) {

	if ( format !== DepthFormat && format !== DepthStencilFormat ) {
		throw new Error( 'THREE.DepthTexture: format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
	}

	const image = { width: width, height: height, depth: depth };
	super( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
	...
}

从源码可以读出几个关键实现事实:

  1. 格式白名单校验:构造函数只接受 DepthFormatDepthStencilFormat 两种格式,其余格式直接抛出 THREE.DepthTexture: format must be either THREE.DepthFormat or THREE.DepthStencilFormat 错误。
  2. 无像素数据image 被定义为 { width, height, depth } 纯描述符,而非实际像素内容。
  3. 参数顺序透传:除 typemagFilterminFilterformatdepth 外,mappingwrapSwrapTanisotropy 未在子类中给默认值,会以 undefined 落入基类构造函数,从而继承 Texture 构造函数 中的默认值(如 Texture.DEFAULT_MAPPINGClampToEdgeWrappingTexture.DEFAULT_ANISOTROPY)。

在深度/立方体贴图变体上,仓库还提供了继承自 DepthTexture 的 CubeDepthTexture,它把单个 image 描述符替换为 6 个相同描述符(每个立方体面一个,见 CubeDepthTexture 构造),并默认使用 CubeReflectionMapping,专用于点光源阴影。

构造函数与全部参数

构造签名(完整 11 个参数):

new DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format, depth )

其中仅 widthheight 为语义上必填,其余均有默认值。各参数官方文档说明与补充如下表:

参数 类型 默认值 含义与要点
width number 必填 纹理宽度(像素)。
height number 必填 纹理高度(像素)。
type number UnsignedIntType 深度数据类型。相关常量见 constants.jsUnsignedIntType(值 1014,默认)、UnsignedShortType(值 1012)、UnsignedInt248Type(值 1020,配合 DepthStencilFormat 使用)。
mapping number Texture.DEFAULT_MAPPING 纹理映射方式;不传则由基类默认值填充。
wrapS number ClampToEdgeWrapping S 方向环绕方式。深度纹理通常不需要重复采样,保持 Clamp 即可。
wrapT number ClampToEdgeWrapping T 方向环绕方式。
magFilter number 文档标注 LinearFilter 放大过滤。注意:当前 v0.185.0 实现(DepthTexture.js 第 28 行)实际写死默认 NearestFilter;深度纹理不生成 mipmap,配合阴影比较采样通常使用最近邻过滤,请以源码实际默认值为准。
minFilter number 文档标注 LinearFilter 缩小过滤。同上,当前实现默认 NearestFilter
anisotropy number Texture.DEFAULT_ANISOTROPY 各向异性过滤级别;不传则由基类默认值填充。
format number DepthFormat 纹理格式,只允许 DepthFormat(值 1026)或 DepthStencilFormat(值 1027),见 constants.js
depth number 1 纹理层数。对普通 2D 深度纹理为 1;创建 3D/2D 阵列深度纹理时传入层数,会写入 image.depth

深度数据的 type 与 format 搭配

  • DepthFormat:每个纹素是单个深度值。WebGL/WebGPU 侧按 type 决定内部格式——默认 UnsignedIntTypeDepthFormat 组合对应 24 位/32 位整数深度。
  • DepthStencilFormat:每个纹素是"深度 + 模板"成对数据,深度分量解释同 DepthFormat,模板分量由内部格式决定;此时 type 通常配合 UnsignedInt248Type(24 位深度 + 8 位模板),才能获得可用的模板存储。
  • depth > 1:用于分层深度纹理。一个典型实现是瓦片阴影节点 TileShadowNode——它对每个阴影瓦片分配一个摄像机与 shadow map,并创建一张"深度阵列纹理":
const depthTexture = new DepthTexture( shadowWidth, shadowHeight,
	undefined, undefined, undefined, undefined,
	undefined, undefined, undefined, undefined, tileCount );
depthTexture.compareFunction = LessCompare;
depthTexture.name = 'ShadowDepthArrayTexture';
const shadowMap = builder.createRenderTarget( shadowWidth, shadowHeight,
	{ format: RedFormat, depth: tileCount, useArrayDepthTexture: true } );
shadowMap.depthTexture = depthTexture;

这里第 11 个参数 tileCount 即用于把深度纹理声明为多层结构,并设置了 compareFunction = LessCompare,体现了 depth 参数在级联/瓦片阴影中的真实用途。

一段可直接运行的最小示例

把深度纹理挂到 WebGLRenderTarget 上,渲染场景后即可取得可采样的深度图。仓库示例 examples/webgl_materials_normalmap.html 使用相同模式:

import * as THREE from 'three';

// 1) 构造深度纹理(默认 DepthFormat + UnsignedIntType)
const depthTexture = new THREE.DepthTexture( width, height );

// 2) 将其作为渲染目标的 depthTexture 选项传入
const renderTarget = new THREE.WebGLRenderTarget( width, height, {
	type: THREE.HalfFloatType,
	depthTexture: depthTexture
});

// 3) 将场景渲染到该目标,深度自动写入 depthTexture
renderer.setRenderTarget( renderTarget );
renderer.render( scene, camera );
renderer.setRenderTarget( null );

// 之后便可在着色器中采样 renderTarget.depthTexture 做深度相关计算

注意:DepthTexture 的宽高应与你使用的渲染目标分辨率一致(或在 WebGPU/WebGL 双渲染器中让渲染管线按目标尺寸同步),这一点与 Texture 基类文档 中"纹理首次使用后其尺寸、格式与类型不可再更改,如需调整应调用 dispose() 后重建"的约束一致。

Properties(属性)详解

DepthTexture 在继承 Texture 大量属性之外,声明并覆写了以下 4 个关键属性。

.compareFunction

类型声明:

NeverCompare | LessCompare | EqualCompare | LessEqualCompare |
GreaterCompare | NotEqualCompare | GreaterEqualCompare | AlwaysCompare
  • 默认值:null
  • 含义:深度比较函数对应的常量码,用于阴影纹理的硬件比较采样(shadow compare)。当不为 null 时,采样器会对"纹理中的存储深度"与"传入片元深度"执行指定比较,把比较结果作为采样值返回——这是 PCF 类软阴影和方向/点/聚光灯光照过滤的基础。相关的 8 个常量定义于 constants.js
常量 数值 通过条件
NeverCompare 512 永不通过
LessCompare 513 新值 < 纹理值
EqualCompare 514 新值 == 纹理值
LessEqualCompare 515 新值 <= 纹理值
GreaterCompare 516 新值 > 纹理值
NotEqualCompare 517 新值 != 纹理值
GreaterEqualCompare 518 新值 >= 纹理值
AlwaysCompare 519 总是通过

设置示例(与 TileShadowNode 一致):

depthTexture.compareFunction = THREE.LessCompare;

未设置(null)时纹理按普通深度值采样,不做深度比较。

.flipY : boolean

  • 默认值:false(覆写基类行为,基类属性见 Texture 基类)。
  • 含义:是否在上传到 GPU 时沿垂直轴翻转纹理。普通图片纹理约定原点在左上,而渲染缓冲/深度数据原点在左下,深度纹理数据直接来自帧缓冲,因此 DepthTexture 在构造时被显式覆写为 false不要手动改为 true,否则深度方向会颠倒,导致比较结果错误。

.generateMipmaps : boolean

  • 默认值:false(覆写基类行为)。
  • 含义:是否为纹理生成 mipmap。DepthTexture 关闭 mipmap 有两方面原因:一是深度纹理通常不具备 mipmap 支持的内部格式;二是深度比较采样与 mipmap 过滤在语义上冲突。也因此应避免依赖 mip 层级过滤,官方实现把缩小/放大过滤默认收敛到最近邻采样(见上文 magFilter/minFilter 说明)。

.isDepthTexture : boolean(只读)

  • 默认值:true
  • 含义:类型标识。three.js 全库普遍使用这类只读标识做鸭子类型判断(避免直接 instanceof),例如在渲染器纹理上传、WebGLShadowMap、TSL 节点系统中识别深度纹理走专门的分支。单元测试 DepthTexture.tests.js 即专门验证该标识为 true

覆写的方法:copy 与 toJSON

DepthTexture 还覆写了两个生命周期方法(见 DepthTexture.js):

  • copy(source):调用基类复制后,将 source.image 拷贝进一个全新的 TextureSource(源码注释标注见 #30540,用于隔离共享图像数据源),并同步 compareFunction
  • toJSON(meta):在基类序列化结果上追加 compareFunction,保证带深度比较设置的纹理在编辑器/序列化场景中可被还原。

渲染管线中如何"自动保存深度"

DepthTexture 本身不产生数据,深度写入发生在渲染流程中。仓库代码中 DepthTexture 被渲染器各子系统大量引用(源码内搜索可见于 src/renderers 下 20 余个文件),典型协同路径包括:

  • 渲染目标深度附件WebGLRendererRenderer(WebGPU)RenderTarget 在目标绑定阶段识别 depthTexture 属性,使该纹理充当渲染目标的深度附件,渲染时深度自动写入。
  • 阴影映射WebGLShadowMap 与 TSL 光照节点 ShadowNodePointShadowNode 使用带深度纹理的渲染目标生成 shadow map。
  • 屏幕空间效果:SSAO、GTAO、SAO、SSR、像素化渲染等后处理 Pass 均以 depthTexture: new DepthTexture() 挂接目标深度:
  • TSL 深度节点:节点系统提供 ViewportDepthTextureNodeviewportDepthTexture() 辅助函数,供着色器图(TSL)中直接读取"不透明物体深度"做软粒子、雾、描边等效果。
  • WebXR 深度感知WebXRDepthSensing 把 WebXR 设备返回的真实深度数据封装为 DepthTexture,使 AR 内容可以基于真实环境深度做遮挡与交互。
  • 延迟渲染webgpu_deferred.html 中把不透明深度纹理作为透明通道的输入,并配合 autoClearDepth: false 实现两趟合一的深度复用。

常见问题与实践建议

  1. 格式传错会直接抛错format 仅接受 DepthFormat/DepthStencilFormat。需要同时拿模板信息(如描边/遮罩后处理)时使用 DepthStencilFormat 并配合 UnsignedInt248Type
  2. 默认过滤看源码而非注释:官方文档与 JSDoc 标注 magFilter/minFilter 默认为 LinearFilter,但 v0.185.0 的实际实现默认是 NearestFilterDepthTexture.js)。深度纹理无 mipmap、且常用硬件深度比较,NearestFilter 是更符合渲染语义的默认,需要线性深度插值时应显式传参并按目标平台能力评估。
  3. 不要翻转、不要 mipmap:保持 flipY = falsegenerateMipmaps = false,二者在构造时已强制关闭,手动开启可能造成深度方向或采样语义错误。
  4. 多层深度请用 depth 参数:二维阵列/三维深度纹理需把层数传给构造参数(参考 TileShadowNode 的瓦片阴影用法);立方体深度请改用 CubeDepthTexture
  5. 属性不可热修改:DepthTexture 复用 Texture 基类约束——首次上传 GPU 后,尺寸/格式/类型不再可改,需要变化时调用 dispose() 后新建。
  6. 深度图可视化需要转换:直接输出深度纹理并非线性灰度;文档没有展开说明 shader 侧写法,实际使用时通常需结合相机近远裁剪面做非线性→线性还原,再用于 AO/雾效/深度测试类效果。
  7. 类型判断:优先使用只读标识 isDepthTexture === true(或派生类 isCubeDepthTexture)做运行时类型测试。

测试与进一步阅读

仓库针对 DepthTexture 的单元测试位于 test/unit/src/textures/DepthTexture.tests.js,覆盖三方面:继承自 Texture、可实例化、isDepthTexturetrue——对应本文讲解的三个核心承诺。

需要继续深入时,建议按如下路径在仓库内检索:

整体上,DepthTexture 的设计思路非常聚焦:提供一个面向"深度即纹理"场景的专用容器,把颜色纹理需要处理的翻转、mipmap、像素来源等问题全部替调用方规避掉,同时保留 compareFunction、多层 depth 等与深度采样强相关的能力,让阴影、AO、延迟渲染和 XR 深度感知等上层特性可以围绕它可靠地构建。

登录后查看全文
热门项目推荐
相关项目推荐