JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>

<script>
THREE.SoftParticlesShader = {

    defines: {
      "USE_SIZEATTENUATION": true,
      "USE_MAP": true,
    },

    uniforms: {

      diffuse: {
        value: new THREE.Color(1, 1, 1)
      },
      map: {
        value: null
      },
      opacity: {
        value: 1
      },
      scale: {
        value: 329
      },
      size: {
        value: 1
      },
      uvTransform: {
        value: new THREE.Matrix3().set(1, 0, 0, 0, 1, 0, 0, 0, 1)
      },
      fCamNear: {
        value: 0.1
      },
      fCamFar: {
        value: 1000
      },
      sceneDepthTexture: {
        value: null
      },
      screenSize: {
        value: null
      },
      sizeAttenuation: {
        value: true
      },

    },

    vertexShader: [
      "uniform float size;",
      "uniform float scale;",

      "void main() {",
      "#include <begin_vertex>",
      "#include <project_vertex>",

      "gl_PointSize = size;",
      "#ifdef USE_SIZEATTENUATION",
      "bool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );",
      "if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );",
      "#endif",
      "}",
    ].join("\n"),

    fragmentShader: [
      "uniform vec3 diffuse;",
      "uniform float opacity;",

      "#include <map_particle_pars_fragment>",

      "uniform sampler2D sceneDepthTexture;",
      "uniform vec2 screenSize;",
      "uniform float fCamNear;",
      "uniform float fCamFar;",

      "float fadeEdge( float particleDepth, float sceneDepth ){",
      // margin makes it blend through the solid objects a little bit more, creating illusion of density
      "float extraMargin = 0.015; ",
      "float a = ( sceneDepth+extraMargin - particleDepth ) * 120.0;",
      "if( a <= 0.0 ) return 0.0;",
      "if( a >= 1.0 ) return...

CSS

body {
  margin: 0;
}

JavaScript

var camera, scene, renderer, stats;
var textureLoader, smokeTexture, smokeParticles, renderTarget;

init();
animate();

function init() {
  // Renderer
  renderer = new THREE.WebGLRenderer( {antialias: true } );
	//renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize (window.innerWidth, window.innerHeight );
	document.body.appendChild( renderer.domElement );

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

  // Camera
  camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 500 );
  camera.position.set( 0, 5.5, 10 );

  //Stats
  stats = new Stats();
  document.body.appendChild( stats.dom );

  // Loaders
  textureLoader = new THREE.TextureLoader();

  // Controls
  var controls = new THREE.OrbitControls( camera, renderer.domElement );

  // Textures
  smokeTexture = textureLoader.load( 'https://i.imgur.com/D3tb7YJ.png' );

  // Lights
  var ambientLight = new THREE.AmbientLight( 0xffffff, 0.3 );
  var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
  directionalLight.position.set( 12, 50, 15 );
  scene.add( ambientLight, directionalLight );

  createStartingMesh();
  initParticles();

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

function createStartingMesh() {

  // Ground
  var floor = new THREE.Mesh(
    new THREE.PlaneBufferGeometry( 30, 400 ),
    new THREE.MeshPhongMaterial( {
      color: 0x105020,
      shininess: 0,
    } )
  );
  floor.rotation.x -= 90 * Math.PI / 180;
  scene.add( floor );

  // Cube
  var cube = new THREE.Mesh(
    new THREE.BoxBufferGeometry( 2, 2, 2 ),
    new THREE.MeshPhongMaterial( {
      color: 0x404040
    } )
  );
  cube.position.set( 0, 1, 0 );
  scene.add( cube );

  // Walls
  var wall1 = new THREE.Mesh(
    new THREE.BoxBufferGeometry( 20, 7, 1 ),
    new THREE.MeshPhongMaterial( {
      color: 0x404040
    } )
  ) ;
  wall1.position.set( 0, 3.5, - 150 );

  var wall2 = new THREE.Mesh(
    new...