diff --git a/shared/src/core/texture.rs b/shared/src/core/texture.rs index e40befa..4aacb05 100644 --- a/shared/src/core/texture.rs +++ b/shared/src/core/texture.rs @@ -78,7 +78,7 @@ impl UVMapping { let dsdy = self.su * ctx.dudy; let dtdx = self.sv * ctx.dvdx; let dtdy = self.sv * ctx.dvdy; - let st = Point2f::new(self.su * ctx.uv[0] + self.du, self.sv * ctx.uv[1] * self.dv); + let st = Point2f::new(self.su * ctx.uv[0] + self.du, self.sv * ctx.uv[1] + self.dv); TexCoord2D { st, dsdx, @@ -107,7 +107,7 @@ impl SphericalMapping { let x2y2 = square(pt.x()) + square(pt.y()); let sqrtx2y2 = x2y2.sqrt(); let dsdp = Vector3f::new(-pt.y(), pt.x(), 0.) / (2. * PI * x2y2); - let dtdp = 1. / (PI * (x2y2 * square(pt.z()))) + let dtdp = 1. / (PI * (x2y2 + square(pt.z()))) * Vector3f::new( pt.x() * pt.z() / sqrtx2y2, pt.y() * pt.z() / sqrtx2y2, @@ -148,7 +148,7 @@ impl CylindricalMapping { let pt = self.texture_from_render.apply_to_point(ctx.p); let x2y2 = square(pt.x()) + square(pt.y()); let dsdp = Vector3f::new(-pt.y(), pt.x(), 0.) / (2. * PI * x2y2); - let dtdp = Vector3f::new(1., 0., 0.); + let dtdp = Vector3f::new(0., 0., 1.); let dpdx = self.texture_from_render.apply_to_vector(ctx.dpdx); let dpdy = self.texture_from_render.apply_to_vector(ctx.dpdy); let dsdx = dsdp.dot(dpdx); diff --git a/shared/src/lights/distant.rs b/shared/src/lights/distant.rs index 017cca0..11247da 100644 --- a/shared/src/lights/distant.rs +++ b/shared/src/lights/distant.rs @@ -5,8 +5,8 @@ use crate::core::interaction::{Interaction, InteractionBase, SimpleInteraction}; use crate::core::light::{LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait}; use crate::core::spectrum::SpectrumTrait; use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths}; -use crate::utils::Ptr; -use crate::{Float, PI}; +use crate::utils::math::square; +use crate::{Float, Ptr, PI}; use num_traits::Float as NumFloat; #[repr(C)] @@ -42,7 +42,7 @@ impl LightTrait for DistantLight { } fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum { - self.scale * self.lemit.sample(&lambda) * PI * self.scene_radius.sqrt() + self.scale * self.lemit.sample(&lambda) * PI * square(self.scene_radius) } fn sample_li( diff --git a/shared/src/materials/diffuse.rs b/shared/src/materials/diffuse.rs index c471aaa..e319c0d 100644 --- a/shared/src/materials/diffuse.rs +++ b/shared/src/materials/diffuse.rs @@ -1,4 +1,3 @@ -use crate::Float; use crate::bxdfs::{ CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF, HairBxDF, }; @@ -11,8 +10,9 @@ use crate::core::scattering::TrowbridgeReitzDistribution; use crate::core::spectrum::{Spectrum, SpectrumTrait}; use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator}; use crate::spectra::{SampledSpectrum, SampledWavelengths}; -use crate::Ptr; use crate::utils::math::clamp; +use crate::Float; +use crate::Ptr; #[repr(C)] #[derive(Clone, Copy, Debug)] @@ -29,7 +29,8 @@ impl MaterialTrait for DiffuseMaterial { ctx: &MaterialEvalContext, lambda: &SampledWavelengths, ) -> BSDF { - let r = tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda); + let spec = tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda); + let r = SampledSpectrum::clamp(&spec, 0., 1.); let bxdf = BxDF::Diffuse(DiffuseBxDF::new(r)); BSDF::new(ctx.ns, ctx.dpdus, bxdf) } diff --git a/shared/src/textures/image.rs b/shared/src/textures/image.rs index 2eb2038..8c5612c 100644 --- a/shared/src/textures/image.rs +++ b/shared/src/textures/image.rs @@ -61,8 +61,9 @@ impl SpectrumImageTexture { }; let mut rgb = rgb * self.scale; if self.invert { - rgb = (RGB::new(1.0, 1.0, 1.0) - rgb).clamp_zero(); + rgb = (RGB::new(1.0, 1.0, 1.0) - rgb); } + rgb = rgb.clamp_zero(); let cs = self .color_space .get() diff --git a/src/core/scene/scene.rs b/src/core/scene/scene.rs index d9a15b5..420edd7 100644 --- a/src/core/scene/scene.rs +++ b/src/core/scene/scene.rs @@ -15,7 +15,7 @@ use crate::lights::sampler::create_light_sampler; use crate::utils::parallel::{run_async, AsyncJob}; use crate::utils::parameters::{NamedTextures, ParameterDictionary, TextureParameterDictionary}; use crate::utils::resolve_filename; -use crate::wavefront::{CreateWavefront, CpuAggregate, CpuWavefrontRenderer}; +use crate::wavefront::{CpuAggregate, CpuWavefrontRenderer, CreateWavefront}; use crate::{Arena, ArenaUpload, FileLoc}; use anyhow::{anyhow, Result}; use parking_lot::Mutex; @@ -367,8 +367,8 @@ impl BasicScene { let mut named = NamedTextures { float_textures: Arc::new(float_textures.clone()), albedo_spectrum_textures: Arc::new(spectrum_textures.clone()), - illuminant_spectrum_textures: Arc::new(spectrum_textures.clone()), - unbounded_spectrum_textures: Arc::new(spectrum_textures.clone()), + illuminant_spectrum_textures: Arc::new(HashMap::new()), + unbounded_spectrum_textures: Arc::new(HashMap::new()), }; // Serial float textures may reference already-loaded textures @@ -389,18 +389,25 @@ impl BasicScene { for (name, entity) in state.serial_spectrum_textures.drain(..) { let render_from_texture = entity.render_from_object.start_transform; - let tex_dict = - TextureParameterDictionary::new(entity.base.parameters.into(), Some(&named)); - let tex = SpectrumTexture::create( - &entity.base.name, - render_from_texture, - tex_dict, - SpectrumType::Albedo, - entity.base.loc, - arena, - ) - .expect("Could not create spectrum texture"); - Arc::make_mut(&mut named.albedo_spectrum_textures).insert(name, Arc::new(tex)); + let make = |st: SpectrumType, named: &NamedTextures, loc| { + let tex_dict = TextureParameterDictionary::new( + entity.base.parameters.clone().into(), + Some(named), + ); + SpectrumTexture::create( + &entity.base.name, + render_from_texture, + tex_dict, + st, + loc, + arena, + ) + .expect("Could not create spectrum texture") + }; + + let albedo = make(SpectrumType::Albedo, &named, entity.base.loc.clone()); + let unbounded = make(SpectrumType::Unbounded, &named, entity.base.loc.clone()); + let illum = make(SpectrumType::Illuminant, &named, entity.base.loc); } named diff --git a/src/materials/conductor.rs b/src/materials/conductor.rs index e2231bc..905729b 100644 --- a/src/materials/conductor.rs +++ b/src/materials/conductor.rs @@ -62,7 +62,6 @@ impl CreateMaterial for ConductorMaterial { remap_roughness, ); - arena.alloc(material); Ok(Material::Conductor(material)) } } diff --git a/src/textures/image.rs b/src/textures/image.rs index a44affd..6448437 100644 --- a/src/textures/image.rs +++ b/src/textures/image.rs @@ -4,8 +4,8 @@ use crate::core::texture::{ SpectrumTextureTrait, }; use crate::utils::mipmap::{FilterFunction, MIPMap, MIPMapFilterOptions}; -use crate::utils::{FileLoc, TextureParameterDictionary, resolve_filename}; -use crate::{Arena}; +use crate::utils::{resolve_filename, FileLoc, TextureParameterDictionary}; +use crate::Arena; use anyhow::Result; use shared::core::color::RGB; use shared::core::color::{ColorEncoding, SRGBEncoding}; @@ -143,7 +143,7 @@ impl SpectrumTextureTrait for SpectrumImageTexture { return RGBUnboundedSpectrum::new(&cs, rgb).sample(lambda); } SpectrumType::Albedo => { - return RGBAlbedoSpectrum::new(&cs, rgb).sample(lambda); + return RGBAlbedoSpectrum::new(&cs, rgb.clamp(0., 1.)).sample(lambda); } _ => return RGBIlluminantSpectrum::new(&cs, rgb).sample(lambda), } diff --git a/src/utils/parameters.rs b/src/utils/parameters.rs index 4df4332..98e8d9d 100644 --- a/src/utils/parameters.rs +++ b/src/utils/parameters.rs @@ -907,6 +907,7 @@ impl TextureParameterDictionary { if let Some(tex) = map.get(tex_name) { return Some(Arc::clone(tex)); } + panic!( "[{:?}] Couldn't find spectrum texture named '{}'", p.loc, tex_name diff --git a/src/wavefront/integrator.rs b/src/wavefront/integrator.rs index 9116998..cc2f90b 100644 --- a/src/wavefront/integrator.rs +++ b/src/wavefront/integrator.rs @@ -18,6 +18,7 @@ use shared::core::interaction::InteractionTrait; use shared::core::light::{Light, LightSampleContext, LightTrait}; use shared::core::material::{MaterialEvalContext, MaterialTrait}; use shared::core::primitive::Primitive; +use shared::core::primitive::PrimitiveTrait; use shared::core::sampler::{get_camera_sample, CameraSample, Sampler, SamplerTrait}; use shared::core::texture::{BasicTextureEvaluator, TextureEvalContext, UniversalTextureEvaluator}; use shared::lights::sampler::{LightSampler, LightSamplerTrait}; @@ -55,7 +56,7 @@ where camera: Arc, sampler: Arc, aggregate: Arc, - lights: Vec>, + mut lights: Vec>, arena: &Arena, ) -> CpuWavefrontRenderer { let max_depth = parameters @@ -84,6 +85,11 @@ where let cpu_aggregate = CpuAggregate::new(*aggregate); + let bounds = aggregate.bounds(); + for light in &mut lights { + Arc::::make_mut(light).preprocess(&bounds); + } + CpuWavefrontRenderer(WavefrontPathIntegrator { aggregate: cpu_aggregate, camera: (*camera).clone(), @@ -419,6 +425,33 @@ impl CpuWavefrontRenderer { let lambda = w.lambda; + // DIAGNOSTIC: print image texture evaluate result for first few diffuse hits + { + use std::sync::atomic::{AtomicU32, Ordering}; + static DIAG_COUNT: AtomicU32 = AtomicU32::new(0); + if let shared::core::material::Material::Diffuse(dm) = material { + if !dm.reflectance.is_null() { + let cnt = DIAG_COUNT.fetch_add(1, Ordering::Relaxed); + if cnt < 5 { + let ref_tex = dm.reflectance.get().unwrap(); + let val = ref_tex.evaluate(&ctx.texture, &lambda); + eprintln!( + "DIAG[{}] diffuse reflectance uv={:?} result={:?}", + cnt, w.uv, val + ); + if let shared::core::texture::SpectrumTexture::Image(img_tex) = ref_tex + { + eprintln!( + " image_ptr_null={} scale={}", + img_tex.image.is_null(), + img_tex.scale + ); + } + } + } + } + } + let mut bsdf = if use_universal { material.get_bsdf(&UniversalTextureEvaluator, &ctx, &lambda) } else {