交互式着色器

Three.js 交互式着色器效果 | 三维可视化 / AI 提示词
📋 AI 提示词
prompt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
使用 Three.js 实现**交互式着色器效果**,具体要求:
【核心特效】
- 五种交互模式:涟漪效果、粒子跟随、画笔效果、引力场、声音可视化
- 实时响应鼠标/触摸输入
- 点击产生扩散涟漪
- 鼠标速度影响效果强度
【场景与光照】
- 深蓝色背景 (#0f0f23 → #1e1e3f 径向渐变)
- OrbitControls 自由视角控制
- 自定义着色器实现交互反馈
【交互与控制】
- 鼠标移动:控制效果方向
- 鼠标点击:触发涟漪扩散
- 鼠标拖拽:绘制轨迹
- GUI 面板切换交互类型、调节灵敏度和衰减
【技术要求】
- Three.js 版本 (ES Module)
- 自定义顶点着色器实现交互变形
- 自定义片元着色器实现五种交互效果
- 完整的鼠标和触摸事件处理
🖼️ 效果预览
🎮 案例演示
📖 效果拆解
| 层次 | 视觉效果 | 技术实现 |
|---|---|---|
| 基础 | 3D平面几何体 | PlaneGeometry (10×10, 256×256分段) |
| 核心特效 | 五种交互效果 | 片元着色器实现涟漪/粒子/画笔/引力/声波 |
| 增强细节 | 点击涟漪扩散 | 基于点击位置和时间的动态波纹 |
| 交互控制 | 实时响应 | 鼠标/触摸事件 + 速度追踪 |
🔧 核心技术点
1. 涟漪效果
为什么需要这个技术:模拟水滴落入水面产生的扩散波纹,是最直观的交互反馈。
glsl
1
2
3
4
5
6
7
8
9
10
11
float rippleEffect(vec2 pos) {
vec2 clickPos = vec2(uClickX, uClickY);
float distanceToClick = length(pos - clickPos);
float waveSpeed = 2.0;
float waveFront = uTimeSinceClick * waveSpeed;
float waveWidth = 0.3;
float wave = smoothstep(waveFront - waveWidth, waveFront, distanceToClick) -
smoothstep(waveFront, waveFront + waveWidth, distanceToClick);
wave *= exp(-distanceToClick * 2.0);
return wave * uMouseDown;
}
2. 粒子跟随效果
为什么需要这个技术:模拟粒子被鼠标吸引并聚集的效果,产生有趣的视觉反馈。
glsl
1
2
3
4
5
6
7
8
float particleFollow(vec2 pos) {
vec2 mousePos = vec2(uMouseX, uMouseY);
float distanceToMouse = length(pos - mousePos);
float attraction = 1.0 / (1.0 + distanceToMouse * 10.0);
float noise = sin(pos.x * 20.0 + uTime * 3.0) * 0.1;
attraction += noise;
return attraction;
}
3. 画笔效果
为什么需要这个技术:模拟鼠标移动时在画布上绘制轨迹的效果。
glsl
1
2
3
4
5
6
7
float brushEffect(vec2 pos) {
vec2 mousePos = vec2(uMouseX, uMouseY);
float distanceToMouse = length(pos - mousePos);
float brushSize = 0.1;
float brush = 1.0 - smoothstep(0.0, brushSize, distanceToMouse);
return brush;
}
4. 引力场效果
为什么需要这个技术:模拟黑洞或引力场对周围物质的吸引效果。
glsl
1
2
3
4
5
6
7
8
float gravityField(vec2 pos) {
vec2 mousePos = vec2(uMouseX, uMouseY);
float distanceToMouse = length(pos - mousePos);
float gravity = 1.0 / (distanceToMouse * distanceToMouse + 0.01);
float angle = atan(pos.y - mousePos.y, pos.x - mousePos.x);
float swirl = sin(angle * 3.0 + uTime * 2.0) * 0.5 + 0.5;
return gravity * swirl;
}
5. 鼠标/触摸事件处理
为什么需要这个技术:实现流畅的交互响应,跟踪鼠标位置、速度和点击状态。
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const interactionState = {
mouseX: 0.0,
mouseY: 0.0,
mouseDown: false,
clickPosition: new THREE.Vector2(0, 0),
timeSinceClick: 0.0,
velocity: new THREE.Vector2(0, 0),
};
renderer.domElement.addEventListener('mousemove', (event) => {
interactionState.mouseX = (event.clientX / window.innerWidth) * 2 - 1;
interactionState.mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
const deltaX = interactionState.mouseX - interactionState.dragPosition.x;
const deltaY = interactionState.mouseY - interactionState.dragPosition.y;
interactionState.velocity.x = deltaX * 10;
interactionState.velocity.y = deltaY * 10;
interactionState.dragPosition.set(interactionState.mouseX, interactionState.mouseY);
});
renderer.domElement.addEventListener('mousedown', (event) => {
interactionState.mouseDown = true;
interactionState.clickPosition.set(interactionState.mouseX, interactionState.mouseY);
interactionState.timeSinceClick = 0.0;
});
6. uniform 变量更新
为什么需要这个技术:将 JavaScript 的交互状态实时传递到着色器。
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function animate() {
interactionState.timeSinceClick += 0.016;
material.uniforms.uMouseX.value = interactionState.mouseX;
material.uniforms.uMouseY.value = interactionState.mouseY;
material.uniforms.uMouseDown.value = interactionState.mouseDown ? 1.0 : 0.0;
material.uniforms.uClickX.value = interactionState.clickPosition.x;
material.uniforms.uClickY.value = interactionState.clickPosition.y;
material.uniforms.uTimeSinceClick.value = interactionState.timeSinceClick;
material.uniforms.uVelocityX.value = interactionState.velocity.x;
material.uniforms.uVelocityY.value = interactionState.velocity.y;
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
💡 调试与优化
| 问题类型 | 表现形式 | 解决方案 |
|---|---|---|
| 涟漪不扩散 | 点击后没有波纹 | 检查 uTimeSinceClick 是否正常递增 |
| 粒子聚集过快 | 引力场效果过于强烈 | 增加 distanceToMouse * distanceToMouse 的系数 |
| 触摸不支持 | 移动端无法交互 | 添加 touchstart 和 touchmove 事件监听 |
| 性能问题 | 复杂场景帧率低 | 减少 PlaneGeometry 分段数 (256→128) |
🚀 扩展思路
| 变体效果 | 核心改动 | 难度 |
|---|---|---|
| 多点触控 | 支持多个手指同时产生独立涟漪 | ⭐⭐ |
| 颜色交互 | 根据鼠标速度或位置改变颜色 | ⭐⭐ |
| 轨迹历史 | 保留鼠标轨迹历史,形成拖尾效果 | ⭐⭐ |
| 物理模拟 | 添加粒子系统的物理碰撞 | ⭐⭐⭐ |
| 导出功能 | 将交互绘制结果导出为图片 | ⭐⭐ |
本文档由 ThreeLab 编辑整理,如需转载,请注明出处。







京公网安备 11010502038735号
💬 评论区
评论功能即将上线,敬请期待!