basic path tracing
This commit is contained in:
parent
7f9af4ceaa
commit
507ee2011c
8 changed files with 43 additions and 16 deletions
BIN
result_image.png
BIN
result_image.png
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 686 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,4 +1,4 @@
|
|||
use std::ops::{Mul, MulAssign};
|
||||
use std::ops::{MulAssign};
|
||||
use cgmath::{ElementWise, Vector4};
|
||||
use image::{DynamicImage, GenericImage, Rgba};
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ pub fn normalize_colors_global(radiosity_buffer: &mut Vec<Vec<Vector4<f32>>>) ->
|
|||
let range = maximum_colors - minimum_colors;
|
||||
//normalize to range
|
||||
for column in &mut *radiosity_buffer {
|
||||
for mut radiosity_value in column {
|
||||
for radiosity_value in column {
|
||||
//normalize to range
|
||||
radiosity_value.div_assign_element_wise(range);
|
||||
//map to [0.0..255]
|
||||
|
|
@ -77,12 +77,13 @@ pub fn map_radmap_to_colors(radiosity_buffer: &Vec<Vec<Vector4<f32>>>) -> Vec<Ve
|
|||
let mut color_buffer: Vec<Vec<Rgba<u8>>> = Vec::with_capacity(radiosity_buffer.len());
|
||||
radiosity_buffer.iter().enumerate().for_each(|(x, col)| {
|
||||
color_buffer.push(Vec::with_capacity(radiosity_buffer[0].len()));
|
||||
col.iter().enumerate().for_each(|(y, color_value)| {
|
||||
col.iter().enumerate().for_each(|(_y, color_value)| {
|
||||
//ceil and cast individual colors
|
||||
let casted = color_value.map(|comp| {
|
||||
f32::ceil(comp) as u8
|
||||
});
|
||||
color_buffer[x].push(Rgba::from([casted.x, casted.y, casted.z, casted.w]));
|
||||
//TODO: no alpha rendering
|
||||
color_buffer[x].push(Rgba::from([casted.x, casted.y, casted.z, 255]));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,9 @@ mod scene_data;
|
|||
mod colors;
|
||||
|
||||
use std::string::String;
|
||||
use std::sync::{Arc, LockResult, Mutex};
|
||||
use cgmath::Vector4;
|
||||
use clap::{Parser};
|
||||
use easy_gltf::Scene;
|
||||
use image::{DynamicImage};
|
||||
use crate::colors::{map_radmap_to_colors, normalize_colors_global, store_colors_to_image};
|
||||
use crate::renderer::render;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
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 rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use easy_gltf::model::{Mode};
|
||||
use easy_gltf::{Camera, Material, Projection, Scene};
|
||||
use easy_gltf::{Camera, Projection, Scene};
|
||||
use crate::Args;
|
||||
use crate::geometry::{Intersectable};
|
||||
use crate::ray::{construct_primary_rays, Ray};
|
||||
use crate::scene_data::IntersectionData;
|
||||
|
||||
const RAY_EPSILON: f32 = 0.0007;
|
||||
const EMISSION_MULTIPLIER: f32 = 10.0;
|
||||
|
||||
pub fn render(scenes: &Vec<Scene>,
|
||||
cl_args: &Args) -> Arc<Mutex<Vec<Vec<Vector4<f32>>>>> {
|
||||
|
|
@ -36,11 +38,11 @@ pub fn render(scenes: &Vec<Scene>,
|
|||
// the distance from the camera origin to the view plane
|
||||
let z: f32 = cl_args.height as f32 / (2.0 * fovy.mul(0.5).tan());
|
||||
|
||||
let mut radiosity_buffer: Arc<Mutex<Vec<Vec<Vector4<f32>>>>> =
|
||||
let radiosity_buffer: Arc<Mutex<Vec<Vec<Vector4<f32>>>>> =
|
||||
Arc::new(Mutex::new(Vec::with_capacity(cl_args.width)));
|
||||
|
||||
//prepare the radiosity buffer
|
||||
(0..cl_args.width).into_iter().for_each(|px| {
|
||||
(0..cl_args.width).into_iter().for_each(|_px| {
|
||||
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));
|
||||
|
|
@ -154,24 +156,50 @@ fn accumulate_colors(intersection_data: &IntersectionData,
|
|||
.get_base_color_alpha(Vector2::new(0.0, 0.0))
|
||||
);
|
||||
|
||||
//TODO: hack, because light sources are always too dim
|
||||
pixel_radiosity *= EMISSION_MULTIPLIER;
|
||||
|
||||
//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();
|
||||
let tangent = (intersected_triangle[0].position -
|
||||
intersected_triangle[1].position).normalize();
|
||||
let face_normal: Vector3<f32> = tangent
|
||||
.cross(intersected_triangle[0].position -
|
||||
intersected_triangle[2].position).normalize();
|
||||
let bitangent = tangent.cross(face_normal);
|
||||
|
||||
/**
|
||||
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 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 secondary_ray = Ray {
|
||||
//prevent self-intersection
|
||||
source: intersection_data.intersection_point() + RAY_EPSILON * face_normal,
|
||||
direction: face_normal,
|
||||
direction: direction.normalize(),
|
||||
};
|
||||
|
||||
let incoming_radiosity = raytrace(
|
||||
//path trace recursively
|
||||
let incoming_radiosity: Vector4<f32> = raytrace(
|
||||
&secondary_ray,
|
||||
global_scene,
|
||||
recursion_depth_left - 1);
|
||||
|
||||
let cos_weighting = direction.dot(face_normal);
|
||||
|
||||
let brdf = 0.5 * intersection_data.material().get_base_color_alpha(
|
||||
Vector2::new(0.0,0.0)
|
||||
);
|
||||
|
||||
//reflected component
|
||||
pixel_radiosity += incoming_radiosity * 0.2;
|
||||
pixel_radiosity += (brdf.mul_element_wise(incoming_radiosity) * cos_weighting * 2.0 * PI) ;
|
||||
|
||||
pixel_radiosity
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
use cgmath::Vector3;
|
||||
use easy_gltf::{Material, Scene};
|
||||
use easy_gltf::{Material};
|
||||
use easy_gltf::model::Triangle;
|
||||
|
||||
pub(crate) struct IntersectionData {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue