首页
/ three.js CubeTextureLoader 完全指南:六面立方体贴图加载、坐标约定与实战应用

three.js CubeTextureLoader 完全指南:六面立方体贴图加载、坐标约定与实战应用

2026-09-07 17:35:31作者:凌朦慧Richard

CubeTextureLoader 是 three.js 中负责将六张单独图片(立方体的六个面)拼装为一张立方体环境贴图(CubeTexture)的专用加载器。无论你是要做场景天空盒背景,还是为 PBR 材质提供环境反射(envMap),都会用到它。读完本文,你将掌握 CubeTextureLoader 的构造函数、load / loadAsync 用法、六面图片的命名与排列顺序约定、坐标系统注意事项,以及它与 ImageLoader、CubeTexture 之间的底层协作机制。

概览:它是什么、能做什么

CubeTextureLoader 继承自 Loader,用于加载立方体贴图(cube map / cube texture)。它的工作方式如下:

  • 底层依赖:六张图片内部是通过 ImageLoader 逐张加载的;
  • 返回类型:加载完成后返回一个 CubeTexture 实例;
  • 输入约定:它只接受「六张独立图片」这种最朴素的立方体贴图定义方式,每个面一张图。垂直/水平十字形(cross)、横排/竖排的 column / row 布局均不被支持
  • 典型用途:直接赋值给 scene.background 制作天空盒,或赋值给材质的 envMap 制作反射/环境光照效果。

代码入口位于 src/loaders/CubeTextureLoader.js,类声明为:

class CubeTextureLoader extends Loader {
	constructor( manager ) { super( manager ); }
	load( urls, onLoad, onProgress, onError ) { /* ... */ }
}

两个必须先搞清楚的关键约定

使用 CubeTextureLoader 之前,有两个容易踩坑的约定必须理解,它们都直接写在类的源码注释中。

1. 立方体贴图的坐标系约定:pos-x 与 neg-x 会被交换

按惯例,cube map 定义在这样一个坐标系里:当沿着正 z 轴方向看过去时,正 x 指向右侧——也就是所谓的左手坐标系。而 three.js 渲染使用的是右手坐标系

因此,three.js 在使用环境贴图时会把 pos-x 与 neg-x(正 x 面与负 x 面)对调。这意味着你在其他工具(如导出器或旧版约定)中按左手系摆放的 px / nx 两张图,在 three.js 里呈现的左右关系可能与你的预期相反。这是行业惯例如实反映,并非 bug,制作贴图时请留意。

2. 默认处于 sRGB 颜色空间

加载得到的立方体贴图默认处于 sRGB 颜色空间。也就是说,loader 内部会自动把纹理的 Texture#colorSpace 属性设置为 SRGBColorSpace,你不必再手动设置。这一点与普通颜色贴图的处理思路一致,也与 newer three.js 版本里「颜色数据用 sRGB、光照/计算数据用 Linear」的整体色彩管理方向相符。

代码示例

官方文档给出的标准用法如下(同步加载的底层回调方式与异步 loadAsync 均可):

const loader = new THREE.CubeTextureLoader().setPath( 'textures/cubeMaps/' );
const cubeTexture = await loader.loadAsync( [
	'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'
] );
scene.background = cubeTexture;

这里 px / nx / py / ny / pz / nz 依次代表六个面,完整的命名与顺序约定见下文「六面顺序」小节。设置为 scene.background 后,相机视锥外的区域即显示为该立方体贴图,形成天空盒效果。

同样也可以把立方体贴图作为材质的环境贴图使用:

const loader = new THREE.CubeTextureLoader();
loader.setPath( 'textures/cube/pisa/' );

const textureCube = loader.load(
	[ 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png' ]
);

const material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } );

更多真实可运行的环境贴图示例,可查阅 examples/webgl_materials_cubemap.htmlexamples/webgl_materials_cubemap_dynamic.htmlexamples/webgl_materials_cubemap_refraction.html 等官方示例页面。

构造函数

new CubeTextureLoader( manager : LoadingManager )

构造一个新的立方体贴图加载器。

  • manager:加载管理器(LoadingManager)。该参数可选,不传时继承 Loader 基类的默认行为——基类构造函数会把 this.manager 指向 DefaultLoadingManager。传入自定义 manager 后,所有六张图片的加载进度、错误事件都会汇总到你指定的 manager 上(例如用于全局进度条)。

CubeTextureLoader 本身没有重写构造函数逻辑,仅仅是 super( manager ) 透传给基类,因此它自动具备基类提供的一组属性与链式 setter 方法(见下文)。

方法详解

.load( urls : Array, onLoad : Function, onProgress : Function, onError : Function ) : CubeTexture

