JSFiddle - React, Tailwind, and code Playground

by spacorum

HTML

<script src='//cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.js'></script> 
<script id="frag1" type="x-shader/x-fragment">
// SHADERTOY: https://www.shadertoy.com/view/MdXyzX

    uniform float iGlobalTime;
    uniform vec2 iResolution;
    uniform vec4      iMouse;
    uniform sampler2D iChannel0;
    varying vec2 fragCoord;
    varying vec2 vUv;
    
float wave(vec2 uv, vec2 emitter, float speed, float phase){
	float dst = distance(uv, emitter);
	return pow((0.5 + 0.5 * sin(dst * phase - iGlobalTime * speed)), 5.0);
}

#define GOLDEN_ANGLE_RADIAN 2.39996
float getwaves(vec2 uv){
	float w = 0.0;
	float sw = 0.0;
	float iter = 0.0;
	float ww = 1.0;
    uv += iGlobalTime * 0.5;
	// it seems its absolutely fastest way for water height function that looks real
	for(int i=0;i<6;i++){
		w += ww * wave(uv * 0.06 , vec2(sin(iter), cos(iter)) * 10.0, 2.0 + iter * 0.08, 2.0 + iter * 3.0);
		sw += ww;
		ww = mix(ww, 0.0115, 0.4);
		iter += GOLDEN_ANGLE_RADIAN;
	}
	
	return w / sw;
}
float getwavesHI(vec2 uv){
	float w = 0.0;
	float sw = 0.0;
	float iter = 0.0;
	float ww = 1.0;
    uv += iGlobalTime * 0.5;
	// it seems its absolutely fastest way for water height function that looks real
	for(int i=0;i<24;i++){
		w += ww * wave(uv * 0.06 , vec2(sin(iter), cos(iter)) * 10.0, 2.0 + iter * 0.08, 2.0 + iter * 3.0);
		sw += ww;
		ww = mix(ww, 0.0115, 0.4);
		iter += GOLDEN_ANGLE_RADIAN;
	}
	
	return w / sw;
}

float H = 0.0;
vec3 normal(vec2 pos, float e, float depth){
    vec2 ex = vec2(e, 0);
    H = getwavesHI(pos.xy) * depth;
    vec3 a = vec3(pos.x, H, pos.y);
    return normalize(cross(normalize(a-vec3(pos.x - e, getwavesHI(pos.xy - ex.xy) * depth, pos.y)), 
                           normalize(a-vec3(pos.x, getwavesHI(pos.xy + ex.yx) * depth, pos.y + e))));
}
mat3 rotmat(vec3 axis, float angle)
{
	axis = normalize(axis);
	float s = sin(angle);
	float c = cos(angle);
	float oc = 1.0 - c;
	
	return mat3(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z *...

JavaScript

var myInstance = {
      scene: new THREE.Scene(),
      camera: new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000),
      gameObjects: [],
      gameObjectsDict: {},
    };
    (function(myInstance) {
      myInstance.camera.position.x = 0;
      myInstance.camera.position.y = 0;
      myInstance.camera.position.z = 3;
      var webgl = new THREE.WebGLRenderer();
      webgl.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(webgl.domElement);

      function onWindowResize() {
        myInstance.camera.aspect = window.innerWidth / window.innerHeight;
        myInstance.camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
      }
      window.addEventListener('resize', onWindowResize, false);
      renderer = webgl
      var light = new THREE.HemisphereLight(0xeeeeee, 0x888888, 1);
      light.position.set(0, 20, 0);
      //myInstance.scene.add(light);
      counter = 0;

      function render() {
        myInstance.gameObjects.forEach(function(item) {
          item.update(counter);
        });
        requestAnimationFrame(render);
        renderer.render(myInstance.scene, myInstance.camera);
      }
      render();
    })(myInstance);

    (function() {
      var gameObject = function(name, x, y, z, col, rx, ry) {
        this.name = name
        this.geometry = new THREE.PlaneGeometry(3, 3);
        uniforms = {
          iGlobalTime: {
            type: "f",
            value: 1.0
          },
          iResolution: {
            type: "v2",
            value: new THREE.Vector2()
          },          
        };
        uniforms.iResolution.value.x = 1; // window.innerWidth;
        uniforms.iResolution.value.y = 1; // window.innerHeight;
        this.material = new THREE.ShaderMaterial({
          uniforms: uniforms,
          side: THREE.DoubleSide,
          vertexShader: document.getElementById('general').textContent,
          fragmentShader:...