Perspective

HTML

<img id="img"...

CSS

canvas, img {
    border: 1px solid black;
}

JavaScript

var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext("2d");

var img = document.getElementById('img');

let y = 0;
let mipstart = [];
ctx.imageSmoothingQuality = "high";
for (let w = 64, m = 0; w >= 1; w >>= 1, m++)
{
	if (m == 0)
		ctx.drawImage(img, 0, y, w, w);
	else
	{
		let lastW = w * 2;
		let lastY = y - lastW;
		ctx.drawImage(canvas, 0, lastY, lastW, lastW, 0, y, w, w);
	}
	mipstart[m] = y * 64;
	y += w;
}
let idata = new Uint32Array(ctx.getImageData(0, 0, 64, 128).data.buffer);

const Width = canvas.width;
const Height = canvas.height;
const HalfWidth = Width / 2;
const HalfHeight = Height / 2;

var pixels = ctx.createImageData(Width, Height);
var pdata = new Uint32Array(pixels.data.buffer);

var dists = [];
for (let i = 1; i < HalfHeight; i++)
	dists[i] = 2 * HalfHeight / i;
dists[0] = dists[1];
dists[HalfHeight] = dists[HalfHeight - 1];

var h = 20;
var ypos = 0;
var xpos = 0;
var dir = 0;
var frame = 0;

let keyLeft = false, keyRight = false, keyUp = false, keyDown = false;
function keyEvent(e)
{
	let down = e.type == "keydown";
	if (e.key == "ArrowLeft")
		keyLeft = down;
	else if (e.key == "ArrowRight")
		keyRight = down;
	else if (e.key == "ArrowUp")
		keyUp = down;
	else if (e.key == "ArrowDown")
		keyDown = down;
}
document.addEventListener("keydown", keyEvent);
document.addEventListener("keyup", keyEvent);


function fetchFromMip(x, y, m)
{
	x = (x & 63) >> m;
	y = (y & 63) >> m;
	return idata[y * 64 + x + mipstart[m]];
}

function draw()
{
	let domip = document.getElementById('mip').checked;
	
	frame++;
	//h = 50 * Math.cos(frame / 40) + 51;
	
	if (keyLeft || keyRight)
	{
		let s = keyLeft ? 1 : -1;
		dir += s * 0.05;
	}

	const dx_x = Math.cos(dir);
	const dx_y = Math.sin(dir);
	const dy_x = -dx_y;
	const dy_y = dx_x;

	if (keyUp || keyDown)
	{
		let s = keyUp ? 10 : -10;
		xpos += s * dy_x;
		ypos += s * dy_y;
	}

	for (let i = 1; i < HalfHeight; i++)
	{
		const y = i + HalfHeight;
		let d = dists[i] * h;
		let mip =...