More proper use of light sources.
This commit is contained in:
parent
24cbdb5ab9
commit
02a0740cac
|
@ -2,6 +2,7 @@ mod spectra_xyz;
|
|||
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Div, DivAssign};
|
||||
|
||||
use float4::Float4;
|
||||
use lerp::Lerp;
|
||||
use self::spectra_xyz::{spectrum_xyz_to_p, EQUAL_ENERGY_REFLECTANCE};
|
||||
|
||||
|
@ -20,10 +21,10 @@ pub trait Color {
|
|||
|
||||
fn to_spectral_sample(&self, hero_wavelength: f32) -> SpectralSample {
|
||||
SpectralSample {
|
||||
e: [self.sample_spectrum(nth_wavelength(hero_wavelength, 0)),
|
||||
self.sample_spectrum(nth_wavelength(hero_wavelength, 1)),
|
||||
self.sample_spectrum(nth_wavelength(hero_wavelength, 2)),
|
||||
self.sample_spectrum(nth_wavelength(hero_wavelength, 3))],
|
||||
e: Float4::new(self.sample_spectrum(nth_wavelength(hero_wavelength, 0)),
|
||||
self.sample_spectrum(nth_wavelength(hero_wavelength, 1)),
|
||||
self.sample_spectrum(nth_wavelength(hero_wavelength, 2)),
|
||||
self.sample_spectrum(nth_wavelength(hero_wavelength, 3))),
|
||||
|
||||
hero_wavelength: hero_wavelength,
|
||||
}
|
||||
|
@ -42,7 +43,7 @@ fn nth_wavelength(hero_wavelength: f32, n: usize) -> f32 {
|
|||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SpectralSample {
|
||||
e: [f32; 4],
|
||||
e: Float4,
|
||||
hero_wavelength: f32,
|
||||
}
|
||||
|
||||
|
@ -50,7 +51,15 @@ impl SpectralSample {
|
|||
pub fn new(wavelength: f32) -> SpectralSample {
|
||||
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
||||
SpectralSample {
|
||||
e: [0.0; 4],
|
||||
e: Float4::new(0.0, 0.0, 0.0, 0.0),
|
||||
hero_wavelength: wavelength,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_value(value: f32, wavelength: f32) -> SpectralSample {
|
||||
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
||||
SpectralSample {
|
||||
e: Float4::new(value, value, value, value),
|
||||
hero_wavelength: wavelength,
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +75,56 @@ impl SpectralSample {
|
|||
}
|
||||
}
|
||||
|
||||
impl Add for SpectralSample {
|
||||
type Output = SpectralSample;
|
||||
fn add(self, rhs: SpectralSample) -> Self::Output {
|
||||
assert!(self.hero_wavelength == rhs.hero_wavelength);
|
||||
SpectralSample {
|
||||
e: self.e + rhs.e,
|
||||
hero_wavelength: self.hero_wavelength,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for SpectralSample {
|
||||
fn add_assign(&mut self, rhs: SpectralSample) {
|
||||
assert!(self.hero_wavelength == rhs.hero_wavelength);
|
||||
self.e = self.e + rhs.e;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for SpectralSample {
|
||||
type Output = SpectralSample;
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
SpectralSample {
|
||||
e: self.e * rhs,
|
||||
hero_wavelength: self.hero_wavelength,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<f32> for SpectralSample {
|
||||
fn mul_assign(&mut self, rhs: f32) {
|
||||
self.e = self.e * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for SpectralSample {
|
||||
type Output = SpectralSample;
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
SpectralSample {
|
||||
e: self.e / rhs,
|
||||
hero_wavelength: self.hero_wavelength,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<f32> for SpectralSample {
|
||||
fn div_assign(&mut self, rhs: f32) {
|
||||
self.e = self.e / rhs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct XYZ {
|
||||
|
|
|
@ -88,6 +88,22 @@ impl Float4 {
|
|||
*self.data.get_unchecked_mut(3) = n;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_0(&self) -> f32 {
|
||||
unsafe { *self.data.get_unchecked(0) }
|
||||
}
|
||||
|
||||
pub fn get_1(&self) -> f32 {
|
||||
unsafe { *self.data.get_unchecked(1) }
|
||||
}
|
||||
|
||||
pub fn get_2(&self) -> f32 {
|
||||
unsafe { *self.data.get_unchecked(2) }
|
||||
}
|
||||
|
||||
pub fn get_3(&self) -> f32 {
|
||||
unsafe { *self.data.get_unchecked(3) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use super::basics::ws_f32;
|
|||
use super::psy::PsyParseError;
|
||||
|
||||
use light::{SphereLight, RectangleLight};
|
||||
use color::XYZ;
|
||||
use color::{XYZ, rec709e_to_xyz};
|
||||
|
||||
pub fn parse_sphere_light(tree: &DataTree) -> Result<SphereLight, PsyParseError> {
|
||||
if let &DataTree::Internal { ref children, .. } = tree {
|
||||
|
@ -37,7 +37,7 @@ pub fn parse_sphere_light(tree: &DataTree) -> Result<SphereLight, PsyParseError>
|
|||
// TODO: handle color space conversions properly.
|
||||
// Probably will need a special color type with its
|
||||
// own parser...?
|
||||
colors.push(XYZ::new(color.0, color.1, color.2));
|
||||
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
||||
} else {
|
||||
// Found color, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError);
|
||||
|
@ -81,7 +81,7 @@ pub fn parse_rectangle_light(tree: &DataTree) -> Result<RectangleLight, PsyParse
|
|||
// TODO: handle color space conversions properly.
|
||||
// Probably will need a special color type with its
|
||||
// own parser...?
|
||||
colors.push(XYZ::new(color.0, color.1, color.2));
|
||||
colors.push(XYZ::from_tuple(rec709e_to_xyz(color)));
|
||||
} else {
|
||||
// Found color, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError);
|
||||
|
|
|
@ -18,7 +18,7 @@ use math::{Matrix4x4, dot, fast_logit};
|
|||
use image::Image;
|
||||
use surface;
|
||||
use scene::Scene;
|
||||
use color::{Color, XYZ, map_0_1_to_wavelength};
|
||||
use color::{Color, XYZ, SpectralSample, map_0_1_to_wavelength};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Renderer {
|
||||
|
@ -139,7 +139,7 @@ impl Renderer {
|
|||
for path in paths.iter() {
|
||||
let mut col =
|
||||
img.get(path.pixel_co.0 as usize, path.pixel_co.1 as usize);
|
||||
col += path.color / self.spp as f32;
|
||||
col += XYZ::from_spectral_sample(&path.color) / self.spp as f32;
|
||||
img.set(path.pixel_co.0 as usize, path.pixel_co.1 as usize, col);
|
||||
}
|
||||
}
|
||||
|
@ -188,8 +188,9 @@ pub struct LightPath {
|
|||
round: u32,
|
||||
time: f32,
|
||||
wavelength: f32,
|
||||
light_attenuation: XYZ,
|
||||
color: XYZ,
|
||||
light_attenuation: SpectralSample,
|
||||
pending_color_addition: SpectralSample,
|
||||
color: SpectralSample,
|
||||
}
|
||||
|
||||
impl LightPath {
|
||||
|
@ -208,8 +209,9 @@ impl LightPath {
|
|||
round: 0,
|
||||
time: time,
|
||||
wavelength: wavelength,
|
||||
light_attenuation: XYZ::new(1.0, 1.0, 1.0),
|
||||
color: XYZ::new(0.0, 0.0, 0.0),
|
||||
light_attenuation: SpectralSample::from_value(1.0, wavelength),
|
||||
pending_color_addition: SpectralSample::new(wavelength),
|
||||
color: SpectralSample::new(wavelength),
|
||||
},
|
||||
|
||||
scene.camera.generate_ray(image_plane_co.0,
|
||||
|
@ -257,7 +259,7 @@ impl LightPath {
|
|||
let lu = self.next_lds_samp();
|
||||
let lv = self.next_lds_samp();
|
||||
// TODO: store incident light info and pdf, and use them properly
|
||||
let (_, shadow_vec, _) =
|
||||
let (light_color, shadow_vec, light_pdf) =
|
||||
light.sample(&space, pos, lu, lv, self.wavelength, self.time);
|
||||
|
||||
let rnor = if dot(nor.into_vector(), ray.dir) > 0.0 {
|
||||
|
@ -266,8 +268,8 @@ impl LightPath {
|
|||
nor.into_vector().normalized()
|
||||
};
|
||||
let la = dot(rnor, shadow_vec.normalized()).max(0.0);
|
||||
self.light_attenuation = XYZ::from_spectral_sample(&XYZ::new(la, la, la)
|
||||
.to_spectral_sample(self.wavelength));
|
||||
// self.light_attenuation = SpectralSample::from_value(la);
|
||||
self.pending_color_addition = light_color * la / light_pdf;
|
||||
*ray = Ray::new(pos + rnor * 0.0001,
|
||||
shadow_vec - rnor * 0.0001,
|
||||
self.time,
|
||||
|
@ -280,8 +282,7 @@ impl LightPath {
|
|||
} else {
|
||||
// Didn't hit anything, so background color
|
||||
let xyz = XYZ::new(0.02, 0.02, 0.02);
|
||||
self.color +=
|
||||
XYZ::from_spectral_sample(&xyz.to_spectral_sample(self.wavelength));
|
||||
self.color += xyz.to_spectral_sample(self.wavelength);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -291,7 +292,7 @@ impl LightPath {
|
|||
1 => {
|
||||
self.round += 1;
|
||||
if let &surface::SurfaceIntersection::Miss = isect {
|
||||
self.color += self.light_attenuation;
|
||||
self.color += self.pending_color_addition;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user