reflection directly along normal
This commit is contained in:
parent
1e752d60bf
commit
7f9af4ceaa
7 changed files with 68 additions and 26 deletions
BIN
result_image.png
BIN
result_image.png
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue