Still broken

This commit is contained in:
Wito Wiala 2026-06-04 16:35:28 +01:00
parent 66032abf76
commit 3fda37fcd1
7 changed files with 114 additions and 65 deletions

View file

@ -118,10 +118,7 @@ impl BSDF {
}
pub fn regularize(&mut self) {
if !self.is_valid() {
let bxdf = &mut self.bxdf;
bxdf.regularize();
}
self.bxdf.regularize();
}
}

View file

@ -195,6 +195,13 @@ pub enum Material {
Mix(MixMaterial),
}
impl Material {
#[inline(never)]
pub fn is_conductor(&self) -> bool {
matches!(self, Material::Conductor(_))
}
}
// TODO: THIS IS A HACK JUST FOR TESTING
impl PartialEq for Material {
fn eq(&self, other: &Self) -> bool {

View file

@ -539,14 +539,14 @@ impl ShapeTrait for TriangleShape {
fn intersect(&self, ray: &Ray, t_max: Option<Float>) -> Option<ShapeIntersection> {
let [p0, p1, p2] = self.get_points();
let tri_isect = self.intersect_triangle(ray, t_max.unwrap_or(0.), p0, p1, p2)?;
let tri_isect = self.intersect_triangle(ray, t_max.unwrap_or(Float::INFINITY), p0, p1, p2)?;
let intr = self.interaction_from_intersection(tri_isect, ray.time, -ray.d);
Some(ShapeIntersection::new(intr, tri_isect.t))
}
fn intersect_p(&self, ray: &Ray, t_max: Option<Float>) -> bool {
let [p0, p1, p2] = self.get_points();
let tri_isect = self.intersect_triangle(ray, t_max.unwrap_or(0.), p0, p1, p2);
let tri_isect = self.intersect_triangle(ray, t_max.unwrap_or(Float::INFINITY), p0, p1, p2);
tri_isect.is_some()
}

View file

@ -338,7 +338,15 @@ impl SampledWavelengths {
}
}
pub fn terminate_secondary_inplace(&mut self) {}
pub fn terminate_secondary_inplace(&mut self) {
if self.secondary_terminated() {
return;
}
self.pdf[0] /= N_SPECTRUM_SAMPLES as Float;
for i in 1..N_SPECTRUM_SAMPLES {
self.pdf[i] = 0.0;
}
}
pub fn sample_uniform(u: Float, lambda_min: Float, lambda_max: Float) -> Self {
let mut lambda = [0.0; N_SPECTRUM_SAMPLES];

View file

@ -248,6 +248,14 @@ pub fn evaluate_pixel_sample<T: RayIntegratorTrait>(
eprintln!(" camera_sample.p_film: {:?}", camera_sample.p_film);
}
eprintln!(
"PATH p=({},{}) l={:?} lambda={:?} fw={}",
pixel.x(),
pixel.y(),
l,
lambda,
camera_sample.filter_weight,
);
film.add_sample(
pixel,
l,

View file

@ -71,7 +71,6 @@ impl WavefrontAggregate for CpuAggregate {
// Medium transition
if intr.material.is_null() {
let mut next = r;
intr.spawn_ray(r.ray.d);
next.ray = intr.spawn_ray(r.ray.d);
next_ray_q.push(next);
return;
@ -143,7 +142,7 @@ impl WavefrontAggregate for CpuAggregate {
(0..n_rays as usize).into_par_iter().for_each(|i| {
let work = unsafe { shadow_ray_q.get(i) };
let ray = Ray::new(work.ray_o, work.ray_d, Some(work.ray_time), Ptr::null());
let ray = Ray::new(work.ray.o, work.ray.d, Some(work.ray.time), Ptr::null());
if !self.aggregate.intersect_p(&ray, Some(work.t_max)) {
let pi = work.pixel_index as usize;
let ld = work.l_d / (work.r_u + work.r_l).average();

View file

@ -4,6 +4,7 @@ use crate::lights::sampler::create_light_sampler;
use crate::Arena;
use crate::ParameterDictionary;
use crate::PbrtProgress;
use log::debug;
use rayon::prelude::*;
use shared::core::bxdf::{FArgs, TransportMode};
use shared::core::camera::{Camera, CameraTrait};
@ -18,7 +19,7 @@ use shared::core::light::{Light, LightSampleContext, LightTrait};
use shared::core::material::{MaterialEvalContext, MaterialTrait};
use shared::core::primitive::Primitive;
use shared::core::sampler::{get_camera_sample, CameraSample, Sampler, SamplerTrait};
use shared::core::texture::{TextureEvalContext, UniversalTextureEvaluator};
use shared::core::texture::{BasicTextureEvaluator, TextureEvalContext, UniversalTextureEvaluator};
use shared::lights::sampler::{LightSampler, LightSamplerTrait};
use shared::spectra::{SampledSpectrum, SampledWavelengths};
use shared::utils::math::square;
@ -26,7 +27,7 @@ use shared::utils::sampling::power_heuristic;
use shared::utils::soa::{SoA, SoAAllocator, WorkQueue};
use shared::wavefront::workitems::*;
use shared::wavefront::{WavefrontAggregate, WavefrontPathIntegrator, WavefrontRenderer};
use shared::{gvec, Ptr};
use shared::{gvec, Ptr, SHADOW_EPSILON};
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
@ -74,6 +75,8 @@ 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() {
@ -81,6 +84,8 @@ where
}
}
eprintln!("infinite_lights len = {}", infinite_lights.len());
// for light in
let cpu_aggregate = CpuAggregate::new(*aggregate);
@ -396,7 +401,9 @@ impl CpuWavefrontRenderer {
return;
};
let tex_eval = UniversalTextureEvaluator;
let _is_cond = material.is_conductor();
// GetMaterialEvalContext
let ctx = MaterialEvalContext {
texture: TextureEvalContext {
p: w.p.into(),
@ -414,8 +421,19 @@ impl CpuWavefrontRenderer {
ns: w.ns,
dpdus: w.dpdus,
};
let lambda = w.lambda;
let mut bsdf = material.get_bsdf(&tex_eval, &ctx, &lambda);
let mut bsdf = if use_universal {
material.get_bsdf(&UniversalTextureEvaluator, &ctx, &lambda)
} else {
material.get_bsdf(&BasicTextureEvaluator, &ctx, &lambda)
};
if lambda.secondary_terminated() {
pixel_sample_state.lambda.set(pi, lambda);
}
if bsdf.flags().is_empty() {
return;
}
@ -446,6 +464,7 @@ impl CpuWavefrontRenderer {
let q = (1.0 - rr_beta).max(0.0_f32);
if rs.indirect.rr < q {
beta = SampledSpectrum::new(0.0);
debug!("Path terminated with RR");
} else {
beta /= 1.0 - q;
}
@ -479,63 +498,74 @@ impl CpuWavefrontRenderer {
// Direct lighting
let flags = bsdf.flags();
if flags.is_non_specular() {
let light_ctx = LightSampleContext {
let mut light_ctx = LightSampleContext {
pi: w.p,
n: w.n,
ns,
};
if let Some(sampled_light) =
if flags.is_reflective() && !flags.is_transmissive() {
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)));
}
let Some(sampled_light) =
light_sampler.sample_with_context(&light_ctx, rs.direct.uc)
{
if let Some(ls) =
else {
return;
};
let Some(ls) =
sampled_light
.light
.sample_li(&light_ctx, rs.direct.u, &lambda, true)
{
if !ls.l.is_black() && ls.pdf > 0.0 {
else {
return;
};
if ls.l.is_black() || ls.pdf <= 0.0 {
return;
}
let wi = ls.wi;
if let Some(f) = bsdf.f(wo, wi, TransportMode::Radiance) {
if !f.is_black() {
let Some(f) = bsdf.f(wo, wi, TransportMode::Radiance) else {
return;
};
if f.is_black() {
return;
}
let beta = w.beta * f * wi.abs_dot(ns.into());
let light_pdf = ls.pdf * sampled_light.p;
let bsdf_pdf =
if sampled_light.light.light_type().is_delta_light() {
let bsdf_pdf = if sampled_light.light.light_type().is_delta_light() {
0.0
} else {
bsdf.pdf(wo, wi, FArgs::default())
};
let r_u = w.r_u * bsdf_pdf;
let r_l = w.r_u * light_pdf;
let ld = beta * ls.l;
let l_d = beta * ls.l;
let ray_o = Ray::spawn_to_interaction(
let ray = Ray::spawn_to_interaction(
&w.p,
&w.n,
w.time,
&ls.p_light.pi(),
&ls.p_light.n(),
);
let t_max = (1.0 - 1e-4)
* (Point3f::from(ls.p_light.p()) - ray_o.o).norm()
/ wi.norm();
shadow_ray_queue.push(ShadowRayWorkItem {
ray_o: ray_o.o,
ray_d: ray_o.d,
ray_time: w.time,
t_max: 1.0 - 1e-4,
ray,
t_max: 1.0 - SHADOW_EPSILON,
lambda,
l_d: ld,
l_d,
r_u,
r_l,
pixel_index: w.pixel_index,
});
}
}
}
}
}
}
});
}
@ -563,19 +593,19 @@ impl CpuWavefrontRenderer {
let current = (depth % 2) as usize;
let ray_queue = &self.ray_queues[current];
let n = ray_queue.size();
let dimension = 6 + 7 * depth;
let pixel_sample_state = &self.pixel_sample_state;
let sampler_proto = &self.sampler;
(0..n as usize).into_par_iter().for_each(|i| {
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 mut sampler = sampler_proto.clone();
sampler.start_pixel_sample(p_pixel, sample_index as i32, Some(dimension));
self.pixel_sample_state.samples.set(
pixel_sample_state.samples.set(
pi,
RaySamples {
direct: DirectSamples {