Three.js 水波纹扩散特效

🎯 提示词

PROMPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
使用 Three.js 实现水波纹扩散特效,具体要求:

**核心特效**
- 点击创建波纹
- 多波纹叠加
- 波前传播动画
- 衰减效果
- 4个实时参数

**场景与光照**
- 黑色背景
- 透明材质
- 平面水平放置

**交互与控制**
- OrbitControls 阻尼旋转
- GUI 面板调节
- 点击屏幕创建波纹

**技术要求**
- Three.js 版本 (ES Module)
- 自定义 ShaderMaterial
- PlaneGeometry 载体
- Raycaster 点击检测

📖 效果拆解

层次 视觉效果 技术实现
基础 水面平面 PlaneGeometry
波纹 点击生成 Raycaster 检测
传播 波前 smoothstep smoothstep(waveFront - width, waveFront, dist)
衰减 指数衰减 exp(-rippleTime * uWaveDecay)
控制 GUI 面板 4个参数 + 清除按钮

🔧 核心技术点

1. 波纹生成与传播

为什么需要这个技术:用 smoothstep 创造清晰的波前,并随时间向外传播。

GLSL
1
2
3
4
5
6
float rippleTime = uTime - ripple.z;
float dist = distance(position.xy, ripple.xy);
float waveFront = rippleTime * uWaveSpeed;
float waveWidth = 0.3;
float wave = smoothstep(waveFront - waveWidth, waveFront, dist)
           * (1.0 - smoothstep(waveFront, waveFront + waveWidth, dist));

2. 波纹衰减

为什么需要这个技术:波纹随时间逐渐减弱消失。

GLSL
1
wave *= exp(-rippleTime * uWaveDecay);

3. 点击交互

为什么需要这个技术:将鼠标点击转换为 3D 世界坐标,在该位置生成波纹。

JAVASCRIPT
1
2
3
4
5
6
7
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObject(mesh);
if (intersects.length > 0) {
    const point = intersects[0].point;
    ripples.push(new THREE.Vector3(point.x, point.y, material.uniforms.uTime.value));
}

4. 多波纹管理

为什么需要这个技术:最多同时存在 10 个波纹,新波纹替代旧波纹。

JAVASCRIPT
1
2
3
4
5
if (ripples.length >= 10) {
    ripples.shift(); // 移除最旧的波纹
}
ripples.push(newRipple);
material.uniforms.uRippleCount.value = ripples.length;

💡 调试与优化

问题类型 表现形式 解决方案
波纹变形 几何体限制 增加 PlaneGeometry 分段数
性能问题 多个波纹时卡顿 限制最多波纹数量
波纹消失太快 效果不明显 降低 uWaveDecay

🚀 扩展思路

变体效果 核心改动 难度
同心圆 静止波纹图案
雨滴效果 随机位置自动生成
3D 水面 球体几何体 ⭐⭐
涟漪纹理 添加法线扰动 ⭐⭐
水波模拟 Navier-Stokes ⭐⭐⭐

本文档由 ThreeLab 编辑整理,如需转载,请注明出处。