Spring cleaning
This commit is contained in:
parent
3fda37fcd1
commit
4188adbc33
13 changed files with 99 additions and 101 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -15,3 +15,6 @@ tests/
|
|||
scenes/
|
||||
compile.sh
|
||||
output/
|
||||
*.md
|
||||
!README.md
|
||||
!INSTALL.md
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use crate::core::geometry::{max, min};
|
|||
use crate::utils::gpu_array_from_fn;
|
||||
use crate::utils::interval::Interval;
|
||||
use crate::utils::math::lerp;
|
||||
use crate::{gamma, gamma_t};
|
||||
use core::mem;
|
||||
use core::ops::{Add, Div, DivAssign, Mul, Sub};
|
||||
use num_traits::{Bounded, Num};
|
||||
|
|
@ -220,7 +221,7 @@ where
|
|||
(center, radius)
|
||||
}
|
||||
|
||||
pub fn insersect(&self, o: Point3<T>, d: Vector3<T>, t_max: T) -> Option<(T, T)> {
|
||||
pub fn intersect(&self, o: Point3<T>, d: Vector3<T>, t_max: T) -> Option<(T, T)> {
|
||||
let mut t0 = T::zero();
|
||||
let mut t1 = t_max;
|
||||
|
||||
|
|
@ -231,6 +232,8 @@ where
|
|||
if t_near > t_far {
|
||||
mem::swap(&mut t_near, &mut t_far);
|
||||
}
|
||||
|
||||
t_far = t_far * (T::one() + (T::one() + T::one()) * gamma_t::<T>(3));
|
||||
t0 = if t_near > t0 { t_near } else { t0 };
|
||||
t1 = if t_far < t1 { t_far } else { t1 };
|
||||
if t0 > t1 {
|
||||
|
|
@ -274,7 +277,10 @@ impl Bounds3f {
|
|||
|
||||
// Check Y
|
||||
let ty_min = (bounds[dir_is_neg[1]].y() - o.y()) * inv_dir.y();
|
||||
let ty_max = (bounds[1 - dir_is_neg[1]].y() - o.y()) * inv_dir.y();
|
||||
let mut ty_max = (bounds[1 - dir_is_neg[1]].y() - o.y()) * inv_dir.y();
|
||||
|
||||
t_max = t_max * (1. + 2. * gamma(3));
|
||||
ty_max = ty_max * (1. + 2. * gamma(3));
|
||||
|
||||
if t_min > ty_max || ty_min > t_max {
|
||||
return None;
|
||||
|
|
@ -321,7 +327,11 @@ impl Bounds3f {
|
|||
let mut t_min = (bounds[dir_is_neg[0]].x() - o.x()) * inv_dir.x();
|
||||
let mut t_max = (bounds[1 - dir_is_neg[0]].x() - o.x()) * inv_dir.x();
|
||||
let ty_min = (bounds[dir_is_neg[1]].y() - o.y()) * inv_dir.y();
|
||||
let ty_max = (bounds[1 - dir_is_neg[1]].y() - o.y()) * inv_dir.y();
|
||||
let mut ty_max = (bounds[1 - dir_is_neg[1]].y() - o.y()) * inv_dir.y();
|
||||
|
||||
|
||||
t_max = t_max * (1. + 2. * gamma(3));
|
||||
ty_max = ty_max * (1. + 2. * gamma(3));
|
||||
|
||||
if t_min > ty_max || ty_min > t_max {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -52,13 +52,13 @@ impl DirectionCone {
|
|||
* Vector3f::new(
|
||||
w.x()
|
||||
* (wp.y() * w.y() + wp.z() * w.z()
|
||||
- wp.x() * (square(w.y() + square(w.z())))),
|
||||
- wp.x() * (square(w.y()) + square(w.z()))),
|
||||
w.y()
|
||||
* (wp.x() * w.x() + wp.z() * w.z()
|
||||
- wp.y() * (square(w.x() + square(w.z())))),
|
||||
- wp.y() * (square(w.x()) + square(w.z()))),
|
||||
w.z()
|
||||
* (wp.x() * w.x() + wp.y() * w.y()
|
||||
- wp.z() * (square(w.x() + square(w.y())))),
|
||||
- wp.z() * (square(w.x()) + square(w.y()))),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -91,10 +91,10 @@ impl DirectionCone {
|
|||
let theta_b = safe_acos(b.cos_theta);
|
||||
let theta_d = a.w.angle_between(b.w);
|
||||
|
||||
if (theta_d + theta_b).min(PI) <= theta_b {
|
||||
if (theta_d + theta_b).min(PI) <= theta_a {
|
||||
return a.clone();
|
||||
}
|
||||
if (theta_d + theta_a).min(PI) <= theta_a {
|
||||
if (theta_d + theta_a).min(PI) <= theta_b {
|
||||
return b.clone();
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ impl DirectionCone {
|
|||
// Find the merged cone's axis and return cone union
|
||||
let theta_r = theta_o - theta_a;
|
||||
let wr = a.w.cross(b.w);
|
||||
if wr.norm_squared() >= 0. {
|
||||
if wr.norm_squared() == 0. {
|
||||
return DirectionCone::entire_sphere();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,25 +43,21 @@ impl Ray {
|
|||
self.o + self.d * t
|
||||
}
|
||||
|
||||
pub fn offset_origin(p: &Point3fi, n: &Normal3f, w: &Vector3f) -> Point3f {
|
||||
let d: Float = Vector3f::from(n.abs()).dot(p.error());
|
||||
let normal: Vector3f = Vector3f::from(*n);
|
||||
|
||||
let mut offset = p.midpoint();
|
||||
if w.dot(normal) < 0.0 {
|
||||
offset -= normal * d;
|
||||
} else {
|
||||
offset += normal * d;
|
||||
pub fn offset_origin(pi: &Point3fi, n: &Normal3f, w: &Vector3f) -> Point3f {
|
||||
let d: Float = Vector3f::from(n.abs()).dot(pi.error());
|
||||
let mut disp: Vector3f = Vector3f::from(*n) * d;
|
||||
if w.dot(Vector3f::from(*n)) < 0.0 {
|
||||
disp = -disp;
|
||||
}
|
||||
|
||||
let mut po = pi.midpoint() + disp;
|
||||
for i in 0..3 {
|
||||
if n[i] > 0.0 {
|
||||
offset[i] = next_float_up(offset[i]);
|
||||
} else if n[i] < 0.0 {
|
||||
offset[i] = next_float_down(offset[i]);
|
||||
if disp[i] > 0.0 {
|
||||
po[i] = next_float_up(po[i]);
|
||||
} else if disp[i] < 0.0 {
|
||||
po[i] = next_float_down(po[i]);
|
||||
}
|
||||
}
|
||||
offset
|
||||
po
|
||||
}
|
||||
|
||||
pub fn spawn(pi: &Point3fi, n: &Normal3f, time: Float, d: Vector3f) -> Ray {
|
||||
|
|
|
|||
|
|
@ -561,6 +561,8 @@ impl SurfaceInteraction {
|
|||
self.shading.n = ns;
|
||||
if orientation {
|
||||
self.common.n = self.n().face_forward(self.shading.n);
|
||||
} else {
|
||||
self.shading.n = self.shading.n.face_forward(self.common.n);
|
||||
}
|
||||
self.shading.dpdu = dpdus;
|
||||
self.shading.dpdv = dpdvs;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::core::geometry::Lerp;
|
||||
use core::ops::{Add, Mul};
|
||||
use num_traits::{Num, PrimInt};
|
||||
use num_traits::{Float as NumFloat, Num, NumCast, PrimInt};
|
||||
|
||||
use crate::core::light::LightTrait;
|
||||
use crate::core::shape::Shape;
|
||||
|
|
@ -104,9 +104,16 @@ pub const PI_OVER_2: Float = core::f32::consts::FRAC_PI_2;
|
|||
pub const PI_OVER_4: Float = core::f32::consts::FRAC_PI_4;
|
||||
pub const SQRT_2: Float = core::f32::consts::SQRT_2;
|
||||
|
||||
#[inline]
|
||||
pub fn gamma_t<T: NumFloat + NumCast>(n: i32) -> T {
|
||||
let n = T::from(n).unwrap();
|
||||
let eps = T::epsilon() / (T::one() + T::one());
|
||||
n * eps / (T::one() - n * eps)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn gamma(n: i32) -> Float {
|
||||
n as Float * MACHINE_EPSILON / (1. - n as Float * MACHINE_EPSILON)
|
||||
gamma_t::<Float>(n)
|
||||
}
|
||||
|
||||
#[cfg(feature = "cpu_debug")]
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ impl DiskShape {
|
|||
}
|
||||
|
||||
fn basic_intersect(&self, r: &Ray, t_max: Float) -> Option<QuadricIntersection> {
|
||||
let oi = self.object_from_render.apply_to_point(r.o);
|
||||
let di = self.object_from_render.apply_to_vector(r.d);
|
||||
let oi = self.object_from_render.apply_to_interval(Point3fi::new_from_point(r.o));
|
||||
let di = self.object_from_render.apply_to_vector_interval(Vector3fi::new_from_vector(r.d));
|
||||
// Reject disk intersections for rays parallel to the disk’s plane
|
||||
if di.z() == 0. {
|
||||
return None;
|
||||
|
|
@ -61,7 +61,7 @@ impl DiskShape {
|
|||
}
|
||||
|
||||
// See if hit point is inside disk radii and phi_max
|
||||
let p_hit: Point3f = oi + t_shape_hit * di;
|
||||
let p_hit: Point3fi = oi + t_shape_hit * di;
|
||||
let dist2 = square(p_hit.x()) + square(p_hit.y());
|
||||
if dist2 > square(self.radius) || dist2 < square(self.inner_radius) {
|
||||
return None;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl SphereShape {
|
|||
let c: Interval =
|
||||
square(oi.x()) + square(oi.y()) + square(oi.z()) - square(Interval::new(self.radius));
|
||||
|
||||
let v: Vector3fi = (oi - b / Vector3fi::from((2. * a) * di)).into();
|
||||
let v: Vector3fi = (oi - b / 2. * a * di).into();
|
||||
let length: Interval = v.norm();
|
||||
let discrim =
|
||||
4. * a * (Interval::new(self.radius) + length) * (Interval::new(self.radius) - length);
|
||||
|
|
@ -120,6 +120,7 @@ impl SphereShape {
|
|||
}
|
||||
|
||||
let mut p_hit = Point3f::from(oi) + Float::from(t_shape_hit) * Vector3f::from(di);
|
||||
p_hit *= self.radius / p_hit.distance(Point3f::new(0., 0., 0.));
|
||||
if p_hit.x() == 0. && p_hit.y() == 0. {
|
||||
p_hit[0] = 1e-5 * self.radius;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,8 +129,8 @@ impl TransformGeneric<Float> {
|
|||
let y = p.y();
|
||||
let z = p.z();
|
||||
let xn = self.m_inv[0][0] * x + self.m_inv[1][1] * y + self.m_inv[2][0] * z;
|
||||
let yn = self.m_inv[0][1] * x + self.m_inv[1][1] * y + self.m_inv[2][1] * z;
|
||||
let zn = self.m_inv[0][2] * x + self.m_inv[1][2] * y + self.m_inv[2][2] * z;
|
||||
let yn = self.m_inv[1][0] * x + self.m_inv[1][1] * y + self.m_inv[2][1] * z;
|
||||
let zn = self.m_inv[2][0] * x + self.m_inv[1][2] * y + self.m_inv[2][2] * z;
|
||||
Normal3f::new(xn, yn, zn)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::core::bxdf::BxDFFlags;
|
||||
use crate::core::film::VisibleSurface;
|
||||
use crate::core::geometry::{
|
||||
Normal3f, Point2f, Point2i, Point3f, Point3fi, Ray, RayDifferential, Vector3f,
|
||||
};
|
||||
|
|
@ -15,22 +16,13 @@ use crate::{Float, Ptr};
|
|||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PixelSampleState {
|
||||
pub filter_weight: SoABuffer<Float>,
|
||||
pub p_film: SoABuffer<Point2f>,
|
||||
pub pixel: SoABuffer<Point2i>,
|
||||
pub l: SoABuffer<SampledSpectrum>,
|
||||
pub lambda: SoABuffer<SampledWavelengths>,
|
||||
pub r_u: SoABuffer<SampledSpectrum>,
|
||||
pub r_l: SoABuffer<SampledSpectrum>,
|
||||
pub prev_intr_ctx: SoABuffer<LightSampleContext>,
|
||||
pub beta: SoABuffer<SampledSpectrum>,
|
||||
pub depth: SoABuffer<u32>,
|
||||
pub specular_bounce: SoABuffer<u8>,
|
||||
pub any_non_specular_bounces: SoABuffer<u8>,
|
||||
pub eta_scale: SoABuffer<Float>,
|
||||
pub filter_weight: SoABuffer<Float>,
|
||||
pub camera_ray_weight: SoABuffer<SampledSpectrum>,
|
||||
pub visible_surface_idx: SoABuffer<u32>,
|
||||
pub visible_surface: SoABuffer<VisibleSurface>,
|
||||
pub samples: SoABuffer<RaySamples>,
|
||||
pub p_pixel: SoABuffer<Point2i>,
|
||||
}
|
||||
|
||||
impl SoA for PixelSampleState {
|
||||
|
|
@ -38,22 +30,13 @@ impl SoA for PixelSampleState {
|
|||
|
||||
fn allocate(n: u32, alloc: &dyn SoAAllocator) -> Self {
|
||||
Self {
|
||||
filter_weight: alloc_soa_buffer(n, alloc),
|
||||
p_film: alloc_soa_buffer(n, alloc),
|
||||
pixel: alloc_soa_buffer(n, alloc),
|
||||
l: alloc_soa_buffer(n, alloc),
|
||||
lambda: alloc_soa_buffer(n, alloc),
|
||||
r_u: alloc_soa_buffer(n, alloc),
|
||||
r_l: alloc_soa_buffer(n, alloc),
|
||||
prev_intr_ctx: alloc_soa_buffer(n, alloc),
|
||||
beta: alloc_soa_buffer(n, alloc),
|
||||
depth: alloc_soa_buffer(n, alloc),
|
||||
specular_bounce: alloc_soa_buffer(n, alloc),
|
||||
any_non_specular_bounces: alloc_soa_buffer(n, alloc),
|
||||
eta_scale: alloc_soa_buffer(n, alloc),
|
||||
filter_weight: alloc_soa_buffer(n, alloc),
|
||||
camera_ray_weight: alloc_soa_buffer(n, alloc),
|
||||
visible_surface_idx: alloc_soa_buffer(n, alloc),
|
||||
visible_surface: alloc_soa_buffer(n, alloc),
|
||||
samples: alloc_soa_buffer(n, alloc),
|
||||
p_pixel: alloc_soa_buffer(n, alloc),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,8 +56,8 @@ pub struct RayWorkItem {
|
|||
pub r_l: SampledSpectrum,
|
||||
pub prev_intr_ctx: LightSampleContext,
|
||||
pub eta_scale: Float,
|
||||
pub specular_bounce: u8,
|
||||
pub any_non_specular_bounces: u8,
|
||||
pub specular_bounce: bool,
|
||||
pub any_non_specular_bounces: bool,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -89,8 +72,8 @@ pub struct RayWorkItemSoA {
|
|||
pub r_l: SoABuffer<SampledSpectrum>,
|
||||
pub prev_intr_ctx: SoABuffer<LightSampleContext>,
|
||||
pub eta_scale: SoABuffer<Float>,
|
||||
pub specular_bounce: SoABuffer<u8>,
|
||||
pub any_non_specular_bounces: SoABuffer<u8>,
|
||||
pub specular_bounce: SoABuffer<bool>,
|
||||
pub any_non_specular_bounces: SoABuffer<bool>,
|
||||
}
|
||||
|
||||
impl SoA for RayWorkItemSoA {
|
||||
|
|
@ -332,14 +315,13 @@ pub struct MaterialEvalWorkItem {
|
|||
pub lambda: SampledWavelengths,
|
||||
pub beta: SampledSpectrum,
|
||||
pub r_u: SampledSpectrum,
|
||||
// pub r_l: SampledSpectrum,
|
||||
pub any_non_specular_bounces: bool,
|
||||
pub depth: u32,
|
||||
pub eta_scale: Float,
|
||||
pub dpdus: Vector3f ,
|
||||
pub dpdus: Vector3f,
|
||||
pub dpdvs: Vector3f,
|
||||
pub dndus: Normal3f,
|
||||
pub dndvs: Normal3f
|
||||
pub dndvs: Normal3f,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -361,15 +343,13 @@ pub struct MaterialEvalWorkItemSoA {
|
|||
pub lambda: SoABuffer<SampledWavelengths>,
|
||||
pub beta: SoABuffer<SampledSpectrum>,
|
||||
pub r_u: SoABuffer<SampledSpectrum>,
|
||||
// pub r_l: SoABuffer<SampledSpectrum>,
|
||||
pub any_non_specular_bounces: SoABuffer<u8>,
|
||||
pub depth: SoABuffer<u32>,
|
||||
pub eta_scale: SoABuffer<Float>,
|
||||
pub dpdus: SoABuffer<Vector3f>,
|
||||
pub dpdvs: SoABuffer<Vector3f>,
|
||||
pub dndus: SoABuffer<Normal3f>,
|
||||
pub dndvs: SoABuffer<Normal3f>
|
||||
|
||||
pub dndvs: SoABuffer<Normal3f>,
|
||||
}
|
||||
|
||||
impl SoA for MaterialEvalWorkItemSoA {
|
||||
|
|
@ -393,7 +373,6 @@ impl SoA for MaterialEvalWorkItemSoA {
|
|||
lambda: alloc_soa_buffer(n, alloc),
|
||||
beta: alloc_soa_buffer(n, alloc),
|
||||
r_u: alloc_soa_buffer(n, alloc),
|
||||
// r_l: alloc_soa_buffer(n, alloc),
|
||||
any_non_specular_bounces: alloc_soa_buffer(n, alloc),
|
||||
depth: alloc_soa_buffer(n, alloc),
|
||||
eta_scale: alloc_soa_buffer(n, alloc),
|
||||
|
|
@ -422,7 +401,6 @@ impl SoA for MaterialEvalWorkItemSoA {
|
|||
lambda: self.lambda.get(i),
|
||||
beta: self.beta.get(i),
|
||||
r_u: self.r_u.get(i),
|
||||
// r_l: self.r_l.get(i),
|
||||
any_non_specular_bounces: self.any_non_specular_bounces.get(i) != 0,
|
||||
depth: self.depth.get(i),
|
||||
eta_scale: self.eta_scale.get(i),
|
||||
|
|
@ -430,7 +408,6 @@ impl SoA for MaterialEvalWorkItemSoA {
|
|||
dpdvs: self.dpdvs.get(i),
|
||||
dndus: self.dndus.get(i),
|
||||
dndvs: self.dndvs.get(i),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +428,6 @@ impl SoA for MaterialEvalWorkItemSoA {
|
|||
self.lambda.set(i, v.lambda);
|
||||
self.beta.set(i, v.beta);
|
||||
self.r_u.set(i, v.r_u);
|
||||
// self.r_l.set(i, v.r_l);
|
||||
self.any_non_specular_bounces
|
||||
.set(i, v.any_non_specular_bounces as u8);
|
||||
self.depth.set(i, v.depth);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use shared::spectra::{
|
|||
cie::SWATCHES_RAW, DenselySampledSpectrum, PiecewiseLinearSpectrum, RGBColorSpace,
|
||||
};
|
||||
use shared::utils::math::{linear_least_squares, SquareMatrix};
|
||||
use shared::{Float, Ptr, leak};
|
||||
use shared::{leak, Float, Ptr};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ impl CreatePixelSensor for PixelSensor {
|
|||
output_colorspace.as_ref(),
|
||||
sensor_illum.as_deref(),
|
||||
imaging_ratio,
|
||||
arena
|
||||
arena,
|
||||
))
|
||||
} else {
|
||||
let r_opt = get_named_spectrum(&format!("{}_r", sensor_name));
|
||||
|
|
@ -129,7 +129,7 @@ impl CreatePixelSensor for PixelSensor {
|
|||
.expect("Sensor must have illuminant"),
|
||||
),
|
||||
imaging_ratio,
|
||||
arena
|
||||
arena,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ impl CreatePixelSensor for PixelSensor {
|
|||
output_colorspace: &RGBColorSpace,
|
||||
sensor_illum: Option<&Spectrum>,
|
||||
imaging_ratio: Float,
|
||||
arena: &Arena
|
||||
arena: &Arena,
|
||||
) -> Self {
|
||||
let spectra = get_spectra_context();
|
||||
let r_bar = CIE_X_DATA.clone();
|
||||
|
|
@ -229,7 +229,6 @@ impl CreatePixelSensor for PixelSensor {
|
|||
imaging_ratio,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub trait CreateFilmBase {
|
||||
|
|
@ -336,6 +335,9 @@ pub trait FilmTrait: Sync {
|
|||
for x in pixel_bounds.p_min.x()..pixel_bounds.p_max.x() {
|
||||
let p = Point2i::new(x, y);
|
||||
let mut rgb = self.get_pixel_rgb(p, Some(splat_scale));
|
||||
if rgb.r > 1.0 || rgb.g > 1.0 || rgb.b > 1.0 {
|
||||
eprintln!("p={:?} get_pixel_rgb=({}, {}, {})", p, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
let mut was_clamped = false;
|
||||
if write_fp16 {
|
||||
if rgb.r > 65504.0 {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::globals::get_options;
|
||||
use log::debug;
|
||||
use rayon::prelude::*;
|
||||
use shared::core::geometry::{Bounds3f, Ray, VectorLike};
|
||||
use shared::core::interaction::{InteractionTrait, SurfaceInteraction};
|
||||
|
|
@ -60,7 +61,7 @@ impl WavefrontAggregate for CpuAggregate {
|
|||
r_u: r.r_u,
|
||||
r_l: r.r_l,
|
||||
depth: r.depth,
|
||||
specular_bounce: r.specular_bounce != 0,
|
||||
specular_bounce: r.specular_bounce,
|
||||
prev_intr_ctx: r.prev_intr_ctx,
|
||||
});
|
||||
return;
|
||||
|
|
@ -83,14 +84,14 @@ impl WavefrontAggregate for CpuAggregate {
|
|||
p: intr.p(),
|
||||
n: intr.n(),
|
||||
uv: intr.common.uv,
|
||||
wo: -r.ray.d,
|
||||
wo: intr.wo(),
|
||||
lambda: r.lambda,
|
||||
pixel_index: r.pixel_index,
|
||||
beta: r.beta,
|
||||
r_u: r.r_u,
|
||||
r_l: r.r_l,
|
||||
depth: r.depth,
|
||||
specular_bounce: r.specular_bounce != 0,
|
||||
specular_bounce: r.specular_bounce,
|
||||
prev_intr_ctx: r.prev_intr_ctx,
|
||||
});
|
||||
}
|
||||
|
|
@ -103,12 +104,20 @@ impl WavefrontAggregate for CpuAggregate {
|
|||
universal_eval_mtl_q
|
||||
};
|
||||
|
||||
if material.is_conductor() {
|
||||
debug!("shading frame: {:?}", intr.shading.dpdu);
|
||||
debug!(
|
||||
"dot product: {:?}",
|
||||
intr.shading.dpdu.normalize().dot(intr.n().into())
|
||||
);
|
||||
}
|
||||
|
||||
eval_q.push(MaterialEvalWorkItem {
|
||||
p: intr.pi(),
|
||||
n: intr.n(),
|
||||
ns: intr.shading.n,
|
||||
dpdu: intr.shading.dpdu,
|
||||
dpdv: intr.shading.dpdv,
|
||||
dpdu: intr.dpdu,
|
||||
dpdv: intr.dpdv,
|
||||
uv: intr.common.uv,
|
||||
wo: intr.wo(),
|
||||
time: r.ray.time,
|
||||
|
|
@ -120,7 +129,7 @@ impl WavefrontAggregate for CpuAggregate {
|
|||
lambda: r.lambda,
|
||||
beta: r.beta,
|
||||
r_u: r.r_u,
|
||||
any_non_specular_bounces: r.any_non_specular_bounces != 0,
|
||||
any_non_specular_bounces: r.any_non_specular_bounces,
|
||||
depth: r.depth,
|
||||
eta_scale: r.eta_scale,
|
||||
dpdus: intr.shading.dpdu,
|
||||
|
|
|
|||
|
|
@ -75,8 +75,6 @@ where
|
|||
let scanlines_per_pass = (max_samples / res_x).max(1);
|
||||
let max_queue_size = res_x * scanlines_per_pass;
|
||||
|
||||
eprintln!("wavefront got {} lights", lights.len());
|
||||
|
||||
let mut infinite_lights = gvec();
|
||||
for light in &lights {
|
||||
if light.light_type().is_infinite() {
|
||||
|
|
@ -84,10 +82,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
eprintln!("infinite_lights len = {}", infinite_lights.len());
|
||||
|
||||
// for light in
|
||||
|
||||
let cpu_aggregate = CpuAggregate::new(*aggregate);
|
||||
|
||||
CpuWavefrontRenderer(WavefrontPathIntegrator {
|
||||
|
|
@ -241,7 +235,7 @@ impl CpuWavefrontRenderer {
|
|||
pixel_bounds.p_min.x() + (pixel_index as i32 % x_resolution),
|
||||
y0 + (pixel_index as i32 / x_resolution),
|
||||
);
|
||||
pixel_sample_state.p_pixel.set(pixel_index, p_pixel);
|
||||
pixel_sample_state.pixel.set(pixel_index, p_pixel);
|
||||
|
||||
// Skipped pixels contribute nothing; their slots are simply never
|
||||
// populated, and update_film filters them by the same bounds test.
|
||||
|
|
@ -263,9 +257,6 @@ impl CpuWavefrontRenderer {
|
|||
pixel_sample_state
|
||||
.filter_weight
|
||||
.set(pixel_index, camera_sample.filter_weight);
|
||||
pixel_sample_state
|
||||
.p_film
|
||||
.set(pixel_index, camera_sample.p_film);
|
||||
|
||||
let Some(camera_ray) = camera.generate_ray(camera_sample, &lambda) else {
|
||||
pixel_sample_state
|
||||
|
|
@ -288,8 +279,8 @@ impl CpuWavefrontRenderer {
|
|||
r_l: SampledSpectrum::new(1.0),
|
||||
prev_intr_ctx: LightSampleContext::default(),
|
||||
eta_scale: 1.0,
|
||||
specular_bounce: 0,
|
||||
any_non_specular_bounces: 0,
|
||||
specular_bounce: false,
|
||||
any_non_specular_bounces: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -318,7 +309,7 @@ impl CpuWavefrontRenderer {
|
|||
if w.depth == 0 || w.specular_bounce {
|
||||
l_contrib += w.beta * le / w.r_u.average();
|
||||
} else {
|
||||
// MIS: combine BSDF and light sampling weights via ratio tracking
|
||||
// Compute MIS-weighted radiance contribution from infinite light
|
||||
let ctx = w.prev_intr_ctx;
|
||||
let light_choice_pdf = light_sampler.pmf_with_context(&ctx, light);
|
||||
let r_l = w.r_l * light_choice_pdf * light.pdf_li(&ctx, w.ray_d, true);
|
||||
|
|
@ -353,13 +344,14 @@ impl CpuWavefrontRenderer {
|
|||
let l_contrib = if w.depth == 0 || w.specular_bounce {
|
||||
w.beta * le / w.r_u.average()
|
||||
} else {
|
||||
let wi = -w.wo;
|
||||
let ctx = w.prev_intr_ctx;
|
||||
let light_choice_pdf = light_sampler.pmf_with_context(&ctx, light);
|
||||
// wi from previous interaction to this light hit
|
||||
let wi = (w.p - Point3f::from(ctx.pi)).normalize();
|
||||
let light_pdf = light_choice_pdf * light.pdf_li(&ctx, wi, true);
|
||||
let r_u = w.r_u;
|
||||
let r_l = w.r_l * light_pdf;
|
||||
w.beta * le / (w.r_u + r_l).average()
|
||||
w.beta * le / (r_u + r_l).average()
|
||||
};
|
||||
|
||||
if !l_contrib.is_black() {
|
||||
|
|
@ -489,8 +481,8 @@ impl CpuWavefrontRenderer {
|
|||
r_l,
|
||||
prev_intr_ctx: ctx,
|
||||
eta_scale,
|
||||
specular_bounce: bs.is_specular() as u8,
|
||||
any_non_specular_bounces: any_non_specular as u8,
|
||||
specular_bounce: bs.is_specular(),
|
||||
any_non_specular_bounces: any_non_specular,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -505,7 +497,7 @@ impl CpuWavefrontRenderer {
|
|||
};
|
||||
|
||||
if flags.is_reflective() && !flags.is_transmissive() {
|
||||
light_ctx.pi = Point3fi::new_from_point(Ray::offset_origin(&w.p, &w.n, &(-wo)));
|
||||
light_ctx.pi = Point3fi::new_from_point(Ray::offset_origin(&w.p, &w.n, &wo));
|
||||
} else if flags.is_transmissive() && flags.is_reflective() {
|
||||
light_ctx.pi = Point3fi::new_from_point(Ray::offset_origin(&w.p, &w.n, &(-wo)));
|
||||
}
|
||||
|
|
@ -573,7 +565,7 @@ impl CpuWavefrontRenderer {
|
|||
(0..self.max_queue_size as usize)
|
||||
.into_par_iter()
|
||||
.for_each(|pixel_index| {
|
||||
let p_pixel = self.pixel_sample_state.p_pixel.get(pixel_index);
|
||||
let p_pixel = self.pixel_sample_state.pixel.get(pixel_index);
|
||||
if !pixel_bounds.contains_exclusive(p_pixel) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -600,7 +592,7 @@ impl CpuWavefrontRenderer {
|
|||
let w = unsafe { ray_queue.storage.get(i) };
|
||||
let dimension = 6 + 7 * w.depth;
|
||||
let pi = w.pixel_index as usize;
|
||||
let p_pixel = pixel_sample_state.p_pixel.get(pi);
|
||||
let p_pixel = pixel_sample_state.pixel.get(pi);
|
||||
|
||||
let mut sampler = sampler_proto.clone();
|
||||
sampler.start_pixel_sample(p_pixel, sample_index as i32, Some(dimension));
|
||||
|
|
|
|||
Loading…
Reference in a new issue