JSFiddle - React, Tailwind, and code Playground

HTML

<!DOCTYPE html>
<html>

<head>
    <title>Timedance Mix Series</title>
    <style>
        body {
            overflow: hidden;
            margin: 0px;
        }

        /* #menuPanel {
            position: absolute;
            background-color: rgba(255, 255, 255, 0.5);
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
        }

        #startButton {
            height: 50px;
            width: 200px;
            margin: -25px -100px;
            position: relative;
            top: 50%;
            left: 50%;
            font-size: 32px;
        } */
    </style>
</head>

<body>
    <!-- <div id="menuPanel">
        <button id="startButton">Click to Start</button>
    </div> -->
    <script type="module" src="client.js"></script>

    <!-- This is the 'compute shader' for the water heightmap: -->
	<script id="heightmapFragmentShader" type="x-shader/x-fragment">

			#include <common>

			uniform vec2 mousePos;
			uniform float mouseSize;
			uniform float viscosityConstant;

			#define deltaTime ( 1.0 / 60.0 )
			#define GRAVITY_CONSTANT ( resolution.x * deltaTime * 3.0 )

			void main()	{

				vec2 cellSize = 1.0 / resolution.xy;

				vec2 uv = gl_FragCoord.xy * cellSize;

				// heightmapValue.x == height
				// heightmapValue.y == velocity
				// heightmapValue.z, heightmapValue.w not used
				vec4 heightmapValue = texture2D( heightmap, uv );

				// Get neighbours
				vec4 north = texture2D( heightmap, uv + vec2( 0.0, cellSize.y ) );
				vec4 south = texture2D( heightmap, uv + vec2( 0.0, - cellSize.y ) );
				vec4 east = texture2D( heightmap, uv + vec2( cellSize.x, 0.0 ) );
				vec4 west = texture2D( heightmap, uv + vec2( - cellSize.x, 0.0 ) );

				float sump = north.x + south.x + east.x + west.x - 4.0 * heightmapValue.x;

				float accel = sump * GRAVITY_CONSTANT;

				// Dynamics
				heightmapValue.y += accel;
				heightmapValue.x += heightmapValue.y * deltaTime;

				// Viscosity
				heightmapValue.x +=...

TypeScript

import * as THREE from '/build/three.module.js'
import { OrbitControls } from '/jsm/controls/OrbitControls'
import Stats from '/jsm/libs/stats.module'
import { GUI } from '/jsm/libs/dat.gui.module'
import { HemisphereLight, MixOperation } from '/build/three.module.js'
import { SimplexNoise } from '/jsm/math/SimplexNoise'
import { GPUComputationRenderer } from '/jsm/misc/GPUComputationRenderer'

// Texture width for simulation
var WIDTH = 128;

// Water size in system units
var BOUNDS = 512;
var BOUNDS_HALF = BOUNDS * 0.5;

var container, stats;
var camera, scene, renderer;
var mouseMoved = false;
var mouseCoords = new THREE.Vector2();
var raycaster = new THREE.Raycaster();

var waterMesh;
var meshRay;
var gpuCompute;
var heightmapVariable;
var waterUniforms;
var smoothShader;
var readWaterLevelShader;
var readWaterLevelRenderTarget;
var readWaterLevelImage;
var waterNormal = new THREE.Vector3();

var NUM_SPHERES = 5;
var spheres = [];
var spheresEnabled = true;

var simplex = new SimplexNoise();

init();
animate();

function init() {

const container = document.createElement( 'div' );
document.body.appendChild( container );

const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.set( 0, 200, 350 );

const scene: THREE.Scene = new THREE.Scene();

const sun: THREE.DirectionalLight = new THREE.DirectionalLight( 0xFFFFFF, 1.0 );
sun.position.set( 300, 400, 175 );
scene.add( sun );

const sun2: THREE.DirectionalLight = new THREE.DirectionalLight ( 0x40A040, 0.6 );
sun2.position.set( - 100, 350, - 200 );
scene.add( sun2 );

const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer()
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

const controls = new OrbitControls(camera, renderer.domElement)
controls.minDistance = 100;
controls.maxDistance = 1000;

const stats =...