three.js - Particles

2024-02-20  本文已影响0人  闪电西兰花
  // 导入three.js
  import * as THREE from 'three'
  // 导入轨道控制器
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

  // scene
  const scene = new THREE.Scene()
  
  // camera
  const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    100
  )
  camera.position.z = 3

  // render
  const renderer = new THREE.WebGLRenderer()
  renderer.setSize(window.innerWidth, window.innerHeight)
  document.body.appendChild(renderer.domElement)

  window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()

    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  })

  // axesHelper (根据自己的需要选择是否添加坐标轴)
  const axesHelper = new THREE.AxesHelper(5)
  scene.add(axesHelper)

  // controls
  const controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true

  // animate
  const clock = new THREE.Clock()
  function animate () {
    let elapsedTime = clock.getElapsedTime()

    controls.update()
    requestAnimationFrame(animate)
    renderer.render(scene, camera)
  }
  animate()
  /**
   * particles
   */
  // Geometry
  const particlesGeometry = new THREE.SphereGeometry(1, 32, 32)  // 球体 - 半径、水平和垂直分段数

  // Material
  const particlesMaterial = new THREE.PointsMaterial({
    size: 0.02, // 粒子大小
    sizeAttenuation: true, // 尺寸衰减,产生透视效果,粒子距离camera越远看起来越小
  })

  // Points
  const particles = new THREE.Points(particlesGeometry, particlesMaterial)
  scene.add(particles)
Simple particles.png
  /**
   * particles
   */
  // Geometry
  const particlesGeometry = new THREE.BufferGeometry()
  const count = 500 // bufferGeometry个数
  const positions = new Float32Array(count * 3) // 参数表示数组长度,每个bufferGeometry有 x,y,z 3个坐标点
  // 填充positions数组
  for(let i = 0; i < count * 3; i++) {
    positions[i] = (Math.random() - 0.5) * 10  // 事粒子居中并扩大显示范围
  }
  // 3个值为一组(向缓冲区几何体添加属性)
  particlesGeometry.setAttribute(
    'position', 
    new THREE.BufferAttribute(positions, 3)
  )

  // Material
  const particlesMaterial = new THREE.PointsMaterial({
    size: 0.02, // 粒子大小
    sizeAttenuation: true, // 尺寸衰减,产生透视效果,粒子距离camera越远看起来越小
  })

  // Points
  const particles = new THREE.Points(particlesGeometry, particlesMaterial)
  scene.add(particles)
Custom geometry.png
  /**
   * particles
   */
  // Geometry
  ...
  const colors = new Float32Array(count * 3)  // 颜色是由 r,g,b 组成的
  // 填充positions数组
  for(let i = 0; i < count * 3; i++) {
    ...
    colors[i] = Math.random()
  }
  // 3个值为一组(向缓冲区几何体添加属性)
  ...
  particlesGeometry.setAttribute(
    'color',
    new THREE.BufferAttribute(colors, 3)
  )

  // Material
  const particlesMaterial = new THREE.PointsMaterial({
    // color: '#ff88cc',
    ...
    depthWrite: false, // depth buffer存储已渲染的部分
    blending: THREE.AdditiveBlending, // 颜色叠加
    vertexColors: true, // 顶点颜色
  })
Different Color of each particle.png
  const clock = new THREE.Clock()
  function animate () {
    let elapsedTime = clock.getElapsedTime()

    // update particles
    for(let i = 0; i < count; i++) {  // count表示particles的数量,但是每个particle都有x,y,z3个坐标信息
      const i3 = i * 3  // 对应每个particle的x坐标值
      const x = particlesGeometry.attributes.position.array[i3]
      particlesGeometry.attributes.position.array[i3 + 1] = Math.sin(elapsedTime + x)
    }
    particlesGeometry.attributes.position.needsUpdate = true  // geometry的属性改变时需要重置

    controls.update()
    requestAnimationFrame(animate)
    renderer.render(scene, camera)
  }
  animate()
particles动画的状态.png
上一篇 下一篇

猜你喜欢

热点阅读