Moved ray intersection code into ray class
This commit is contained in:
34
src/ray.rs
34
src/ray.rs
@@ -1,4 +1,9 @@
|
|||||||
use crate::EPSILON;
|
use crate::{
|
||||||
|
primitive::Intersection,
|
||||||
|
raytracer::phong_shade_point,
|
||||||
|
scene::{Node, Scene},
|
||||||
|
EPSILON, INFINITY,
|
||||||
|
};
|
||||||
use nalgebra::{Point3, Unit, Vector3};
|
use nalgebra::{Point3, Unit, Vector3};
|
||||||
|
|
||||||
pub struct Ray {
|
pub struct Ray {
|
||||||
@@ -13,4 +18,31 @@ impl Ray {
|
|||||||
pub fn at_t(&self, t: f32) -> Point3<f32> {
|
pub fn at_t(&self, t: f32) -> Point3<f32> {
|
||||||
self.a + self.b.into_inner() * (t + EPSILON)
|
self.a + self.b.into_inner() * (t + EPSILON)
|
||||||
}
|
}
|
||||||
|
//Shade a single ray
|
||||||
|
pub fn shade_ray(&self, scene: &Scene) -> Option<Vector3<u8>> {
|
||||||
|
let intersect = self.get_closest_intersection(&scene.nodes);
|
||||||
|
match intersect {
|
||||||
|
Some(intersect) => Some(phong_shade_point(&scene, &intersect)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the closest intersection, given a ray in world coordinates
|
||||||
|
pub fn get_closest_intersection(&self, nodes: &Vec<Node>) -> Option<Intersection> {
|
||||||
|
let mut closest_distance = INFINITY;
|
||||||
|
let mut closest_intersect: Option<Intersection> = None;
|
||||||
|
|
||||||
|
for node in nodes {
|
||||||
|
let primitive = node.primitive.clone();
|
||||||
|
|
||||||
|
if let Some(intersect) = primitive.intersect_ray(self) {
|
||||||
|
if intersect.distance < closest_distance {
|
||||||
|
closest_distance = intersect.distance;
|
||||||
|
closest_intersect = Some(intersect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closest_intersect
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,11 @@
|
|||||||
use crate::{light::Light, primitive::Intersection, ray::Ray, scene::*, INFINITY};
|
use crate::{light::Light, primitive::Intersection, scene::*};
|
||||||
|
|
||||||
use nalgebra::{Unit, Vector3};
|
use nalgebra::{Unit, Vector3};
|
||||||
|
|
||||||
static ZERO_VECTOR: Vector3<f32> = Vector3::new(0.0, 0.0, 0.0);
|
static ZERO_VECTOR: Vector3<f32> = Vector3::new(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
pub fn shade_rays(scene: &Scene, rays: &Vec<Ray>, width: i32, height: i32) -> Vec<Vector3<u8>> {
|
// Function to shade a point in the scene using Phong shading model
|
||||||
let mut pixel_data = vec![Vector3::new(0, 0, 0); (width * height) as usize];
|
|
||||||
|
|
||||||
for (pixel_index, ray) in rays.iter().enumerate() {
|
|
||||||
let intersect = get_closest_intersection(&scene.nodes, ray);
|
|
||||||
let colour = match intersect {
|
|
||||||
Some(intersect) => phong_shade_point(scene, &intersect),
|
|
||||||
None => {
|
|
||||||
// Handle rays that miss objects (e.g., use a background color or environment map)
|
|
||||||
Vector3::new(0, 0, 0)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
pixel_data[pixel_index] = colour;
|
|
||||||
}
|
|
||||||
pixel_data
|
|
||||||
}
|
|
||||||
//Shade a single ray
|
|
||||||
pub fn shade_ray(scene: &Scene, ray: &Ray) -> Option<Vector3<u8>> {
|
|
||||||
let intersect = get_closest_intersection(&scene.nodes, ray);
|
|
||||||
match intersect {
|
|
||||||
Some(intersect) => Some(phong_shade_point(&scene, &intersect)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the closest intersection, given a ray in world coordinates
|
|
||||||
pub fn get_closest_intersection(nodes: &Vec<Node>, ray: &Ray) -> Option<Intersection> {
|
|
||||||
let mut closest_distance = INFINITY;
|
|
||||||
let mut closest_intersect: Option<Intersection> = None;
|
|
||||||
|
|
||||||
for node in nodes {
|
|
||||||
let primitive = node.primitive.clone();
|
|
||||||
|
|
||||||
if let Some(intersect) = primitive.intersect_ray(ray) {
|
|
||||||
if intersect.distance < closest_distance {
|
|
||||||
closest_distance = intersect.distance;
|
|
||||||
closest_intersect = Some(intersect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closest_intersect
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to shade a point placed in our scene
|
|
||||||
pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8> {
|
pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8> {
|
||||||
//Useful vectors !!!! CHECK IF WE CAN OPTIMISE
|
|
||||||
//Unpack the intersection data
|
|
||||||
let Intersection {
|
let Intersection {
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
@@ -63,9 +17,8 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
|
|||||||
let kd = material.kd;
|
let kd = material.kd;
|
||||||
let ks = material.ks;
|
let ks = material.ks;
|
||||||
let shininess = material.shininess;
|
let shininess = material.shininess;
|
||||||
// We should now have all the information for our ray-tracer
|
|
||||||
|
|
||||||
// Let us first compute the ambient light component and set it as out base colour
|
// Compute the ambient light component and set it as base colour
|
||||||
let mut colour = kd.component_mul(ambient_light);
|
let mut colour = kd.component_mul(ambient_light);
|
||||||
|
|
||||||
for light in &scene.lights {
|
for light in &scene.lights {
|
||||||
@@ -75,7 +28,7 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
|
|||||||
falloff: light_falloff,
|
falloff: light_falloff,
|
||||||
} = light;
|
} = light;
|
||||||
|
|
||||||
// Get light incidence vector
|
// Compute light incidence vector and its distance
|
||||||
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 light_incidence = Unit::new_normalize(to_light);
|
||||||
@@ -103,8 +56,11 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
|
|||||||
ZERO_VECTOR
|
ZERO_VECTOR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update colour with diffuse and specular components
|
||||||
colour += light_colour.component_mul(&((diffuse + specular) * falloff));
|
colour += light_colour.component_mul(&((diffuse + specular) * falloff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 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 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;
|
let b = nalgebra::clamp(colour.z * 255.0, 0.0, 255.0) as u8;
|
||||||
|
|||||||
10
src/state.rs
10
src/state.rs
@@ -1,6 +1,6 @@
|
|||||||
//Use linear algebra module
|
//Use linear algebra module
|
||||||
|
|
||||||
use crate::raytracer;
|
use crate::raytracer::*;
|
||||||
use crate::{gui::Gui, ray::Ray, scene::Scene};
|
use crate::{gui::Gui, ray::Ray, scene::Scene};
|
||||||
use crate::{gui::GuiEvent, log_error};
|
use crate::{gui::GuiEvent, log_error};
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ use std::error::Error;
|
|||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use pixels::{Pixels, SurfaceTexture};
|
use pixels::{Pixels, SurfaceTexture, TextureError};
|
||||||
use winit::dpi::{LogicalSize, PhysicalSize};
|
use winit::dpi::{LogicalSize, PhysicalSize};
|
||||||
use winit::event::{Event, KeyboardInput, MouseButton, VirtualKeyCode, WindowEvent};
|
use winit::event::{Event, KeyboardInput, MouseButton, VirtualKeyCode, WindowEvent};
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
@@ -139,11 +139,9 @@ impl State {
|
|||||||
self.clear();
|
self.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&mut self, size: &PhysicalSize<u32>) -> Result<(), Box<dyn Error>> {
|
fn resize(&mut self, size: &PhysicalSize<u32>) -> Result<(), TextureError> {
|
||||||
let mut pixels = self.pixels.lock().unwrap();
|
let mut pixels = self.pixels.lock().unwrap();
|
||||||
pixels
|
pixels.resize_surface(size.width, size.height)
|
||||||
.resize_surface(size.width, size.height)
|
|
||||||
.map_err(Box::new)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard_input(&mut self, key: &KeyboardInput) {
|
fn keyboard_input(&mut self, key: &KeyboardInput) {
|
||||||
|
|||||||
Reference in New Issue
Block a user