JSFiddle - React, Tailwind, and code Playground

by Paul West

HTML

<script id="fragmentShaderLava" type="x-shader/x-fragment">

				vec4 noise = texture2D( texture1, vUv * uvScale );
				vec2 T1 = vUv + vec2( 1.5, - 1.5 ) * time * 0.02;
				vec2 T2 = vUv + vec2( - 0.5, 2.0 ) * time * 0.01;

				T1.x += noise.x * 2.0;
				T1.y += noise.y * 2.0;
				T2.x -= noise.y * 0.2;
				T2.y += noise.z * 0.2;

				float p = texture2D( texture1, T1 * 2.0 ).a;

				vec4 color = texture2D( texture2, T2 * 2.0 );
				vec4 temp = color * ( vec4( p, p, p, p ) * 2.0 ) + ( color * color - 0.1 );

				if( temp.r > 1.0 ) { temp.bg += clamp( temp.r - 8.0, 0.0, 1.0 ); }
				if( temp.g > 1.0 ) { temp.rb += temp.g - 1.0; }
				if( temp.b > 1.0 ) { temp.rg += temp.b - 1.0; }

				lavaColor = temp;

</script>

<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>

<script type="importmap">
{
	"imports": {
		"three": "https://cdn.skypack.dev/[email protected]"
	}
}
</script>

CSS

body {
	margin: 0;
	background-color: #777;
	color: #fff;
	font-family: Monospace;
	font-size: 13px;
	line-height: 24px;
	overscroll-behavior: none;
}

a {
	color: #ff0;
	text-decoration: none;
}

a:hover {
	text-decoration: underline;
}

button {
	cursor: pointer;
	text-transform: uppercase;
}

#info {
	position: absolute;
	top: 0px;
	width: 100%;
	padding: 10px;
	box-sizing: border-box;
	text-align: center;
	-moz-user-select: none;
	-webkit-user-select: none;
	-ms-user-select: none;
	user-select: none;
	pointer-events: none;
	z-index: 1; /* TODO Solve this in HTML */
}

a, button, input, select {
	pointer-events: auto;
}

.dg.ac {
	-moz-user-select: none;
	-webkit-user-select: none;
	-ms-user-select: none;
	user-select: none;
	z-index: 2 !important; /* TODO Solve this in HTML */
}

#overlay {
	position: absolute;
	font-size: 16px;
	z-index: 2;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-direction: column;
	background: rgba(0,0,0,0.7);
}

	#overlay button {
		background: transparent;
		border: 0;
		border: 1px solid rgb(255, 255, 255);
		border-radius: 4px;
		color: #ffffff;
		padding: 12px 18px;
		text-transform: uppercase;
		cursor: pointer;
	}

#notSupported {
	width: 50%;
	margin: auto;
	background-color: #f00;
	margin-top: 20px;
	padding: 10px;
}

    © 2021 GitHub, Inc.
    Terms
    Privacy
    Security
    Status
    Docs

    Contact GitHub
    Pricing
    API
    Training
    Blog
    About

Loading complete

JavaScript

import * as THREE from "three";
import { OrbitControls } from "https://cdn.skypack.dev/[email protected]/examples/jsm/controls/OrbitControls";
import { GUI } from 'https://cdn.skypack.dev/[email protected]/examples/jsm/libs/lil-gui.module.min.js';

import { EffectComposer } from 'https://cdn.skypack.dev/[email protected]/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'https://cdn.skypack.dev/[email protected]/examples/jsm/postprocessing/RenderPass';
import { UnrealBloomPass } from 'https://cdn.skypack.dev/[email protected]/examples/jsm/postprocessing/UnrealBloomPass';

import { ImprovedNoise } from 'https://cdn.skypack.dev/[email protected]/examples/jsm/math/ImprovedNoise';

const params = {
  exposure: 1.05,
  bloomStrength: 1.5,
  bloomThreshold: 0.5,
  bloomRadius: 0
};


let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(-5, 8, 8).setLength(10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
//renderer.setClearColor(0x201000, 0);
renderer.toneMapping = THREE.ReinhardToneMapping;
document.body.appendChild(renderer.domElement);

let controls = new OrbitControls(camera, renderer.domElement);

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

let g = new THREE.PlaneGeometry(20, 20, 400, 400);
g.rotateX(-Math.PI * 0.5);
let pos = g.attributes.position;
let uv = g.attributes.uv;
let v2 = new THREE.Vector2();
const perlin = new ImprovedNoise();
for(let i = 0; i < pos.count; i++){
	v2.fromBufferAttribute(uv, i).multiplyScalar(10);
  let y = perlin.noise( v2.x, v2.y, 100 );
  y = Math.pow(Math.abs(y), 0.5)*0.5;
  pos.setY(i, y);
}
g.computeVertexNormals();
let tl = new THREE.TextureLoader();
let uniforms = {
	rectSize: {value: new THREE.Vector2(5, 4)},
  rectWidth: {value: 0.125},
  uvScale: {value: new THREE.Vector2( 2.0, 2.0 )},
  time: {value: 0},
 ...