Fixed camera
This commit is contained in:
@@ -51,16 +51,12 @@ impl Camera {
|
||||
}
|
||||
|
||||
pub fn cast_rays(&self, width: u32, height: u32) -> Vec<Ray> {
|
||||
//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<f32>) {
|
||||
|
||||
@@ -13,13 +13,12 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
|
||||
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<u8>
|
||||
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)
|
||||
}
|
||||
|
||||
11
src/scene.rs
11
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<dyn Primitive>,
|
||||
@@ -42,7 +39,6 @@ pub struct Scene {
|
||||
pub materials: Vec<Material>,
|
||||
pub lights: Vec<Light>,
|
||||
pub cameras: Vec<Camera>,
|
||||
pub ambient_light: Vector3<f32>,
|
||||
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<f32>) {
|
||||
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<Vector3<f32>> {
|
||||
Arc::new(self.ambient_light)
|
||||
}
|
||||
|
||||
pub fn from_script(filename: &str) -> Result<Scene, Box<EvalAltResult>> {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
Reference in New Issue
Block a user