three.js WebGLCubeRenderTarget 全面指南:立方体渲染目标与动态环境贴图
2026/9/9 15:14:16 网站建设 项目流程

three.js WebGLCubeRenderTarget 全面指南:立方体渲染目标与动态环境贴图

【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js

WebGLCubeRenderTarget是 three.js(当前仓库GitHub_Trending/th/three.js)在 WebGL 渲染环境下用于生成立方体贴图(Cube Map)的渲染目标类型。它常与 CubeCamera 配合,把场景中某一点六个方向的视图分别渲染成立方体的六个面,从而为物体提供包含周围环境的实时反射;也可通过fromEquirectangularTexture()将一张等距柱状投影(Equirectangular)贴图一次性地烘焙为立方体贴图。读完本文,你将掌握其构造参数、纹理选项、clear()fromEquirectangularTexture()的用法与底层实现,并能在真实示例中搭建一套“动态环境反射”的渲染管线。

概览:继承关系与定位

文档页 docs/pages/WebGLCubeRenderTarget.html 给出的继承链为:

EventDispatcher → RenderTarget → WebGLRenderTarget → WebGLCubeRenderTarget

从 src/renderers/WebGLCubeRenderTarget.js 的实现可见,它在构造时调用super( size, size, options ),即宽高始终相等(这正是立方体贴图各面必须为正方形的直接原因);随后把默认纹理替换为 6 面共享同一image对象的CubeTexture,从而真正成为一个“面向立方体六个面渲染”的特殊渲染目标。

值得强调的是它的定位边界:它专属于WebGLRenderer路径;WebGPU 渲染器使用的是等价的 src/renderers/common/CubeRenderTarget.js(CubeRenderTarget,详见文末对照小节)。

构造函数与配置选项

new WebGLCubeRenderTarget( size, options )

const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256 ); // 或带上纹理选项 const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter, type: THREE.HalfFloatType } );

size:渲染目标边长(像素),默认1。由于构造实现是super( size, size, options ),它同时作为宽和高。实际项目通常取128256512等 2 的幂——当开启 mipmap 时 2 的幂尺寸配合LinearMipmapLinearFilter才能得到正确的完整 mipmap 链。

options:完整配置对象。与普通WebGLRenderTarget的 options 一致,字段定义于 src/core/RenderTarget.js 中的RenderTarget~Options。下表为最常用的字段及其默认值:

