JSFiddle - React, Tailwind, and code Playground

by Paul West

HTML

<script>
let blocksImg = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGfSURBVDhPZZMxbsMwEAT5HX8hgDtXKQUYiIE07OVUafIAQ35BnpAfqPDvMvQIi4tCHA57K93ukZTax/Xae/95rmmawJbrupLvy52SnPJxe/+eX4mv8wuxKy/HQ3hzixzNBB7gyMnowShk2pCLEHhZFkvNAiCJzYBOcnajdJjq4WgEzcGKBistMwzSXHEYnchgnBhtnmebsxVKsOObZYYBPRHyZMRkloxLMipIoG4poxn2tWxIYEA/AAlCP4wtcx9uix51lVbIoPSpgGCIltHIYrXG/L3rHQYzD8fgeiMkHxD7FkUHjBbA2bWhlKyK2YdadWcyxPYfqKVN1MkGDMvbqv3JHouKPg05vqLdKWsT6Vi6G4XqiQcn6kGNI4quiiw/fJ0sUWcxim1VxbPCRgZASXhDm4FCisLk9Fl+TjAsgOraEHoA+DplKPUQjDuIojZiyDBgwjdrv4p6/A839OcOCEqxcgJIlphO1YnPt5OljKdEBgPkx39QFZXbqfvC02X7k9USpJTxBcEwoCfNOw9JmGwR0v4MCPYyU1Z8OR5+AaYiqFz1UTlXAAAAAElFTkSuQmCC`;
</script>

CSS

body{
  overflow: hidden;
  margin: 0;
}

JavaScript

import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
import {ImprovedNoise} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/math/ImprovedNoise";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 5, 20).setLength(40);
let renderer = new THREE.WebGLRenderer();
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.target.set(8, 0, 8);
controls.update();

let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));

let texAtlas = new THREE.TextureLoader().load(blocksImg);
let texStep = 1 / 2; 

let g = new THREE.BoxGeometry(1, 1, 1);
let m = new THREE.MeshLambertMaterial({
	onBeforeCompile: shader => {
  	shader.uniforms.texAtlas = {value: texAtlas};
    shader.vertexShader = `
    	attribute float texIdx;
    	varying float vTexIdx;
      ${shader.vertexShader}
    `.replace(
    	`void main() {`,
      `void main() {
      	vTexIdx = texIdx;
      `
    );
    //console.log(shader.vertexShader);
    shader.fragmentShader = `
    	uniform sampler2D texAtlas;
    	varying float vTexIdx;
      ${shader.fragmentShader}
    `.replace(
    	`#include <map_fragment>`,
      `#include <map_fragment>
      	
       	vec2 blockUv = ${texStep} * (floor(vTexIdx + 0.1) + vUv); 
        vec4 blockColor = texture(texAtlas, blockUv);
        diffuseColor *= blockColor;
      `
    );
    console.log(shader.fragmentShader);
  }
});
m.defines = {"USE_UV" : ""};
let blocks = new THREE.InstancedMesh(g, m, 10240);

let perlin...