Skip to content

Instantly share code, notes, and snippets.

@DataKinds
Last active August 29, 2015 14:23
Show Gist options
  • Save DataKinds/452dbe5f9465b0151388 to your computer and use it in GitHub Desktop.
Save DataKinds/452dbe5f9465b0151388 to your computer and use it in GitHub Desktop.
Raytracer
<html>
<head>
<title>Raytrace</title>
<script type="text/javascript" src="vector.js"></script>
<script type="text/javascript" src="raytracer.js"></script>
</head>
<body>
<canvas id="raytraceCanvas" width="100" height="100">
get off of internet explorer
</canvas>
</body>
</html>
var Sphere = function(position, r, color) { //color in form [r, g, b]
this.position = position;
this.x = position.x;
this.y = position.y;
this.z = position.z;
this.r = r;
this.color = color;
}
//z = up
var Camera = function(direction, position) { //rotation on the x, y, and z axis
this.createRays = function(distanceX, distanceZ) {
for(var i = 0; i < canvas.width; i++) {
for(var j = 0; j < canvas.height; j++) {
var currentRay = new Ray(direction, new Vector.Rect((position.x + (i * distanceX)) - (position.x + (canvas.width * distanceX)) / 2, position.y, position.z + (j * distanceZ) - (position.z + (canvas.height * distanceZ)) / 2), [i, j]);
currentRay.update();
}
}
}
}
//each ray is a polar vector and a rectangular vector
//the polar vector, (magnitude, rx, rz), says the length and direction
//the rectangular vector, (x, y, z), says the origin or last reflection of the ray
//rotation on the x axis moves ray in the z directions
//rotation on the z axis moves ray in the x directions
//rotation on the y axis is "tilt", it isn't necessary for a ray. x and z are all that are needed to point in any direction
//y = forward (movement if no angle)
var precision = 0.1; //lower number = higher precision (0 bounded)
var maxIterations = 150; //max times that a ray can go without rendering as white
var Ray = function(direction, position, pixel) { //pixel = what pixel this ray was sent from
this.color = "#FFFFFF";
this.iterations = 0;
this.done = false;
this.draw = function() {
ctx.fillStyle = this.color;
ctx.fillRect(pixel[0], pixel[1], 1, 1);
}
this.update = function() {
while(!this.done) {
this.iterations += 1;
position.x += -precision * Math.sin(direction.rz); //trig functions take radians
position.y += precision * Math.cos(direction.rx);
position.z += precision * Math.sin(direction.rx);
//console.log(position.z.toString())
for (var sphereIndex = 0; sphereIndex < Scene.length; sphereIndex++) {
var currentSphere = Scene[sphereIndex];
//console.log(position.toString() + " rect = " + (Vector.subtract(position, currentSphere.position)).toString() + " polar = " + (Vector.subtract(position, currentSphere.position).toPolar()).toString());
//if (Math.abs(position.x - currentSphere.x) < currentSphere.r + contactMarginOfError &&
// Math.abs(position.y - currentSphere.y) < currentSphere.r + contactMarginOfError &&
// Math.abs(position.z - currentSphere.z) < currentSphere.r + contactMarginOfError) { //if a ray is colliding with a sphere
var distanceToSphere = Vector.subtract(currentSphere.position, position).toPolar().magnitude;
//console.log(distanceToSphere.toString());
if(distanceToSphere < currentSphere.r) {
this.bounces += 1;
this.color = "#FF0000";
this.done = true;
//to reflect a vector over a normal:
//Vnew = -2*(V dot N)*N + V
}
}
if(this.iterations > maxIterations) {
this.done = true;
}
}
//console.log("~~~~~~~~~");
this.draw();
}
}
window.onload = function() {
canvas = document.getElementById("raytraceCanvas");
ctx = canvas.getContext("2d");
Scene = [(new Sphere(new Vector.Rect(0, 6, 0), 24, "#FF0000"))];
SceneCamera = new Camera(new Vector.Polar(1, 0, 0), new Vector.Rect(0,0,0));
//SceneCamera.createRays();
}
var Vector = {};
Vector.Rect = function(x, y, z) {
this.magnitude = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
this.toRect = function() { return this; }
this.toPolar = function() { return new Vector.Polar(this.magnitude, Math.acos(z/this.magnitude), Math.atan2(y, x)) }
this.x = x;
this.y = y;
this.z = z;
this.toString = function() { return "(" + x.toString() + ", " + y.toString() + ", " + z.toString() + ")" }
}
Vector.Polar = function(magnitude, rx, rz) { //rz = theta, rx = phi
//this._vec = new Vector.Rect(-magnitude * Math.cos(rz), magnitude * Math.sin(rz), magnitude * Math.cos(rx));
this._vec = new Vector.Rect(Math.cos(rz) * Math.cos(rx) * magnitude, Math.sin(rz) * Math.cos(rx) * magnitude, Math.sin(rx) * magnitude);
this.magnitude = magnitude;
this.toRect = function() { return new this._vec; }
this.toPolar = function() { return this; }
this.rx = rx;
this.rz = rz;
this.toString = function() { return "(" + magnitude.toString() + ", " + rx.toString() + ", " + rz.toString() + ")" }
}
Vector.add = function(v1, v2) {
return new Vector.Rect(v1.toRect().x + v2.toRect().x, v1.toRect().y + v2.toRect().y, v1.toRect().z + v2.toRect().z);
}
Vector.subtract = function(v1, v2) {
return new Vector.Rect(v1.toRect().x - v2.toRect().x, v1.toRect().y - v2.toRect().y, v1.toRect().z - v2.toRect().z);
}
Vector.product = function(s,v) {
return new Vector.Rect(s * v.toRect().x, s * v.toRect().y, s * v.toRect().z);
}
Vector.dotProduct = function(v1, v2) {
return (v1.toRect().x * v2.toRect().x + v1.toRect().y * v2.toRect().y + v1.toRect().z * v2.toRect().z);
}
Vector.crossProduct = function(v1, v2) {
return new Vector.Rect(v1.toRect().y * v2.toRect().z - v1.toRect().z * v2.toRect().y, v1.toRect().z * v2.toRect().x - v1.toRect().x * v2.toRect().z, v1.toRect().x * v2.toRect().y - v1.toRect().y * v2.toRect().x);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment