Three.js 物理模拟着色器 | 三维可视化 / AI 提示词
📋 AI 提示词
prompt
使用 Three.js 实现**物理模拟着色器效果**,具体要求:
【核心特效】
- 五种物理模拟:波动方程、热传导、流体动力学、弹性力学、电磁场
- 基于物理方程的实时计算
- 动态顶点位移形成物理波纹
- 可调的物理参数(波速、粘度、弹性、阻尼等)
【场景与光照】
- 深蓝色背景 (#0f0f23 → #1e1e3f 径向渐变)
- OrbitControls 自由视角控制
- 自定义着色器实现物理模拟效果
【交互与控制】
- OrbitControls 鼠标拖拽旋转
- 鼠标滚轮缩放
- GUI 面板切换物理类型、调节参数
【技术要求】
- Three.js 版本 (ES Module)
- 自定义顶点着色器实现五种物理方程
- 自定义片元着色器实现颜色可视化
- lil-gui 参数控制
🖼️ 效果预览

🎮 案例演示
📖 效果拆解
| 层次 | 视觉效果 | 技术实现 |
|---|---|---|
| 基础 | 3D平面几何体 | PlaneGeometry (12×12, 512×512分段) |
| 核心特效 | 五种物理模拟 | 顶点着色器实现波动/热传导/流体/弹性/电磁方程 |
| 增强细节 | 颜色渐变和发光 | 片元着色器根据物理值插值颜色 |
| 交互控制 | 类型切换和参数调节 | lil-gui 控制物理类型/波速/粘度等 |
🔧 核心技术点
1. 波动方程模拟
为什么需要这个技术:模拟波在二维介质中的传播,是图形学中常用的动态效果基础。
glsl
float waveEquation(vec2 pos) {
float r = length(pos);
float k = 10.0; // 波数
float omega = uWaveSpeed * k; // 角频率
if(r < 0.01) r = 0.01;
return sin(k * r - omega * uTime) / r;
}
2. 热传导方程模拟
为什么需要这个技术:模拟热量从热源向外扩散的过程,产生柔和的衰减效果。
glsl
float heatConduction(vec2 pos) {
float initialHeat = exp(-length(pos) * 5.0);
float diffusion = 1.0 / (1.0 + uTime * 2.0);
return initialHeat * exp(-length(pos) * length(pos) /
(4.0 * uViscosity * uTime + 0.1)) * diffusion;
}
3. 流体动力学涡旋场
为什么需要这个技术:模拟多个涡旋叠加的流体力学效果,产生复杂的旋涡图案。
glsl
float fluidDynamics(vec2 pos) {
float vorticity = 0.0;
for(int i = 0; i < 3; i++) {
float angle = float(i) * 2.0944; // 120度间隔
vec2 vortexCenter = vec2(cos(angle), sin(angle)) * 0.5;
vec2 relativePos = pos - vortexCenter;
float vortexStrength = sin(uTime * 0.5 + float(i)) * 2.0;
vorticity += vortexStrength * sin(atan(relativePos.y, relativePos.x) * 3.0 +
uTime * 2.0) / (length(relativePos) + 0.1);
}
return vorticity;
}
4. 弹性力学振动
为什么需要这个技术:模拟弹性材料的振动衰减过程,展示胡克定律的动态效果。
glsl
float elasticity(vec2 pos) {
float r = length(pos);
float amplitude = exp(-uDamping * uTime); // 振幅衰减
float frequency = 5.0 * uElasticity;
return amplitude * sin(frequency * r - uTime * 3.0) * exp(-r * 3.0);
}
5. 电磁场模拟
为什么需要 this技术:模拟电磁波的传播和偏振现象,展示麦克斯韦方程组的可视化。
glsl
float electromagneticField(vec2 pos) {
float kx = 8.0;
float ky = 6.0;
float omega = 3.0;
float Ex = sin(kx * pos.x + ky * pos.y - omega * uTime);
float By = cos(kx * pos.x + ky * pos.y - omega * uTime);
return sqrt(Ex * Ex + By * By);
}
6. 顶点着色器物理计算选择
为什么需要这个技术:根据用户选择的物理类型,动态切换计算方程。
glsl
uniform int uPhysicsType;
void main() {
float physicsValue = 0.0;
if(uPhysicsType == 0) {
physicsValue = waveEquation(position.xy);
} else if(uPhysicsType == 1) {
physicsValue = heatConduction(position.xy);
} else if(uPhysicsType == 2) {
physicsValue = fluidDynamics(position.xy);
} else if(uPhysicsType == 3) {
physicsValue = elasticity(position.xy);
} else {
physicsValue = electromagneticField(position.xy);
}
vec3 newPosition = position;
newPosition.z += physicsValue * 0.8;
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}
💡 调试与优化
| 问题类型 | 表现形式 | 解决方案 |
|---|---|---|
| 波动无限增大 | 波动方程振幅失控 | 添加阻尼项 exp(-damping * time) |
| 流体不稳定 | 涡旋计算出现NaN | 检查 atan() 输入,避免除零 |
| 热传导过慢 | 热量扩散不明显 | 增加 uViscosity 或减小 uTime 系数 |
| 性能问题 | 复杂场景帧率低 | 减少 PlaneGeometry 分段数 (512→256) |
🚀 扩展思路
- 多物理耦合:将波动和热传导结合,产生热波效应
- 交互式扰动:鼠标点击添加局部扰动源
- 3D体积渲染:扩展到3D空间,实现真正的体积物理模拟
- 声音可视化:将声波方程与音频数据关联
- 流体力学网格:使用更复杂的CFD方法模拟真实流体
📚 相关学习资源
©️ 版权声明
*本文档由 ThreeLab 编辑整理,专注 Three.js 着色器、Web 3D、GIS 可视化技术分享。如需转载,请注明出处。