Still broken
This commit is contained in:
parent
66032abf76
commit
3fda37fcd1
7 changed files with 114 additions and 65 deletions
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue