Fixed camera

This commit is contained in:
STP
2023-11-25 00:04:41 -05:00
parent ccac1f414d
commit ab284e8e98
4 changed files with 50 additions and 65 deletions

View File

@@ -5,18 +5,21 @@ let target = P(0.0, 0.0, 0.0);
let up = V(0.0, 1.0, 3.0); let up = V(0.0, 1.0, 3.0);
let cam = Camera(eye, target, up, 70.0, 1.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(light2);
scene.addLight(ambient);
// let sphere = Sphere(P(0.0,0.0,0.0), 4.0, material); // let sphere = Sphere(P(0.0,0.0,0.0), 4.0, material);
// let node = Node(sphere); // let node = Node(sphere);
// scene.addNode(node); // scene.addNode(node);
let stein = Torus(1.0,2.0, material); let stein = Stein(5.0,10.0, material);
let node = Node(stein); let node = Node(stein);
scene.addNode(node); scene.addNode(node);

View File

@@ -51,16 +51,12 @@ impl Camera {
} }
pub fn cast_rays(&self, width: u32, height: u32) -> Vec<Ray> { pub fn cast_rays(&self, width: u32, height: u32) -> Vec<Ray> {
//All good
let aspect = width as f64 / height as f64; let aspect = width as f64 / height as f64;
let fovy_radians = (self.fovy as f64).to_radians(); let fovy_radians = (self.fovy as f64).to_radians();
let fovh_radians = 2.0 * ((fovy_radians / 2.0).tan() * aspect).atan(); let fovh_radians = 2.0 * ((fovy_radians / 2.0).tan() * aspect).atan();
// All good
let view_direction = (self.target - self.eye).normalize(); let view_direction = (self.target - self.eye).normalize();
//All good let hor = (view_direction.cross(&self.up)).normalize();
let hor = view_direction.cross(&self.up).normalize(); // pointing right let vert = (view_direction.cross(&hor)).normalize();
let vert = view_direction.cross(&hor).normalize(); // pointing up
//All good
let h_width = 2.0 * (fovh_radians / 2.0).tan(); let h_width = 2.0 * (fovh_radians / 2.0).tan();
let v_height = 2.0 * (fovy_radians / 2.0).tan(); let v_height = 2.0 * (fovy_radians / 2.0).tan();
//All good //All good
@@ -69,10 +65,13 @@ impl Camera {
let mut rays = Vec::with_capacity(width as usize * height as usize); let mut rays = Vec::with_capacity(width as usize * height as usize);
for j in 0..height { let half_w = width as i32 / 2;
for i in 0..width { let half_h = height as i32 / 2;
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); 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 direction = view_direction + horizontal + vertical;
let ray = Ray::new(self.eye, Unit::new_normalize(direction)); 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 aspect = width as f64 / height as f64;
let fovy_radians = (self.fovy as f64).to_radians(); let fovy_radians = (self.fovy as f64).to_radians();
let fovh_radians = 2.0 * ((fovy_radians / 2.0).tan() * aspect).atan(); 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 view_direction = (self.target - self.eye).normalize();
let hor = view_direction.cross(&self.up).normalize(); // pointing right let hor = (view_direction.cross(&self.up)).normalize();
let vert = view_direction.cross(&hor).normalize(); // pointing up let vert = (view_direction.cross(&hor)).normalize();
let h_width = 2.0 * (fovh_radians / 2.0).tan(); let h_width = 2.0 * (fovh_radians / 2.0).tan();
let v_height = 2.0 * (fovy_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_hor_vec = hor * (h_width / width as f64) as f32;
let d_vert_vec = vert * (v_height / height 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 half_w = width as i32 / 2;
let horizontal = ((x as f32 / width as f32) - 0.5) * h_width as f32; let half_h = height as i32 / 2;
let vertical = ((y as f32 / height as f32) - 0.5) * v_height as f32;
// Calculate the ray direction by summing up the components let horizontal = (x as i32 - half_w) as f32 * (d_hor_vec);
let direction = Unit::new_normalize( let vertical = (-(y as i32) + half_h) as f32 * (d_vert_vec);
view_direction + (horizontal * d_hor_vec) + (vertical * 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<f32>) { pub fn set_position(&mut self, eye: Point3<f32>) {

View File

@@ -13,13 +13,12 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
material, material,
.. ..
} = intersect; } = intersect;
let ambient_light = &scene.ambient_light;
let kd = material.kd; let kd = material.kd;
let ks = material.ks; let ks = material.ks;
let shininess = material.shininess; let shininess = material.shininess;
// Compute the ambient light component and set it as base colour // 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 { for light in &scene.lights {
let Light { let Light {
@@ -28,42 +27,36 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
falloff: light_falloff, falloff: light_falloff,
} = light; } = light;
// Compute light incidence vector and its distance // Point to light
let to_light = light_position - point; let to_light = light_position - point;
let light_distance = to_light.norm(); 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 // Compute light falloff
let falloff = 1.0 let falloff = 1.0
/ (light_falloff[0] / (1.0
+ light_falloff[0]
+ light_falloff[1] * light_distance + light_falloff[1] * light_distance
+ light_falloff[2] * light_distance * light_distance); + light_falloff[2] * light_distance.powi(2));
// Compute diffuse let light_intensity = light_colour.component_mul(&(diffuse + specular)) * falloff;
let n_dot_l = normal.dot(&light_incidence); colour += &light_intensity;
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));
} }
// Clamp colour values to [0, 255] and convert to u8 colour *= 255.0;
let r = nalgebra::clamp(colour.x * 255.0, 0.0, 255.0) as u8; let (r, g, b) = (colour.x as u8, colour.y as u8, colour.z 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;
Vector3::new(r, g, b) Vector3::new(r, g, b)
} }

View File

@@ -4,9 +4,6 @@ use crate::primitive::*;
use nalgebra::{Matrix4, Point3, Vector3}; use nalgebra::{Matrix4, Point3, Vector3};
use rhai::{Engine, EvalAltResult}; use rhai::{Engine, EvalAltResult};
use std::sync::Arc; use std::sync::Arc;
const LIGHT_AMBIENT: f32 = 0.2;
#[derive(Clone)] #[derive(Clone)]
pub struct Node { pub struct Node {
pub primitive: Arc<dyn Primitive>, pub primitive: Arc<dyn Primitive>,
@@ -42,7 +39,6 @@ pub struct Scene {
pub materials: Vec<Material>, pub materials: Vec<Material>,
pub lights: Vec<Light>, pub lights: Vec<Light>,
pub cameras: Vec<Camera>, pub cameras: Vec<Camera>,
pub ambient_light: Vector3<f32>,
pub camera: Camera, pub camera: Camera,
} }
@@ -61,7 +57,6 @@ impl Scene {
120.0, 120.0,
1.0, 1.0,
), ),
ambient_light: Vector3::new(LIGHT_AMBIENT, LIGHT_AMBIENT, LIGHT_AMBIENT),
} }
} }
fn add_node(&mut self, node: Node) { fn add_node(&mut self, node: Node) {
@@ -76,9 +71,6 @@ impl Scene {
fn add_camera(&mut self, camera: Camera) { fn add_camera(&mut self, camera: Camera) {
self.cameras.push(camera); self.cameras.push(camera);
} }
fn set_ambient(&mut self, intensity: Vector3<f32>) {
self.ambient_light = intensity;
}
fn set_camera(&mut self, camera: Camera) { fn set_camera(&mut self, camera: Camera) {
self.camera = camera; self.camera = camera;
} }
@@ -86,9 +78,6 @@ impl Scene {
fn get_camera(&self) -> &Camera { fn get_camera(&self) -> &Camera {
&self.camera &self.camera
} }
fn get_ambient(&self) -> Arc<Vector3<f32>> {
Arc::new(self.ambient_light)
}
pub fn from_script(filename: &str) -> Result<Scene, Box<EvalAltResult>> { pub fn from_script(filename: &str) -> Result<Scene, Box<EvalAltResult>> {
let mut engine = Engine::new(); let mut engine = Engine::new();