3d-漫天雪花

219 阅读2分钟

接上一节 星空

今天依然是使用几何体的实例BufferGeometry;

特点:

  • 使用 WebGL 缓冲区存储顶点数据,性能更高。
  • 更适合复杂的几何体或需要动态更新的场景。

我们封装一个函数用来批量创建不同的点云对象 当然为了区分不同的物体,我们对材质的数量纹理大小做设定

function createPoints(count,url, size = 0.5){
const particlesGeometry = new THREE.BufferGeometry();


  // 设置缓冲区数组
  const positions = new Float32Array(count * 3);
  // 设置粒子顶点颜色
  const colors = new Float32Array(count * 3);
  // 设置顶点
  for (let i = 0; i < count * 3; i++) {
    positions[i] = (Math.random() - 0.5) * 100;
    colors[i] = Math.random();
  }
  particlesGeometry.setAttribute(
    "position",
    new THREE.BufferAttribute(positions, 3)
  );
  particlesGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));

  // 设置点材质
  const pointsMaterial = new THREE.PointsMaterial();
  pointsMaterial.size = size;
  pointsMaterial.color.set(0xfff000);
  // 相机深度而衰减
  pointsMaterial.sizeAttenuation = true;

  // 载入纹理
  const textureLoader = new THREE.TextureLoader();
  const texture = textureLoader.load(`./particles/${url}.png`);//通过url来区别不同纹理
  // 设置点材质纹理
  pointsMaterial.map = texture;
  pointsMaterial.alphaMap = texture;
  pointsMaterial.transparent = true;
  pointsMaterial.depthWrite = false;
  pointsMaterial.blending = THREE.AdditiveBlending;
  // 设置启动顶点颜色
  pointsMaterial.vertexColors = true;

  const points = new THREE.Points(particlesGeometry, pointsMaterial);

  scene.add(points);
  return points;
}

通过url 和size来定义纹理和大小然后返回return points;

const points = createPoints(10000"1", 1.5);//

这个"1",是下面的图片

1.png

下雪在视觉上就是从上到下所以我们需要找到points这个星云的运动相关属性,实现物体动态变化,有时间概念。

matrix

  • 类型THREE.Matrix4
  • 描述:对象的本地变换矩阵,用于定义对象的位置、旋转和缩放。
points.matrix.setPosition(new THREE.Vector3(1, 2, 3)); // 设置位置

matrixWorld

  • 类型THREE.Matrix4
  • 描述:对象的全局变换矩阵,表示对象在世界空间中的位置、旋转和缩放。

points.updateMatrixWorld(); // 更新全局变换矩阵

position

  • 类型THREE.Vector3
  • 描述:对象的位置。

points.position.set(1, 2, 3); // 设置位置

rotation

  • 类型THREE.Euler
  • 描述:对象的旋转,以欧拉角表示。
points.rotation.set(Math.PI / 4, 0, 0); // 设置旋转

旋转: 有这么几种和位置相关的,其中 rotation 对象的旋转,以欧拉角表示,那我们用它来模仿雪天下雪的模样,

// 设置时钟
const clock = new THREE.Clock();
const time = clock.getElapsedTime();

时间: clock.getElapsedTime() 的主要作用是提供一个高精度的时间计数器(以秒为单位),用于以下场景:

  1. 动画:控制动画的播放速度和时间同步。
  2. 粒子系统:控制粒子的生命周期、速度变化等。
  3. 动态效果:实现基于时间的动态变化,例如物体的移动、旋转、缩放等。

上述 条件全部具备那么就可以利用render函数来实现动态的下雪情景代码如下:


function render() {
  let time = clock.getElapsedTime();
  points.rotation.x = time * 0.3;
  renderer.render(scene, camera);
  //   渲染下一帧的时候就会调用render函数
  requestAnimationFrame(render);
}

实现效果如下图

chrome-capture-2025-1-7.gif

可以设定数量,纹理,尺寸大小:


const points2 = createPoints(10000"xuehua", 1);
const points3 = createPoints,5000"xuehua", 2);

效果如下

chrome-capture-2025-1-702.gif