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();