JSFiddle - React, Tailwind, and code Playground

by tfoller

HTML

<canvas id="main_canvas" width="500" height="500"></canvas>

<script type="x-shader/x-vertex" id="vs_imesh">
  #ifdef USE_INSTANCING_COLOR
  	attribute vec3 instanceRGID;
  #endif

  varying vec3 vrgID;
  varying vec3 vColor;
  void main() {
	  vec4 pos = vec4(position, 1.0);

    #ifdef USE_INSTANCING
  	  pos = instanceMatrix * pos;
    #endif

    gl_Position = projectionMatrix * modelViewMatrix * pos;

    #ifdef USE_INSTANCING_COLOR
    	vColor = instanceColor;
      vrgID = instanceRGID;
    #else
    	vColor = vec3(1.0);
    	vrgID = vec3(1.0);
    #endif
  }
  </script>

<script type="x-shader/x-fragment" id="fs_imesh">
  varying vec3 vColor;
  varying vec3 vrgID;
  void main() {
  	gl_FragColor = vec4(vrgID + vColor, 1.0);
  }
  </script>

CSS

@import url("https://alikim.com/_v1_jsm/css/controls.css");

JavaScript

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

import {
  quaternFromETh
} from 'https://alikim.com/_v1_jsm/geometry.js'

import GMRNG from 'https://alikim.com/_v1_jsm/rng.js'

import * as CONTROLS from 'https://alikim.com/_v1_jsm/controls.js'

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

const getShader = (uiObj, id) => {
  let src = get(id).textContent;
  src = src.replace(/#include '([^']+)'/g,
    function() {
      const $1 = arguments[1];
      const elem = get($1);
      if (!elem) console.error(`include shader '${$1}' not found`);
      return elem.textContent;
    });
  return src;
};

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, 100];
const mid = -0.5 * (near + far);
const camera = new THREE.PerspectiveCamera(45, w / h, near, far);
camera.position.set(3, 4, 3);
camera.lookAt(0, 0, 0);

const scene = new THREE.Scene();
scene.background = new THREE.Color(0.01, 0.01, 0.15);

const geo = new THREE.CylinderGeometry(0.5, 0.7, 1, 6);

const mat = new THREE.ShaderMaterial({
  uniforms: {

  },
  vertexShader: getShader({}, 'vs_imesh'),
  fragmentShader: getShader({}, 'fs_imesh')
});

const size = 3;

const imesh = new THREE.InstancedMesh(geo, mat, size);

const mtx = new THREE.Matrix4();

const e = [1, 0, 0];

for (let i = 0; i < size; i++) {

  const q = quaternFromETh(e, Math.PI / 8 * i);

  const sc = new THREE.Vector3(1, 1 - i * 0.2, 1);

  mtx.compose(
    new THREE.Vector3(0, 0, 0).add(new THREE.Vector3(0, 0, i)),
    new THREE.Quaternion(q[1], q[2], q[3], q[0]),
    sc);

  imesh.setMatrixAt(i, mtx);
  imesh.setColorAt(i, new THREE.Color(i / 4, 1 - i / 4, 1));
}

const rgID = [0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5];

imesh.geometry.setAttribute('instanceRGID', 
new THREE.InstancedBufferAttribute(new Float32Array(rgID),...