From ab284e8e9871b38dc4df951b81becc5c3dfce16a Mon Sep 17 00:00:00 2001 From: STP Date: Sat, 25 Nov 2023 00:04:41 -0500 Subject: [PATCH] Fixed camera --- scene.rhai | 9 +++++--- src/camera.rs | 42 +++++++++++++++++++------------------- src/raytracer.rs | 53 +++++++++++++++++++++--------------------------- src/scene.rs | 11 ---------- 4 files changed, 50 insertions(+), 65 deletions(-) diff --git a/scene.rhai b/scene.rhai index 9b955a9..9376344 100644 --- a/scene.rhai +++ b/scene.rhai @@ -5,18 +5,21 @@ let target = P(0.0, 0.0, 0.0); let up = V(0.0, 1.0, 3.0); let cam = Camera(eye, target, up, 70.0, 1.0); -let material = Material(V(0.5,0.5,0.5), V(0.8, 0.8, 0.8), 0.5); +let material = Material(V(0.5,0.5,0.5), V(0.8, 0.8, 0.8), 25.0); -let light2 = Light(P(0.0,0.0,-10.0), V(0.8, 0.8, 0.8), V(0.2, 0.0, 0.0)); +let ambient = Light(P(10.0,0.0,0.0), V(1.0,1.0,1.0), V(0.0, 0.0, 0.0)); + +let light2 = Light(P(0.0,0.0,10.0), V(0.0,1.0,1.0), V(0.1, 0.01, 0.001)); scene.addLight(light2); + scene.addLight(ambient); // let sphere = Sphere(P(0.0,0.0,0.0), 4.0, material); // let node = Node(sphere); // scene.addNode(node); -let stein = Torus(1.0,2.0, material); +let stein = Stein(5.0,10.0, material); let node = Node(stein); scene.addNode(node); diff --git a/src/camera.rs b/src/camera.rs index 6df0fe7..a908fe6 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -51,16 +51,12 @@ impl Camera { } pub fn cast_rays(&self, width: u32, height: u32) -> Vec { - //All good let aspect = width as f64 / height as f64; let fovy_radians = (self.fovy as f64).to_radians(); let fovh_radians = 2.0 * ((fovy_radians / 2.0).tan() * aspect).atan(); - // All good let view_direction = (self.target - self.eye).normalize(); - //All good - let hor = view_direction.cross(&self.up).normalize(); // pointing right - let vert = view_direction.cross(&hor).normalize(); // pointing up - //All good + let hor = (view_direction.cross(&self.up)).normalize(); + let vert = (view_direction.cross(&hor)).normalize(); let h_width = 2.0 * (fovh_radians / 2.0).tan(); let v_height = 2.0 * (fovy_radians / 2.0).tan(); //All good @@ -69,10 +65,13 @@ impl Camera { let mut rays = Vec::with_capacity(width as usize * height as usize); - for j in 0..height { - for i in 0..width { - let horizontal = (i as f32 - width as f32 / 2.0) * (d_hor_vec); - let vertical = (j as f32 - height as f32 / 2.0) * (d_vert_vec); + let half_w = width as i32 / 2; + let half_h = height as i32 / 2; + + for j in 0..height as i32 { + for i in 0..width as i32 { + let horizontal = (i - half_w) as f32 * (d_hor_vec); + let vertical = (-j + half_h) as f32 * (d_vert_vec); let direction = view_direction + horizontal + vertical; let ray = Ray::new(self.eye, Unit::new_normalize(direction)); @@ -86,24 +85,25 @@ impl Camera { let aspect = width as f64 / height as f64; let fovy_radians = (self.fovy as f64).to_radians(); let fovh_radians = 2.0 * ((fovy_radians / 2.0).tan() * aspect).atan(); - let view_direction = (self.target - self.eye).normalize(); // Normalize the view direction vector - let hor = view_direction.cross(&self.up).normalize(); // pointing right - let vert = view_direction.cross(&hor).normalize(); // pointing up + let view_direction = (self.target - self.eye).normalize(); + let hor = (view_direction.cross(&self.up)).normalize(); + let vert = (view_direction.cross(&hor)).normalize(); let h_width = 2.0 * (fovh_radians / 2.0).tan(); let v_height = 2.0 * (fovy_radians / 2.0).tan(); + //All good let d_hor_vec = hor * (h_width / width as f64) as f32; let d_vert_vec = vert * (v_height / height as f64) as f32; - // Calculate the offsets for the pixel's position on the image plane - let horizontal = ((x as f32 / width as f32) - 0.5) * h_width as f32; - let vertical = ((y as f32 / height as f32) - 0.5) * v_height as f32; + let half_w = width as i32 / 2; + let half_h = height as i32 / 2; - // Calculate the ray direction by summing up the components - let direction = Unit::new_normalize( - view_direction + (horizontal * d_hor_vec) + (vertical * d_vert_vec), - ); + let horizontal = (x as i32 - half_w) as f32 * (d_hor_vec); + let vertical = (-(y as i32) + half_h) as f32 * (d_vert_vec); - Ray::new(self.eye, direction) + let direction = view_direction + horizontal + vertical; + let ray = Ray::new(self.eye, Unit::new_normalize(direction)); + + Ray::new(self.eye, Unit::new_normalize(direction)) } pub fn set_position(&mut self, eye: Point3) { diff --git a/src/raytracer.rs b/src/raytracer.rs index 0d42f4a..6db5a94 100644 --- a/src/raytracer.rs +++ b/src/raytracer.rs @@ -13,13 +13,12 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3 material, .. } = intersect; - let ambient_light = &scene.ambient_light; let kd = material.kd; let ks = material.ks; let shininess = material.shininess; // Compute the ambient light component and set it as base colour - let mut colour = kd.component_mul(ambient_light); + let mut colour = ZERO_VECTOR; for light in &scene.lights { let Light { @@ -28,42 +27,36 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3 falloff: light_falloff, } = light; - // Compute light incidence vector and its distance + // Point to light let to_light = light_position - point; let light_distance = to_light.norm(); - let light_incidence = Unit::new_normalize(to_light); + let to_light = Unit::new_normalize(to_light); + // Point to camera + let to_camera = Unit::new_normalize(-incidence.into_inner()); + // Diffuse component + let n_dot_l = normal.dot(&to_light).max(0.0); + let diffuse = n_dot_l * kd; + // Specular component + let mut specular = ZERO_VECTOR; + if n_dot_l > 0.0 { + // Halfway vector. + let h = Unit::new_normalize(to_camera.lerp(&to_light, 0.5)); + let n_dot_h = normal.dot(&h).max(0.0); + specular = ks * n_dot_h.powf(shininess); + } // Compute light falloff let falloff = 1.0 - / (light_falloff[0] + / (1.0 + + light_falloff[0] + light_falloff[1] * light_distance - + light_falloff[2] * light_distance * light_distance); + + light_falloff[2] * light_distance.powi(2)); - // Compute diffuse - let n_dot_l = normal.dot(&light_incidence); - let diffuse = if n_dot_l > 0.0 { - kd * n_dot_l - } else { - ZERO_VECTOR - }; - - // Compute specular - let h = (&light_incidence.into_inner() + incidence.into_inner()).normalize(); - let n_dot_h = normal.dot(&h); - let specular = if n_dot_h > 0.0 { - ks * n_dot_h.powf(shininess) - } else { - ZERO_VECTOR - }; - - // Update colour with diffuse and specular components - colour += light_colour.component_mul(&((diffuse + specular) * falloff)); + let light_intensity = light_colour.component_mul(&(diffuse + specular)) * falloff; + colour += &light_intensity; } - // Clamp colour values to [0, 255] and convert to u8 - let r = nalgebra::clamp(colour.x * 255.0, 0.0, 255.0) as u8; - let g = nalgebra::clamp(colour.y * 255.0, 0.0, 255.0) as u8; - let b = nalgebra::clamp(colour.z * 255.0, 0.0, 255.0) as u8; - + colour *= 255.0; + let (r, g, b) = (colour.x as u8, colour.y as u8, colour.z as u8); Vector3::new(r, g, b) } diff --git a/src/scene.rs b/src/scene.rs index 11bd595..dce3c5a 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -4,9 +4,6 @@ use crate::primitive::*; use nalgebra::{Matrix4, Point3, Vector3}; use rhai::{Engine, EvalAltResult}; use std::sync::Arc; - -const LIGHT_AMBIENT: f32 = 0.2; - #[derive(Clone)] pub struct Node { pub primitive: Arc, @@ -42,7 +39,6 @@ pub struct Scene { pub materials: Vec, pub lights: Vec, pub cameras: Vec, - pub ambient_light: Vector3, pub camera: Camera, } @@ -61,7 +57,6 @@ impl Scene { 120.0, 1.0, ), - ambient_light: Vector3::new(LIGHT_AMBIENT, LIGHT_AMBIENT, LIGHT_AMBIENT), } } fn add_node(&mut self, node: Node) { @@ -76,9 +71,6 @@ impl Scene { fn add_camera(&mut self, camera: Camera) { self.cameras.push(camera); } - fn set_ambient(&mut self, intensity: Vector3) { - self.ambient_light = intensity; - } fn set_camera(&mut self, camera: Camera) { self.camera = camera; } @@ -86,9 +78,6 @@ impl Scene { fn get_camera(&self) -> &Camera { &self.camera } - fn get_ambient(&self) -> Arc> { - Arc::new(self.ambient_light) - } pub fn from_script(filename: &str) -> Result> { let mut engine = Engine::new();