color corrections and parameter tweaks
This commit is contained in:
parent
507ee2011c
commit
8cb5476588
6 changed files with 33 additions and 35 deletions
BIN
result_image.png
BIN
result_image.png
Binary file not shown.
|
Before Width: | Height: | Size: 686 KiB After Width: | Height: | Size: 469 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -2,11 +2,10 @@ use std::ops::{MulAssign};
|
||||||
use cgmath::{ElementWise, Vector4};
|
use cgmath::{ElementWise, Vector4};
|
||||||
use image::{DynamicImage, GenericImage, Rgba};
|
use image::{DynamicImage, GenericImage, Rgba};
|
||||||
|
|
||||||
|
const GAMMA: f32 = 2.0;
|
||||||
|
|
||||||
/// normalizes the color for k rays on a single pixel
|
/// normalizes the color for k rays on a single pixel
|
||||||
pub fn normalize_color_single_pixel(radiosity_vector: Vector4<f32>, rays_per_pixel: usize) -> Rgba<u8> {
|
pub fn normalize_color_single_pixel(radiosity_vector: Vector4<f32>) -> Rgba<u8> {
|
||||||
radiosity_vector.map(|component|
|
|
||||||
f32::ceil(component / rays_per_pixel as f32) as u8
|
|
||||||
);
|
|
||||||
|
|
||||||
let radiosity_as_arr = [
|
let radiosity_as_arr = [
|
||||||
radiosity_vector.x,
|
radiosity_vector.x,
|
||||||
|
|
@ -31,41 +30,40 @@ pub fn normalize_color_single_pixel(radiosity_vector: Vector4<f32>, rays_per_pix
|
||||||
|
|
||||||
pub fn normalize_colors_global(radiosity_buffer: &mut Vec<Vec<Vector4<f32>>>) -> &Vec<Vec<Vector4<f32>>> {
|
pub fn normalize_colors_global(radiosity_buffer: &mut Vec<Vec<Vector4<f32>>>) -> &Vec<Vec<Vector4<f32>>> {
|
||||||
//largest radiosity found yet
|
//largest radiosity found yet
|
||||||
let mut maximum_colors = Vector4::new(
|
let mut maximum_radiosity = f32::NEG_INFINITY;
|
||||||
f32::NEG_INFINITY,
|
|
||||||
f32::NEG_INFINITY,
|
|
||||||
f32::NEG_INFINITY,
|
|
||||||
f32::NEG_INFINITY);
|
|
||||||
//smallest radiosity found yet
|
//smallest radiosity found yet
|
||||||
let mut minimum_colors = Vector4::new(
|
let mut minimum_radiosity = f32::INFINITY;
|
||||||
f32::INFINITY,
|
|
||||||
f32::INFINITY,
|
|
||||||
f32::INFINITY,
|
|
||||||
f32::INFINITY);
|
|
||||||
//find maximum and minimum radiosity
|
//find maximum and minimum radiosity
|
||||||
radiosity_buffer.iter().for_each(|col| {
|
radiosity_buffer.iter().for_each(|col| {
|
||||||
col.iter().for_each(|color| {
|
col.iter().for_each(|color| {
|
||||||
maximum_colors.x = f32::max(maximum_colors.x, color.x);
|
maximum_radiosity = f32::max(maximum_radiosity, color.x);
|
||||||
maximum_colors.y = f32::max(maximum_colors.y, color.y);
|
maximum_radiosity = f32::max(maximum_radiosity, color.y);
|
||||||
maximum_colors.z = f32::max(maximum_colors.z, color.z);
|
maximum_radiosity = f32::max(maximum_radiosity, color.z);
|
||||||
maximum_colors.w = f32::max(maximum_colors.w, color.w);
|
|
||||||
|
|
||||||
minimum_colors.x = f32::min(minimum_colors.x, color.x);
|
minimum_radiosity = f32::min(minimum_radiosity, color.x);
|
||||||
minimum_colors.y = f32::min(minimum_colors.y, color.y);
|
minimum_radiosity = f32::min(minimum_radiosity, color.y);
|
||||||
minimum_colors.z = f32::min(minimum_colors.z, color.z);
|
minimum_radiosity = f32::min(minimum_radiosity, color.z);
|
||||||
minimum_colors.w = f32::min(minimum_colors.w, color.w);
|
});
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//calculate difference between min and max pixel radiosity
|
//calculate difference between min and max pixel radiosity
|
||||||
let range = maximum_colors - minimum_colors;
|
//TODO: drop upper 20 percent of radiosity to illiminate outliers
|
||||||
|
let range = (maximum_radiosity * 0.8) - minimum_radiosity;
|
||||||
//normalize to range
|
//normalize to range
|
||||||
for column in &mut *radiosity_buffer {
|
for column in &mut *radiosity_buffer {
|
||||||
for radiosity_value in column {
|
for radiosity_value in column {
|
||||||
|
//Gamma correct
|
||||||
|
radiosity_value.map(|single_channel_radiosity|
|
||||||
|
f32::powf(single_channel_radiosity, 1.0/GAMMA)
|
||||||
|
);
|
||||||
//normalize to range
|
//normalize to range
|
||||||
radiosity_value.div_assign_element_wise(range);
|
radiosity_value.div_assign_element_wise(range);
|
||||||
//map to [0.0..255]
|
//map to [0.0..255]
|
||||||
radiosity_value.mul_assign(255.0);
|
radiosity_value.mul_assign(255.0);
|
||||||
|
radiosity_value.map(|single_ch_radiosity|
|
||||||
|
f32::max(single_ch_radiosity, 255.0)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use std::ops::{Add, Mul};
|
use std::ops::{Add, Mul};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, LockResult, Mutex};
|
||||||
use cgmath::{Angle, ElementWise, InnerSpace, 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, Projection, Scene};
|
use easy_gltf::{Camera, Projection, Scene};
|
||||||
|
use rayon::prelude::IntoParallelRefIterator;
|
||||||
use crate::Args;
|
use crate::Args;
|
||||||
use crate::geometry::{Intersectable};
|
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;
|
const RAY_EPSILON: f32 = 0.0007;
|
||||||
const EMISSION_MULTIPLIER: f32 = 10.0;
|
|
||||||
|
|
||||||
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>>>>> {
|
||||||
|
|
@ -68,7 +68,7 @@ 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, cl_args.recurse)
|
raytrace(&ray, render_scene, cl_args.recurse)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -156,8 +156,6 @@ fn accumulate_colors(intersection_data: &IntersectionData,
|
||||||
.get_base_color_alpha(Vector2::new(0.0, 0.0))
|
.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
|
//get the intersected triangle and calculate the face normals
|
||||||
let intersected_triangle = intersection_data.intersected_triangle();
|
let intersected_triangle = intersection_data.intersected_triangle();
|
||||||
|
|
@ -168,9 +166,9 @@ fn accumulate_colors(intersection_data: &IntersectionData,
|
||||||
intersected_triangle[2].position).normalize();
|
intersected_triangle[2].position).normalize();
|
||||||
let bitangent = tangent.cross(face_normal);
|
let bitangent = tangent.cross(face_normal);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
generate random direction on hemisphere
|
generate random direction on hemisphere
|
||||||
**/
|
*/
|
||||||
let phi = rand::random::<f32>() * 2.0 * PI;
|
let phi = rand::random::<f32>() * 2.0 * PI;
|
||||||
//allow arbitrary angles
|
//allow arbitrary angles
|
||||||
let theta = rand::random::<f32>() * 2.0 * PI;
|
let theta = rand::random::<f32>() * 2.0 * PI;
|
||||||
|
|
@ -192,14 +190,16 @@ fn accumulate_colors(intersection_data: &IntersectionData,
|
||||||
global_scene,
|
global_scene,
|
||||||
recursion_depth_left - 1);
|
recursion_depth_left - 1);
|
||||||
|
|
||||||
|
|
||||||
let cos_weighting = direction.dot(face_normal);
|
let cos_weighting = direction.dot(face_normal);
|
||||||
|
|
||||||
let brdf = 0.5 * intersection_data.material().get_base_color_alpha(
|
//make ray contribution decay exponentially
|
||||||
Vector2::new(0.0,0.0)
|
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));
|
||||||
|
|
||||||
//reflected component
|
//reflected component
|
||||||
pixel_radiosity += (brdf.mul_element_wise(incoming_radiosity) * cos_weighting * 2.0 * PI) ;
|
pixel_radiosity += brdf.mul_element_wise(incoming_radiosity) * cos_weighting * 2.0 * PI;
|
||||||
|
|
||||||
pixel_radiosity
|
pixel_radiosity
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue