求助:使用ThreeJS实现三张图片置换贴图过渡遇阻
使用Three.js结合置换贴图实现三张图片过渡
核心原理说明
置换贴图本质是一张灰度图,每个像素的亮度值(通常取r通道,灰度图RGB通道值一致)代表该位置的"置换强度"。我们可以利用这个值控制不同图片的显示权重,实现基于像素的过渡效果。
步骤1:添加置换贴图与进度控制Uniform
先在材质中添加置换贴图的uniform,同时设置正确的纹理参数避免边缘异常;另外添加过渡进度参数,用于控制三张图的切换阶段:
import * as THREE from 'three'; // 假设你已加载置换贴图,命名为displacementTexture // 配置纹理参数 displacementTexture.wrapS = THREE.ClampToEdgeWrapping; displacementTexture.wrapT = THREE.ClampToEdgeWrapping; displacementTexture.minFilter = THREE.LinearFilter; const planeMaterial = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide, uniforms: { uTime: { value: 0 }, uTexture1: { value: imgTexture1 }, uTexture2: { value: imgTexture2 }, uTexture3: { value: imgTexture3 }, uDisplacementMap: { value: displacementTexture }, uProgress: { value: 0 } // 过渡进度,范围0~2 } });
步骤2:修改片段着色器逻辑
在片段着色器中,先获取置换贴图的灰度值,再根据进度参数拆分过渡阶段,用置换值控制图片混合权重:
varying vec2 vUv; uniform sampler2D uTexture1; uniform sampler2D uTexture2; uniform sampler2D uTexture3; uniform sampler2D uDisplacementMap; uniform float uProgress; void main() { // 获取置换强度,可通过乘数调整过渡幅度 float displacement = texture2D(uDisplacementMap, vUv).r * 2.0; // 拆分两次过渡阶段:0~1是图1→图2,1~2是图2→图3 float stage1 = clamp(uProgress, 0.0, 1.0); float stage2 = clamp(uProgress - 1.0, 0.0, 1.0); // 第一次过渡:用置换值和进度控制图1与图2的混合 vec3 mix12 = mix( texture2D(uTexture1, vUv).rgb, texture2D(uTexture2, vUv).rgb, stage1 * displacement ); // 第二次过渡:基于前一次结果混合图3 vec3 finalColor = mix( mix12, texture2D(uTexture3, vUv).rgb, stage2 * displacement ); gl_FragColor = vec4(finalColor, 1.0); }
步骤3:驱动过渡动画
在动画循环中更新uProgress的值,实现平滑过渡:
function animate() { requestAnimationFrame(animate); // 进度在0~2之间循环,4000ms完成一次完整过渡,可调整速度 planeMaterial.uniforms.uProgress.value = (Date.now() % 4000) / 2000; renderer.render(scene, camera); } animate();
关键细节提示
- 优先使用灰度置换贴图,若用彩色图,可通过
(r+g+b)/3计算平均亮度作为置换值。 - 调整
displacement的乘数(如*1.5或*3)可控制过渡的剧烈程度,数值越大效果越明显。 - 若想要柔和过渡边缘,可对置换值做平滑处理:
displacement = smoothstep(0.2, 0.8, displacement)。
内容的提问来源于stack exchange,提问作者Mariano Piriz
相关产品推荐
相关产品推荐

