From 2e69164dde33fb177cf5092a20d2b24ca86a88ef Mon Sep 17 00:00:00 2001 From: STP Date: Mon, 13 Nov 2023 01:26:59 -0500 Subject: [PATCH] Added phong shading --- src/primitive.rs | 3 ++- src/raytracer.rs | 60 +++++++++++++++++++++++++++++++++++++++++++----- src/scene.rs | 4 ++-- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/primitive.rs b/src/primitive.rs index 831790b..ef49b2f 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -1,12 +1,13 @@ use crate::ray::Ray; use crate::{EPSILON, INFINITY}; -use lazy_static::lazy_static; use nalgebra::{distance, Matrix4, Point3, Vector3}; use roots::{find_roots_quadratic, Roots}; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::Path; +use lazy_static::lazy_static; + lazy_static! { static ref MAGENTA_MATERIAL: Material = Material::magenta(); } diff --git a/src/raytracer.rs b/src/raytracer.rs index 90ba6c1..8910049 100644 --- a/src/raytracer.rs +++ b/src/raytracer.rs @@ -1,9 +1,16 @@ use crate::{ + light::Light, primitive::{Intersection, Primitive}, ray::Ray, scene::Scene, INFINITY, }; +use lazy_static::lazy_static; +lazy_static! { + static ref VEC3_ONE: Vector3 = Vector3::new(1.0, 1.0, 1.0); + static ref VEC3_ZERO: Vector3 = Vector3::new(1.0, 1.0, 1.0); +} + use nalgebra::{distance, Matrix4, Point3, Vector3, Vector4}; // Find the closest intersection, given a ray in world coordinates @@ -30,23 +37,64 @@ fn get_closest_intersection<'a>(scene: &'a Scene, ray: &Ray) -> Option Option> { +fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3 { + //Useful vectors !!!! CHECK IF WE CAN OPTIMISE + let zero_vector = Vector3::new(0.0, 0.0, 0.0); + let one_vector = Vector3::new(1.0, 1.0, 1.0); //Unpack the intersection data let Intersection { primitive, point, normal, incidence, - distance, + .. } = intersect; let ambient_light = scene.ambient_light; let material = primitive.get_material(); let kd = material.kd; - let ks = material.kd; + let ks = material.ks; let shininess = material.shininess; // We should now have all the information for our ray-tracer - // Let us first compute the ambient light component - let ambient = ambient_light * kd; - None + // Let us first compute the ambient light component and set it as out base colour + let mut colour = kd.component_mul(&ambient_light); + + for light in &scene.lights { + let Light { + position: light_position, + colour: light_colour, + falloff: light_falloff, + } = light; + + // Get light incidence vector + let to_light = light_position - point; + let light_distance = to_light.norm(); + let light_incidence = to_light.normalize(); + + // Compute light falloff + let falloff = 1.0 + / (light_falloff[0] + + light_falloff[1] * light_distance + + light_falloff[2] * light_distance * light_distance); + + // 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 + incidence).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 + }; + + colour += light_colour.component_mul(&((diffuse + specular) * falloff)); + } + nalgebra::clamp(colour, zero_vector, one_vector) } diff --git a/src/scene.rs b/src/scene.rs index 8b0f373..492771c 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -5,8 +5,8 @@ use nalgebra::Vector3; pub struct Scene<'a> { pub primitives: Vec>>, - lights: Vec, - camera: Camera, + pub lights: Vec, + pub cameras: Vec, pub ambient_light: Vector3, }