Three.js 水波纹扩散特效
🎯 提示词
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 创造清晰的波前,并随时间向外传播。
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. 波纹衰减
为什么需要这个技术:波纹随时间逐渐减弱消失。
wave *= exp(-rippleTime * uWaveDecay);
3. 点击交互
为什么需要这个技术:将鼠标点击转换为 3D 世界坐标,在该位置生成波纹。
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 个波纹,新波纹替代旧波纹。
if (ripples.length >= 10) {
ripples.shift();
}
ripples.push(newRipple);
material.uniforms.uRippleCount.value = ripples.length;
💡 调试与优化
| 问题类型 |
表现形式 |
解决方案 |
| 波纹变形 |
几何体限制 |
增加 PlaneGeometry 分段数 |
| 性能问题 |
多个波纹时卡顿 |
限制最多波纹数量 |
| 波纹消失太快 |
效果不明显 |
降低 uWaveDecay |
🚀 扩展思路
| 变体效果 |
核心改动 |
难度 |
| 同心圆 |
静止波纹图案 |
⭐ |
| 雨滴效果 |
随机位置自动生成 |
⭐ |
| 3D 水面 |
球体几何体 |
⭐⭐ |
| 涟漪纹理 |
添加法线扰动 |
⭐⭐ |
| 水波模拟 |
Navier-Stokes |
⭐⭐⭐ |
本文档由 ThreeLab 编辑整理,如需转载,请注明出处。
💬 评论区
评论功能即将上线,敬请期待!