🌌 Three.js 几何变化动画配合噪声粒子教程:让你的代码也会“呼吸”

一、前言:当数学遇上艺术 🎨

Three.js 是 WebGL 的魔术师,它能在浏览器里召唤出立方体、星系、时间感与情绪。而当它遇上"噪声粒子(Noise Particles)",我们就能做出一种仿佛会呼吸的几何动画。

这不仅仅是动画,而是一种"数据哲学" ------ 在浮点与顶点之间,每一个粒子都在询问存在的意义。


二、底层原理🌊:几何变化与噪声的"粒子哲学"

1. 几何变化(Geometry Morphing)

  • 几何的顶点(vertex)是动态的向量集合,你可以理解为一群情绪不稳定的小点。
  • 改变它们的坐标,就是让它们"跳舞"。

2. 噪声(Noise)

  • 普通的随机数像是喝多了的鹦鹉,杂乱无章。
  • 而噪声(如 Perlin Noise 或 Simplex Noise)是"带旋律的随机"------一种自然界常见的渐变模式。

通过给每个顶点一个"噪声驱动的偏移",我们就能得到有机的变化感。想象一下海浪、呼吸、风中的草。


三、技术结构:怎么让坐标"呼吸"🌬️

我们利用以下逻辑:

  1. 创建基础几何体,例如球体或平面;
  2. 在每一帧中,为每个顶点叠加一层噪声偏移;
  3. 通过时间参数让噪声随帧变化,从而产生动态效果;
  4. 同时结合粒子(PointMaterial)渲染,让几何看起来像在散发能量。

四、核心代码讲解:JS 实战 💻

ini 复制代码
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { SimplexNoise } from "three/examples/jsm/math/SimplexNoise.js"; // 引入噪声

// 🌍 初始化场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x080808);

// 📷 相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

// 🎞️ 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 🧭 控制器
const controls = new OrbitControls(camera, renderer.domElement);

// 🌐 创建几何体点云
const geometry = new THREE.SphereGeometry(1, 128, 128);
const material = new THREE.PointsMaterial({
  color: 0x66ccff,
  size: 0.02,
});
const points = new THREE.Points(geometry, material);
scene.add(points);

// 🌪 生成噪声对象
const noise = new SimplexNoise();

// 🔄 动画逻辑
function animate() {
  requestAnimationFrame(animate);

  const time = performance.now() * 0.001; // 时间参数

  geometry.attributes.position.needsUpdate = true; // 告诉Three.js刷新顶点
  const positions = geometry.attributes.position.array;

  // 🌀 每个顶点加上噪声偏移
  for (let i = 0; i < positions.length; i += 3) {
    const x = positions[i];
    const y = positions[i + 1];
    const z = positions[i + 2];
    const n = noise.noise3d(x * 0.7, y * 0.7, time * 0.3);
    positions[i] = x + n * 0.05;
    positions[i + 1] = y + n * 0.05;
    positions[i + 2] = z + n * 0.05;
  }

  points.rotation.y += 0.002;
  renderer.render(scene, camera);
}

animate();

// 📱 自适应
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

💡 核心思想

每一帧我们重新计算顶点位置 + 噪声干扰,让几何体轻微抖动,形似"呼吸球体"。通过 PointsMaterial 将物体转化为粒子可视化。


五、为什么噪声让动画看起来"自然"🌾

大自然不喜欢陡峭的转折。

风不会突然变向,波浪不会瞬间下沉。

噪声用于建立"连续的不确定性":

  • 每个点都有随机偏移;
  • 但这种随机变化是逐渐的,而非突兀;
  • 结果就是------流畅、有机、具有生命感。

🎭 一句话概括

噪声就是"让随机数装得像命运"的艺术。


六、小技巧 🌈

  • 做光影交互:可以让粒子颜色随噪声变化,像极了能量在流动。
  • 混合多层噪声:叠加快慢两层噪声,获得更复杂的形态。
  • 用 GUI 调参:让用户通过滑杆调节噪声强度与速度,实验不同"生命频率"。

七、附录:响应式可视化布局图🌐

下面是一个 HTML 可运行版本(自动适配屏幕),直接复制运行👇

ini 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8" />
  <title>Three.js 噪声粒子呼吸球</title>
  <script src="https://cdn.jsdelivr.net/npm/three@0.161.0/build/three.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.161.0/examples/js/controls/OrbitControls.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.161.0/examples/js/math/SimplexNoise.js"></script>
  <style>
    body { margin: 0; background: #000; overflow: hidden; }
    canvas { display: block; width: 100%; height: 100%; }
  </style>
</head>
<body>
  <script>
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000010);

    const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
    camera.position.z = 5;

    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    const controls = new THREE.OrbitControls(camera, renderer.domElement);

    const geo = new THREE.SphereGeometry(1, 128, 128);
    const mat = new THREE.PointsMaterial({ color: 0x44ccff, size: 0.02 });
    const mesh = new THREE.Points(geo, mat);
    scene.add(mesh);

    const noise = new SimplexNoise();

    function animate() {
      requestAnimationFrame(animate);
      const t = Date.now() * 0.001;
      const pos = geo.attributes.position.array;

      for (let i = 0; i < pos.length; i += 3) {
        const x = pos[i], y = pos[i+1], z = pos[i+2];
        const n = noise.noise3d(x*0.7, y*0.7, t*0.3);
        pos[i] = x + n * 0.05;
        pos[i+1] = y + n * 0.05;
        pos[i+2] = z + n * 0.05;
      }

      geo.attributes.position.needsUpdate = true;
      mesh.rotation.y += 0.002;
      renderer.render(scene, camera);
    }

    animate();

    window.addEventListener("resize", () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });
  </script>
</body>
</html>

八、结语:代码的呼吸 🌬️

当你看到屏幕上那一片不断律动的粒子球,请记得:

每一个顶点,都在计算与随机之间寻找平衡;

每一阵噪声,都是动态世界的轻叹。

于是,当数字开始"呼吸",我们也许就在靠近计算的艺术

🌟 致程序员的浪漫宣言:

"我在浏览器里造了一个星球,它并不完美,但它会呼吸。" 🌐💙

相关推荐
Code Crafter33 分钟前
ES6-ES14 新特性速查
前端·ecmascript·es6
Lhuu(重开版35 分钟前
CSS从0到1
前端·css·tensorflow
CDwenhuohuo1 小时前
微信小程序里用 setData() 修改数据并打印输出 的几种写法
javascript·微信小程序·小程序
不说别的就是很菜2 小时前
【前端面试】HTML篇
前端·html
前端一小卒2 小时前
生产环境Sourcemap策略:从苹果事故看前端构建安全架构设计
前端·javascript
im_AMBER2 小时前
React 18
前端·javascript·笔记·学习·react.js·前端框架
老前端的功夫2 小时前
Vue2中key的深度解析:Diff算法的性能优化之道
前端·javascript·vue.js·算法·性能优化
集成显卡3 小时前
AI取名大师 | PM2 部署 Bun.js 应用及配置 Let‘s Encrypt 免费 HTTPS 证书
开发语言·javascript·人工智能
han_3 小时前
前端高频面试题之Vue(高级篇)
前端·vue.js·面试
不说别的就是很菜3 小时前
【前端面试】CSS篇
前端·css·面试