JSFiddle - React, Tailwind, and code Playground

by Paul West

HTML

<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/three@0.160.0/build/three.module.js",
      "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
    }
  }
</script>

CSS

body {
  overflow: hidden;
  margin: 0;
}

JavaScript

import * as THREE from "three";
import {OrbitControls} from "three/addons/controls/OrbitControls.js";
import {GUI} from "three/addons/libs/lil-gui.module.min.js";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(8, 16, 12);
let renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);

window.addEventListener("resize", event => {
	camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
})

let controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.target = new THREE.Vector3(0, 2.5, 0);
controls.update();

let geom = new THREE.BoxGeometry().translate(0, 0.5, 0);


let mu = {
  thickness: {value: 2}
}
for(let i = -4.5; i <= 4.5; i++){
	for(let j = -4.5; j <= 4.5; j++){
  	let material = new THREE.MeshBasicMaterial();
    material.defines = {"USE_UV" : ""};
    material.onBeforeCompile = shader => {
    	shader.uniforms.thickness = mu.thickness;
      shader.fragmentShader = `
      	uniform float thickness;
        
        float edgeFactor(vec2 p){
          vec2 grid = abs(fract(p - 0.5) - 0.5) / fwidth(p) / thickness;
          return min(grid.x, grid.y);
        }
        
        ${shader.fragmentShader}
      `.replace(
      	`#include <dithering_fragment>`,
        `#include <dithering_fragment>
        	float a = clamp(edgeFactor(vUv), 0., 1.);
      
      		gl_FragColor.rgb = mix(vec3(0), gl_FragColor.rgb, a);
        `
      );
      console.log(shader.fragmentShader);
    }
    
		let box = new THREE.Mesh( geom, material );
    box.material.color.setHSL(Math.random(), 0.75, 0.5);
    box.scale.y = THREE.MathUtils.randInt(1, 10);
    box.position.set(i, 0, j);
		scene.add( box );  	
  }
}

let gui = new GUI();
gui.add(mu.thickness,...