学习threejs,使用EffectComposer后期处理组合器(采用RenderPass、MaskPass、ClearMaskPass、ShaderPass渲染通道)_threejs effectcomposer
👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:threejs gis工程师
文章目录
- 一、🍀前言
-
- 1.1 ☘️THREE.EffectComposer 后期处理
-
- 1.1.1 ☘️代码示例
- 1.1.2 ☘️构造函数
- 1.1.3 ☘️属性
- 1.1.4 ☘️方法
- 1.2 ☘️THREE.RenderPass
-
- 1.2.1 ☘️构造函数
- 1.2.2 ☘️属性
- 1.2.3 ☘️方法
- 1.3 ☘️THREE.MaskPass
-
- 1.3.1 ☘️构造函数
- 1.3.2 ☘️属性
- 1.3.3 ☘️方法
- 1.4 ☘️THREE.ClearMaskPass
-
- 1.4.1 ☘️构造函数
- 1.4.2 ☘️属性
- 1.4.3 ☘️方法
- 1.5 ☘️THREE.ShaderPass
-
- 1.5.1 ☘️构造函数
- 1.5.2 ☘️属性
- 1.5.3 ☘️方法
- 二、🍀使用EffectComposer后期处理组合器(采用RenderPass、MaskPass、ClearMaskPass、ShaderPass渲染通道)
-
- 1. ☘️实现思路
- 2. ☘️代码样例
一、🍀前言
本文详细介绍如何基于threejs在三维场景中使用EffectComposer后期处理组合器(采用RenderPass、MaskPass、ClearMaskPass、ShaderPass渲染通道),亲测可用。希望能帮助到您。一起学习,加油!加油!
1.1 ☘️THREE.EffectComposer 后期处理
THREE.EffectComposer 用于在three.js中实现后期处理效果。该类管理了产生最终视觉效果的后期处理过程链。 后期处理过程根据它们添加/插入的顺序来执行,最后一个过程会被自动渲染到屏幕上。
1.1.1 ☘️代码示例
import { EffectComposer } from \'three/examples/jsm/postprocessing/EffectComposer.js\';import { RenderPass } from \'three/examples/jsm/postprocessing/RenderPass.js\';// 初始化 composerconst composer = new EffectComposer(renderer);// 创建 RenderPass 并添加到 composerconst renderPass = new RenderPass(scene, camera);composer.addPass(renderPass);// 添加其他后期处理通道(如模糊)// composer.addPass(blurPass);// 在动画循环中渲染function animate() { composer.render(); requestAnimationFrame(animate);}
1.1.2 ☘️构造函数
EffectComposer( renderer : WebGLRenderer, renderTarget : WebGLRenderTarget )
renderer – 用于渲染场景的渲染器。
renderTarget – (可选)一个预先配置的渲染目标,内部由 EffectComposer 使用。
1.1.3 ☘️属性
.passes : Array
一个用于表示后期处理过程链(包含顺序)的数组。
渲染通道:BloomPass 该通道会使得明亮区域参入较暗的区域。模拟相机照到过多亮光的情形DotScreenPass 将一层黑点贴到代表原始图片的屏幕上FilmPass 通过扫描线和失真模拟电视屏幕MaskPass 在当前图片上贴一层掩膜,后续通道只会影响被贴的区域RenderPass 该通道在指定的场景和相机的基础上渲染出一个新的场景SavePass 执行该通道时,它会将当前渲染步骤的结果复制一份,方便后面使用。这个通道实际应用中作用不大;ShaderPass 使用该通道你可以传入一个自定义的着色器,用来生成高级的、自定义的后期处理通道TexturePass 该通道可以将效果组合器的当前状态保存为一个纹理,然后可以在其他EffectCoposer对象中将该纹理作为输入参数
.readBuffer : WebGLRenderTarget
内部读缓冲区的引用。过程一般从该缓冲区读取先前的渲染结果。
.renderer : WebGLRenderer
内部渲染器的引用。
.renderToScreen : Boolean
最终过程是否被渲染到屏幕(默认帧缓冲区)。
.writeBuffer : WebGLRenderTarget
内部写缓冲区的引用。过程常将它们的渲染结果写入该缓冲区。
1.1.4 ☘️方法
.addPass ( pass : Pass ) : undefined
pass – 将被添加到过程链的过程
将传入的过程添加到过程链。
.dispose () : undefined
释放此实例分配的 GPU 相关资源。每当您的应用程序不再使用此实例时调用此方法。
.insertPass ( pass : Pass, index : Integer ) : undefined
pass – 将被插入到过程链的过程。
index – 定义过程链中过程应插入的位置。
将传入的过程插入到过程链中所给定的索引处。
.isLastEnabledPass ( passIndex : Integer ) : Boolean
passIndex – 被用于检查的过程
如果给定索引的过程在过程链中是最后一个启用的过程,则返回true。 由EffectComposer所使用,来决定哪一个过程应当被渲染到屏幕上。
.removePass ( pass : Pass ) : undefined
pass – 要从传递链中删除的传递。
从传递链中删除给定的传递。
.render ( deltaTime : Float ) : undefined
deltaTime – 增量时间值。
执行所有启用的后期处理过程,来产生最终的帧,
.reset ( renderTarget : WebGLRenderTarget ) : undefined
renderTarget – (可选)一个预先配置的渲染目标,内部由 EffectComposer 使用。
重置所有EffectComposer的内部状态。
.setPixelRatio ( pixelRatio : Float ) : undefined
pixelRatio – 设备像素比
设置设备的像素比。该值通常被用于HiDPI设备,以阻止模糊的输出。 因此,该方法语义类似于WebGLRenderer.setPixelRatio()。
.setSize ( width : Integer, height : Integer ) : undefined
width – EffectComposer的宽度。
height – EffectComposer的高度。
考虑设备像素比,重新设置内部渲染缓冲和过程的大小为(width, height)。 因此,该方法语义类似于WebGLRenderer.setSize()。
.swapBuffers () : undefined
交换内部的读/写缓冲。
1.2 ☘️THREE.RenderPass
THREE.RenderPass用于将场景渲染到中间缓冲区,为后续的后期处理效果(如模糊、色调调整等)提供基础。
1.2.1 ☘️构造函数
RenderPass(scene, camera, overrideMaterial, clearColor, clearAlpha)
- scene THREE.Scene 要渲染的 Three.js 场景对象。
- camera THREE.Camera 场景对应的相机(如 PerspectiveCamera)。
- overrideMaterial THREE.Material (可选) 覆盖场景中所有物体的材质(默认 null)。
- clearColor THREE.Color (可选) 渲染前清除画布的颜色(默认不主动清除)。
- clearAlpha number (可选) 清除画布的透明度(默认 0)。
1.2.2 ☘️属性
.enabled:boolean
是否启用此通道(默认 true)。设为 false 可跳过渲染。
.clear:boolean
渲染前是否清除画布(默认 true)。若需叠加多个 RenderPass,可设为 false。
.needsSwap:boolean
是否需要在渲染后交换缓冲区(通常保持默认 false)。
1.2.3 ☘️方法
.setSize(width, height)
调整通道的渲染尺寸(通常由 EffectComposer 自动调用)。
width: 画布宽度(像素)。
height: 画布高度(像素)。
1.3 ☘️THREE.MaskPass
THREE.MaskPass是 Three.js 后期处理模块中用于创建遮罩效果的通道,允许将特定区域渲染到缓冲区,以便后续处理(如局部特效、混合叠加等)。
1.3.1 ☘️构造函数
new MaskPass(scene, camera)
- scene THREE.Scene 用于生成遮罩的专用场景(仅包含需作为遮罩的物体)。
- camera THREE.Camera 与遮罩场景匹配的相机(需与主场景相机同步参数)。
1.3.2 ☘️属性
.enabled:boolean
是否启用此通道(默认 true)。设为 false 可临时禁用效果。
.inverse:boolean
是否反转遮罩区域(默认 false)。
false: 遮罩区域为物体渲染部分。
true: 遮罩区域为物体外的部分。
1.3.3 ☘️方法
.setSize(width, height)
调整通道的渲染尺寸(通常由 EffectComposer 自动调用)。
width: 画布宽度(像素)。
height: 画布高度(像素)。
1.4 ☘️THREE.ClearMaskPass
THREE.ClearMaskPass是 Three.js 后期处理模块中用于清除遮罩状态的通道,与 MaskPass 配合使用,恢复后续通道的正常渲染逻辑。
1.4.1 ☘️构造函数
ClearMaskPass()
无参数。该通道的唯一作用是清除 MaskPass 设置的遮罩状态。
1.4.2 ☘️属性
.enabled:boolean
是否启用此通道(默认 true)。设为 false 可跳过渲染。
1.4.3 ☘️方法
.setSize(width, height)
调整通道的渲染尺寸(通常由 EffectComposer 自动调用)。
width: 画布宽度(像素)。
height: 画布高度(像素)。
1.5 ☘️THREE.ShaderPass
THREE.ShaderPass是 Three.js 后期处理模块的核心组件之一,允许开发者通过自定义着色器(Shader)实现任意特效,为后期处理链提供高度灵活性。
1.5.1 ☘️构造函数
ShaderPass(shader, textureID)
- shader Object 包含着色器代码和 uniforms 的配置对象。
- textureID string (可选) 输入纹理的 uniform 名称(默认 tDiffuse)。
1.5.2 ☘️属性
.enabled:boolean
是否启用此通道(默认 true)。设为 false 可临时禁用效果。
.uniforms:object
着色器 uniforms 的引用,支持动态修改参数:
shaderPass.uniforms.uStrength.value = 0.8; // 修改自定义参数
.renderToScreen:boolean
是否直接渲染到屏幕(默认 false)。若为最后通道,需设为 true。
1.5.3 ☘️方法
.setSize(width, height)
调整通道的渲染尺寸(通常由 EffectComposer 自动调用)。
width: 画布宽度(像素)。
height: 画布高度(像素)。
二、🍀使用EffectComposer后期处理组合器(采用RenderPass、MaskPass、ClearMaskPass、ShaderPass渲染通道)
1. ☘️实现思路
- 1、初始化Scene三维场景sceneEarth、sceneMars、sceneBG。
- 2、初始化camera相机camera、cameraBG,设置cameraBG相机位置,定义camera相机位置 camera.position.set,设置camera相机方向camera.lookAt。
- 3、初始化renderer渲染器。
- 4、创建THREE.AmbientLight环境光源ambi、ambi2,场景sceneEarth添加ambi环境光源,场景sceneMars添加ambi2环境光源。创建DirectionalLight平行光源spotLight、spotLight2,设置spotLight、spotLight2位置和光强,场景sceneEarth添加spotLight平行光源,场景sceneMars添加spotLight2平行光源。
- 5、加载几何模型:
- 5.1 定义createMarshMesh方法(参数:geom 几何对象),用于生成火星网格对象。
- 5.2 定义createMarshMesh方法(参数:geom 几何对象),用于生成地球网格对象。
- 5.3 调用createEarthMesh方法创建地球网格对象sphere,设置sphere位置,sceneEarth场景添加sphere。
- 5.4 调用createMarshMesh方法创建火星网格对象sphere2,设置sphere2位置,sceneMars场景添加sphere2。
- 5.5 创建二维平面星空网格对象bgPlane,设置bgPlane的位置和大小,场景sceneBG添加bgPlane。
- 5.6 创建THREE.RenderPass渲染通道bgPass、renderPass、renderPass2,创建创建THREE.ShaderPass特效通道effectCopy、effectSepia、effectColorify,创建THREE.MaskPass渲染通道earthMask、marsMask,创建THREE.ClearMaskPass渲染通道clearMask,设置相关参数。
- 5.7 THREE.EffectComposer后期处理组合器composer,composer按顺序添加bgPass、renderPass、renderPass2、marsMask、effectColorify、clearMask、earthMask、effectSepia、clearMask、effectCopy。
- 5.8 定义render方法,实现sphere、sphere2的旋转动画,调用composer的渲染方法render。具体代码参考下面代码样例。
- 6、加入stats监控器,监控帧数信息。
2. ☘️代码样例
<!DOCTYPE html><html><head> <title>学习threejs,使用EffectComposer后期处理组合器(采用RenderPass、MaskPass、ClearMaskPass、ShaderPass渲染通道)</title> <script type=\"text/javascript\" src=\"../libs/three.js\"></script> <script type=\"text/javascript\" src=\"../libs/stats.js\"></script> <script type=\"text/javascript\" src=\"../libs/dat.gui.js\"></script> <script type=\"text/javascript\" src=\"../libs/OrbitControls.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/ShaderPass.js\"></script> <script type=\"text/javascript\" src=\"../libs/shaders/CopyShader.js\"></script> <script type=\"text/javascript\" src=\"../libs/shaders/ColorifyShader.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/BloomPass.js\"></script> <script type=\"text/javascript\" src=\"../libs/shaders/ConvolutionShader.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/EffectComposer.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/MaskPass.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/FilmPass.js\"></script> <script type=\"text/javascript\" src=\"../libs/shaders/FilmShader.js\"></script> <script type=\"text/javascript\" src=\"../libs/shaders/SepiaShader.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/RenderPass.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/SavePass.js\"></script> <script type=\"text/javascript\" src=\"../libs/postprocessing/TexturePass.js\"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style></head><body><div id=\"Stats-output\"></div><div id=\"WebGL-output\"></div><script type=\"text/javascript\"> // 初始化 function init() { var stats = initStats(); // 创建三维场景sceneEarth(地球)、sceneMars(火星)、sceneMars(背景) var sceneEarth = new THREE.Scene(); var sceneMars = new THREE.Scene(); var sceneBG = new THREE.Scene(); // 创建相机camera、cameraBG,camera用于地球和火星网格对象,cameraBG用于背景 var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); var cameraBG = new THREE.OrthographicCamera(-window.innerWidth, window.innerWidth, window.innerHeight, -window.innerHeight, -10000, 10000); cameraBG.position.z = 50; // 创建渲染器webGLRenderer,设置渲染器的背景色、大小和投影 var webGLRenderer = new THREE.WebGLRenderer(); webGLRenderer.setClearColor(new THREE.Color(0x000, 1.0)); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.shadowMapEnabled = true; var sphere = createEarthMesh(new THREE.SphereGeometry(10, 40, 40)); sphere.position.x = -10; var sphere2 = createMarshMesh(new THREE.SphereGeometry(5, 40, 40)); sphere2.position.x = 10; sceneEarth.add(sphere); sceneMars.add(sphere2); // 设置相机camera的位置和方向 camera.position.x = -10; camera.position.y = 15; camera.position.z = 25; camera.lookAt(new THREE.Vector3(0, 0, 0)); var orbitControls = new THREE.OrbitControls(camera); orbitControls.autoRotate = false; var clock = new THREE.Clock(); var ambi = new THREE.AmbientLight(0x181818); var ambi2 = new THREE.AmbientLight(0x181818); sceneEarth.add(ambi); sceneMars.add(ambi2); var spotLight = new THREE.DirectionalLight(0xffffff); spotLight.position.set(550, 100, 550); spotLight.intensity = 0.6; var spotLight2 = new THREE.DirectionalLight(0xffffff); spotLight.position.set(550, 100, 550); spotLight.intensity = 0.6; sceneEarth.add(spotLight); sceneMars.add(spotLight2); var materialColor = new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture(\"../assets/textures/starry-deep-outer-space-galaxy.jpg\"), depthTest: false }); var bgPlane = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), materialColor); bgPlane.position.z = -100; bgPlane.scale.set(window.innerWidth * 2, window.innerHeight * 2, 1); sceneBG.add(bgPlane); // webGLRenderer渲染器绑定html要素 document.getElementById(\"WebGL-output\").appendChild(webGLRenderer.domElement); var bgPass = new THREE.RenderPass(sceneBG, cameraBG); var renderPass = new THREE.RenderPass(sceneEarth, camera); renderPass.clear = false; var renderPass2 = new THREE.RenderPass(sceneMars, camera); renderPass2.clear = false; var effectCopy = new THREE.ShaderPass(THREE.CopyShader); effectCopy.renderToScreen = true; var clearMask = new THREE.ClearMaskPass(); // earth mask var earthMask = new THREE.MaskPass(sceneEarth, camera);// earthMask.inverse = true; // mars mask var marsMask = new THREE.MaskPass(sceneMars, camera);// marsMask.inverse = true; var effectSepia = new THREE.ShaderPass(THREE.SepiaShader); effectSepia.uniforms[\'amount\'].value = 0.8; var effectColorify = new THREE.ShaderPass(THREE.ColorifyShader); effectColorify.uniforms[\'color\'].value.setRGB(0.5, 0.5, 1); var composer = new THREE.EffectComposer(webGLRenderer); composer.renderTarget1.stencilBuffer = true; composer.renderTarget2.stencilBuffer = true; composer.addPass(bgPass); composer.addPass(renderPass); composer.addPass(renderPass2); composer.addPass(marsMask); composer.addPass(effectColorify); composer.addPass(clearMask); composer.addPass(earthMask); composer.addPass(effectSepia); composer.addPass(clearMask); composer.addPass(effectCopy); render(); function createMarshMesh(geom) { var planetTexture = THREE.ImageUtils.loadTexture(\"../assets/textures/planets/Mars_2k-050104.png\"); var normalTexture = THREE.ImageUtils.loadTexture(\"../assets/textures/planets/Mars-normalmap_2k.png\"); var planetMaterial = new THREE.MeshPhongMaterial(); planetMaterial.normalMap = normalTexture; planetMaterial.map = planetTexture;// planetMaterial.shininess = 150; // create a multimaterial var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [planetMaterial]); return mesh; } function createEarthMesh(geom) { var planetTexture = THREE.ImageUtils.loadTexture(\"../assets/textures/planets/Earth.png\"); var specularTexture = THREE.ImageUtils.loadTexture(\"../assets/textures/planets/EarthSpec.png\"); var normalTexture = THREE.ImageUtils.loadTexture(\"../assets/textures/planets/EarthNormal.png\"); var planetMaterial = new THREE.MeshPhongMaterial(); planetMaterial.specularMap = specularTexture; planetMaterial.specular = new THREE.Color(0x4444aa); planetMaterial.normalMap = normalTexture; planetMaterial.map = planetTexture;// planetMaterial.shininess = 150; // create a multimaterial var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [planetMaterial]); return mesh; } function render() { webGLRenderer.autoClear = false; stats.update(); //sphere.rotation.y=step+=0.01; var delta = clock.getDelta(); orbitControls.update(delta); sphere.rotation.y += 0.002; sphere2.rotation.y += 0.002; // render using requestAnimationFrame requestAnimationFrame(render); // webGLRenderer.render(scene, camera); composer.render(delta); } function initStats() { var stats = new Stats(); stats.setMode(0); stats.domElement.style.position = \'absolute\'; stats.domElement.style.left = \'0px\'; stats.domElement.style.top = \'0px\'; document.getElementById(\"Stats-output\").appendChild(stats.domElement); return stats; } } window.onload = init;</script></body></html>
效果如下