选项默认值说明
generateMipmapsfalse是否生成 mipmap。环境贴图反射通常置true以降低采样锯齿
minFilter/magFilterLinearFilter过滤方式;配合 mipmap 常用LinearMipmapLinearFilter
formatRGBAFormat颜色纹理格式
typeUnsignedByteType纹理数据类型,如HalfFloatType(HDR 反射常用)
wrapS/wrapTClampToEdgeWrappingUV 环绕方式
anisotropy1各向异性过滤等级
colorSpaceNoColorSpace色彩空间(如SRGBColorSpace
depthBuffertrue是否分配深度缓冲
stencilBufferfalse是否分配模板缓冲
samples0MSAA 采样数,0表示关闭
depthTexturenull可选的深度纹理
internalFormatnull内部格式覆盖项

构造器将这些选项通过内部的_setTextureOptions( options )(见 src/core/RenderTarget.js)写入纹理,因此凡是在WebGLRenderTarget上可用的纹理配置,在立方体渲染目标上同样生效。单元测试 test/unit/src/renderers/WebGLCubeRenderTarget.tests.js 也专门验证了“传入magFilter: NearestFilter的 options 后,object.texture.magFilter应为NearestFilter”这一行为。

属性

.isWebGLCubeRenderTarget : boolean(只读)

类型判定标志,默认true。构造器中直接写入,用于运行时区分该对象是否为立方体渲染目标,等价于其它对象的isXXX惯例标志。

.texture : CubeTexture

文档页标注为 “Overwritten with a different texture type”,源码中确实将基类的Texture覆写为CubeTexture

const image = { width: size, height: size, depth: 1 }; const images = [ image, image, image, image, image, image ]; this.texture = new CubeTexture( images ); this._setTextureOptions( options ); this.texture.isRenderTargetTexture = true;

需要注意:CubeTexture本身在 src/textures/CubeTexture.js 中默认flipY = false,这与普通纹理不同。正是这个texture.isRenderTargetTexture标志,帮助渲染器识别“这是渲染目标的输出纹理”,从而避免对坐标方向做多余的翻转(源码注释详细解释了 WebGL 立方体贴图历史上遵循左手坐标系、而 three.js 世界为右手坐标系,环境贴图因此表现为 px/nx 交换的约定)。渲染时把该纹理赋给材质即可作为环境映射使用:

material.envMap = cubeRenderTarget.texture;

继承自基类的属性

立方体渲染目标同样继承RenderTarget的公开属性,例如widthheightdepthviewportscissorsamplesdepthBufferstencilBuffer等(详见 src/core/RenderTarget.js),其中depth默认1viewport/scissor初始化为整个目标区域。由于继承自EventDispatcher,还可在其上监听dispose事件。

方法

.clear( renderer, color = true, depth = true, stencil = true )

清除立方体渲染目标中六个面的缓冲。源码实现是依次将渲染器绑定到第 0~5 个面并执行renderer.clear()

clear( renderer, color = true, depth = true, stencil = true ) { const currentRenderTarget = renderer.getRenderTarget(); for ( let i = 0; i < 6; i ++ ) { renderer.setRenderTarget( this, i ); renderer.clear( color, depth, stencil ); } renderer.setRenderTarget( currentRenderTarget ); }

注意它先把当前渲染目标保存下来、清理完成后恢复,因此调用前后不会破坏你正在进行的渲染状态。三个布尔参数分别控制颜色、深度、模板缓冲是否被清除,默认均true

.fromEquirectangularTexture( renderer, texture ) : WebGLCubeRenderTarget

把一张等距柱状投影贴图(panorama 全景图)转换为立方体贴图并写入本渲染目标。这是一个同步完成的烘焙操作,完成即可直接用本目标作为环境贴图。转换结果保存了源纹理的类型、色彩空间、mipmap 开关及过滤方式:

fromEquirectangularTexture( renderer, texture ) { this.texture.type = texture.type; this.texture.colorSpace = texture.colorSpace; this.texture.generateMipmaps = texture.generateMipmaps; this.texture.minFilter = texture.minFilter; this.texture.magFilter = texture.magFilter; // ... 渲染 6 面 return this; }

典型用法:

const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 512, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } ); // 例如从 RGBELoader 加载的 HDR 全景图 texture cubeRenderTarget.fromEquirectangularTexture( renderer, equirectTexture ); scene.environment = cubeRenderTarget.texture;

从源码结构看,该方法的底层原理值得展开:

  • 它构造一个 5×5×5 的BoxGeometry,配合side: BackSideblending: NoBlendingShaderMaterial,把立方体作为被采样对象;
  • 顶点着色器中用transformDirection( position, modelMatrix )把顶点位置变换为世界方向vWorldDirection
  • 片元着色器调用 three.js 着色器库中equirectUv( direction )完成“世界方向 → 等距柱状 UV”的映射,再采样sampler2D tEquirect得到颜色;
  • 随后创建new CubeCamera( 1, 10, this )并调用camera.update( renderer, mesh ),一次调用即把立方体的六个面渲染进本目标的六个面;
  • 两个值得注意的细节:若源纹理minFilterLinearMipmapLinearFilter,转换期间会临时退化为LinearFilter(源码注释 “Avoid blurred poles”),结束后恢复;所有临时 geometry / material 在结束后均被dispose()

该流程的完整参数与行为可在 src/renderers/WebGLCubeRenderTarget.js 中核对。

实战:用 CubeCamera 打造动态实时环境反射

WebGLCubeRenderTarget最常见的动态场景是与 CubeCamera(源码 src/cameras/CubeCamera.js)配合:在运动物体所在位置,用六个PerspectiveCamera(fov 为 -90、aspect 为 1)分别向六个方向渲染一次场景,输出即该点周围的实时环境。文档 docs/pages/CubeCamera.html.md 给出的经典工作流:

// 1. 创建立方体渲染目标 const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } ); // 2. 创建 CubeCamera(near、far、渲染目标),并加入场景 const cubeCamera = new THREE.CubeCamera( 1, 100000, cubeRenderTarget ); scene.add( cubeCamera ); // 3. 把渲染目标纹理作为材质 envMap const chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeRenderTarget.texture } ); const car = new THREE.Mesh( carGeometry, chromeMaterial ); scene.add( car ); // 4. 更新环境:让目标物体暂时不可见,避免其“自我遮挡” car.visible = false; cubeCamera.position.copy( car.position ); cubeCamera.update( renderer, scene ); // 5. 渲染主场景 car.visible = true; renderer.render( scene, camera );

