JSFiddle - React, Tailwind, and code Playground

by Paul West

HTML

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

CSS

body{
  overflow: hidden;
  margin: 0;
}

JavaScript

import * as THREE from "three";
import {
  OrbitControls
} from "three/addons/controls/OrbitControls.js";

class Atlas extends THREE.CanvasTexture{
	constructor(){
    let c = document.createElement("canvas");
    c.height = 128;
    c.width = 128 * 6;

    let u = (val) => val * c.height * 0.01;

    let ctx = c.getContext("2d");

    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, c.width, c.height);

    let letters = [..."АБВГДЕ"];
    ctx.fillStyle = "#000";
    ctx.font = `bold ${u(80)}px Arial`;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    letters.forEach((l, lIdx) => {
      ctx.fillText(l, (0.5 + lIdx) * 128, 64);
    })

    super(c);
    this.colorSpace = "srgb";
    this.anisotropy = renderer.capabilities.getMaxAnisotropy();
  }
}

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(innerWidth, innerHeight);
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;

let g = new THREE.PlaneGeometry();
let m = new THREE.MeshBasicMaterial({
	side: THREE.DoubleSide,
	map: new Atlas(),
  onBeforeCompile: shader => {
  	shader.uniforms.atlasSize = {value: new THREE.Vector2(6, 1)}
  	shader.vertexShader = `
    	uniform vec2 atlasSize;
    	attribute vec2 uvOffset;
      ${shader.vertexShader}
    `.replace(
    	`#include <uv_vertex>`,
      `#include <uv_vertex>
      
      	vMapUv = ( mapTransform * vec3( (MAP_UV + uvOffset) / atlasSize, 1 ) ).xy;
      `
    );
    console.log(shader.vertexShader);
  }
})
let amount = 100;
let io = new THREE.InstancedMesh(g, m, amount);
let uvOffset = [];
let dummy = new...