从给定的 URL 数组开始加载,并在加载完成后把完整的立方体贴图传给 onLoad() 回调。该方法会立即返回一个新的 CubeTexture 对象,可直接用于材质创建;若采取这种方式,贴图可能在对应加载流程结束后才在场景中"弹出"显示。

urls

包含 6 个图片 URL 的数组,每个面对应一张图。顺序必须是:

  1. pos-x(px,正 x 面)
  2. neg-x(nx,负 x 面)
  3. pos-y(py,正 y 面)
  4. neg-y(ny,负 y 面)
  5. pos-z(pz,正 z 面)
  6. neg-z(nz,负 z 面)

同时也允许传入 data URI(如 base64 内嵌图片)数组。需要特别注意的是,该数组必须恰好包含 6 个条目,六张图全部加载完毕才会触发 onLoad(源码逻辑见下文的「内部工作原理」)。

onLoad:加载流程全部完成时执行的回调,收到参数为组装好的 CubeTexture。

onProgress该 loader 不支持进度回调。原因在于其底层 ImageLoader 自 r84 起已放弃对 progress 事件的支持,故此处直接传 undefined 即可,传入的进度回调会被忽略。

onError:任意一张图片加载出错时执行。

重写Loader#load返回:立方体贴图(CubeTexture)。

.loadAsync( urls : Array, onProgress : Function ) : Promise

load 的 Promise 化版本,来自基类 Loader。其实现本质上是把 load 包进一个 Promise:成功时 resolve(texture),任一图片失败时 reject(error)。本文开头示例使用的即此方法,配合 async / await 编码体验最佳。

继承自 Loader 的链式配置方法

CubeTextureLoader 继承 Loader 基类的以下配置项(全部返回 this,可链式调用):

方法 作用 默认值
setPath( path ) 设置所有图片 URL 的前缀基础路径,传入的 urls 会被拼接在此路径之后 ''
setCrossOrigin( crossOrigin ) 设置跨域字符串,用于加载允许 CORS 的其他域名资源 'anonymous'
setWithCredentials( value ) 是否让底层 XMLHttpRequest 携带凭证(cookie、Authorization 头等);注意对本地/同域加载无效果 false
setResourcePath( resourcePath ) 设置依赖资源(如纹理)的基础路径 ''
setRequestHeader( requestHeader ) 为 HTTP 请求设置自定义请求头 {}

例如,先 setPathsetCrossOrigin 的典型组合写法:

const loader = new THREE.CubeTextureLoader()
	.setPath( 'https://example.com/textures/' )
	.setCrossOrigin( 'anonymous' );

其中 crossOriginpathwithCredentialsresourcePathrequestHeader 都是基类构造函数中初始化的公开属性(见 Loader.js),你也可以直接赋值后调用 load

六张图片的加载顺序与成功判定

CubeTextureLoader 对六张图片采取并发发起、全部到齐才回调的策略。阅读 src/loaders/CubeTextureLoader.js#L59-L98 的源码,可以还原出完整的内部流程:

load( urls, onLoad, onProgress, onError ) {

	const texture = new CubeTexture();
	texture.colorSpace = SRGBColorSpace;   // 关键:默认 sRGB

	const loader = new ImageLoader( this.manager );  // 复用传入的 manager
	loader.setCrossOrigin( this.crossOrigin );       // 透传跨域设置
	loader.setPath( this.path );                     // 透传基础路径

	let loaded = 0;

	function loadTexture( i ) {
		loader.load( urls[ i ], function ( image ) {
			texture.images[ i ] = image;   // 按下标写入对应面
			loaded ++;
			if ( loaded === 6 ) {          // 六张全部成功才完成
				texture.needsUpdate = true;
				if ( onLoad ) onLoad( texture );
			}
		}, undefined, onError );           // onProgress 直接传 undefined
	}

	for ( let i = 0; i < urls.length; ++ i ) loadTexture( i );

	return texture;                        // 先返回,图片异步填充
}

这段实现揭示了几个重要事实:

  1. texture.images[i] 按下标对应urls 数组第 i 张图片被写进 CubeTexture 的第 i 个面,因此六面的排列顺序直接决定贴图朝向,必须严格遵循前文约定的 px、nx、py、ny、pz、nz 顺序;
  2. 计数判定:内部维护 loaded 计数器,只有 loaded === 6(六张全部成功)才置 texture.needsUpdate = true 并触发 onLoad。这解释了为何 onLoad 的触发时机是整个立方体贴图而非单张图片——单张失败走 onError,且永远不会触发 onLoad
  3. onProgress 被显式忽略:源码调用 loader.load(url, onLoad, undefined, onError),与文档「Unsupported in this loader」一致;
  4. 返回时机load() 是同步返回 CubeTexture 对象的(此时内部 images 还为空),图片在网络层异步填充。这正是文档提醒的"如果直接拿返回值用,贴图可能稍后才在场景中弹出"的原因。

