🌌 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>

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

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

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

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

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

🌟 致程序员的浪漫宣言:

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

相关推荐
kkkkk0211066 小时前
JavaScript性能优化实战:深度剖析瓶颈与高效解决方案
开发语言·javascript·性能优化
亿元程序员6 小时前
每次游戏卡的时候,策划总问:是不是DrawCall太高了?
前端
golang学习记6 小时前
刚刚,OpenAI首个AI浏览器发布!颠覆Chrome,彻底改变你上网的方式|附实测
前端
吃饺子不吃馅6 小时前
项目上localStorage太杂乱,逼我写了一个可视化浏览器插件
前端·javascript·chrome
golang学习记6 小时前
从0 死磕全栈之Next.js 环境变量实战指南:企业级多环境(dev/test/prod)配置最佳实践
前端
.生产的驴6 小时前
React 集成Redux数据状态管理 数据共享 全局共享
前端·javascript·react.js·前端框架·css3·html5·safari
IT_陈寒6 小时前
Redis性能优化的7个隐藏技巧:从慢查询到亿级QPS的实战经验分享
前端·人工智能·后端
艾小码7 小时前
ES6+革命:8大特性让你的JavaScript代码质量翻倍
前端·javascript
两个西柚呀7 小时前
Vue组件的一些底层细节
前端·javascript·vue.js