JSFiddle - React, Tailwind, and code Playground

by tfoller

HTML

<canvas id="main_canvas" style="border: solid 1px red;" width=500 height=500></canvas>
<div><input type="checkbox" id="sort" checked/> <span> sort</span></div>

CSS

body {
            background: #000;
            color: #ccc;
        }
        
        #main_canvas2 {
          background: repeating-linear-gradient(90deg, rgba(80, 40, 70, 1) 0px, rgba(80, 40, 70, 1) 2px, rgba(0, 0, 0, 1) 2px, rgba(0, 0, 0, 1) 4px);
        }

#ctrl_over {
  position: absolute;
  opacity: 0.5;
  bottom: 9px;
  right: 5px;

  color: #aaa;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 13px;
}

#ctrl_sw {
  border: solid 1px #aaa;
  padding: 3px;
  margin-left: 10px;
  cursor: pointer;
  font-size: 11px;
  text-transform: uppercase;
}

#canv_wrap {
  position:relative;
  margin: 0px;
  padding: 0px;
  display: inline-block;
}

JavaScript

import * as THREE from 'https://alikim.com/_v1_jsm/three.module.js'

import { hslRgb } from 'https://alikim.com/_v1_jsm/glsl_ported.js'

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

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

const canvas = get('main_canvas');

const [w, h] = [canvas.width, canvas.height];
const [w2, h2] = [w * 0.5, h * 0.5];
const renderer = new THREE.WebGLRenderer({
  antialias: false,
  alpha: true,
  canvas,
});
renderer.setPixelRatio(window.devicePixelRatio);

const gl = renderer.getContext();

const [near, far] = [1, 500];
const mid = 0.5 * (near + far);
const camera = new THREE.PerspectiveCamera(45, w / h, near, far);

camera.position.set(0, 0, mid);

const total = 3000;

const vertices = [];
const colors = [];

// for sortng
const data = [];

for ( let i = 0; i < total; i ++ ) {
  const x = THREE.MathUtils.randFloatSpread( 100 );
  const y = THREE.MathUtils.randFloatSpread( 100 );
  const z = THREE.MathUtils.randFloatSpread( 100 );
  
  data[i] = [
    x, y, z,
    ...hslRgb([THREE.MathUtils.randFloat(0, 1), 1, 0.5]), THREE.MathUtils.randFloat(0, 1),
  ];
  
  vertices.push(x, y, z);
  colors.push(...data[i].slice(3));
}

const geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 4 ) );
const attr_pos = geometry.attributes.position;
const attr_clr = geometry.attributes.color;
const F32A_pos = attr_pos.array;
const F32A_clr = attr_clr.array;

const compByDist = (a, b) => {
  const pos =  camera.position;
  const cam_pos = [pos.x, pos.y, pos.z];
  const [dA, dB] = [new Array(3), new Array(3)];
  for(let i = 0; i < 3; i++) {
    dA[i] = a[i] - cam_pos[i];
    dB[i] = b[i] - cam_pos[i];
  }
  const distA = dA[0] * dA[0] + dA[1] * dA[1] + dA[2] * dA[2];
  const distB = dB[0] * dB[0] + dB[1] * dB[1] + dB[2] * dB[2];
  return distA - distB;
};

const sortPoints = () => {
 ...