JSFiddle - React, Tailwind, and code Playground

by Paul West

CSS

body{
  overflow: hidden;
  margin: 0;
}

JavaScript

import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {
  OrbitControls
} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 30, 50);
let renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(innerWidth, innerHeight);
//renderer.setClearColor(0xffffff)
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", event => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
})

let controls = new OrbitControls(camera, renderer.domElement);

let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.25));

let g = new THREE.PlaneGeometry(50, 50, 15, 15);
g.rotateX(-Math.PI * 0.5);
let vertData = [];
let v3 = new THREE.Vector3(); // for re-use
for (let i = 0; i < g.attributes.position.count; i++) {
  v3.fromBufferAttribute(g.attributes.position, i);
  vertData.push({
    initH: v3.y,
    amplitude: THREE.MathUtils.randFloatSpread(2),
    phase: THREE.MathUtils.randFloat(0, Math.PI)
  })
}
let m = new THREE.MeshLambertMaterial({
  color: "aqua"
});
let o = new THREE.Mesh(g, m);
scene.add(o);

let clock = new THREE.Clock();

renderer.setAnimationLoop(() => {

  let time = clock.getElapsedTime();

  vertData.forEach((vd, idx) => {
    let y = vd.initH + Math.sin(time + vd.phase) * vd.amplitude;
    g.attributes.position.setY(idx, y);
  })
  g.attributes.position.needsUpdate = true;
  g.computeVertexNormals();

  renderer.render(scene, camera);
});