Created
August 25, 2018 14:14
-
-
Save Garciat/8f0f4a8d9b40f172e8de74b0bf8dbfde to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<body style="margin:0"> | |
<canvas></canvas> | |
</body> | |
<script> | |
let SCRW = document.body.clientWidth; | |
let SCRH = document.body.clientHeight; | |
let canvas = document.querySelector('canvas'); | |
canvas.width = SCRW; | |
canvas.height = SCRH; | |
let mouse = {x: 0, y: 0}; | |
canvas.addEventListener('mousemove', ev => { | |
mouse.x = ev.clientX; | |
mouse.y = ev.clientY; | |
}); | |
let ctx = canvas.getContext('2d'); | |
function makeTile() { | |
let d = 0.05; | |
return [ | |
[ | |
{x: 0, y: 0}, | |
{x: 1, y: 0}, | |
{x: 1-d, y: d}, | |
{x: d, y: d} | |
], | |
[ | |
{x: 1, y: 0}, | |
{x: 1, y: 1}, | |
{x: 1-d, y: 1-d}, | |
{x: 1-d, y: d} | |
], | |
[ | |
{x: 1, y: 1}, | |
{x: 0, y: 1}, | |
{x: d, y: 1-d}, | |
{x: 1-d, y: 1-d} | |
], | |
[ | |
{x: 0, y: 1}, | |
{x: 0, y: 0}, | |
{x: d, y: d}, | |
{x: d, y: 1-d} | |
], | |
[ | |
{x: d, y: d}, | |
{x: 1-d, y: d}, | |
{x: 1-d, y: 1-d}, | |
{x: d, y: 1-d} | |
] | |
]; | |
} | |
function scaledGroup(group, kx, ky) { | |
return group.map(s => s.map(({x, y}) => ({x: x*kx, y: y*ky}))); | |
} | |
function displacedGroup(group, dx, dy) { | |
return group.map(s => s.map(({x, y}) => ({x: x+dx, y: y+dy}))); | |
} | |
function fillShape(shape) { | |
ctx.beginPath(); | |
ctx.moveTo(shape[shape.length-1].x, shape[shape.length-1].y); | |
for (let p of shape) { | |
ctx.lineTo(p.x, p.y); | |
} | |
ctx.fill(); | |
} | |
let lights = [ | |
{x: 0, y: 0, z: 50} | |
]; | |
class Vec3 { | |
static make(x, y, z) { | |
return {x, y, z}; | |
} | |
static sub(u, v) { | |
return Vec3.make(u.x-v.x, u.y-v.y, u.z-v.z); | |
} | |
static lengthSq(u) { | |
return u.x*u.x + u.y*u.y + u.z*u.z; | |
} | |
static length(u) { | |
return Math.sqrt(Vec3.lengthSq(u)); | |
} | |
static normalize(u) { | |
let n = Vec3.length(u); | |
return Vec3.make(u.x/n, u.y/n, u.z/n); | |
} | |
static dot(u, v) { | |
return u.x*v.y + u.y*v.y + u.z*v.z; | |
} | |
static angle(u, v) { | |
return Math.acos(Vec3.dot(u, v) / (Vec3.length(u) * Vec3.length(v))); | |
} | |
} | |
function draw() { | |
let tw = 50; | |
let th = 20; | |
let nx = Math.ceil(SCRW / tw) + 1; | |
let ny = Math.ceil(SCRH / th) + 1; | |
let normals = [ | |
{x: 0.3, y: 0, z: 0}, | |
{x: 0, y: 0.3, z: 0}, | |
{x: -0.3, y: 0, z: 0}, | |
{x: 0, y: -0.3, z: 0}, | |
{x: 0, y: 0, z: 1} | |
]; | |
lights[0].x = mouse.x; | |
lights[0].y = mouse.y; | |
for (let i = 0; i < ny; ++i) { | |
for (let j = 0; j < nx; ++j) { | |
let x = tw*j - tw/2*(i%2); | |
let y = th*i; | |
let group = displacedGroup(scaledGroup(makeTile(), tw, th), x, y); | |
let v = {x: x + tw/2, y: y + th/2, z: 0}; | |
for (let i = 0; i < group.length; ++i) { | |
let shape = group[i]; | |
let L = 0; | |
let a = Vec3.angle(normals[i], Vec3.sub(lights[0], v)); | |
L += 60 * (1 - Math.max(a, Math.PI/2)/Math.PI/2) * Vec3.length(Vec3.sub(lights[0], v))/300; | |
ctx.fillStyle = `hsl(0, 10%, ${100-L}%)`; | |
fillShape(shape); | |
} | |
} | |
} | |
} | |
function loop(t) { | |
draw(t); | |
requestAnimationFrame(loop); | |
} | |
loop(); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment