Ray Marching

More efficient ray-casting!

by ElijahCirioli

HTML

<canvas id="canvas" width="600" height="600"></canvas>

CSS

#canvas {
	border: 3px solid black;
}

JavaScript

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var objects = [];
var angle = 0;
var x = 50;
var y = 300;

function Circle(x, y, r) {
	this.x = x;
	this.y = y;
	this.r = r;
}

Circle.prototype.distance = function(x, y) {
	return Math.sqrt(((y - this.y) * (y - this.y)) + ((x - this.x) * (x - this.x))) - this.r;
}

function Square(x, y, r) {
	this.x = x;
	this.y = y;
	this.r = r;
}

Square.prototype.distance = function(x, y) {
	var dx = 0;
	var dy = 0;
	
	if (x < this.x - this.r) { //left
		dx = this.x - this.r - x;
	} else if (x > this.x + this.r) { //right
		dx = this.x + this.r - x;
	}
	if (y < this.y - this.r) { //top
		dy = this.y - this.r - y;
	} else if (y > this.y + this.r) { //bottom
		dy = this.y + this.r - y;
	}
	
	return magnitude(dx, dy);
}

function setup() {
	objects.push(new Circle(300, 500, 80));
	objects.push(new Circle(120, 400, 30));
	objects.push(new Circle(320, 160, 100));
	objects.push(new Circle(360, 310, 10));
	objects.push(new Circle(470, 400, 60));
	objects.push(new Square(100, 60, 50));
	objects.push(new Square(550, 280, 30));

	requestAnimationFrame(draw);
}

function draw() {
	//draw background
	context.fillStyle = "white";
	context.fillRect(0, 0, canvas.width, canvas.height);
	
	//draw objects
	context.fillStyle = "red";
	for (var i = 0; i < objects.length; i++) {
		var o = objects[i];
		if (o instanceof Circle) {
			context.beginPath();
			context.arc(o.x, o.y, o.r, 0, 2 * Math.PI);
			context.fill();
		} else {
			context.fillRect(o.x - o.r, o.y - o.r, o.r * 2, o.r * 2);
		}	
	}
	
	//cast ray
	var dist = castRay(x, y);
	
	//draw ray
	context.fillStyle = "black";
	context.font = "16px arial";
	if (dist < 99999) {
		context.fillText(dist.toFixed(3), 520, 585);
	} else {
		context.fillText("infinity", 520, 585);
	}
	context.strokeStyle = "black";
	context.lineWidth = 2;
	context.beginPath();
	context.moveTo(x, y);
	context.lineTo(x + (700 * Math.cos(angle)), y + (700 *...