-
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.
Loading status checks…
add Ch1 Ep4 Diffuse Lighting and demo!
Showing
11 changed files
with
367 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> Diffuse Lighting </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/diffuseLighting.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,146 @@ | ||
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 pixelColor = new Vector3(); // x = r, y = g, z = b | ||
|
||
let skyColor = new Vector3(0.2, 0.6, 1.0); | ||
let groundColor = new Vector3(0.4, 0.4, 0.4); | ||
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, -15); | ||
let sphereColor = new Vector3(0.8, 0.01, 0.01); | ||
|
||
let t = 0; | ||
let nearestT = 0; | ||
let intersectionColor = new Vector3(); | ||
let intersectionPoint = new Vector3(); | ||
let intersectionNormal = new Vector3(); | ||
|
||
|
||
let directionToLight = new Vector3(1, 1, 1); | ||
directionToLight.normalize(); | ||
let sunLightColor = new Vector3(1, 1, 1); | ||
|
||
let ambientColor = new Vector3(); | ||
let ambientIntensity = 0.4; | ||
let diffuseColor = new Vector3(); | ||
let diffuseIntensity = 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 is now in the range of 0.0 to 1.0 (left to right) | ||
// canvasY is now in the range of 0.0 to 1.0 (bottom to top) | ||
|
||
canvasX *= 2; // canvasX now goes from 0.0 to 2.0 (left to right) | ||
canvasY *= 2; // canvasY now goes from 0.0 to 2.0 (bottom to top) | ||
canvasX -= 1; // canvasX now goes from -1.0 to +1.0 (left to right) | ||
canvasY -= 1; // canvasY now goes from -1.0 to +1.0 (bottom to top) | ||
|
||
canvasX *= aspectRatio; | ||
|
||
rayDirection.set(canvasX, canvasY, -1.5); | ||
rayDirection.normalize(); | ||
|
||
gradientSkyColor.mix(fogColor, skyColor, rayDirection.y * 1.5); | ||
|
||
// Important: must reset nearestT for each pixel! | ||
nearestT = Infinity; | ||
// Important: must also reset pixelColor to black (no color) for each pixel! | ||
pixelColor.set(0, 0, 0); | ||
|
||
t = intersectSphere(spherePosition, sphereRadius, rayOrigin, rayDirection); | ||
if (t < nearestT) | ||
{ | ||
nearestT = t; | ||
intersectionPoint.getPointAlongRay(rayOrigin, rayDirection, t); | ||
intersectionNormal.copy(intersectionPoint); | ||
intersectionNormal.subtract(spherePosition); | ||
intersectionColor.copy(sphereColor); | ||
} | ||
|
||
t = intersectPlane(planeOrigin, planeNormal, rayOrigin, rayDirection); | ||
if (t < nearestT) | ||
{ | ||
nearestT = t; | ||
intersectionNormal.copy(planeNormal); | ||
intersectionColor.copy(groundColor); | ||
} | ||
|
||
// if the ray hit anything at all, apply lighting to the intersection (using the recorded intersection data) | ||
if (nearestT < Infinity) | ||
{ | ||
intersectionNormal.normalize(); | ||
|
||
ambientColor.copy(intersectionColor); | ||
ambientColor.multiplyScalar(ambientIntensity); | ||
|
||
diffuseColor.copy(intersectionColor); | ||
diffuseColor.multiplyColor(sunLightColor); | ||
diffuseIntensity = intersectionNormal.dot(directionToLight); | ||
diffuseIntensity = Math.max(0, diffuseIntensity); | ||
diffuseColor.multiplyScalar(diffuseIntensity); | ||
|
||
pixelColor.add(ambientColor); | ||
pixelColor.add(diffuseColor); | ||
|
||
pixelColor.mix(pixelColor, gradientSkyColor, nearestT * 0.004); | ||
} | ||
|
||
// if the ray missed everything, set the pixel color to the background color | ||
if (nearestT == Infinity) | ||
{ | ||
pixelColor.copy(gradientSkyColor); | ||
} | ||
|
||
pixelColor.multiplyScalar(255); | ||
pixelColor.floor(); | ||
|
||
//"rgb(r,g,b)" | ||
context.fillStyle = "rgb(" + pixelColor.x + "," + pixelColor.y + "," + pixelColor.z + ")"; | ||
context.fillRect(column, row, 1, 1); | ||
} | ||
} | ||
} // 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,181 @@ | ||
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.multiplyColor = function(otherColorVector) | ||
{ | ||
this.x *= otherColorVector.x; | ||
this.y *= otherColorVector.y; | ||
this.z *= otherColorVector.z; | ||
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; | ||
}; | ||
|
||
Vector3.prototype.getPointAlongRay = function(rayOrigin, rayDirection, t) | ||
{ | ||
this.x = rayOrigin.x + (t * rayDirection.x); | ||
this.y = rayOrigin.y + (t * rayDirection.y); | ||
this.z = rayOrigin.z + (t * rayDirection.z); | ||
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