JSFiddle - React, Tailwind, and code Playground

by tfoller

HTML

<canvas id="main_canvas" width="500" height="300"></canvas>
<div><button id="play">play</button></div>

CSS

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  background: #112233;
  width: 100vw;
  height: 100vh;
}

#main_canvas {
  display: block;
  box-sizing: content-box;
  border: solid 1px grey;
  margin: 10px;
}

#play, #test {
  padding: 3px 5px;
  cursor: pointer;
  margin-left: 10px;
}

JavaScript

import * as THREE from 'https://unpkg.com/three/build/three.module.js'

import { hslRgb } from 'https://alikim.com/jsm/glsl.module.js'

const get = id => document.getElementById(id);

// 3D

const canvas = get('main_canvas');
const [w, h] = [canvas.width, canvas.height];
const renderer = new THREE.WebGLRenderer({
  antialias: true,
  canvas: canvas,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(w, h);

const [near, far] = [1, 1000];
const camera = new THREE.PerspectiveCamera(45, w / h, near, far);

const scene = new THREE.Scene();
scene.background = new THREE.Color(0.05, 0, 0.05);

const light = {};
light.dir = new THREE.DirectionalLight(0xffffff, 0.8);
light.dir.position.set(1, 1, 1);

Object.keys(light).forEach(k => { scene.add(light[k]) });

const PI2 = 2 * Math.PI;
const geo = new THREE.BoxGeometry(1, 1, 1);
const mat = new THREE.MeshLambertMaterial();
const cube = [];

for(let i = 0; i < 100; i++) {
  cube[i] = new THREE.Mesh(geo, mat.clone());
  cube[i].material.color = new THREE.Color(...hslRgb([Math.random(), 0.9, 0.5]));
  const sz = 20 + 50 * Math.random();
  cube[i].scale.set(sz, sz, sz);
  const x = 200 * 2 * (Math.random() - 0.5);
  const y = 100 * 2 * (Math.random() - 0.5);
  const z = 100 * 2 * (Math.random() - 0.5);
  cube[i].position.set(x, y, -0.5 * (near + far) + z);
  cube[i].rotation.set(PI2 * Math.random(), PI2 * Math.random(), PI2 * Math.random());
  scene.add(cube[i]);
}

// render the same scene on texture

function objectSelector(renderer, scene, camera, obj, light, w, h) {
    const nm = ['renderer', 'scene', 'camera', 'obj', 'light', 'w', 'h'];
    Array.from(arguments).forEach((v, i) => { this[nm[i]] = v });
    const opt = {
        magFilter: THREE.NearestFilter,
        minFilter: THREE.NearestFilter,
    };
    this.outputRT = new THREE.WebGLRenderTarget(1, 1, opt);
}

objectSelector.prototype.render = function (x, y) {
    const bg = this.scene.background;
    this.scene.background = null;
    const amb =...