How would I go about making this animation in three.js? I have something but it looks like a fabric sheet!

What I’m looking for:

What I have:

Current code:

  import { useRef, useMemo } from 'react'
    import { Canvas, useFrame } from '@react-three/fiber'
    import * as THREE from 'three'
    
    function Particles({ count = 10000 }) {
      const mesh = useRef<THREE.Points>(null)
      const light = useRef<THREE.PointLight>(null)
    
      const particles = useMemo(() => {
        const temp = new Float32Array(count * 3)
        for (let i = 0; i < count; i++) {
          const i3 = i * 3
          temp[i3] = (Math.random() - 0.5) * 10
          temp[i3 + 1] = Math.random() * 5
          temp[i3 + 2] = (Math.random() - 0.5) * 10
        }
        return temp
      }, [count])
    
      useFrame((state) => {
        const time = state.clock.getElapsedTime()
        if (mesh.current) {
          for (let i = 0; i < count; i++) {
            const i3 = i * 3
            mesh.current.geometry.attributes.position.array[i3 + 1] =
              Math.sin(
                (mesh.current.geometry.attributes.position.array[i3] + time) * 0.5
              ) *
                2 +
              Math.sin(
                (mesh.current.geometry.attributes.position.array[i3 + 2] + time) *
                  0.5
              ) *
                2
          }
          mesh.current.geometry.attributes.position.needsUpdate = true
        }
        if (light.current) {
          light.current.position.x = Math.sin(time * 0.7) * 3
          light.current.position.y = Math.cos(time * 0.5) * 4
          light.current.position.z = Math.cos(time * 0.3) * 3
        }
      })
    
      return (
        <>
          <pointLight ref={light} distance={40} intensity={8} color='white' />
          <points ref={mesh}>
            <bufferGeometry>
              <bufferAttribute
                attach='attributes-position'
                count={particles.length / 3}
                array={particles}
                itemSize={3}
              />
            </bufferGeometry>
            <pointsMaterial size={0.05} color='white' />
          </points>
        </>
      )
    }
    
    export default function WaveParticle3D() {
      return (
        <div className='w-full h-screen'>
          <Canvas camera={{ position: [0, 0, 10], fov: 75 }}>
            <color attach='background' args={['black']} />
            <Particles />
          </Canvas>
        </div>
      )
    }

This has me stumped since I’ve never really used Three.js before… any tips?

Out of curiosity, how did you already achieve what you’re looking for…

Is that not the way to achieve what you’re looking for?