JSFiddle - React, Tailwind, and code Playground

by tfoller

HTML

<link type="text/css" rel="stylesheet" href="https://alikim.com/_v1_jsm/css/controls.css">

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

<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
  <script type="importmap">
    {
      "imports": {
        "three": "https://unpkg.com/[email protected]/build/three.module.js",
        "three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
      }
    }
  </script>
  
  <script type="x-shader/x-vertex" id="vs">

	varying vec2 vuv;
  varying vec2 vndc;

    void main() {

        vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);

				vec4 pos = projectionMatrix * mvPosition;

        gl_Position = pos;

				vuv = uv;
        vndc = pos.xy / pos.w;
    }
</script>

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

	varying vec2 vuv;
  varying vec2 vndc;

	uniform vec2 mouse;
  uniform sampler2D map;

    void main() {
    
    	
    
    	// wide highlight
    	// float dif = clamp(1.0 - length(mouse - vndc), 0.0, 1.0);
    
    	// focused highlight
      float falloff = 10.0;
    	float dif = pow(falloff, -clamp(length(mouse - vndc), 0.0, 1.0));
            
      vec4 clr1 = dif * vec4(dif);
      vec4 clr2 = texture2D(map, vuv);
       
		  gl_FragColor = vec4(clr1 + clr2);
    }
</script>

JavaScript

import * as THREE from 'three'

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

// 3D

const canvas = document.getElementById('main_canvas');
const [w, h] = [canvas.width, canvas.height];
const renderer = new THREE.WebGLRenderer({
  antialias: true,
  canvas: canvas,
});
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.z = mid;

const tex = new THREE.TextureLoader().load(
	'https://alikim.com/_v1_jsm/textures/uv.png',
  render,
);

const quad = new THREE.Mesh(
  new THREE.PlaneGeometry(20, 20),
  new THREE.ShaderMaterial( {
    vertexShader: document.getElementById('vs').textContent,
    fragmentShader: document.getElementById('fs').textContent,
    uniforms: {
    	map: { value: tex },
    	mouse: { get value() { return mouse } }
    }
  }),
);


const scene = new THREE.Scene();
scene.add(quad);

const mouseToNDC = evt => {
	const w = parseInt(canv_stl.width);
	const h = parseInt(canv_stl.height);
	return [2 * evt.offsetX / w - 1, 1 - 2 * evt.offsetY / h];
};

let mouse = [0,0];
const canv_stl = canvas.style;
canvas.addEventListener('mousemove', evt => { mouse = mouseToNDC(evt); render(); })

function render() { 
	
	renderer.render(scene, camera);
}

const createControls = () => {
  CONTROLS.create({
    cont: canvas, 
    cam: camera,
    type: 'Trackball', 
    overlay: true, 
    lookAt: [0, 0, 0],
    callback: render,
    sens: {p: 0.05},
  });
};

createControls();
render();