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