diffuse path tracing

This commit is contained in:
CDaut 2023-11-28 01:02:12 +01:00
parent 8cb5476588
commit 44514117cd
10 changed files with 62 additions and 46 deletions

View file

@ -48,8 +48,7 @@ pub fn normalize_colors_global(radiosity_buffer: &mut Vec<Vec<Vector4<f32>>>) ->
});
//calculate difference between min and max pixel radiosity
//TODO: drop upper 20 percent of radiosity to illiminate outliers
let range = (maximum_radiosity * 0.8) - minimum_radiosity;
let range = maximum_radiosity - minimum_radiosity;
//normalize to range
for column in &mut *radiosity_buffer {
for radiosity_value in column {

View file

@ -49,6 +49,7 @@ fn main() {
&args.gltf_file_path)
.expect(&*format!("Failed to load glTF file {}", &args.gltf_file_path));
println!("Path tracing image. Columns finished:");
let mut radiosity_buffer: Vec<Vec<Vector4<f32>>> = match render(scenes, &args).lock() {
Ok(buffer) => {buffer.to_vec()}
Err(_) => {panic!("Unable to lock radiosity buffer!")}
@ -64,6 +65,6 @@ fn main() {
let output_image =
store_colors_to_image(as_colors);
output_image.save("result_image.png").expect("Unable to save image!");
output_image.save("../output_image.png").expect("Unable to save image!");
}

View file

@ -1,11 +1,13 @@
use indicatif::ProgressIterator;
use std::f32::consts::PI;
use std::ops::{Add, Mul};
use std::sync::{Arc, LockResult, Mutex};
use std::sync::{Arc, Mutex};
use cgmath::{Angle, ElementWise, InnerSpace, Matrix4, Vector2, Vector3, Vector4};
use cgmath::num_traits::abs;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use easy_gltf::model::{Mode};
use easy_gltf::{Camera, Projection, Scene};
use rayon::prelude::IntoParallelRefIterator;
use indicatif::ParallelProgressIterator;
use crate::Args;
use crate::geometry::{Intersectable};
use crate::ray::{construct_primary_rays, Ray};
@ -51,36 +53,38 @@ pub fn render(scenes: &Vec<Scene>,
});
//iterate over all pixels in the image
(0..cl_args.width).into_par_iter().for_each(|px| {
(0..cl_args.height).into_par_iter().for_each(|py| {
//construct all rays
let rays: Vec<Ray> = construct_primary_rays(
(cl_args.width, cl_args.height),
(px, py),
&transform_matrix,
z,
cl_args.multiplier,
);
//let the initial pixel color be black and opaque
let mut pixel_radiosity: Vector4<f32> = Vector4::new(0.0, 0.0, 0.0, 1.0);
//cast each ray and get the output luminosity and sum them up
rays.iter().for_each(|ray| {
pixel_radiosity = pixel_radiosity.add(
raytrace(&ray, render_scene, cl_args.recurse)
(0..cl_args.width).into_par_iter()
.progress_count(cl_args.width as u64)
.for_each(|px| {
(0..cl_args.height).into_par_iter().for_each(|py| {
//construct all rays
let rays: Vec<Ray> = construct_primary_rays(
(cl_args.width, cl_args.height),
(px, py),
&transform_matrix,
z,
cl_args.multiplier,
);
});
//store radiosity into the buffer
match radiosity_buffer.clone().lock() {
Ok(mut buffer) => {
buffer[px][py] = pixel_radiosity;
//let the initial pixel color be black and opaque
let mut pixel_radiosity: Vector4<f32> = Vector4::new(0.0, 0.0, 0.0, 1.0);
//cast each ray and get the output luminosity and sum them up
rays.iter().for_each(|ray| {
pixel_radiosity = pixel_radiosity.add(
raytrace(&ray, render_scene, cl_args.recurse)
);
});
//store radiosity into the buffer
match radiosity_buffer.clone().lock() {
Ok(mut buffer) => {
buffer[px][py] = pixel_radiosity;
}
Err(_) => { panic!("Unable to lock pixel buffer!") }
}
Err(_) => { panic!("Unable to lock pixel buffer!") }
}
});
});
});
radiosity_buffer
}
@ -121,6 +125,7 @@ fn raytrace(ray: &Ray, scene: &Scene, recursion_depth_left: usize) -> Vector4<f3
isec,
model.material(),
triangle.clone(),
ray,
)
);
}
@ -161,27 +166,31 @@ fn accumulate_colors(intersection_data: &IntersectionData,
let intersected_triangle = intersection_data.intersected_triangle();
let tangent = (intersected_triangle[0].position -
intersected_triangle[1].position).normalize();
let face_normal: Vector3<f32> = tangent
let mut face_normal: Vector3<f32> = tangent
.cross(intersected_triangle[0].position -
intersected_triangle[2].position).normalize();
let bitangent = tangent.cross(face_normal);
//flip normal if face is hit from behind
if face_normal.dot(-intersection_data.ray().direction) < 0.0 {
face_normal *= -1.0;
}
let bitangent = tangent.cross(face_normal).normalize();
/*
generate random direction on hemisphere
*/
let phi = rand::random::<f32>() * 2.0 * PI;
//allow arbitrary angles
let theta = rand::random::<f32>() * 2.0 * PI;
let radius = rand::random::<f32>();
let sqrt_radius = f32::sqrt(rand::random::<f32>());
let sin_theta = f32::sin(theta);
let direction = tangent * f32::cos(phi) * sin_theta +
bitangent * f32::sin(phi) * sin_theta +
face_normal * f32::cos(theta);
let direction = (tangent * f32::cos(phi) * sqrt_radius +
bitangent * f32::sin(phi) * sqrt_radius +
face_normal * f32::sqrt(1.0 - radius)).normalize();
let secondary_ray = Ray {
//prevent self-intersection
source: intersection_data.intersection_point() + RAY_EPSILON * face_normal,
direction: direction.normalize(),
direction,
};
//path trace recursively
@ -193,10 +202,8 @@ fn accumulate_colors(intersection_data: &IntersectionData,
let cos_weighting = direction.dot(face_normal);
//make ray contribution decay exponentially
let brdf = intersection_data.material()
.get_base_color_alpha(Vector2::new(0.0, 0.0))
* (1.0 - f32::powf(6.0, -0.5 * recursion_depth_left as f32));
.get_base_color_alpha(Vector2::new(0.0, 0.0));
//reflected component
pixel_radiosity += brdf.mul_element_wise(incoming_radiosity) * cos_weighting * 2.0 * PI;

View file

@ -2,22 +2,26 @@ use std::sync::Arc;
use cgmath::Vector3;
use easy_gltf::{Material};
use easy_gltf::model::Triangle;
use crate::ray::Ray;
pub(crate) struct IntersectionData {
pub(crate) struct IntersectionData<'a> {
intersection_point: Vector3<f32>,
material: Arc<Material>,
intersected_triangle: Triangle,
ray: &'a Ray,
}
impl IntersectionData {
impl IntersectionData<'_>{
pub fn new(
intersection_point: Vector3<f32>,
material: Arc<Material>,
intersected_triangle: Triangle) -> IntersectionData {
intersected_triangle: Triangle,
ray: &Ray) -> IntersectionData {
IntersectionData {
intersection_point,
material,
intersected_triangle,
ray,
}
}
@ -32,4 +36,8 @@ impl IntersectionData {
pub fn intersected_triangle(&self) -> Triangle {
self.intersected_triangle
}
pub fn ray(&self) -> &Ray {
self.ray
}
}