-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Ch1_Ep3 Ray-Sphere Intersect Code & Demo!
- Loading branch information
Showing
11 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
html, body | ||
{ | ||
background-color: gray; | ||
margin: 0%; | ||
overflow: hidden; | ||
} | ||
|
||
#myCanvas | ||
{ | ||
position: fixed; | ||
background-color: black; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
#userInfo | ||
{ | ||
position: fixed; | ||
color: white; | ||
bottom: 2%; | ||
left: 1%; | ||
font-family: Arial, Helvetica, sans-serif; | ||
font-size: x-large; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title> Intersect Sphere </title> | ||
<link href="css/rayTracingStyles.css" rel="stylesheet"> | ||
</head> | ||
|
||
<body> | ||
<canvas id="myCanvas"> </canvas> | ||
<p id="userInfo"> user text info </p> | ||
|
||
<script src="js/mathUtils.js"> </script> | ||
<script src="js/intersectSphere.js"> </script> | ||
</body> | ||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
let canvas = document.getElementById("myCanvas"); | ||
let context = canvas.getContext("2d"); | ||
|
||
let aspectRatio = 0; | ||
|
||
let userInfo = document.getElementById("userInfo"); | ||
|
||
|
||
window.addEventListener("resize", handleWindowResize); | ||
function handleWindowResize() | ||
{ | ||
canvas.width = window.innerWidth; | ||
canvas.height = window.innerHeight; | ||
|
||
aspectRatio = canvas.width / canvas.height; | ||
|
||
userInfo.innerHTML = "canvasW: " + canvas.width + " canvasH: " + canvas.height + "<br>" + | ||
"total pixel count: " + (canvas.width * canvas.height); | ||
|
||
// redraw the screen | ||
draw(); | ||
} | ||
|
||
let canvasX = 0; | ||
let canvasY = 0; | ||
|
||
let rayOrigin = new Vector3(0, 0, 0); | ||
let rayDirection = new Vector3(); | ||
let colorVector = new Vector3(); // x = r, y = g, z = b | ||
|
||
let skyColor = new Vector3(0.2, 0.6, 1.0); | ||
let groundColor = new Vector3(0.5, 0.5, 0.5); | ||
let fogColor = new Vector3(0.7, 0.7, 0.7); | ||
let gradientSkyColor = new Vector3(); | ||
|
||
let planeOrigin = new Vector3(0, -3, 0); | ||
let planeNormal = new Vector3(0, 1, 0); | ||
planeNormal.normalize(); | ||
|
||
let sphereRadius = 3; | ||
let spherePosition = new Vector3(0, planeOrigin.y + sphereRadius, -10); | ||
let sphereColor = new Vector3(0.8, 0.01, 0.01); | ||
|
||
let t = 0; | ||
let nearestT = 0; | ||
|
||
function draw() | ||
{ | ||
// loop over all pixels on screen | ||
for (let row = 0; row < canvas.height; row++) | ||
{ | ||
for (let column = 0; column < canvas.width; column++) | ||
{ | ||
canvasX = column / (canvas.width - 1); | ||
canvasY = row / (canvas.height - 1); | ||
// flip Y coordinates so 0 is bottom of screen and 1 is top of screen | ||
canvasY = 1 - canvasY; | ||
// canvasX goes from 0.0 to 1.0 | ||
// canvasY goes from 0.0 to 1.0 | ||
|
||
canvasX *= 2; // canvasX goes from 0 to 2 | ||
canvasY *= 2; // canvasY goes from 0 to 2 | ||
canvasX -= 1; | ||
canvasY -= 1; | ||
// canvasX now goes from -1.0 to +1.0 (left to right) | ||
// canvasY now goes from -1.0 to +1.0 (bottom to top) | ||
|
||
canvasX *= aspectRatio; | ||
// if (row == 0) | ||
// { | ||
// console.log("canvasX is " + canvasX); | ||
// } | ||
|
||
rayDirection.set(canvasX, canvasY, -1); | ||
rayDirection.normalize(); | ||
|
||
gradientSkyColor.mix(fogColor, skyColor, rayDirection.y * 1.5); | ||
|
||
// Important: must reset nearestT for each pixel! | ||
nearestT = Infinity; | ||
|
||
t = intersectSphere(spherePosition, sphereRadius, rayOrigin, rayDirection); | ||
if (t < nearestT) | ||
{ | ||
nearestT = t; | ||
colorVector.copy(sphereColor); | ||
} | ||
|
||
t = intersectPlane(planeOrigin, planeNormal, rayOrigin, rayDirection); | ||
if (t < nearestT) | ||
{ | ||
nearestT = t; | ||
colorVector.mix(groundColor, gradientSkyColor, t * 0.008); | ||
} | ||
|
||
if (nearestT == Infinity) | ||
{ | ||
colorVector.copy(gradientSkyColor); | ||
} | ||
|
||
colorVector.multiplyScalar(255); | ||
colorVector.floor(); | ||
|
||
//"rgb(r,g,b)" | ||
context.fillStyle = "rgb(" + colorVector.x + "," + colorVector.y + "," + colorVector.z + ")"; | ||
context.fillRect(column, row, 1, 1); | ||
} | ||
///console.log("canvasY is " + canvasY); | ||
} | ||
} // end function draw() | ||
|
||
// jumpstart the drawing of the screen | ||
handleWindowResize(); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
function Vector3(x = 0, y = 0, z = 0) | ||
{ | ||
this.x = x; | ||
this.y = y; | ||
this.z = z; | ||
return this; | ||
} | ||
|
||
Vector3.prototype.set = function(x, y, z) | ||
{ | ||
this.x = x; | ||
this.y = y; | ||
this.z = z; | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.copy = function(otherVector) | ||
{ | ||
this.x = otherVector.x; | ||
this.y = otherVector.y; | ||
this.z = otherVector.z; | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.add = function(otherVector) | ||
{ | ||
this.x += otherVector.x; | ||
this.y += otherVector.y; | ||
this.z += otherVector.z; | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.subtract = function(otherVector) | ||
{ | ||
this.x -= otherVector.x; | ||
this.y -= otherVector.y; | ||
this.z -= otherVector.z; | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.multiplyScalar = function(scalarNumber) | ||
{ | ||
this.x *= scalarNumber; | ||
this.y *= scalarNumber; | ||
this.z *= scalarNumber; | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.floor = function() | ||
{ | ||
this.x = Math.floor(this.x); | ||
this.y = Math.floor(this.y); | ||
this.z = Math.floor(this.z); | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.absolute = function() | ||
{ | ||
this.x = Math.abs(this.x); | ||
this.y = Math.abs(this.y); | ||
this.z = Math.abs(this.z); | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.vectorLength = function() | ||
{ | ||
return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z)); | ||
}; | ||
|
||
let inverseLength = 0; | ||
Vector3.prototype.normalize = function() | ||
{ | ||
inverseLength = 1 / this.vectorLength(); | ||
this.x *= inverseLength; | ||
this.y *= inverseLength; | ||
this.z *= inverseLength; | ||
return this; | ||
}; | ||
|
||
Vector3.prototype.dot = function(otherVector) | ||
{ | ||
return (this.x * otherVector.x) + (this.y * otherVector.y) + (this.z * otherVector.z); | ||
}; | ||
|
||
Vector3.prototype.mix = function(vectorA, vectorB, t) | ||
{ | ||
t = Math.min(t, 1); | ||
t = Math.max(t, 0); | ||
this.x = vectorA.x + (vectorB.x - vectorA.x) * t; | ||
this.y = vectorA.y + (vectorB.y - vectorA.y) * t; | ||
this.z = vectorA.z + (vectorB.z - vectorA.z) * t; | ||
return this; | ||
}; | ||
|
||
|
||
let planeO_rayO_vec = new Vector3(); | ||
let rayD_dot_planeN = 0; | ||
let result = 0; | ||
|
||
function intersectPlane(planeOrigin, planeNormal, rayOrigin, rayDirection) | ||
{ | ||
rayD_dot_planeN = rayDirection.dot(planeNormal); | ||
if (rayD_dot_planeN >= 0) | ||
{ | ||
return Infinity; | ||
} | ||
|
||
planeO_rayO_vec.copy(planeOrigin); | ||
planeO_rayO_vec.subtract(rayOrigin); | ||
result = planeO_rayO_vec.dot(planeNormal) / rayD_dot_planeN; | ||
if (result > 0) | ||
{ | ||
return result; | ||
} | ||
|
||
return Infinity; | ||
} | ||
|
||
let t0 = 0; | ||
let t1 = 0; | ||
let discriminant = 0; | ||
let oneOver_2a = 0; | ||
|
||
function solveQuadratic(a, b, c) | ||
{ | ||
discriminant = (b * b) - (4 * a * c); | ||
if (discriminant < 0) | ||
{ | ||
return false; | ||
} | ||
discriminant = Math.sqrt(discriminant); | ||
oneOver_2a = 1 / (2 * a); | ||
t0 = (-b - discriminant) * oneOver_2a; | ||
t1 = (-b + discriminant) * oneOver_2a; | ||
return true; | ||
} | ||
|
||
let L = new Vector3(); | ||
// note: in the video for a, b, and c below, I put them all on one line, such as | ||
// let a, b, c = 0; However, this does not initialize all three to 0 as I had thought. | ||
let a = 0; | ||
let b = 0; | ||
let c = 0; | ||
|
||
function intersectSphere(spherePosition, sphereRadius, rayOrigin, rayDirection) | ||
{ | ||
L.copy(rayOrigin); | ||
L.subtract(spherePosition); | ||
a = rayDirection.dot(rayDirection); | ||
b = 2 * L.dot(rayDirection); | ||
c = L.dot(L) - (sphereRadius * sphereRadius); | ||
if (solveQuadratic(a, b, c) == false) | ||
{ | ||
return Infinity; | ||
} | ||
if (t0 > 0) | ||
{ | ||
return t0; | ||
} | ||
else if (t1 > 0) | ||
{ | ||
return t1; | ||
} | ||
return Infinity; | ||
} |
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