Albedo shading with light support

This commit is contained in:
Madeline Pace
2021-12-18 17:34:05 -05:00
parent 66b6592599
commit f75c6ae729
2 changed files with 86 additions and 32 deletions

30
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,30 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "lldb",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/target/debug/rustyrays",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"sourceMap": {
"/rustc/*": "${env:HOME}/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust"
},
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

View File

@@ -33,6 +33,20 @@ struct OrthoCamera {
plane: bmp::Image
}
struct LightSrc {
pos: Vec3<f64>,
intensity: f64
}
impl LightSrc {
fn new(pos: Vec3<f64>, intensity: f64) -> LightSrc {
LightSrc {
pos: pos,
intensity: intensity
}
}
}
impl OrthoCamera {
fn new(pos: Vec3<f64>) -> OrthoCamera {
OrthoCamera {
@@ -57,59 +71,69 @@ impl Sphere {
// Implemented from
// http://kylehalladay.com/blog/tutorial/math/2013/12/24/Ray-Sphere-Intersection.html
fn intersection(&self, primary_ray: &Ray, t1: &mut f64, t2: &mut f64) -> bool {
let l = self.pos - primary_ray.pos;
let tc = dot(&l, &primary_ray.dir);
fn intersection(&self, ray: &Ray) -> Option<f64> {
let l = self.pos - ray.pos;
let adj = l.dot(&ray.dir);
let d2 = l.dot(&l) - (adj * adj);
let radius2 = self.radius * self.radius;
if tc < 0.0 {
return false;
if d2 > radius2 {
return None;
}
let d = f64::sqrt((l.norm() * l.norm()) as f64 - (tc*tc));
let thc = (radius2 - d2).sqrt();
let t0 = adj - thc;
let t1 = adj + thc;
if d > self.radius { return false };
if t0 < 0.0 && t1 < 0.0 {
return None;
}
let t1c = f64::sqrt(f64::powf(self.radius, 2.0) - f64::powf(d, 2.0));
*t1 = tc - t1c;
*t2 = tc + t1c;
return true;
let distance = if t0 < t1 { t0 } else { t1 };
Some(distance)
}
}
fn main() {
let mut camera = OrthoCamera::new(Vec3::new(0.0, 0.0, 0.0));
let mut spheres = Vec::new();
let light = LightSrc::new(Vec3::new(120.0, 0.0, 100.0), 500.0);
for i in 0..15 {
let mut rng = rand::thread_rng();
let x: f64 = rng.gen::<f64>() * 250.0;
let y: f64 = rng.gen::<f64>() * 250.0;
let z: f64 = rng.gen::<f64>() * 250.0;
let radius: f64 = rng.gen::<f64>() * 40.0;
spheres.push(Sphere::new(Vec3::new(x, y, 1000.0), radius));
}
spheres.push(Sphere::new(Vec3::new(125.0, 50.0, 100.0), 20.0));
spheres.push(Sphere::new(Vec3::new(150.0, 150.0, 100.0), 40.0));
// for i in 0..15 {
// let mut rng = rand::thread_rng();
// let x: f64 = rng.gen::<f64>() * 250.0;
// let y: f64 = rng.gen::<f64>() * 250.0;
// let z: f64 = rng.gen::<f64>() * 250.0;
// let radius: f64 = rng.gen::<f64>() * 40.0;
// spheres.push(Sphere::new(Vec3::new(x, y, 1000.0), radius));
// }
for (x, y) in camera.plane.coordinates() {
camera.plane.set_pixel(x, y, px!(0, 0, 0));
camera.plane.set_pixel(x, y, px!(0, y, 0));
}
for (x, y) in camera.plane.coordinates() {
for sphere in &spheres {
let ray = Ray::new(Vec3::new(x as f64, y as f64, camera.pos.z as f64), Vec3::new(0.0, 0.0, 1.0));
let mut t1 = 0.0;
let mut t2 = 0.0;
let mut tfront = 0.0;
let result = sphere.intersection(&ray, &mut t1, &mut t2);
let result = sphere.intersection(&ray);
tfront = if t2 > t1 { t1 } else { t2 };
let hit = ray.at(tfront);
let normal = hit - sphere.pos;
//let angle = abs(&hit1.normalize().dot(&normal.normalize()));
let angle = f64::abs(f64::acos(hit.dot(&normal)/(hit.norm()*normal.norm())));
if result == true {
camera.plane.set_pixel(x, y, px!(80.0 * angle, 80.0 * angle, 80.0 * angle));
match result {
Some(distance) => {
let hit = ray.at(distance);
let normal = sphere.pos - hit;
let light_vec = hit - light.pos;
let angle = f64::abs(f64::acos(hit.dot(&normal)/(hit.norm()*normal.norm())));
let light_power = (normal.normalize().dot(&light_vec.normalize()) as f64).max(0.0) * light.intensity;
let light_reflected = 2.0 / std::f64::consts::PI;
let light_calc = light_power * light_reflected;
println!("{}", light_calc);
camera.plane.set_pixel(x, y, px!(light_calc, light_calc, light_calc));
}
None => { },
}
}
}