reflection directly along normal

This commit is contained in:
CDaut 2023-11-27 20:59:25 +01:00
parent 1e752d60bf
commit 7f9af4ceaa
7 changed files with 68 additions and 26 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -37,6 +37,9 @@ pub struct Args {
///start in debug mode (e.g. without parallelization) ///start in debug mode (e.g. without parallelization)
#[arg(long)] #[arg(long)]
debug: bool, debug: bool,
///path tracing recursion depth
#[arg(long)]
recurse: usize
} }
fn main() { fn main() {

View file

@ -1,6 +1,6 @@
use std::ops::{Add, Mul}; use std::ops::{Add, Mul};
use std::sync::{Arc, LockResult, Mutex}; use std::sync::{Arc, LockResult, Mutex};
use cgmath::{Angle, ElementWise, Matrix4, Vector2, Vector3, Vector4}; use cgmath::{Angle, ElementWise, InnerSpace, Matrix4, Vector2, Vector3, Vector4};
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use easy_gltf::model::{Mode}; use easy_gltf::model::{Mode};
use easy_gltf::{Camera, Material, Projection, Scene}; use easy_gltf::{Camera, Material, Projection, Scene};
@ -9,6 +9,8 @@ use crate::geometry::{Intersectable};
use crate::ray::{construct_primary_rays, Ray}; use crate::ray::{construct_primary_rays, Ray};
use crate::scene_data::IntersectionData; use crate::scene_data::IntersectionData;
const RAY_EPSILON: f32 = 0.0007;
pub fn render(scenes: &Vec<Scene>, pub fn render(scenes: &Vec<Scene>,
cl_args: &Args) -> Arc<Mutex<Vec<Vec<Vector4<f32>>>>> { cl_args: &Args) -> Arc<Mutex<Vec<Vec<Vector4<f32>>>>> {
let render_scene: &Scene = &scenes[cl_args.scene_index]; let render_scene: &Scene = &scenes[cl_args.scene_index];
@ -38,13 +40,17 @@ pub fn render(scenes: &Vec<Scene>,
Arc::new(Mutex::new(Vec::with_capacity(cl_args.width))); Arc::new(Mutex::new(Vec::with_capacity(cl_args.width)));
//prepare the radiosity buffer //prepare the radiosity buffer
(0..cl_args.height).into_iter().for_each(|py| { (0..cl_args.width).into_iter().for_each(|px| {
radiosity_buffer.lock().unwrap().push(Vec::with_capacity(cl_args.height)) let mut empty_vector = Vec::with_capacity(cl_args.height);
for _ in 0..cl_args.height {
empty_vector.push(Vector4::new(0.0, 0.0, 0.0, 0.0));
}
radiosity_buffer.lock().unwrap().push(empty_vector);
}); });
//iterate over all pixels in the image //iterate over all pixels in the image
(0..cl_args.width).into_iter().for_each(|px| { (0..cl_args.width).into_par_iter().for_each(|px| {
(0..cl_args.height).into_iter().for_each(|py| { (0..cl_args.height).into_par_iter().for_each(|py| {
//construct all rays //construct all rays
let rays: Vec<Ray> = construct_primary_rays( let rays: Vec<Ray> = construct_primary_rays(
(cl_args.width, cl_args.height), (cl_args.width, cl_args.height),
@ -60,27 +66,28 @@ pub fn render(scenes: &Vec<Scene>,
//cast each ray and get the output luminosity and sum them up //cast each ray and get the output luminosity and sum them up
rays.iter().for_each(|ray| { rays.iter().for_each(|ray| {
pixel_radiosity = pixel_radiosity.add( pixel_radiosity = pixel_radiosity.add(
raytrace(ray, render_scene, 4) raytrace(ray, render_scene, cl_args.recurse)
); );
}); });
//store radiosity into the buffer //store radiosity into the buffer
match radiosity_buffer.clone().lock() { match radiosity_buffer.clone().lock() {
Ok(mut buffer) => { Ok(mut buffer) => {
buffer[px].push(pixel_radiosity); buffer[px][py] = pixel_radiosity;
} }
Err(_) => { panic!("Unable to lock pixel buffer!") } Err(_) => { panic!("Unable to lock pixel buffer!") }
} }
}); });
}); });
radiosity_buffer radiosity_buffer
} }
fn raytrace(ray: &Ray, scene: &Scene, recursion_depth: u32) -> Vector4<f32> { fn raytrace(ray: &Ray, scene: &Scene, recursion_depth_left: usize) -> Vector4<f32> {
let mut pixel_radiosity: Vector4<f32> = Vector4::new(0.0, 0.0, 0.0, 255.0); let mut pixel_radiosity: Vector4<f32> = Vector4::new(0.0, 0.0, 0.0, 1.0);
//abort if no recursion steps are left
if recursion_depth_left == 0 { return pixel_radiosity; }
let mut smallest_t: f32 = f32::MAX; let mut smallest_t: f32 = f32::MAX;
let mut intersection_data: Option<IntersectionData> = None; let mut intersection_data: Option<IntersectionData> = None;
@ -100,8 +107,8 @@ fn raytrace(ray: &Ray, scene: &Scene, recursion_depth: u32) -> Vector4<f32> {
//iterate all triangles in a model //iterate all triangles in a model
triangles.iter().for_each(|triangle| { triangles.iter().for_each(|triangle| {
match triangle.test_isec(&ray) { match triangle.test_isec(&ray) {
//boilerplate implementation to set pixel to red if any intersection happened
None => {} None => {}
//set data if intersection has been detected
Some((t, isec)) => { Some((t, isec)) => {
// a new closer Point is found // a new closer Point is found
if t < smallest_t { if t < smallest_t {
@ -110,7 +117,9 @@ fn raytrace(ray: &Ray, scene: &Scene, recursion_depth: u32) -> Vector4<f32> {
Option::from( Option::from(
IntersectionData::new( IntersectionData::new(
isec, isec,
model.material()) model.material(),
triangle.clone(),
)
); );
} }
} }
@ -120,8 +129,9 @@ fn raytrace(ray: &Ray, scene: &Scene, recursion_depth: u32) -> Vector4<f32> {
match intersection_data { match intersection_data {
Some(isec_data) => { Some(isec_data) => {
pixel_radiosity = accumulate_colors(isec_data.intersection_point(), pixel_radiosity = accumulate_colors(&isec_data,
isec_data.material()); &scene,
recursion_depth_left);
} }
None {} => {} None {} => {}
} }
@ -130,19 +140,38 @@ fn raytrace(ray: &Ray, scene: &Scene, recursion_depth: u32) -> Vector4<f32> {
} }
/// called iff an intersection is detected to (recursively) accumulate radiosity at intersection /// called iff an intersection is detected to (recursively) accumulate radiosity at intersection
fn accumulate_colors(_intersection_point: Vector3<f32>, isec_material: &Arc<Material>) -> Vector4<f32> { fn accumulate_colors(intersection_data: &IntersectionData,
global_scene: &Scene,
recursion_depth_left: usize) -> Vector4<f32> {
let mut pixel_radiosity: Vector4<f32> let mut pixel_radiosity: Vector4<f32>
= Vector4::new(0.0, 0.0, 0.0, 1.0); = Vector4::new(0.0, 0.0, 0.0, 1.0);
//accumulate colors at point //accumulate colors at point
//emmisive Component //emissive Component
pixel_radiosity += pixel_radiosity +=
isec_material.emissive.factor.extend(1.0) intersection_data.material().emissive.factor.extend(1.0)
.mul_element_wise( .mul_element_wise(
isec_material.get_base_color_alpha(Vector2::new(0.0, 0.0)) intersection_data.material()
.get_base_color_alpha(Vector2::new(0.0, 0.0))
); );
//get the intersected triangle and calculate the face normals
let intersected_triangle = intersection_data.intersected_triangle();
let face_normal: Vector3<f32> = (intersected_triangle[0].position - intersected_triangle[1].position)
.cross(intersected_triangle[0].position - intersected_triangle[2].position).normalize();
//TODO: Path tracing. Scatter ray in one random direction let secondary_ray = Ray {
//prevent self-intersection
source: intersection_data.intersection_point() + RAY_EPSILON * face_normal,
direction: face_normal,
};
let incoming_radiosity = raytrace(
&secondary_ray,
global_scene,
recursion_depth_left - 1);
//reflected component
pixel_radiosity += incoming_radiosity * 0.2;
pixel_radiosity pixel_radiosity
} }

View file

@ -1,17 +1,23 @@
use std::sync::Arc; use std::sync::Arc;
use cgmath::Vector3; use cgmath::Vector3;
use easy_gltf::Material; use easy_gltf::{Material, Scene};
use easy_gltf::model::Triangle;
pub(crate) struct IntersectionData { pub(crate) struct IntersectionData {
intersection_point: Vector3<f32>, intersection_point: Vector3<f32>,
material: Arc<Material> material: Arc<Material>,
intersected_triangle: Triangle,
} }
impl IntersectionData { impl IntersectionData {
pub fn new(intersection_point: Vector3<f32>, material: Arc<Material>) -> IntersectionData{ pub fn new(
intersection_point: Vector3<f32>,
material: Arc<Material>,
intersected_triangle: Triangle) -> IntersectionData {
IntersectionData { IntersectionData {
intersection_point, intersection_point,
material, material,
intersected_triangle,
} }
} }
@ -22,4 +28,8 @@ impl IntersectionData{
pub fn material(&self) -> &Arc<Material> { pub fn material(&self) -> &Arc<Material> {
&self.material &self.material
} }
pub fn intersected_triangle(&self) -> Triangle {
self.intersected_triangle
}
} }