
three.js WebGLCubeRenderTarget 全面指南立方体渲染目标与动态环境贴图【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsWebGLCubeRenderTarget是 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.jsCubeRenderTarget详见文末对照小节。构造函数与配置选项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 )它同时作为宽和高。实际项目通常取128、256或512等 2 的幂——当开启 mipmap 时 2 的幂尺寸配合LinearMipmapLinearFilter才能得到正确的完整 mipmap 链。options完整配置对象。与普通WebGLRenderTarget的 options 一致字段定义于 src/core/RenderTarget.js 中的RenderTarget~Options。下表为最常用的字段及其默认值选项默认值说明generateMipmapsfalse是否生成 mipmap。环境贴图反射通常置true以降低采样锯齿minFilter/magFilterLinearFilter过滤方式配合 mipmap 常用LinearMipmapLinearFilterformatRGBAFormat颜色纹理格式typeUnsignedByteType纹理数据类型如HalfFloatTypeHDR 反射常用wrapS/wrapTClampToEdgeWrappingUV 环绕方式anisotropy1各向异性过滤等级colorSpaceNoColorSpace色彩空间如SRGBColorSpacedepthBuffertrue是否分配深度缓冲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覆写为CubeTextureconst 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的公开属性例如width、height、depth、viewport、scissor、samples、depthBuffer、stencilBuffer等详见 src/core/RenderTarget.js其中depth默认1、viewport/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: BackSide、blending: NoBlending的ShaderMaterial把立方体作为被采样对象顶点着色器中用transformDirection( position, modelMatrix )把顶点位置变换为世界方向vWorldDirection片元着色器调用 three.js 着色器库中equirectUv( direction )完成“世界方向 → 等距柱状 UV”的映射再采样sampler2D tEquirect得到颜色随后创建new CubeCamera( 1, 10, this )并调用camera.update( renderer, mesh )一次调用即把立方体的六个面渲染进本目标的六个面两个值得注意的细节若源纹理minFilter为LinearMipmapLinearFilter转换期间会临时退化为LinearFilter源码注释 “Avoid blurred poles”结束后恢复所有临时 geometry / material 在结束后均被dispose()。该流程的完整参数与行为可在 src/renderers/WebGLCubeRenderTarget.js 中核对。实战用 CubeCamera 打造动态实时环境反射WebGLCubeRenderTarget最常见的动态场景是与 CubeCamera源码 src/cameras/CubeCamera.js配合在运动物体所在位置用六个PerspectiveCamerafov 为 -90、aspect 为 1分别向六个方向渲染一次场景输出即该点周围的实时环境。文档 docs/pages/CubeCamera.html.md 给出的经典工作流// 1. 创建立方体渲染目标 const cubeRenderTarget new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } ); // 2. 创建 CubeCameranear、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.html与examples/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.jsCubeRenderTarget。两者 API 高度一致同样new CubeRenderTarget( size, options )、覆写CubeTexture、提供fromEquirectangularTexture()与clear()区别在于前者基于WebGLRenderer与ShaderMaterial驱动立方体转换而后者直接继承RenderTarget、内部用NodeMaterial与 TSL 节点equirectUV、positionWorldDirection实现由文档 docs/pages/CubeRenderTarget.html.md 收录。选用哪个类型取决于你的渲染器是WebGLRenderer还是WebGPURenderer——fromEquirectangularTexture的用法在两条渲染路径上保持一致。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考