从 src/cameras/CubeCamera.js 的实现看,CubeCamera.update()会依次以renderer.setRenderTarget( renderTarget, 0..5, activeMipmapLevel )切换六个面并分别渲染;其中第 6 面(NZ)渲染完成时所有面均已定义,随即恢复texture.generateMipmaps让 mipmap 在最后一次render()中一并生成,最后把texture.needsPMREMUpdate置为true。此外它还会临时关闭renderer.xr.enabled、并缓存与恢复当前的渲染目标与立方体面索引,避免污染外部渲染状态。调用者需要自行处理“目标物体自遮挡”问题(上面的car.visible = false即是官方推荐的规避手段)。

仓库内可运行的真实示例

仓库在 examples/webgl_materials_cubemap_dynamic.html 中提供了完整的动态反射示例,其关键片段:

// HDR 全景作为背景与全局环境 new HDRLoader().setPath( 'textures/equirectangular/' ).load( 'quarry_01_1k.hdr', function ( texture ) { texture.mapping = THREE.EquirectangularReflectionMapping; scene.background = texture; scene.environment = texture; } ); // 256 大小的立方体渲染目标,半浮点精度(适合 HDR 反射) cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256 ); cubeRenderTarget.texture.type = THREE.HalfFloatType; cubeCamera = new THREE.CubeCamera( 1, 1000, cubeRenderTarget ); // 金属球材质的 envMap 指向立方体渲染目标纹理 material = new THREE.MeshStandardMaterial( { envMap: cubeRenderTarget.texture, roughness: 0.05, metalness: 1 } );

动画循环中每一帧都执行cubeCamera.update( renderer, scene ),使金属球始终反射到移动的立方体与环面结物体——这就是“动态环境贴图”最直观的呈现。该示例还演示了两个关键实践:HDR 反射应把texture.type设为THREE.HalfFloatType,以及半浮点纹理下对采样滤波的要求。仓库中另见examples/webgl_materials_cubemap_render_to_mipmaps.htmlexamples/webgl_lightprobe_cubecamera.html等基于WebGLCubeRenderTarget的衍生用法。

源码级要点补充

  • 坐标约定:构造器中有一段详细注释——WebGL 立方体贴图按历史上 RenderMan 规范的左手坐标系约定存储(沿 +z 看时 +x 朝右),而 three.js 世界为右手坐标系;普通环境贴图因此常出现 px/nx 交换的观感,而isRenderTargetTexture标志让渲染器自动跳过该翻转。阅读 src/renderers/WebGLCubeRenderTarget.js 顶部注释可完整理解这一约定。
  • 内存/尺寸:六面共享同一份image对象,单面尺寸为size,因此总内存约为普通同尺寸纹理的 6 倍,创建时应权衡分辨率。
  • 测试证据:单元测试 test/unit/src/renderers/WebGLCubeRenderTarget.tests.js 确认了继承关系(instanceof WebGLRenderTarget)、无参实例化、以及 options 能传导至纹理三个事实。
  • 资源释放:不再使用时应调用dispose(),该方法自基类RenderTarget继承并派发dispose事件,便于渲染器释放对应 GPU 资源。

WebGPU 时代的对应物:CubeRenderTarget

仓库在渲染架构演进中,为 WebGPU 渲染路径提供了功能对等的 src/renderers/common/CubeRenderTarget.js(CubeRenderTarget)。两者 API 高度一致:同样new CubeRenderTarget( size, options )、覆写CubeTexture、提供fromEquirectangularTexture()clear();区别在于前者基于WebGLRendererShaderMaterial驱动立方体转换,而后者直接继承RenderTarget、内部用NodeMaterial与 TSL 节点(equirectUVpositionWorldDirection)实现,由文档 docs/pages/CubeRenderTarget.html.md 收录。选用哪个类型,取决于你的渲染器是WebGLRenderer还是WebGPURenderer——fromEquirectangularTexture的用法在两条渲染路径上保持一致。

【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询