JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>

<div id="container"></div>

<script type="x-shader/x-vertex" id="vertexShader">
  // uniform float amplitude;
  // attribute float size;
  uniform float amplitude;
	
	attribute vec4 customColor;

  varying vec4 varColor;

  void main()
  {
  varColor = customColor;

  vec4 pos = vec4(position, 1.0);
  pos.z *= amplitude;

  vec4 mvPosition = modelViewMatrix * pos;

  gl_PointSize = 1.0;
  gl_Position = projectionMatrix * mvPosition;
  }
</script>

<script type="x-shader/x-fragment" id="fragmentShader">
  varying vec4 varColor;

  void main()
  {
  gl_FragColor = varColor;
  }
</script>

CSS

body {
	  margin: 0;
}

JavaScript

var container;
var camera, scene, renderer;
var controls;

var shaderUniforms;

var particles = [];
var particleSystem;

var imageWidth = 1004;
var imageHeight = 1023;
var imageData = null;

var animationTime = 0;
var animationDelta = 0.03;

init();
// tick();

function init() {
  createScene();
  createControls();
  createPixelData();

  window.addEventListener('resize', onWindowResize, false);
}

function createScene() {
  container = document.getElementById('container');

  scene = new THREE.Scene();
	scene.background = new THREE.Color( 0xffffff );

  camera = new THREE.PerspectiveCamera(20, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.z = 3000;
  camera.lookAt(scene.position)

  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setClearColor(0x000000, 1);

  container.appendChild(renderer.domElement);
}

function createControls() {
  controls = new THREE.TrackballControls(camera, renderer.domElement);

  controls.rotateSpeed = 1.0;
  controls.zoomSpeed = 1.2;
  controls.panSpeed = 0.8;

  controls.noZoom = false;
  controls.noPan = true;

  controls.staticMoving = true;
  controls.dynamicDampingFactor = 0.3;
}

function createPixelData() {
  var image = document.createElement("img");
  var canvas = document.createElement("canvas");
  var context = canvas.getContext("2d");
  
  image.crossOrigin = "Anonymous";
  image.onload = function() {
    image.width = canvas.width = imageWidth;
    image.height = canvas.height = imageHeight;
    
    context.fillStyle = context.createPattern(image, 'no-repeat');
    context.fillRect(0, 0, imageWidth, imageHeight);
    //context.drawImage(image, 0, 0, imageWidth, imageHeight);
    
    imageData = context.getImageData(0, 0, imageWidth, imageHeight).data;

    createPaticles();
    tick();
  };
  
  image.src = "https://i.imgur.com/WFuhtIt.png";
}

function createPaticles() {
  var colors = [];
  var weights =...