完整指南)
three.js RenderPass 深度解析基于 EffectComposer 的后期处理美颜通道beauty pass完整指南【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js导读在 three.js 的后期处理Post Processing管线中RenderPass 是所有基于EffectComposer的效果链的第一棒它接收场景与相机把正常渲染结果以美颜通道beauty pass的形式写入渲染目标供后续模糊、泛光、辉光等效果逐级加工。本文以官方 API 文档为主体结合仓库内 RenderPass.js 的真实实现与 webgl_postprocessing.html 等示例完整讲解它的导入方式、构造函数参数、全部属性、渲染流程与底层原理让你能正确搭建属于自己的后期处理管线。核心作用什么是 RenderPass从源码注释见 RenderPass.js可以准确概括它的定位它接收一个相机和一个场景为后续的后期处理效果产生一张 beauty pass美颜/基础渲染通道。继承关系上它属于Pass → RenderPass即它继承自 Pass.js 中定义的抽象基类Pass。在官方文档中RenderPass通常作为整条后期处理链上的第一个通道被加入EffectComposer负责把原始场景渲染结果从默认帧缓冲转移到后续特效可以读取的缓冲中。最小代码示例const renderPass new RenderPass( scene, camera ); composer.addPass( renderPass );这段代码在 EffectComposer.js 的类注释示例中同样出现是官方推荐的标准用法。导入方式RenderPass是一个 addon附加模块并未打包进 three.js 核心因此必须显式从 addons 目录导入import { RenderPass } from three/addons/postprocessing/RenderPass.js;它依赖 three.js 核心的Color类与同目录的Pass基类实际源码中的导入语句为import { Color } from three; import { Pass } from ./Pass.js;构造函数详解new RenderPass( scene, camera, overrideMaterial, clearColor, clearAlpha )从 RenderPass.js 可以看到五个参数中只有前两个是必传项后三个均有默认值参数类型默认值说明sceneScene必传要渲染的场景cameraCamera必传用于该次渲染的相机透视相机或正交相机均可overrideMaterialMaterialnull覆盖材质。若设置场景中所有物体统一使用该材质渲染clearColornumber \| Color \| stringnull本次渲染的清屏颜色null表示沿用 renderer 当前清屏色clearAlphanumbernull本次渲染的清屏透明度null表示沿用 renderer 当前透明度构造函数内部把参数原样存入实例属性this.scene、this.camera、this.overrideMaterial、this.clearColor、this.clearAlpha同时初始化了三个与Pass基类默认值不同的布尔标志与一个私有颜色暂存对象this.clear true; // 基类默认 falseRenderPass 重写为默认执行清屏 this.clearDepth false; // 仅当 clearfalse 时是否仍只清深度 this.needsSwap false; // 基类默认 trueRenderPass 禁用交换 this.isRenderPass true; // 只读类型标记 this._oldClearColor new Color();需要特别说明的参数语义clearColor/clearAlpha传null的含义并非不执行清屏而是不修改 renderer 的清屏状态使用 renderer 现有的setClearColor()/setClearAlpha()值。若想让整张画面在渲染前清成指定颜色只需给这两个参数赋值clearColor支持与 renderer 相同的三种形式十六进制数字如0x112233、THREE.Color实例或 CSS 颜色字符串如red。overrideMaterial一旦设置render()时会把scene.overrideMaterial临时替换为你传入的材质渲染完成后再还原。该机制的底层字段定义于 Scene.jsthis.overrideMaterial null用途包括调试线框/白模查看或批量修改渲染外观。与 Pass 基类默认值的差异速查Pass基类Pass.js默认enabled true、needsSwap true、clear false、renderToScreen false。而RenderPass重写了clear true默认要清屏与needsSwap false渲染结果不需要与交换缓冲互换。原因在于RenderPass 通常位于链首其结果要留在当前缓冲中直接被下一通道读取。属性全览.camera : Camera本次渲染使用的相机。RenderPass 本身不创建相机必须由使用者传入并自行维护其位置、朝向与投影参数。.clear : boolean默认true表示在渲染前执行一次清屏操作。这是对 Pass#clear 的重写基类默认为false。.clearAlpha : number本次渲染的清屏透明度默认null沿用 renderer 设置。取值范围通常为 0~1。.clearColor : number | Color | string本次渲染的清屏颜色默认null沿用 renderer 设置。支持数值、Color实例或颜色字符串。.clearDepth : boolean默认false。当.clear被设为false、但又想单独清掉深度缓冲比如为透明背景叠加场景做准备时可将其置为true这样在不清颜色/模板的情况下单独执行clearDepth()。.isRenderPass : boolean只读默认true用于类型标记表明该 pass 负责渲染场景本体。源码中显式注释为readonly。.needsSwap : boolean默认false重写自 Pass#needsSwap基类默认true。语义是本通道渲染完成后不需要composer 交换 read/write 缓冲。原因见 EffectComposer.js 的驱动逻辑——只有needsSwap true的 pass 在渲染后才会触发swapBuffers()。.overrideMaterial : Material覆盖材质默认null。若设置场景中所有对象都会使用该材质渲染。.scene : Scene要渲染的场景。渲染方法与内部执行流程render( renderer, writeBuffer, readBuffer, deltaTime, maskActive )该方法在基类中只是一个抛出错误的抽象占位Pass.jsRenderPass 对其进行了重写以实现实际渲染逻辑。其中rendererWebGLRenderer。注意此通道只面向 WebGLRenderer设计Pass.js 明确说明整个后处理模块仅适用于 WebGL 渲染器。writeBuffer写入缓冲理论上是本通道的渲染目标。readBuffer读取缓冲本通道可从其中获取前一 pass 的结果。deltaTime时间增量秒。maskActive当前是否有模板遮罩Mask处于激活状态。从 RenderPass.js 的实现可以看到其完整的执行序列render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { // 1) 关闭渲染器的自动清屏改由本通道自己控制清屏时机 const oldAutoClear renderer.autoClear; renderer.autoClear false; // 2) 若设置了 overrideMaterial临时替换场景的 overrideMaterial if ( this.overrideMaterial ! null ) { oldOverrideMaterial this.scene.overrideMaterial; this.scene.overrideMaterial this.overrideMaterial; } // 3) 若设置了 clearColor/clearAlpha保存旧值并临时改写 renderer 清屏状态 if ( this.clearColor ! null ) { renderer.getClearColor( this._oldClearColor ); renderer.setClearColor( this.clearColor, renderer.getClearAlpha() ); } if ( this.clearAlpha ! null ) { oldClearAlpha renderer.getClearAlpha(); renderer.setClearAlpha( this.clearAlpha ); } // 4) 需要时只清深度 if ( this.clearDepth true ) { renderer.clearDepth(); } // 5) 指定渲染目标renderToScreen 时渲染到屏幕(null)否则渲染到 readBuffer renderer.setRenderTarget( this.renderToScreen ? null : readBuffer ); // 6) 需要时按 renderer 的颜色/深度/模板自动清屏标志执行 clear if ( this.clear true ) { renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); } // 7) 真正渲染场景 renderer.render( this.scene, this.camera ); // 8) 依次还原 overrideMaterial、clearColor、clearAlpha、autoClear ... }三个值得注意的实现细节渲染目标是readBuffer而非writeBuffer。这与直觉相反却是刻意的设计因为needsSwap falsecomposer 不会在它之后交换缓冲渲染结果写入readBuffer后即停留在那里供下一通道作为输入读取。临时状态一律还原。步骤 8 会把scene.overrideMaterial、renderer 清屏颜色/透明度以及autoClear全部恢复为进入前的值避免污染链上后续 pass 的渲染状态。renderToScreen决定最终落点。源码用this.renderToScreen ? null : readBuffer决定渲染目标而renderToScreen本身由 composer 在每个 pass 执行前统一赋值——最后一个启用中的 pass 会被自动设为true见 EffectComposer.js。与 EffectComposer 的协作流程EffectComposer维护了一个有序的 pass 数组this.passes并通过 addPass / insertPass / removePass 管理成员。composer.render()会逐一遍历所有enabled的 pass按顺序调用各自的render()for ( let i 0, il this.passes.length; i il; i ) { const pass this.passes[ i ]; if ( pass.enabled false ) continue; pass.renderToScreen ( this.renderToScreen this.isLastEnabledPass( i ) ); pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive ); if ( pass.needsSwap ) { /* ... */ this.swapBuffers(); } }典型管线如下import { EffectComposer } from three/addons/postprocessing/EffectComposer.js; import { RenderPass } from three/addons/postprocessing/RenderPass.js; import { ShaderPass } from three/addons/postprocessing/ShaderPass.js; import { OutputPass } from three/addons/postprocessing/OutputPass.js; // ...创建 renderer / scene / camera... const composer new EffectComposer( renderer ); composer.addPass( new RenderPass( scene, camera ) ); // ① 正常渲染 → beauty pass composer.addPass( new ShaderPass( myEffectShader ) ); // ② 你的自定义后处理 composer.addPass( new OutputPass() ); // ③ 色调映射/颜色空间转换并输出屏幕 function animate() { composer.render(); // 替代 renderer.render() requestAnimationFrame( animate ); }这正是 webgl_postprocessing.html 的真实结构——EffectComposer创建后首先addPass( new RenderPass( scene, camera ) )再依次追加ShaderPass点阵、RGB 偏移与OutputPass最后用composer.render()替代renderer.render()驱动循环。仓库中 30 余个后期处理示例如 webgl_postprocessing_unreal_bloom.html、webgl_postprocessing_ssao.html 等均遵循此模式。为什么最后通常要接一个 OutputPass由于 RenderPass 之后所有效果都在浮点半精度HalfFloatType的离屏缓冲中完成EffectComposer 默认创建HalfFloatType渲染目标见 EffectComposer.js最后一个通道负责把结果做色调映射与 sRGB 转换后再输出到屏幕避免画面发灰或颜色失真。链末通道会被 composer 自动标记为renderToScreen无需手动设置。多相机 / 深度反转等进阶场景一个 EffectComposer 内可以加入多个 RenderPass。例如 webgl_reversed_depth_buffer.html 中就为三个不同相机分别创建了各自的 composer每个 composer 都从自己的new RenderPass(...)开始。这印证了 RenderPass 的复用性一个场景相机组合即是一条独立后处理链的起点。与模板遮罩MaskPass的组合render()签名中的maskActive由 composer 根据链上是否存在MaskPass/ClearMaskPass动态维护EffectComposer.js。当 RenderPass 之后紧跟遮罩类通道时只有遮罩区域内的像素会继续被后续效果影响。RenderPass 自身不对遮罩状态做任何假设仅把它透传给后续逻辑因此放在遮罩开始前是最稳妥的编排方式。完整可运行的实战模板以下示例整合了场景搭建、RenderPass 接入、两段式后期处理与输出可直接在基于 import map 的 three.js 项目中运行script typeimportmap { imports: { three: ./build/three.module.js, three/addons/: ./examples/jsm/ } } /script script typemodule import * as THREE from three; import { EffectComposer } from three/addons/postprocessing/EffectComposer.js; import { RenderPass } from three/addons/postprocessing/RenderPass.js; import { OutputPass } from three/addons/postprocessing/OutputPass.js; let renderer, scene, camera, composer; init(); animate(); function init() { // 渲染器 renderer new THREE.WebGLRenderer(); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); // 场景与相机 scene new THREE.Scene(); camera new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 100 ); camera.position.z 3; const geometry new THREE.BoxGeometry( 1, 1, 1 ); const material new THREE.MeshStandardMaterial( { color: 0x00aaff } ); scene.add( new THREE.Mesh( geometry, material ) ); scene.add( new THREE.AmbientLight( 0xffffff, 0.5 ) ); // 后期处理管线RenderPass 作为第一通道 composer new EffectComposer( renderer ); composer.addPass( new RenderPass( scene, camera ) ); composer.addPass( new OutputPass() ); } function animate() { requestAnimationFrame( animate ); composer.render(); // 用 composer.render() 代替 renderer.render() } /script常见使用要点与注意事项RenderPass 必须在所有依赖场景结果的 pass 之前加入通常第一个addPass就是它顺序决定画面内容来源放错位置会得到上一帧或错误通道的输入。透明背景的两种做法希望保留渲染器全局清屏色时保持clearColor/clearAlpha为null希望本通道专用某种清屏色时在构造或属性中显式指定例如renderPass.clearColor 0x000000; renderPass.clearAlpha 1;。调试场景外观设置overrideMaterial如new THREE.MeshBasicMaterial({ color: 0xff0000 })可强制所有物体单色渲染用于检查网格布局不影响后续要还原的材质。不需要自动清屏时把clear设为false可在不清屏的前提下继续叠加渲染若此时仍需保留有效深度可单独开启clearDepth true。大小与像素比composer 创建时按renderer.getPixelRatio()生成内部缓冲窗口缩放时应同时调用renderer.setSize()与composer.setSize()见 webgl_postprocessing.html避免通道输出与画布尺寸错位。适用环境限定整个postprocessing模块含 RenderPass仅在 WebGL 渲染器下工作WebGPU 渲染路径请使用对应的节点化后处理方案。延伸阅读RenderPass 官方文档、Pass 基类文档、EffectComposer 文档源码RenderPass.js、Pass.js、EffectComposer.js实战示例webgl_postprocessing.html基础多效果链、webgl_postprocessing_unreal_bloom.html泛光、webgl_reversed_depth_buffer.html多 RenderPass 多管线【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考