threejs粒子系统,仰望星空

1,417 阅读1分钟

粒子系统是3D世界里最常用的系统,这里使用threejs做了一个星空的粒子系统,源码里有详细的使用过程和说明,也可以在线实时查看动态效果,供感兴趣的小伙伴们学习和参考,有需要的可以去仓库拉源码

喜欢的同学给个星星吧 (^_−)☆

动态演示:

手机,pc浏览器访问(http://47.110.129.207/me-smart-ui/)

点击查看threejs动效部分即可

项目地址:

项目代码中有详细的使用过程和说明

https: //gitee.com/superzay/threejs-animate

效果图

这里只贴一张静态图了,gif搞起来实在有点麻烦,上面的演示中可以看到实时动态效果

1650449983968.gif

完整代码如下:

也可以去仓库拉代码,比较完整

<!DOCTYPE html>
<html>

<head>
  <title>threejs</title>
  <style>
    body {
      padding: 0;
      margin: 0
    }

    canvas {
      width: 100%;
      height: 100%;
      background: #fff;
    }
  </style>
</head>

<body>

</body>
<script type='module'>
  import * as THREE from 'https://cdn.skypack.dev/three@v0.129.0';
  import { OrbitControls } from 'https://cdn.skypack.dev/three@v0.129.0/examples/jsm/controls/OrbitControls.js';

  // 喜欢的同学给个星星吧 (^_−)☆

  (async function () {
    //创建渲染器
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.setClearColor('#000', 1);
    document.body.appendChild(renderer.domElement);


    //创建场景
    var scene = new THREE.Scene();

    //创建相机
    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100000);
    camera.position.z = 1000; //设置相机位置
    //camera.lookAt(new )
    scene.add(camera)


    // 添加点光源
    let light1 = new THREE.PointLight('#fff');
    light1.position.set(0, 1160, 22160);
    // scene.add(light1)

    // 添加环境光
    let ambient = new THREE.AmbientLight('#fff', 1);
    scene.add(ambient)

    // 添加辅助线
    let axisHelper = new THREE.AxisHelper(500);
    //scene.add(axisHelper);

    // 创建控制器
    let controls = new OrbitControls(camera, renderer.domElement)

    //渲染函数
    function render() {
      controls.update() // Update controls
      //渲染场景
      renderer.render(scene, camera);
      requestAnimationFrame(render)
    }

    //发起渲染
    requestAnimationFrame(render)

    // 加载纹理图
    const promiseStar = new Promise((resolve, reject) => {
      new THREE.TextureLoader().load("http://182.43.179.137:81/public/images/texture-smoke.png", function (texture) {
        resolve(texture)
      });
    })
    const promiseEarth = new Promise((resolve, reject) => {
      new THREE.TextureLoader().load("http://182.43.179.137:81/public/images/texture-earth.png", function (texture) {
        resolve(texture)
      });
    })
    const [state, [textureStar, textureEarth], err] = await Promise.all([promiseStar, promiseEarth]).then(rs => [true, rs, null], err => [false, null, err])
    if (!state) return

    // 定义Point类
    class Point {
      constructor() {
        this.range = 3000; // 分布半径
        this.center = { // 分布中心
          x: 0,
          y: 0,
          z: 0,
        }
        this.position = { // 粒子位置
          x: Math.random() * 2 * this.range + this.center.x - this.range,
          y: Math.random() * 2 * this.range + this.center.y - this.range,
          z: Math.random() * 2 * this.range + this.center.z - this.range
        };
        this.speed = { // 粒子移动速度
          x: Math.random() * 10 - 5,
          y: Math.random() * 10 - 5,
          z: Math.random() * 10 - 5,
        }
        this.color = '#aaa';// 粒子颜色
        this.createTime = Date.now(); // 粒子创建时间
        this.updateTime = Date.now(); // 上次更新时间
      }

      // 更新粒子位置
      updatePosition() {
        const time = Date.now() - this.updateTime
        this.updateTime = Date.now()
        this.position.x += this.speed.x * time / 1000
        this.position.y += this.speed.y * time / 1000
        this.position.z += this.speed.z * time / 1000
      }
    }

    // 批量创建粒子
    const vertices = []
    for (let i = 0; i < (window.innerWidth >1200 ? 10000 : 2000); i++) {
      vertices.push(new Point())
    }

    // 先创建一个空的缓冲几何体
    const geometry = new THREE.BufferGeometry();
    geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array([]), 3)); // 一个顶点由3个坐标构成

    // 创建材质
    const material = new THREE.PointsMaterial({
      color: '#ffff00',
      size: 15,
      map: textureStar, // 纹理图
      transparent: true,// 开启透明度
      depthWrite: false,

    });

    // 创建点,并添加进场景
    const points = new THREE.Points(geometry, material);
    scene.add(points);



    // 不间断更新粒子位置
    setInterval(() => {
      const list = []
      vertices.forEach(point => {
        point.updatePosition()
        const { x, y, z } = point.position
        list.push(x, y, z)
      })

      // 粒子位置更新入几何体
      geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(list), 3));

    }, 50)

    // 地球
    const earthGeometry = new THREE.SphereGeometry(80, 100, 100)
    const earthMaterial = new THREE.MeshPhongMaterial({
      map: textureEarth
    })
    const earth = new THREE.Mesh(earthGeometry, earthMaterial)
    scene.add(earth)

  })()

</script>


</html>