Fixed camera
This commit is contained in:
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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>) {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/scene.rs
11
src/scene.rs
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user