JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://threejs.org/build/three.min.js"></script>


<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<script src="https://threejs.org/examples/js/misc/GPUComputationRenderer.js"></script>

<script id="heightmapFragmentShader" type="x-shader/x-fragment">

    #include <common>

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

    void main()	{

        vec2 cellSize = 1.0 / resolution.xy;

        vec2 uv = gl_FragCoord.xy * cellSize;

        // heightmapValue.x == height from previous frame
        // heightmapValue.y == height from penultimate frame
        // 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 ) );

        // https://web.archive.org/web/20080618181901/http://freespace.virgin.net/hugo.elias/graphics/x_water.htm

        float newHeight = ( ( north.x + south.x + east.x + west.x ) * 0.5 - heightmapValue.y ) * viscosityConstant;

        // Mouse influence
        float mousePhase = clamp( length( ( uv - vec2( 0.5 ) ) * BOUNDS - vec2( mousePos.x, - mousePos.y ) ) * PI / mouseSize, 0.0, PI );
        newHeight += ( cos( mousePhase ) + 1.0 ) * 0.28;

        heightmapValue.y = heightmapValue.x;
        heightmapValue.x = newHeight;

        gl_FragColor = heightmapValue;

    }

</script>

<!-- This is just a smoothing 'compute shader' for using manually: -->
<script id="smoothFragmentShader" type="x-shader/x-fragment">

    uniform sampler2D smoothTexture;

    void main()	{

        vec2 cellSize = 1.0 / resolution.xy;

        vec2 uv =...

CSS

body{
  overflow: hidden;
  margin: 0;
}

JavaScript

// Texture width for simulation
// Texture width for simulation
const WIDTH = 128;

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

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

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

const NUM_SPHERES = 5;
const spheres = [];
let spheresEnabled = true;



init();
animate();

function init() {

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

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

    scene = new THREE.Scene();

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

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

    renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
    });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    container.appendChild(renderer.domElement);


    container.style.touchAction = 'none';
    container.addEventListener('pointermove', onPointerMove);

    document.addEventListener('keydown', function (event) {

        // W Pressed: Toggle wireframe
        if (event.keyCode === 87) {

            waterMesh.material.wireframe = !waterMesh.material.wireframe;
            waterMesh.material.needsUpdate = true;

        }

    });

    window.addEventListener('resize', onWindowResize);


    const text = new THREE.TextureLoader().load("./baked.jpg")

    const effectController = {
      ...