底层协作:ImageLoader 与 Cache 缓存

CubeTextureLoader 把 this.managerthis.crossOriginthis.path 三个配置透传给内部新建的 ImageLoader,即每个 CubeTextureLoader 实例的六张图共享同一个 ImageLoader 实例与同一套路径/跨域配置。

ImageLoader 内部有两个值得了解的机制:

  • URL 解析:加载前会执行 url = this.manager.resolveURL( url )(配合 setPath 拼接 base path 在进入 ImageLoader 之前已完成),便于 LoadingManager 做 URL 重写;
  • Cache 缓存:图片以 image:${url} 为键缓存在 Cache 中。当同一 URL 再次被请求且缓存图片已 complete 时,会通过 setTimeout(0) 异步直接返回缓存结果,避免重复网络请求;若缓存图片尚未加载完成,新的回调会被挂到等待队列里,待原始图片加载完成后一并触发(见 ImageLoader.js#L53-L86)。

对 CubeTextureLoader 的意义:如果六张图中某几张曾被其他 CubeTextureLoader(或 TextureLoader)加载过,多次调用会命中缓存、显著提速;而全部六张图仍是并发请求,不存在按序串行等待。

返回的 CubeTexture 对象

加载结果 CubeTextureTexture 的子类,除继承 Texture 全部属性外,还有以下特点(其 API 文档见 docs/pages/CubeTexture.html.md):

  • 默认映射为 CubeReflectionMapping:用于反射/天空盒采样;
  • flipY 默认为 false:立方体贴图不会在 GPU 上传时沿 Y 轴翻转,这与普通纹理相反,是 CubeTexture 构造函数里被显式覆盖的行为;
  • imagesimage 的别名get images() / set images() 只是读写内部的 this.image,即六张图片的数组;
  • isCubeTexture 只读标志true,可用于类型判断;
  • 包装/采样相关默认值(来自 Texture 基类链):wrapSwrapT 默认 ClampToEdgeWrapping(环境贴图通常不应平铺)、magFilter 默认 LinearFilterminFilter 默认 LinearMipmapLinearFilterformat 默认 RGBAFormattype 默认 UnsignedByteTypeanisotropy 默认 Texture.DEFAULT_ANISOTROPY

若需在加载后微调,典型做法是修改返回纹理的 mapping(如切换 CubeReflectionMapping / CubeRefractionMapping)、采样器或直接替换某个面的图片后把 needsUpdate 置为 true

单元测试与源码结构佐证

仓库在 test/unit/src/loaders/CubeTextureLoader.tests.js 中为 CubeTextureLoader 提供了 QUnit 单元测试,覆盖两点:

  • 继承关系:断言 new CubeTextureLoader()Loader 的实例(instanceof Loader === true);
  • 可实例化new CubeTextureLoader() 能正常创建对象。

上述断言与 src/loaders/CubeTextureLoader.jsclass CubeTextureLoader extends Loader 的声明互相印证。该加载器没有复杂的解析逻辑(无需 parse()),职责集中且实现精简,因此测试面较窄。

与之配套的纹理侧测试位于 test/unit/src/textures/CubeTexture.tests.js,验证 CubeTexture 自身的属性与行为。

实践清单与常见问题

综合全文,给出实战建议清单:

  1. setPath 再传相对文件名:让 urls 数组保持六个简短文件名,路径统一管理,便于换资源目录;
  2. 严格保证顺序为 px, nx, py, ny, pz, nz:任意两面对调都会导致天空盒/环境贴图镜像或朝向错误;
  3. 确保 urls 长度恰为 6:源码只在 loaded === 6 时回调,少于 6 张永远不会触发 onLoad(且多传条目时会对超出 6 的部分继续加载,但只前 6 个下标会被写入纹理);
  4. 不要依赖 onProgress:该 loader 明确不支持,需要精确到单张的进度信息请自行用六个 Promise/单独监听;
  5. 跨域注意:跨域加载图片须配合 setCrossOrigin('anonymous') 且服务器返回正确的 CORS 头;纯 data URI 则可跳过跨域设置;
  6. 色彩空间无需操心:loader 已把 colorSpace 设为 SRGBColorSpace,不要重复设置为线性空间以免颜色过曝/变暗;
  7. Pos-x / neg-x 交换是正常行为:源于左手系约定与 three.js 右手系的差异,纹理在第三方工具里"看起来反了"不代表写错。

只要遵守六面顺序与两坐标约定,CubeTextureLoader 就能以最少的代码为你的场景注入天空盒或环境反射能力。

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391