ThreeJS网格波浪

196 阅读1分钟

在实时图形和视觉效果中,波动能为场景增添令人惊叹的动态效果。本文将着重介绍如何在 Three.js 中实现一个波动效果的平面(WavePlane),该平面可以通过对 3D 模型应用简单的噪声函数来自然生成波动效果。

import * as THREE from 'three'
import { createNoise2D } from 'simplex-noise'

type PlaneConfigType = {
  color: string | number
  width: number
  height: number
  segments: number
}

export class WavePlane {
  entity: any
  simplex: any
  factor: number
  cycle: number
  scale: number
  speed: number

  constructor(
    planeConfig: PlaneConfigType = {
      width: 5000,
      height: 5000,
      color: 0x7ee6e7,
      segments: Math.pow(2, 8),
    }
  ) {
    const { width, height, segments, color } = planeConfig
    const geometry = new THREE.PlaneGeometry(width, height, segments, segments)
    const material = new THREE.MeshLambertMaterial({
      color: '#202020',
      emissive: color,
      opacity: 0.1,
      blending: THREE.NoBlending,
      side: THREE.FrontSide,
      transparent: false,
      depthTest: false,
      wireframe: true,
    })
    this.entity = new THREE.Mesh(geometry, material)
    this.entity.rotation.set(Math.PI / 2, 0, 0)
    this.simplex = createNoise2D()
    this.factor = 300
    this.cycle = 0
    this.scale = 30
    this.speed = 0.005
  }
  boostrap(threeCore: any) {
    threeCore.scene.add(this.entity)
    threeCore.mixins.set('WavePlane', () => this.update())
  }
  update() {
    const positionAttribute = this.entity.geometry.attributes.position
    positionAttribute.needsUpdate = true
    for (let i = 0; i < positionAttribute.count; i++) {
      const x = positionAttribute.getX(i)
      const y = positionAttribute.getY(i)
      const xoff = x / this.factor
      const yoff = y / this.factor + this.cycle
      let rand = this.simplex(xoff, yoff) * this.scale
      positionAttribute.setZ(i, rand)
    }
    this.cycle += this.speed
  }
}