Compare commits
5 commits
1b8ca71b0e
...
7c35f9b180
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c35f9b180 | |||
| 2e9526ce18 | |||
| 87afe4168d | |||
| 86151918e2 | |||
| 661fe73867 |
42 changed files with 905 additions and 552 deletions
14
Cargo.toml
14
Cargo.toml
|
|
@ -76,3 +76,17 @@ wrong_self_convention = "allow"
|
|||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
||||
# Renders run through `cargo test`, whose profile inherits from `dev`. Cargo's
|
||||
# default there is opt-level = 0, which costs ~15x on ray throughput.
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
|
||||
# Applies to dependencies only -- Cargo excludes workspace members from "*".
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 3
|
||||
|
||||
# `shared` is a workspace member, so it needs naming explicitly. It holds the
|
||||
# geometry/BSDF/sampling math, so it wants full optimisation.
|
||||
[profile.dev.package.shared]
|
||||
opt-level = 3
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.100"
|
||||
bitflags = "2.10.0"
|
||||
half = "2.7.1"
|
||||
half = { version = "2.7.1", default-features = false }
|
||||
bytemuck = { version = "1.24.0", features = ["derive"] }
|
||||
enum_dispatch = "0.3.13"
|
||||
ash = { version = "0.38", optional = true }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::core::bsdf::BSDFSample;
|
||||
use crate::core::bxdf::{BxDFFlags, BxDFReflTransFlags, BxDFTrait, FArgs, TransportMode};
|
||||
use crate::core::geometry::{
|
||||
abs_cos_theta, cos_theta, same_hemisphere, Normal3f, Point2f, Vector3f, VectorLike,
|
||||
Normal3f, Point2f, Vector3f, VectorLike, abs_cos_theta, cos_theta, same_hemisphere,
|
||||
};
|
||||
use crate::core::scattering::{
|
||||
fr_complex_from_spectrum, fr_dielectric, reflect, refract, TrowbridgeReitzDistribution,
|
||||
TrowbridgeReitzDistribution, fr_complex_from_spectrum, fr_dielectric, reflect, refract,
|
||||
};
|
||||
use crate::spectra::SampledSpectrum;
|
||||
use crate::utils::math::square;
|
||||
|
|
@ -362,7 +362,6 @@ impl BxDFTrait for ThinDielectricBxDF {
|
|||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn regularize(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn regularize(&mut self) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,4 +73,118 @@ impl BxDFTrait for DiffuseBxDF {
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DiffuseTransmissionBxDF;
|
||||
pub struct DiffuseTransmissionBxDF {
|
||||
pub r: SampledSpectrum,
|
||||
pub t: SampledSpectrum,
|
||||
}
|
||||
|
||||
impl DiffuseTransmissionBxDF {
|
||||
pub fn new(r: SampledSpectrum, t: SampledSpectrum) -> Self {
|
||||
Self { r, t }
|
||||
}
|
||||
}
|
||||
|
||||
impl BxDFTrait for DiffuseTransmissionBxDF {
|
||||
fn flags(&self) -> BxDFFlags {
|
||||
let r_flags = if !self.r.is_black() {
|
||||
BxDFFlags::DIFFUSE_REFLECTION
|
||||
} else {
|
||||
BxDFFlags::UNSET
|
||||
};
|
||||
let t_flags = if !self.t.is_black() {
|
||||
BxDFFlags::DIFFUSE_TRANSMISSION
|
||||
} else {
|
||||
BxDFFlags::UNSET
|
||||
};
|
||||
|
||||
r_flags | t_flags
|
||||
}
|
||||
|
||||
fn f(&self, wo: Vector3f, wi: Vector3f, _mode: TransportMode) -> SampledSpectrum {
|
||||
if !same_hemisphere(wo, wi) {
|
||||
return self.r * INV_PI;
|
||||
}
|
||||
self.t * INV_PI
|
||||
}
|
||||
|
||||
fn sample_f(&self, wo: Vector3f, uc: Float, u: Point2f, f_args: FArgs) -> Option<BSDFSample> {
|
||||
let reflection_flags =
|
||||
BxDFReflTransFlags::from_bits_truncate(BxDFReflTransFlags::REFLECTION.bits());
|
||||
let transmission_flags =
|
||||
BxDFReflTransFlags::from_bits_truncate(BxDFReflTransFlags::TRANSMISSION.bits());
|
||||
|
||||
let pr = if !f_args.sample_flags.contains(reflection_flags) {
|
||||
0.
|
||||
} else {
|
||||
self.r.max_component_value()
|
||||
};
|
||||
|
||||
let pt = if !f_args.sample_flags.contains(transmission_flags) {
|
||||
0.
|
||||
} else {
|
||||
self.t.max_component_value()
|
||||
};
|
||||
|
||||
if (pr == 0.) && (pt == 0.) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut wi = sample_cosine_hemisphere(u);
|
||||
if wo.z() < 0. {
|
||||
wi[2] *= -1.;
|
||||
}
|
||||
let pdf = cosine_hemisphere_pdf(abs_cos_theta(wi)) * pr / (pr + pt);
|
||||
|
||||
let flags = if uc < pr / (pr + pt) {
|
||||
BxDFFlags::DIFFUSE_REFLECTION
|
||||
} else {
|
||||
BxDFFlags::DIFFUSE_TRANSMISSION
|
||||
};
|
||||
|
||||
let bsdf = BSDFSample {
|
||||
f: self.r * INV_PI,
|
||||
wi,
|
||||
pdf,
|
||||
flags,
|
||||
..Default::default()
|
||||
};
|
||||
Some(bsdf)
|
||||
}
|
||||
|
||||
fn pdf(&self, wo: Vector3f, wi: Vector3f, f_args: FArgs) -> Float {
|
||||
let reflection_flags =
|
||||
BxDFReflTransFlags::from_bits_truncate(BxDFReflTransFlags::REFLECTION.bits());
|
||||
let transmission_flags =
|
||||
BxDFReflTransFlags::from_bits_truncate(BxDFReflTransFlags::TRANSMISSION.bits());
|
||||
|
||||
let pr = if !f_args.sample_flags.contains(reflection_flags) {
|
||||
0.
|
||||
} else {
|
||||
self.r.max_component_value()
|
||||
};
|
||||
|
||||
let pt = if !f_args.sample_flags.contains(transmission_flags) {
|
||||
0.
|
||||
} else {
|
||||
self.t.max_component_value()
|
||||
};
|
||||
|
||||
if (pr == 0.) && (pt == 0.) {
|
||||
return 0.;
|
||||
}
|
||||
|
||||
let cos_factor = cosine_hemisphere_pdf(abs_cos_theta(wi));
|
||||
|
||||
if same_hemisphere(wo, wi) {
|
||||
return pr / (pr + pt) * cos_factor;
|
||||
} else {
|
||||
return pt / (pr + pt) * cos_factor;
|
||||
}
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn regularize(&mut self) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ pub trait BxDFTrait: Any {
|
|||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum BxDF {
|
||||
Diffuse(DiffuseBxDF),
|
||||
DiffuseTransmission(DiffuseTransmissionBxDF),
|
||||
Dielectric(DielectricBxDF),
|
||||
ThinDielectric(ThinDielectricBxDF),
|
||||
Conductor(ConductorBxDF),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use core::fmt;
|
|||
use core::ops::{
|
||||
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
||||
};
|
||||
use anyhow::{Result, bail};
|
||||
use crate::utils::error::{Error, Result};
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use num_traits::Float as NumFloat;
|
||||
|
||||
|
|
@ -686,7 +686,7 @@ impl ColorEncoding {
|
|||
match name {
|
||||
"sRGB" | "srgb" => Ok(ColorEncoding::SRGB(SRGBEncoding)),
|
||||
"linear" => Ok(ColorEncoding::Linear(LinearEncoding)),
|
||||
_ => bail!("Unknown color encoding: {}", name),
|
||||
_ => Err(Error::UnknownColorEncoding),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::core::color::{ColorEncoding, ColorEncodingTrait, LINEAR};
|
|||
use crate::core::geometry::{Bounds2f, Point2f, Point2fi, Point2i};
|
||||
use crate::utils::math::{f16_to_f32_software, lerp, square};
|
||||
use crate::{gvec_with_capacity, Float, GVec, Ptr};
|
||||
use anyhow::{bail, Result};
|
||||
use crate::utils::error::{Error, Result};
|
||||
use core::hash;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use num_traits::Float as NumFloat;
|
||||
|
|
@ -23,7 +23,7 @@ impl WrapMode {
|
|||
"black" => Ok(WrapMode::Black),
|
||||
"repeat" => Ok(WrapMode::Repeat),
|
||||
"octahedralsphere" => Ok(WrapMode::OctahedralSphere),
|
||||
_ => bail!("{:?}: wrap mode unknown", name),
|
||||
_ => Err(Error::UnknownWrapMode),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -503,7 +503,7 @@ impl FilterFunction {
|
|||
"trilinear" => Ok(FilterFunction::Trilinear),
|
||||
"bilinear" => Ok(FilterFunction::Bilinear),
|
||||
"point" => Ok(FilterFunction::Point),
|
||||
_ => bail!("Filter function unknown"),
|
||||
_ => Err(Error::UnknownFilterFunction),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::materials::*;
|
|||
use core::ops::Deref;
|
||||
use enum_dispatch::enum_dispatch;
|
||||
|
||||
use crate::Float;
|
||||
use crate::bxdfs::{
|
||||
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF,
|
||||
};
|
||||
|
|
@ -13,15 +14,12 @@ use crate::core::image::{Image, WrapMode, WrapMode2D};
|
|||
use crate::core::interaction::{Interaction, InteractionTrait, ShadingGeom, SurfaceInteraction};
|
||||
use crate::core::scattering::TrowbridgeReitzDistribution;
|
||||
use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
||||
use crate::core::texture::{
|
||||
FloatTexture, SpectrumTexture, TextureEvalContext, TextureEvaluator,
|
||||
};
|
||||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvalContext, TextureEvaluator};
|
||||
use crate::materials::*;
|
||||
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||
use crate::utils::Ptr;
|
||||
use crate::utils::hash::hash_float;
|
||||
use crate::utils::math::clamp;
|
||||
use crate::utils::Ptr;
|
||||
use crate::Float;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
|
|
@ -162,7 +160,7 @@ pub trait MaterialTrait {
|
|||
&self,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF;
|
||||
|
||||
fn get_bssrdf<T: TextureEvaluator>(
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@ use crate::core::filter::FilterTrait;
|
|||
use crate::core::geometry::{Bounds2f, Point2f, Point2i, Vector2f};
|
||||
use crate::core::pbrt::{Float, ONE_MINUS_EPSILON, PI, PI_OVER_2, PI_OVER_4};
|
||||
use crate::utils::math::{
|
||||
clamp, encode_morton_2, inverse_radical_inverse, lerp, log2_int,
|
||||
BinaryPermuteScrambler, DigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler,
|
||||
PRIME_TABLE_SIZE, Scrambler, clamp, encode_morton_2, inverse_radical_inverse, lerp, log2_int,
|
||||
owen_scrambled_radical_inverse, permutation_element, radical_inverse, round_up_pow2,
|
||||
scrambled_radical_inverse, sobol_interval_to_index, sobol_sample, BinaryPermuteScrambler,
|
||||
DigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler, Scrambler, PRIME_TABLE_SIZE,
|
||||
scrambled_radical_inverse, sobol_interval_to_index, sobol_sample,
|
||||
};
|
||||
use crate::utils::rng::Rng;
|
||||
use crate::utils::sobol::N_SOBOL_DIMENSIONS;
|
||||
use crate::utils::{hash::*, sobol};
|
||||
use crate::{gvec, GVec, Ptr};
|
||||
use crate::{GVec, Ptr, gvec};
|
||||
use enum_dispatch::enum_dispatch;
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -530,6 +530,18 @@ pub struct ZSobolSampler {
|
|||
dim: u32,
|
||||
}
|
||||
|
||||
/// pbrt writes `0x55555555u * dimension` -- a 32-bit unsigned product that wraps.
|
||||
#[inline]
|
||||
fn scramble_seed(dim: u32) -> u64 {
|
||||
0x5555_5555u32.wrapping_mul(dim) as u64
|
||||
}
|
||||
|
||||
/// pbrt's `Hash(dimension, seed)`: both are `int`, so exactly 8 packed bytes.
|
||||
#[inline]
|
||||
fn dim_seed_hash(dim: u32, seed: u64) -> u64 {
|
||||
hash_buffer(&[dim, seed as u32], 0)
|
||||
}
|
||||
|
||||
impl ZSobolSampler {
|
||||
pub fn new(
|
||||
samples_per_pixel: i32,
|
||||
|
|
@ -537,10 +549,12 @@ impl ZSobolSampler {
|
|||
randomize: RandomizeStrategy,
|
||||
seed: Option<u64>,
|
||||
) -> Self {
|
||||
let log2_samples_per_pixel = log2_int(samples_per_pixel as Float) as u32;
|
||||
// pbrt calls the integer Log2Int overload; the float one disagrees for
|
||||
// non-power-of-two sample counts.
|
||||
let log2_samples_per_pixel = (samples_per_pixel.max(1) as u32).ilog2();
|
||||
let res = round_up_pow2(full_resolution.x().max(full_resolution.y()));
|
||||
let log4_samples_per_pixel = log2_samples_per_pixel.div_ceil(2);
|
||||
let n_base4_digits = log2_int(res as Float) as u32 + log4_samples_per_pixel as u32;
|
||||
let n_base4_digits = (res.max(1) as u32).ilog2() + log4_samples_per_pixel;
|
||||
Self {
|
||||
randomize,
|
||||
seed: seed.unwrap_or(0),
|
||||
|
|
@ -590,7 +604,7 @@ impl ZSobolSampler {
|
|||
|
||||
let higher_digits = self.morton_index >> (digit_shift + 2);
|
||||
|
||||
let mix_input = higher_digits ^ (0x55555555 * self.dim as u64);
|
||||
let mix_input = higher_digits ^ scramble_seed(self.dim);
|
||||
let p = (mix_bits(mix_input) >> 24) % 24;
|
||||
|
||||
digit = PERMUTATIONS[p as usize][digit as usize] as u64;
|
||||
|
|
@ -599,8 +613,9 @@ impl ZSobolSampler {
|
|||
}
|
||||
|
||||
if pow2_samples {
|
||||
let lsb = self.morton_index & 1;
|
||||
sample_index |= lsb;
|
||||
let digit = self.morton_index & 1;
|
||||
sample_index |=
|
||||
digit ^ (mix_bits((self.morton_index >> 1) ^ scramble_seed(self.dim)) & 1);
|
||||
}
|
||||
|
||||
sample_index
|
||||
|
|
@ -609,8 +624,9 @@ impl ZSobolSampler {
|
|||
|
||||
impl SamplerTrait for ZSobolSampler {
|
||||
fn samples_per_pixel(&self) -> i32 {
|
||||
todo!()
|
||||
1 << self.log2_samples_per_pixel
|
||||
}
|
||||
|
||||
fn start_pixel_sample(&mut self, p: Point2i, sample_index: i32, dim: Option<u32>) {
|
||||
self.dim = dim.unwrap_or(0);
|
||||
self.morton_index = (encode_morton_2(p.x() as u32, p.y() as u32)
|
||||
|
|
@ -620,31 +636,25 @@ impl SamplerTrait for ZSobolSampler {
|
|||
|
||||
fn get1d(&mut self) -> Float {
|
||||
let sample_index = self.get_sample_index();
|
||||
let hash_input = [self.dim as u64, self.seed];
|
||||
let hash = hash_buffer(&hash_input, 0) as u32;
|
||||
self.dim += 1;
|
||||
if self.randomize == RandomizeStrategy::None {
|
||||
return sobol_sample(sample_index, self.dim, NoRandomizer);
|
||||
}
|
||||
let hash = dim_seed_hash(self.dim, self.seed) as u32;
|
||||
// Always Sobol dimension 0 -- decorrelation comes from the hash.
|
||||
match self.randomize {
|
||||
RandomizeStrategy::None => sobol_sample(sample_index, 0, NoRandomizer),
|
||||
RandomizeStrategy::PermuteDigits => {
|
||||
sobol_sample(sample_index, self.dim, BinaryPermuteScrambler::new(hash))
|
||||
sobol_sample(sample_index, 0, BinaryPermuteScrambler::new(hash))
|
||||
}
|
||||
RandomizeStrategy::FastOwen => {
|
||||
sobol_sample(sample_index, self.dim, FastOwenScrambler::new(hash))
|
||||
sobol_sample(sample_index, 0, FastOwenScrambler::new(hash))
|
||||
}
|
||||
RandomizeStrategy::Owen => {
|
||||
sobol_sample(sample_index, self.dim, OwenScrambler::new(hash))
|
||||
}
|
||||
RandomizeStrategy::None => unreachable!(),
|
||||
RandomizeStrategy::Owen => sobol_sample(sample_index, 0, OwenScrambler::new(hash)),
|
||||
}
|
||||
}
|
||||
|
||||
fn get2d(&mut self) -> Point2f {
|
||||
let sample_index = self.get_sample_index();
|
||||
self.dim += 2;
|
||||
let hash_input = [self.dim as u64, self.seed];
|
||||
let hash = hash_buffer(&hash_input, 0);
|
||||
let hash = dim_seed_hash(self.dim, self.seed);
|
||||
let sample_hash = [hash as u32, (hash >> 32) as u32];
|
||||
if self.randomize == RandomizeStrategy::None {
|
||||
return Point2f::new(
|
||||
|
|
@ -675,16 +685,92 @@ impl SamplerTrait for ZSobolSampler {
|
|||
}
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct MLTSampler;
|
||||
struct PrimarySample {
|
||||
value: Float,
|
||||
last_mod_iteration: i64,
|
||||
value_backup: Float,
|
||||
mod_backup: i64,
|
||||
}
|
||||
|
||||
impl PrimarySample {
|
||||
fn backup(&mut self) {
|
||||
self.value_backup = self.value;
|
||||
self.mod_backup = self.last_mod_iteration;
|
||||
}
|
||||
|
||||
fn restore(&mut self) {
|
||||
self.value = self.value_backup;
|
||||
self.last_mod_iteration = self.mod_backup;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MLTSampler {
|
||||
mutations_per_pixel: i32,
|
||||
rng: Rng,
|
||||
sigma: Float,
|
||||
large_step_prob: Float,
|
||||
stream_count: i32,
|
||||
x: GVec<PrimarySample>,
|
||||
current_iter: i64,
|
||||
large_step: bool,
|
||||
last_large_step_iter: i64,
|
||||
stream_ind: i32,
|
||||
sample_ind: i32,
|
||||
seed: u64,
|
||||
}
|
||||
|
||||
impl MLTSampler {
|
||||
pub fn new(
|
||||
mutations_per_pixel: i32,
|
||||
rng_seq_ind: i32,
|
||||
sigma: Float,
|
||||
large_step_prob: Float,
|
||||
stream_count: i32,
|
||||
seed: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
mutations_per_pixel,
|
||||
rng: Rng::new(mix_bits(rng_seq_ind.try_into().unwrap()) ^ mix_bits(seed)),
|
||||
seed,
|
||||
sigma,
|
||||
large_step_prob,
|
||||
stream_count,
|
||||
x: gvec(),
|
||||
current_iter: 0,
|
||||
large_step: true,
|
||||
last_large_step_iter: 0,
|
||||
stream_ind: 0,
|
||||
sample_ind: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_next_index(&mut self) -> i32 {
|
||||
self.sample_ind += 1;
|
||||
self.stream_ind + self.stream_count * self.sample_ind
|
||||
}
|
||||
}
|
||||
|
||||
impl SamplerTrait for MLTSampler {
|
||||
fn samples_per_pixel(&self) -> i32 {
|
||||
todo!()
|
||||
self.mutations_per_pixel
|
||||
}
|
||||
fn start_pixel_sample(&mut self, _p: Point2i, _sample_index: i32, _dim: Option<u32>) {
|
||||
todo!()
|
||||
|
||||
fn start_pixel_sample(&mut self, p: Point2i, sample_index: i32, dim: Option<u32>) {
|
||||
let hash_input = [p.x() as u64, p.y() as u64, self.seed];
|
||||
let sequence_index = hash_buffer(&hash_input, 0);
|
||||
self.rng.set_sequence(sequence_index);
|
||||
self.rng
|
||||
.advance((sample_index as u64) * 65536 + (dim.unwrap_or(0) as u64));
|
||||
}
|
||||
|
||||
fn get1d(&mut self) -> Float {
|
||||
todo!()
|
||||
#[cfg(not(any(feature = "cuda", feature = "vulkan")))]
|
||||
{
|
||||
return 0.;
|
||||
}
|
||||
|
||||
let ind = self.get_next_index();
|
||||
}
|
||||
fn get2d(&mut self) -> Point2f {
|
||||
todo!()
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ impl MaterialTrait for CoatedDiffuseMaterial {
|
|||
&self,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
let r = SampledSpectrum::clamp(
|
||||
&tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda),
|
||||
|
|
@ -220,7 +220,7 @@ impl MaterialTrait for CoatedConductorMaterial {
|
|||
&self,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
let mut iurough = tex_eval.evaluate_float(&self.interface_uroughness, ctx);
|
||||
let mut ivrough = tex_eval.evaluate_float(&self.interface_vroughness, ctx);
|
||||
|
|
@ -234,7 +234,6 @@ impl MaterialTrait for CoatedConductorMaterial {
|
|||
|
||||
let mut ieta = self.interface_eta.evaluate(lambda[0]);
|
||||
if self.interface_eta.is_constant() {
|
||||
let mut lambda = *lambda;
|
||||
lambda.terminate_secondary_inplace();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ impl MaterialTrait for HairMaterial {
|
|||
&self,
|
||||
_tex_eval: &T,
|
||||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
_lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
todo!()
|
||||
}
|
||||
|
|
@ -103,7 +103,7 @@ impl MaterialTrait for MeasuredMaterial {
|
|||
&self,
|
||||
_tex_eval: &T,
|
||||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
_lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
// MeasuredBxDF::new(&self.brdf, lambda)
|
||||
todo!()
|
||||
|
|
@ -157,7 +157,7 @@ impl MaterialTrait for SubsurfaceMaterial {
|
|||
&self,
|
||||
_tex_eval: &T,
|
||||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
_lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ 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::utils::math::clamp;
|
||||
use crate::utils::Ptr;
|
||||
use crate::utils::math::clamp;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
@ -55,7 +55,7 @@ impl MaterialTrait for ConductorMaterial {
|
|||
&self,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
let mut u_rough = tex_eval.evaluate_float(&self.u_roughness, ctx);
|
||||
let mut v_rough = tex_eval.evaluate_float(&self.v_roughness, ctx);
|
||||
|
|
@ -88,7 +88,7 @@ impl MaterialTrait for ConductorMaterial {
|
|||
|
||||
fn get_bssrdf<T>(
|
||||
&self,
|
||||
tex_eval: &T,
|
||||
_tex_eval: &T,
|
||||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
) -> Option<BSSRDF> {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::Ptr;
|
||||
use crate::bxdfs::{
|
||||
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF, HairBxDF,
|
||||
ThinDielectricBxDF,
|
||||
};
|
||||
use crate::core::bsdf::BSDF;
|
||||
use crate::core::bssrdf::BSSRDF;
|
||||
|
|
@ -11,7 +13,6 @@ use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
|||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
||||
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||
use crate::utils::math::clamp;
|
||||
use crate::Ptr;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
@ -29,11 +30,11 @@ impl MaterialTrait for DielectricMaterial {
|
|||
&self,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
let mut sampled_eta = self.eta.evaluate(lambda[0]);
|
||||
if !self.eta.is_constant() {
|
||||
lambda.terminate_secondary();
|
||||
lambda.terminate_secondary_inplace();
|
||||
}
|
||||
|
||||
if sampled_eta == 0.0 {
|
||||
|
|
@ -92,18 +93,29 @@ impl MaterialTrait for ThinDielectricMaterial {
|
|||
fn get_bsdf<T: TextureEvaluator>(
|
||||
&self,
|
||||
_tex_eval: &T,
|
||||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
todo!()
|
||||
let mut sampled_eta = self.eta.evaluate(lambda[0]);
|
||||
if !self.eta.is_constant() {
|
||||
lambda.terminate_secondary_inplace();
|
||||
}
|
||||
|
||||
if sampled_eta == 0. {
|
||||
sampled_eta = 1.;
|
||||
}
|
||||
|
||||
let bxdf = BxDF::ThinDielectric(ThinDielectricBxDF::new(sampled_eta));
|
||||
BSDF::new(ctx.ns, ctx.dpdus, bxdf)
|
||||
}
|
||||
|
||||
fn get_bssrdf<T>(
|
||||
&self,
|
||||
_tex_eval: &T,
|
||||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
) -> Option<BSSRDF> {
|
||||
todo!()
|
||||
None
|
||||
}
|
||||
|
||||
fn can_evaluate_textures(&self, _tex_eval: &dyn TextureEvaluator) -> bool {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use crate::Float;
|
||||
use crate::Ptr;
|
||||
use crate::bxdfs::{
|
||||
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF, HairBxDF,
|
||||
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF,
|
||||
DiffuseTransmissionBxDF, HairBxDF,
|
||||
};
|
||||
use crate::core::bsdf::BSDF;
|
||||
use crate::core::bssrdf::BSSRDF;
|
||||
|
|
@ -11,8 +14,6 @@ use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
|||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
||||
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||
use crate::utils::math::clamp;
|
||||
use crate::Float;
|
||||
use crate::Ptr;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
@ -27,7 +28,7 @@ impl MaterialTrait for DiffuseMaterial {
|
|||
&self,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
let spec = tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda);
|
||||
let r = SampledSpectrum::clamp(&spec, 0., 1.);
|
||||
|
|
@ -41,7 +42,7 @@ impl MaterialTrait for DiffuseMaterial {
|
|||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
) -> Option<BSSRDF> {
|
||||
todo!()
|
||||
None
|
||||
}
|
||||
|
||||
fn can_evaluate_textures(&self, tex_eval: &dyn TextureEvaluator) -> bool {
|
||||
|
|
@ -64,21 +65,33 @@ impl MaterialTrait for DiffuseMaterial {
|
|||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct DiffuseTransmissionMaterial {
|
||||
pub image: Ptr<Image>,
|
||||
pub normal_map: Ptr<Image>,
|
||||
pub displacement: Ptr<FloatTexture>,
|
||||
pub reflectance: Ptr<FloatTexture>,
|
||||
pub transmittance: Ptr<FloatTexture>,
|
||||
pub reflectance: Ptr<SpectrumTexture>,
|
||||
pub transmittance: Ptr<SpectrumTexture>,
|
||||
pub scale: Float,
|
||||
}
|
||||
|
||||
impl MaterialTrait for DiffuseTransmissionMaterial {
|
||||
fn get_bsdf<T: TextureEvaluator>(
|
||||
&self,
|
||||
_tex_eval: &T,
|
||||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
todo!()
|
||||
let r = SampledSpectrum::clamp(
|
||||
&(self.scale * tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda)),
|
||||
0.,
|
||||
1.,
|
||||
);
|
||||
let t = SampledSpectrum::clamp(
|
||||
&(self.scale * tex_eval.evaluate_spectrum(&self.transmittance, ctx, lambda)),
|
||||
0.,
|
||||
1.,
|
||||
);
|
||||
|
||||
let bxdf = BxDF::DiffuseTransmission(DiffuseTransmissionBxDF::new(r, t));
|
||||
BSDF::new(ctx.ns, ctx.dpdus, bxdf)
|
||||
}
|
||||
fn get_bssrdf<T>(
|
||||
&self,
|
||||
|
|
@ -86,15 +99,15 @@ impl MaterialTrait for DiffuseTransmissionMaterial {
|
|||
_ctx: &MaterialEvalContext,
|
||||
_lambda: &SampledWavelengths,
|
||||
) -> Option<BSSRDF> {
|
||||
todo!()
|
||||
None
|
||||
}
|
||||
|
||||
fn can_evaluate_textures(&self, tex_eval: &dyn TextureEvaluator) -> bool {
|
||||
tex_eval.can_evaluate(&[self.reflectance, self.transmittance], &[])
|
||||
tex_eval.can_evaluate(&[], &[self.reflectance, self.transmittance])
|
||||
}
|
||||
|
||||
fn get_normal_map(&self) -> Option<&Image> {
|
||||
self.image.get()
|
||||
self.normal_map.get()
|
||||
}
|
||||
|
||||
fn get_displacement(&self) -> Ptr<FloatTexture> {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ impl MaterialTrait for MixMaterial {
|
|||
&self,
|
||||
tex_eval: &T,
|
||||
ctx: &MaterialEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
if let Some(mat) = self.choose_material(tex_eval, ctx) {
|
||||
mat.get_bsdf(tex_eval, ctx, lambda)
|
||||
|
|
|
|||
|
|
@ -7,14 +7,17 @@ use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
|||
use crate::utils::{Ptr, math::square};
|
||||
use num_traits::Float as NumFloat;
|
||||
|
||||
fn checkerboard(
|
||||
ctx: &TextureEvalContext,
|
||||
map2d: Ptr<TextureMapping2D>,
|
||||
map3d: Ptr<TextureMapping3D>,
|
||||
) -> Float {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum CheckerMap {
|
||||
D2(TextureMapping2D),
|
||||
D3(TextureMapping3D),
|
||||
}
|
||||
|
||||
fn checkerboard(ctx: &TextureEvalContext, checker_map: CheckerMap) -> Float {
|
||||
let d = |x: Float| -> Float {
|
||||
let y = x / 2. - (x / 2.).floor() - 0.5;
|
||||
return x / 2. + y * (1. - 2. * y.abs());
|
||||
x / 2. + y * (1. - 2. * y.abs())
|
||||
};
|
||||
|
||||
let bf = |x: Float, r: Float| -> Float {
|
||||
|
|
@ -24,49 +27,53 @@ fn checkerboard(
|
|||
(d(x + r) - 2. * d(x) + d(x - r)) / square(r)
|
||||
};
|
||||
|
||||
if !map2d.is_null() {
|
||||
assert!(map3d.is_null());
|
||||
let c = map2d.map(&ctx);
|
||||
match checker_map {
|
||||
CheckerMap::D2(map) => {
|
||||
let c = map.map(ctx);
|
||||
let ds = 1.5 * c.dsdx.abs().max(c.dsdy.abs());
|
||||
let dt = 1.5 * c.dtdx.abs().max(c.dtdy.abs());
|
||||
// Integrate product of 2D checkerboard function and triangle filter
|
||||
0.5 - bf(c.st[0], ds) * bf(c.st[1], dt) / 2.
|
||||
} else {
|
||||
assert!(!map3d.is_null());
|
||||
let c = map3d.map(&ctx);
|
||||
}
|
||||
CheckerMap::D3(map) => {
|
||||
let c = map.map(ctx);
|
||||
let dx = 1.5 * c.dpdx.x().abs().max(c.dpdy.x().abs());
|
||||
let dy = 1.5 * c.dpdx.y().abs().max(c.dpdy.y().abs());
|
||||
let dz = 1.5 * c.dpdx.z().abs().max(c.dpdy.z().abs());
|
||||
0.5 - bf(c.p.x(), dx) * bf(c.p.y(), dy) * bf(c.p.z(), dz)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct FloatCheckerboardTexture {
|
||||
pub map2d: Ptr<TextureMapping2D>,
|
||||
pub map3d: Ptr<TextureMapping3D>,
|
||||
pub map: CheckerMap,
|
||||
pub tex: [Ptr<FloatTexture>; 2],
|
||||
}
|
||||
|
||||
impl FloatCheckerboardTexture {
|
||||
pub fn new(map: CheckerMap, tex: [Ptr<FloatTexture>; 2]) -> Self {
|
||||
Self { map, tex }
|
||||
}
|
||||
|
||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let w = checkerboard(&ctx, self.map2d, self.map3d);
|
||||
let w = checkerboard(ctx, self.map);
|
||||
|
||||
let mut t0 = 0.0;
|
||||
let mut t1 = 0.0;
|
||||
|
||||
if w != 1.0 {
|
||||
if let Some(tex) = self.tex[0].get() {
|
||||
if w != 1.0
|
||||
&& let Some(tex) = self.tex[0].get()
|
||||
{
|
||||
t0 = tex.evaluate(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if w != 0.0 {
|
||||
if let Some(tex) = self.tex[1].get() {
|
||||
if w != 0.0
|
||||
&& let Some(tex) = self.tex[1].get()
|
||||
{
|
||||
t1 = tex.evaluate(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
(1.0 - w) * t0 + w * t1
|
||||
}
|
||||
|
|
@ -75,31 +82,34 @@ impl FloatCheckerboardTexture {
|
|||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct SpectrumCheckerboardTexture {
|
||||
pub map2d: Ptr<TextureMapping2D>,
|
||||
pub map3d: Ptr<TextureMapping3D>,
|
||||
pub map: CheckerMap,
|
||||
pub tex: [Ptr<SpectrumTexture>; 2],
|
||||
}
|
||||
|
||||
impl SpectrumCheckerboardTexture {
|
||||
pub fn new(map: CheckerMap, tex: [Ptr<SpectrumTexture>; 2]) -> Self {
|
||||
Self { map, tex }
|
||||
}
|
||||
|
||||
pub fn evaluate(
|
||||
&self,
|
||||
ctx: &TextureEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
) -> SampledSpectrum {
|
||||
let w = checkerboard(ctx, self.map2d, self.map3d);
|
||||
let w = checkerboard(ctx, self.map);
|
||||
let mut t0 = SampledSpectrum::new(0.);
|
||||
let mut t1 = SampledSpectrum::new(0.);
|
||||
if w != 1.0 {
|
||||
if let Some(tex) = self.tex[0].get() {
|
||||
if w != 1.0
|
||||
&& let Some(tex) = self.tex[0].get()
|
||||
{
|
||||
t0 = tex.evaluate(ctx, lambda);
|
||||
}
|
||||
}
|
||||
|
||||
if w != 0.0 {
|
||||
if let Some(tex) = self.tex[1].get() {
|
||||
if w != 0.0
|
||||
&& let Some(tex) = self.tex[1].get()
|
||||
{
|
||||
t1 = tex.evaluate(ctx, lambda);
|
||||
}
|
||||
}
|
||||
|
||||
t0 * (1.0 - w) + t1 * w
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use crate::Float;
|
||||
use crate::core::geometry::{Point2f, VectorLike};
|
||||
use crate::core::texture::{
|
||||
FloatTexture, SpectrumTexture, TextureEvalContext, TextureMapping2D,
|
||||
};
|
||||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvalContext, TextureMapping2D};
|
||||
use crate::spectra::sampled::{SampledSpectrum, SampledWavelengths};
|
||||
use crate::utils::Ptr;
|
||||
use crate::utils::math::square;
|
||||
|
|
@ -22,18 +20,30 @@ fn inside_polka_dot(st: Point2f) -> bool {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
false
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FloatDotsTexture {
|
||||
pub mapping: TextureMapping2D,
|
||||
pub outside_dot: Ptr<FloatTexture>,
|
||||
pub inside_dot: Ptr<FloatTexture>,
|
||||
pub outside_dot: Ptr<FloatTexture>,
|
||||
}
|
||||
|
||||
impl FloatDotsTexture {
|
||||
pub fn new(
|
||||
mapping: TextureMapping2D,
|
||||
inside_dot: Ptr<FloatTexture>,
|
||||
outside_dot: Ptr<FloatTexture>,
|
||||
) -> Self {
|
||||
Self {
|
||||
mapping,
|
||||
inside_dot,
|
||||
outside_dot,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let c = self.mapping.map(ctx);
|
||||
let target_texture = if inside_polka_dot(c.st) {
|
||||
|
|
@ -54,11 +64,22 @@ impl FloatDotsTexture {
|
|||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct SpectrumDotsTexture {
|
||||
pub mapping: TextureMapping2D,
|
||||
pub outside_dot: Ptr<SpectrumTexture>,
|
||||
pub inside_dot: Ptr<SpectrumTexture>,
|
||||
pub outside_dot: Ptr<SpectrumTexture>,
|
||||
}
|
||||
|
||||
impl SpectrumDotsTexture {
|
||||
pub fn new(
|
||||
mapping: TextureMapping2D,
|
||||
inside_dot: Ptr<SpectrumTexture>,
|
||||
outside_dot: Ptr<SpectrumTexture>,
|
||||
) -> Self {
|
||||
Self {
|
||||
mapping,
|
||||
inside_dot,
|
||||
outside_dot,
|
||||
}
|
||||
}
|
||||
pub fn evaluate(
|
||||
&self,
|
||||
ctx: &TextureEvalContext,
|
||||
|
|
|
|||
|
|
@ -5,11 +5,18 @@ use crate::utils::noise::fbm;
|
|||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FBmTexture {
|
||||
pub mapping: TextureMapping3D,
|
||||
pub omega: Float,
|
||||
pub octaves: u32,
|
||||
pub omega: Float,
|
||||
}
|
||||
|
||||
impl FBmTexture {
|
||||
pub fn new(mapping: TextureMapping3D, octaves: u32, omega: Float) -> Self {
|
||||
Self {
|
||||
mapping,
|
||||
omega,
|
||||
octaves,
|
||||
}
|
||||
}
|
||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let c = self.mapping.map(ctx);
|
||||
fbm(c.p, c.dpdx, c.dpdy, self.omega, self.octaves)
|
||||
|
|
|
|||
39
shared/src/utils/error.rs
Normal file
39
shared/src/utils/error.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//! Errors for the shared crate.
|
||||
//!
|
||||
//! `shared` is `#![no_std]` and is compiled for SPIR-V and CUDA, so it must not
|
||||
//! depend on `anyhow` -- whose default features enable `std`. These variants are
|
||||
//! `Copy` and allocation-free; the CPU-side caller holds the offending string and
|
||||
//! the `FileLoc`, so it supplies those when reporting.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
UnknownWrapMode,
|
||||
UnknownFilterFunction,
|
||||
UnknownColorEncoding,
|
||||
/// `look_at` received an up vector parallel to the viewing direction.
|
||||
DegenerateLookAt,
|
||||
/// A transform matrix could not be inverted (pbrt's `InverseOrDie`).
|
||||
SingularMatrix,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
Self::UnknownWrapMode => "unknown wrap mode",
|
||||
Self::UnknownFilterFunction => "unknown filter function",
|
||||
Self::UnknownColorEncoding => "unknown color encoding",
|
||||
Self::DegenerateLookAt => {
|
||||
"LookAt: \"up\" vector and viewing direction are parallel"
|
||||
}
|
||||
Self::SingularMatrix => "matrix is not invertible",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Stable in core since 1.81, and the same trait `std::error::Error` re-exports --
|
||||
// so `?` and `anyhow::Context` keep working unchanged on the CPU side.
|
||||
impl core::error::Error for Error {}
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
|
@ -2,6 +2,7 @@ pub mod alloc;
|
|||
pub mod atomic;
|
||||
pub mod complex;
|
||||
pub mod containers;
|
||||
pub mod error;
|
||||
pub mod hash;
|
||||
pub mod interval;
|
||||
pub mod math;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use alloc::string::String;
|
||||
use crate::Float;
|
||||
use crate::core::geometry::{Bounds2f, Bounds2i, Point2f, Point2i};
|
||||
use core::ops::Deref;
|
||||
|
|
@ -17,6 +18,7 @@ pub struct BasicPBRTOptions {
|
|||
pub disable_wavelength_jitter: bool,
|
||||
pub disable_texture_filtering: bool,
|
||||
pub force_diffuse: bool,
|
||||
pub record_pixel_statistics: bool,
|
||||
pub use_gpu: bool,
|
||||
pub wavefront: bool,
|
||||
pub interactive: bool,
|
||||
|
|
@ -33,6 +35,7 @@ impl Default for BasicPBRTOptions {
|
|||
disable_wavelength_jitter: false,
|
||||
disable_texture_filtering: false,
|
||||
force_diffuse: false,
|
||||
record_pixel_statistics: false,
|
||||
use_gpu: false,
|
||||
wavefront: false,
|
||||
interactive: false,
|
||||
|
|
@ -42,7 +45,7 @@ impl Default for BasicPBRTOptions {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PBRTOptions {
|
||||
pub basic: BasicPBRTOptions,
|
||||
|
||||
|
|
@ -52,8 +55,8 @@ pub struct PBRTOptions {
|
|||
pub image_file: &'static str,
|
||||
pub pixel_samples: Option<i32>,
|
||||
pub gpu_device: Option<u32>,
|
||||
pub mse_reference_image: Option<&'static str>,
|
||||
pub mse_reference_output: Option<&'static str>,
|
||||
pub mse_reference_image: Option<String>,
|
||||
pub mse_reference_output: Option<String>,
|
||||
pub debug_start: Option<(Point2i, i32)>,
|
||||
pub quick_render: bool,
|
||||
pub upgrade: bool,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::core::interaction::{
|
|||
};
|
||||
use crate::utils::gpu_array_from_fn;
|
||||
use crate::{gamma, Float};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use crate::utils::error::{Error, Result};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
|
@ -2125,15 +2125,7 @@ pub fn look_at(
|
|||
// Initialize first three columns of viewing matrix
|
||||
let dir = (look - pos).normalize();
|
||||
if Vector3f::from(up).normalize().cross(dir).norm() == 0. {
|
||||
bail!(
|
||||
"LookAt: \"up\" vector ({}, {}, {}) and viewing direction ({}, {}, {}) passed to LookAt are pointing in the same direction.",
|
||||
up.x(),
|
||||
up.y(),
|
||||
up.z(),
|
||||
dir.x(),
|
||||
dir.y(),
|
||||
dir.z()
|
||||
);
|
||||
return Err(Error::DegenerateLookAt);
|
||||
}
|
||||
let right = Vector3f::from(up).normalize().cross(dir).normalize();
|
||||
let new_up = dir.cross(right);
|
||||
|
|
@ -2150,8 +2142,6 @@ pub fn look_at(
|
|||
world_from_camera[2][2] = dir.z();
|
||||
world_from_camera[3][2] = 0.;
|
||||
|
||||
let camera_from_world = world_from_camera
|
||||
.inverse()
|
||||
.context("Failed to inverse viewing matrix")?;
|
||||
let camera_from_world = world_from_camera.inverse().ok_or(Error::SingularMatrix)?;
|
||||
Ok(TransformGeneric::new(camera_from_world, world_from_camera))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::globals::get_options;
|
||||
use shared::Ptr;
|
||||
use shared::bxdfs::DiffuseBxDF;
|
||||
use shared::core::bsdf::BSDF;
|
||||
use shared::core::bssrdf::BSSRDF;
|
||||
|
|
@ -10,13 +11,12 @@ use shared::core::material::{Material, MaterialEvalContext, MaterialTrait};
|
|||
use shared::core::sampler::{Sampler, SamplerTrait};
|
||||
use shared::core::texture::UniversalTextureEvaluator;
|
||||
use shared::spectra::SampledWavelengths;
|
||||
use shared::Ptr;
|
||||
|
||||
pub trait InteractionGetter {
|
||||
fn get_bsdf(
|
||||
&mut self,
|
||||
r: &Ray,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
camera: &Camera,
|
||||
sampler: &mut Sampler,
|
||||
materials: &[Material],
|
||||
|
|
@ -35,7 +35,7 @@ impl InteractionGetter for SurfaceInteraction {
|
|||
fn get_bsdf(
|
||||
&mut self,
|
||||
r: &Ray,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
camera: &Camera,
|
||||
sampler: &mut Sampler,
|
||||
materials: &[Material],
|
||||
|
|
@ -98,7 +98,7 @@ impl InteractionGetter for MediumInteraction {
|
|||
fn get_bsdf(
|
||||
&mut self,
|
||||
_r: &Ray,
|
||||
_lambda: &SampledWavelengths,
|
||||
_lambda: &mut SampledWavelengths,
|
||||
_camera: &Camera,
|
||||
_sampler: &mut Sampler,
|
||||
_materials: &[Material],
|
||||
|
|
@ -121,7 +121,7 @@ impl InteractionGetter for SimpleInteraction {
|
|||
fn get_bsdf(
|
||||
&mut self,
|
||||
_r: &Ray,
|
||||
_lambda: &SampledWavelengths,
|
||||
_lambda: &mut SampledWavelengths,
|
||||
_camera: &Camera,
|
||||
_sampler: &mut Sampler,
|
||||
_materials: &[Material],
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
use super::entities::*;
|
||||
use super::BasicScene;
|
||||
use super::entities::*;
|
||||
use crate::Arena;
|
||||
use crate::spectra::get_colorspace_device;
|
||||
use crate::utils::error::FileLoc;
|
||||
use crate::utils::parameters::{ParameterDictionary, ParsedParameterVector};
|
||||
use crate::utils::parser::{ParserError, ParserTarget};
|
||||
use crate::Arena;
|
||||
use anyhow::Context;
|
||||
use crate::utils::parser::{AtLoc, ParserError, ParserTarget};
|
||||
use shared::Float;
|
||||
use shared::core::camera::CameraTransform;
|
||||
use shared::core::geometry::Vector3f;
|
||||
use shared::spectra::RGBColorSpace;
|
||||
use shared::utils::options::RenderingCoordinateSystem;
|
||||
use shared::utils::options::{PBRTOptions, RenderingCoordinateSystem};
|
||||
use shared::utils::transform;
|
||||
use shared::utils::transform::{AnimatedTransform, Transform};
|
||||
use shared::Float;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::sync::Arc;
|
||||
|
|
@ -24,6 +23,16 @@ fn normalize_utf8(input: &str) -> String {
|
|||
input.nfc().collect::<String>()
|
||||
}
|
||||
|
||||
/// pbrt's `normalizeArg` (util/args.h:22): downcase and drop `-`/`_` so option
|
||||
/// names can be written a little loosely.
|
||||
fn normalize_arg(input: &str) -> String {
|
||||
input
|
||||
.chars()
|
||||
.filter(|c| *c != '-' && *c != '_')
|
||||
.flat_map(|c| c.to_lowercase())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
struct TransformSet {
|
||||
t: [Transform; MAX_TRANSFORMS],
|
||||
|
|
@ -125,6 +134,11 @@ pub struct BasicSceneBuilder {
|
|||
named_material_names: HashSet<String>,
|
||||
medium_names: HashSet<String>,
|
||||
|
||||
/// `Option` directives accumulate here during parsing. The global options are
|
||||
/// a `OnceLock` written after the parse, so they cannot be mutated in place
|
||||
/// the way pbrt mutates its global `Options`.
|
||||
pending_options: PBRTOptions,
|
||||
|
||||
current_camera: Option<CameraSceneEntity>,
|
||||
current_film: Option<SceneEntity>,
|
||||
current_integrator: Option<SceneEntity>,
|
||||
|
|
@ -177,6 +191,7 @@ impl BasicSceneBuilder {
|
|||
spectrum_texture_names: HashSet::new(),
|
||||
named_material_names: HashSet::new(),
|
||||
medium_names: HashSet::new(),
|
||||
pending_options: PBRTOptions::default(),
|
||||
current_camera: Some(CameraSceneEntity {
|
||||
base: SceneEntity {
|
||||
name: "perspective".into(),
|
||||
|
|
@ -211,6 +226,12 @@ impl BasicSceneBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Options gathered from the scene's `Option` directives. Callers merge these
|
||||
/// with any command-line options and pass the result to `init_pbrt`.
|
||||
pub fn options(&self) -> &PBRTOptions {
|
||||
&self.pending_options
|
||||
}
|
||||
|
||||
fn for_active_transforms<F>(&mut self, f: F)
|
||||
where
|
||||
F: Fn(&Transform) -> Transform,
|
||||
|
|
@ -254,12 +275,6 @@ impl BasicSceneBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<anyhow::Error> for ParserError {
|
||||
fn from(e: anyhow::Error) -> Self {
|
||||
ParserError::Generic(e.to_string(), FileLoc::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl ParserTarget for BasicSceneBuilder {
|
||||
fn reverse_orientation(&mut self, loc: FileLoc) -> Result<(), ParserError> {
|
||||
self.verify_world("ReverseOrientation", &loc)?;
|
||||
|
|
@ -329,8 +344,7 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
uz: Float,
|
||||
loc: FileLoc,
|
||||
) -> Result<(), ParserError> {
|
||||
let t = transform::look_at((ex, ey, ez), (lx, ly, lz), (ux, uy, uz))
|
||||
.with_context(|| format!("at {}", loc))?;
|
||||
let t = transform::look_at((ex, ey, ez), (lx, ly, lz), (ux, uy, uz)).at(&loc)?;
|
||||
self.for_active_transforms(|cur| cur * &t);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -447,8 +461,65 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn option(&mut self, _name: &str, _value: &str, _loc: FileLoc) -> Result<(), ParserError> {
|
||||
todo!()
|
||||
fn option(&mut self, name: &str, value: &str, loc: FileLoc) -> Result<(), ParserError> {
|
||||
let bad = |what: &str| {
|
||||
Err(ParserError::Generic(
|
||||
format!("{value:?}: expected {what} for option {name:?}"),
|
||||
loc.clone(),
|
||||
))
|
||||
};
|
||||
let as_bool = |b: &mut bool| match value {
|
||||
"true" => {
|
||||
*b = true;
|
||||
Ok(())
|
||||
}
|
||||
"false" => {
|
||||
*b = false;
|
||||
Ok(())
|
||||
}
|
||||
_ => bad("\"true\" or \"false\""),
|
||||
};
|
||||
|
||||
let opts = &mut self.pending_options;
|
||||
match normalize_arg(name).as_str() {
|
||||
"disablepixeljitter" => as_bool(&mut opts.basic.disable_pixel_jitter)?,
|
||||
"disabletexturefiltering" => as_bool(&mut opts.basic.disable_texture_filtering)?,
|
||||
"disablewavelengthjitter" => as_bool(&mut opts.basic.disable_wavelength_jitter)?,
|
||||
"forcediffuse" => as_bool(&mut opts.basic.force_diffuse)?,
|
||||
"pixelstats" => as_bool(&mut opts.basic.record_pixel_statistics)?,
|
||||
"wavefront" => as_bool(&mut opts.basic.wavefront)?,
|
||||
"displacementedgescale" => match value.parse::<Float>() {
|
||||
Ok(v) => opts.displacement_edge_scale = v,
|
||||
Err(_) => return bad("a floating-point value"),
|
||||
},
|
||||
"seed" => match value.parse::<i32>() {
|
||||
Ok(v) => opts.basic.seed = v,
|
||||
Err(_) => return bad("an integer"),
|
||||
},
|
||||
// The tokenizer has already dequoted these, so unlike pbrt we do not
|
||||
// re-check for surrounding quotes.
|
||||
"msereferenceimage" => {
|
||||
opts.mse_reference_image = Some(value.to_string())
|
||||
}
|
||||
"msereferenceout" => {
|
||||
opts.mse_reference_output = Some(value.to_string())
|
||||
}
|
||||
"rendercoordsys" => {
|
||||
opts.basic.rendering_space = match value {
|
||||
"camera" => RenderingCoordinateSystem::Camera,
|
||||
"cameraworld" => RenderingCoordinateSystem::CameraWorld,
|
||||
"world" => RenderingCoordinateSystem::World,
|
||||
_ => return bad("\"camera\", \"cameraworld\" or \"world\""),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(ParserError::Generic(
|
||||
format!("{name:?}: unknown option"),
|
||||
loc,
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pixel_filter(
|
||||
|
|
@ -534,7 +605,8 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
params,
|
||||
&self.graphics_state.medium_attributes,
|
||||
self.graphics_state.color_space.clone(),
|
||||
)?;
|
||||
)
|
||||
.at(&loc)?;
|
||||
let render_from_object = self.render_from_object();
|
||||
let entity = MediumSceneEntity {
|
||||
base: SceneEntity {
|
||||
|
|
@ -702,7 +774,8 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
params.clone(),
|
||||
&self.graphics_state.texture_attributes,
|
||||
self.graphics_state.color_space.clone(),
|
||||
)?;
|
||||
)
|
||||
.at(&loc)?;
|
||||
|
||||
if type_name != "float" && type_name != "spectrum" {
|
||||
return Err(ParserError::Generic(
|
||||
|
|
@ -762,7 +835,8 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
params,
|
||||
&self.graphics_state.material_attributes,
|
||||
self.graphics_state.color_space.clone(),
|
||||
)?;
|
||||
)
|
||||
.at(&loc)?;
|
||||
let entity = SceneEntity {
|
||||
name: name.to_string(),
|
||||
loc,
|
||||
|
|
@ -794,7 +868,8 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
params,
|
||||
&self.graphics_state.material_attributes,
|
||||
self.graphics_state.color_space.clone(),
|
||||
)?;
|
||||
)
|
||||
.at(&loc)?;
|
||||
|
||||
// pbrt stores an empty entity name here: the material type comes from the
|
||||
// "type" parameter (scene.cpp:719).
|
||||
|
|
@ -827,7 +902,8 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
params.clone(),
|
||||
&self.graphics_state.medium_attributes,
|
||||
self.graphics_state.color_space.clone(),
|
||||
)?;
|
||||
)
|
||||
.at(&loc)?;
|
||||
|
||||
let render_from_light = self.render_from_object();
|
||||
|
||||
|
|
@ -874,7 +950,8 @@ impl ParserTarget for BasicSceneBuilder {
|
|||
params.clone(),
|
||||
&self.graphics_state.shape_attributes,
|
||||
self.graphics_state.color_space.clone(),
|
||||
)?;
|
||||
)
|
||||
.at(&loc)?;
|
||||
|
||||
let render_from_object = self.render_from_object_at(0);
|
||||
let object_from_render = render_from_object.inverse();
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
use crate::textures::*;
|
||||
use crate::utils::{MIPMap, MIPMapFilterOptions, TextureParameterDictionary};
|
||||
use crate::{Arena, FileLoc};
|
||||
use anyhow::{anyhow, Result};
|
||||
use anyhow::{Result, anyhow};
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use shared::Float;
|
||||
use shared::core::color::ColorEncoding;
|
||||
use shared::core::geometry::Vector3f;
|
||||
use shared::core::image::WrapMode;
|
||||
use shared::core::texture::SpectrumType;
|
||||
use shared::core::texture::{
|
||||
CylindricalMapping, PlanarMapping, SphericalMapping, TextureEvalContext, TextureMapping2D,
|
||||
UVMapping,
|
||||
CylindricalMapping, PlanarMapping, PointTransformMapping, SphericalMapping,
|
||||
TextureEvalContext, TextureMapping2D, TextureMapping3D, UVMapping,
|
||||
};
|
||||
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
||||
use shared::textures::{
|
||||
|
|
@ -18,22 +19,10 @@ use shared::textures::{
|
|||
SpectrumConstantTexture, SpectrumDotsTexture, WindyTexture, WrinkledTexture,
|
||||
};
|
||||
use shared::utils::Transform;
|
||||
use shared::Float;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex, OnceLock};
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait FloatTextureTrait {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext) -> Float;
|
||||
}
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait SpectrumTextureTrait {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[enum_dispatch(FloatTextureTrait)]
|
||||
pub enum FloatTexture {
|
||||
Constant(FloatConstantTexture),
|
||||
Checkerboard(FloatCheckerboardTexture),
|
||||
|
|
@ -49,19 +38,12 @@ pub enum FloatTexture {
|
|||
Bilerp(FloatBilerpTexture),
|
||||
}
|
||||
|
||||
|
||||
impl Default for FloatTexture {
|
||||
fn default() -> Self {
|
||||
FloatTexture::Constant(FloatConstantTexture::new(1.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for Arc<FloatTexture> {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
self.as_ref().evaluate(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CreateFloatTexture {
|
||||
fn create(
|
||||
render_from_texture: Transform,
|
||||
|
|
@ -101,7 +83,6 @@ impl FloatTexture {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[enum_dispatch(SpectrumTextureTrait)]
|
||||
pub enum SpectrumTexture {
|
||||
Constant(SpectrumConstantTexture),
|
||||
Checkerboard(SpectrumCheckerboardTexture),
|
||||
|
|
@ -120,6 +101,7 @@ pub trait CreateSpectrumTexture {
|
|||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<SpectrumTexture>;
|
||||
}
|
||||
|
||||
|
|
@ -130,29 +112,29 @@ impl SpectrumTexture {
|
|||
params: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
arena: &Arena,
|
||||
) -> Result<Self> {
|
||||
match name {
|
||||
"constant" => {
|
||||
SpectrumConstantTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||
SpectrumConstantTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
||||
}
|
||||
"scale" => {
|
||||
SpectrumScaledTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||
SpectrumScaledTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
||||
}
|
||||
"mix" => SpectrumMixTexture::create(render_from_texture, params, spectrum_type, loc),
|
||||
"mix" => SpectrumMixTexture::create(render_from_texture, params, spectrum_type, loc, arena),
|
||||
"directionmix" => {
|
||||
SpectrumDirectionMixTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||
SpectrumDirectionMixTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
||||
}
|
||||
"bilerp" => {
|
||||
SpectrumBilerpTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||
SpectrumBilerpTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
||||
}
|
||||
"imagemap" => {
|
||||
SpectrumImageTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||
SpectrumImageTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
||||
}
|
||||
"checkerboard" => {
|
||||
SpectrumCheckerboardTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||
SpectrumCheckerboardTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
||||
}
|
||||
"dots" => SpectrumDotsTexture::create(render_from_texture, params, spectrum_type, loc),
|
||||
"dots" => SpectrumDotsTexture::create(render_from_texture, params, spectrum_type, loc, arena),
|
||||
_ => Err(anyhow!(
|
||||
"Spectrum texture type '{}' unknown at {}",
|
||||
name,
|
||||
|
|
@ -162,12 +144,6 @@ impl SpectrumTexture {
|
|||
}
|
||||
}
|
||||
|
||||
impl SpectrumTextureTrait for Arc<SpectrumTexture> {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
self.as_ref().evaluate(ctx, lambda)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CreateTextureMapping {
|
||||
fn create(
|
||||
params: &TextureParameterDictionary,
|
||||
|
|
@ -221,6 +197,21 @@ impl CreateTextureMapping for TextureMapping2D {
|
|||
}
|
||||
}
|
||||
|
||||
impl CreateTextureMapping for TextureMapping3D {
|
||||
fn create(
|
||||
params: &TextureParameterDictionary,
|
||||
render_from_texture: &Transform,
|
||||
loc: &FileLoc,
|
||||
) -> Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let mapping = PointTransformMapping::new(render_from_texture.inverse());
|
||||
Ok(TextureMapping3D::PointTransform(mapping))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub static TEXTURE_CACHE: OnceLock<Mutex<HashMap<TexInfo, Arc<MIPMap>>>> = OnceLock::new();
|
||||
|
||||
pub fn get_texture_cache() -> &'static Mutex<HashMap<TexInfo, Arc<MIPMap>>> {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ pub trait RayIntegratorTrait {
|
|||
fn li(
|
||||
&self,
|
||||
ray: Ray,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
sampler: &mut Sampler,
|
||||
visible_surface: bool,
|
||||
arena: &Arena,
|
||||
|
|
@ -69,7 +69,8 @@ impl CreateIntegrator for PathIntegrator {
|
|||
let _max_depth = parameters.get_one_int("maxdepth", 5)?;
|
||||
let _regularize = parameters.get_one_bool("regularize", false)?;
|
||||
let light_sampler = create_light_sampler("power", &lights, arena);
|
||||
let integrator = PathIntegrator::new(aggregate, lights, camera, light_sampler, config, materials);
|
||||
let integrator =
|
||||
PathIntegrator::new(aggregate, lights, camera, light_sampler, config, materials);
|
||||
Ok(integrator)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use super::RayIntegratorTrait;
|
||||
use super::base::IntegratorBase;
|
||||
use super::constants::*;
|
||||
use super::state::PathState;
|
||||
use super::RayIntegratorTrait;
|
||||
use crate::core::interaction::InteractionGetter;
|
||||
use crate::Arena;
|
||||
use shared::core::bsdf::{BSDFSample, BSDF};
|
||||
use crate::core::interaction::InteractionGetter;
|
||||
use shared::core::bsdf::{BSDF, BSDFSample};
|
||||
use shared::core::bxdf::{BxDFFlags, FArgs, TransportMode};
|
||||
use shared::core::camera::Camera;
|
||||
use shared::core::film::VisibleSurface;
|
||||
|
|
@ -72,7 +72,6 @@ pub struct PathIntegrator {
|
|||
materials: Vec<Material>,
|
||||
}
|
||||
|
||||
|
||||
impl PathIntegrator {
|
||||
pub fn new(
|
||||
aggregate: Arc<Primitive>,
|
||||
|
|
@ -208,7 +207,7 @@ impl RayIntegratorTrait for PathIntegrator {
|
|||
fn li(
|
||||
&self,
|
||||
mut ray: Ray,
|
||||
lambda: &SampledWavelengths,
|
||||
lambda: &mut SampledWavelengths,
|
||||
sampler: &mut Sampler,
|
||||
want_visible: bool,
|
||||
_arena: &Arena,
|
||||
|
|
@ -247,7 +246,9 @@ impl RayIntegratorTrait for PathIntegrator {
|
|||
}
|
||||
|
||||
// Get BSDF
|
||||
let Some(mut bsdf) = isect.get_bsdf(&ray, lambda, &self.camera, sampler, &self.materials) else {
|
||||
let Some(mut bsdf) =
|
||||
isect.get_bsdf(&ray, lambda, &self.camera, sampler, &self.materials)
|
||||
else {
|
||||
state.specular_bounce = true;
|
||||
isect.skip_intersection(&mut ray, t_hit);
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::base::IntegratorBase;
|
||||
use super::RayIntegratorTrait;
|
||||
use super::base::IntegratorBase;
|
||||
use crate::core::camera::InitMetadata;
|
||||
use crate::core::film::FilmTrait;
|
||||
use crate::core::image::{HostImage, ImageIO, ImageMetadata};
|
||||
|
|
@ -7,12 +7,12 @@ use crate::globals::get_options;
|
|||
use crate::spectra::get_spectra_context;
|
||||
use crate::{Arena, PbrtProgress};
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use shared::Float;
|
||||
use shared::core::camera::{Camera, CameraTrait};
|
||||
use shared::core::geometry::{Bounds2i, Point2i};
|
||||
use shared::core::sampler::get_camera_sample;
|
||||
use shared::core::sampler::{Sampler, SamplerTrait};
|
||||
use shared::spectra::SampledSpectrum;
|
||||
use shared::Float;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ pub fn evaluate_pixel_sample<T: RayIntegratorTrait>(
|
|||
lu = 0.5;
|
||||
}
|
||||
|
||||
let lambda = camera.get_film().sample_wavelengths(lu);
|
||||
let mut lambda = camera.get_film().sample_wavelengths(lu);
|
||||
let film = camera.get_film();
|
||||
let filter = film.get_filter();
|
||||
let camera_sample = get_camera_sample(sampler, pixel, filter);
|
||||
|
|
@ -229,7 +229,7 @@ pub fn evaluate_pixel_sample<T: RayIntegratorTrait>(
|
|||
let initialize_visible_surface = film.uses_visible_surface();
|
||||
let (mut l, visible_surface) = integrator.li(
|
||||
camera_ray.ray,
|
||||
&lambda,
|
||||
&mut lambda,
|
||||
sampler,
|
||||
initialize_visible_surface,
|
||||
arena,
|
||||
|
|
|
|||
|
|
@ -1,51 +1,61 @@
|
|||
use crate::Arena;
|
||||
use crate::core::texture::{
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTextureTrait, SpectrumTexture,
|
||||
SpectrumTextureTrait,
|
||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture, SpectrumTexture,
|
||||
};
|
||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
||||
use anyhow::Result;
|
||||
use shared::core::texture::{SpectrumType, TextureEvalContext};
|
||||
use shared::{
|
||||
spectra::{SampledSpectrum, SampledWavelengths},
|
||||
textures::{FloatBilerpTexture, SpectrumBilerpTexture},
|
||||
utils::Transform,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::texture::FloatTexture,
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
};
|
||||
use shared::core::spectrum::Spectrum;
|
||||
use shared::core::texture::{SpectrumType, TextureMapping2D};
|
||||
use shared::spectra::ConstantSpectrum;
|
||||
use shared::textures::{FloatBilerpTexture, SpectrumBilerpTexture};
|
||||
use shared::utils::Transform;
|
||||
|
||||
impl CreateFloatTexture for FloatBilerpTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||
|
||||
impl FloatTextureTrait for FloatBilerpTexture {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext) -> shared::Float {
|
||||
todo!()
|
||||
let tex = FloatBilerpTexture::new(
|
||||
map,
|
||||
parameters.get_one_float("v00", 0.)?,
|
||||
parameters.get_one_float("v01", 1.)?,
|
||||
parameters.get_one_float("v10", 0.)?,
|
||||
parameters.get_one_float("v11", 1.)?,
|
||||
);
|
||||
Ok(FloatTexture::Bilerp(tex))
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumBilerpTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumBilerpTexture {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
todo!()
|
||||
let get = |name: &str, def: Spectrum| {
|
||||
let s = parameters
|
||||
.get_one_spectrum(name, Some(def), spectrum_type)
|
||||
.unwrap_or(def);
|
||||
arena.alloc(s)
|
||||
};
|
||||
|
||||
let tex = SpectrumBilerpTexture::new(
|
||||
map,
|
||||
get("v00", zero),
|
||||
get("v01", one),
|
||||
get("v10", zero),
|
||||
get("v11", one),
|
||||
);
|
||||
Ok(SpectrumTexture::Bilerp(tex))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,79 @@
|
|||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, bail};
|
||||
use shared::{
|
||||
core::texture::SpectrumType,
|
||||
textures::{FloatCheckerboardTexture, SpectrumCheckerboardTexture},
|
||||
core::spectrum::Spectrum,
|
||||
core::texture::{SpectrumType, TextureMapping2D, TextureMapping3D},
|
||||
spectra::ConstantSpectrum,
|
||||
textures::{CheckerMap, FloatCheckerboardTexture, SpectrumCheckerboardTexture},
|
||||
utils::Transform,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::texture::{
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait,
|
||||
SpectrumTexture, SpectrumTextureTrait,
|
||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture,
|
||||
SpectrumTexture,
|
||||
},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
utils::{ArenaUpload, FileLoc, TextureParameterDictionary},
|
||||
};
|
||||
|
||||
impl CreateFloatTexture for FloatCheckerboardTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
fn checker_map(
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
) -> Result<CheckerMap> {
|
||||
match parameters.get_one_int("dimension", 2)? {
|
||||
2 => Ok(CheckerMap::D2(TextureMapping2D::create(
|
||||
¶meters,
|
||||
&render_from_texture,
|
||||
&loc,
|
||||
)?)),
|
||||
3 => Ok(CheckerMap::D3(TextureMapping3D::create(
|
||||
¶meters,
|
||||
&render_from_texture,
|
||||
&loc,
|
||||
)?)),
|
||||
dim => bail!("{loc}: {dim} dimensional checkerboard texture not supported"),
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for FloatCheckerboardTexture {
|
||||
fn evaluate(&self, _ctx: &shared::core::texture::TextureEvalContext) -> shared::Float {
|
||||
todo!()
|
||||
impl CreateFloatTexture for FloatCheckerboardTexture {
|
||||
fn create(
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
let tex1 = arena.upload(parameters.get_float_texture("tex1", 1.)?);
|
||||
let tex2 = arena.upload(parameters.get_float_texture("tex2", 0.)?);
|
||||
let map = checker_map(render_from_texture, parameters, loc)?;
|
||||
let tex = FloatCheckerboardTexture::new(map, [tex1, tex2]);
|
||||
Ok(FloatTexture::Checkerboard(tex))
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumCheckerboardTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
||||
let tex = |name: &str, def: Spectrum| {
|
||||
arena.upload(
|
||||
parameters
|
||||
.get_spectrum_texture(name, Some(def), spectrum_type)
|
||||
.expect("default supplied"),
|
||||
)
|
||||
};
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumCheckerboardTexture {
|
||||
fn evaluate(
|
||||
&self,
|
||||
_ctx: &shared::core::texture::TextureEvalContext,
|
||||
_lambda: &shared::spectra::SampledWavelengths,
|
||||
) -> shared::spectra::SampledSpectrum {
|
||||
todo!()
|
||||
let tex1 = tex("tex1", one);
|
||||
let tex2 = tex("tex2", zero);
|
||||
|
||||
let map = checker_map(render_from_texture, parameters, loc)?;
|
||||
let tex = SpectrumCheckerboardTexture::new(map, [tex1, tex2]);
|
||||
Ok(SpectrumTexture::Checkerboard(tex))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,46 @@
|
|||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
use shared::core::spectrum::Spectrum;
|
||||
use shared::spectra::ConstantSpectrum;
|
||||
use shared::{
|
||||
core::texture::{SpectrumType, TextureEvalContext},
|
||||
core::texture::SpectrumType,
|
||||
textures::{FloatConstantTexture, SpectrumConstantTexture},
|
||||
utils::Transform,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::texture::{
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait,
|
||||
SpectrumTexture, SpectrumTextureTrait,
|
||||
},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, SpectrumTexture },
|
||||
utils::{FileLoc, TextureParameterDictionary}
|
||||
};
|
||||
|
||||
impl CreateFloatTexture for FloatConstantTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for FloatConstantTexture {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext) -> shared::Float {
|
||||
todo!()
|
||||
let value = parameters.get_one_float("value", 1.)?;
|
||||
Ok(FloatTexture::Constant(FloatConstantTexture::new(value)))
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumConstantTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
||||
let value = parameters
|
||||
.get_one_spectrum("value", Some(one), spectrum_type)
|
||||
.unwrap_or(one);
|
||||
Ok(SpectrumTexture::Constant(SpectrumConstantTexture::new(
|
||||
value,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumConstantTexture {
|
||||
fn evaluate(
|
||||
&self,
|
||||
_ctx: &TextureEvalContext,
|
||||
_lambda: &shared::spectra::SampledWavelengths,
|
||||
) -> shared::spectra::SampledSpectrum {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,57 @@
|
|||
use crate::Arena;
|
||||
use crate::{Arena, ArenaUpload};
|
||||
use anyhow::Result;
|
||||
use shared::{
|
||||
core::texture::SpectrumType,
|
||||
core::spectrum::Spectrum,
|
||||
core::texture::{SpectrumType, TextureMapping2D},
|
||||
spectra::ConstantSpectrum,
|
||||
textures::{FloatDotsTexture, SpectrumDotsTexture},
|
||||
utils::Transform,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::texture::{
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait,
|
||||
SpectrumTexture, SpectrumTextureTrait,
|
||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture,
|
||||
SpectrumTexture,
|
||||
},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
};
|
||||
|
||||
impl FloatTextureTrait for FloatDotsTexture {
|
||||
fn evaluate(&self, _ctx: &shared::core::texture::TextureEvalContext) -> shared::Float {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateFloatTexture for FloatDotsTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||
let inside = parameters.get_float_texture("inside", 1.)?;
|
||||
let outside = parameters.get_float_texture("outside", 1.)?;
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumDotsTexture {
|
||||
fn evaluate(
|
||||
&self,
|
||||
_ctx: &shared::core::texture::TextureEvalContext,
|
||||
_lambda: &shared::spectra::SampledWavelengths,
|
||||
) -> shared::spectra::SampledSpectrum {
|
||||
todo!()
|
||||
let tex = FloatDotsTexture::new(map, arena.upload(inside), arena.upload(outside));
|
||||
|
||||
Ok(FloatTexture::Dots(tex))
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumDotsTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
||||
|
||||
let get = |name: &str, def: Spectrum| {
|
||||
let t = parameters
|
||||
.get_spectrum_texture(name, Some(def), spectrum_type)
|
||||
.expect("default supplied");
|
||||
arena.upload(t)
|
||||
};
|
||||
let tex = SpectrumDotsTexture::new(map, get("inside", one), get("outside", zero));
|
||||
Ok(SpectrumTexture::Dots(tex))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
use shared::core::texture::TextureEvalContext;
|
||||
use shared::core::texture::{TextureEvalContext, TextureMapping3D};
|
||||
use shared::{textures::FBmTexture, utils::Transform};
|
||||
|
||||
use crate::{
|
||||
core::texture::{CreateFloatTexture, FloatTexture, FloatTextureTrait},
|
||||
core::texture::{CreateFloatTexture, CreateTextureMapping, FloatTexture},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
};
|
||||
|
||||
impl CreateFloatTexture for FBmTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for FBmTexture {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext) -> shared::Float {
|
||||
todo!()
|
||||
let map = TextureMapping3D::create(¶meters, &render_from_texture, &loc)?;
|
||||
let tex = FBmTexture::new(
|
||||
map,
|
||||
parameters.get_one_int("octaves", 5)?.try_into().unwrap(),
|
||||
parameters.get_one_float("roughness", 0.5)?,
|
||||
);
|
||||
Ok(FloatTexture::FBm(tex))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use crate::core::texture::{get_texture_cache, CreateTextureMapping, TexInfo};
|
||||
use crate::core::texture::{
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait, SpectrumTexture,
|
||||
SpectrumTextureTrait,
|
||||
};
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, SpectrumTexture
|
||||
};
|
||||
use crate::utils::mipmap::{MIPMap, MIPMapFilterOptions};
|
||||
use crate::utils::{resolve_filename, FileLoc, TextureParameterDictionary};
|
||||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
use shared::core::color::RGB;
|
||||
use shared::core::color::{ColorEncoding, SRGBEncoding};
|
||||
use shared::core::geometry::Vector2f;
|
||||
|
|
@ -15,7 +14,7 @@ use shared::core::spectrum::SpectrumTrait;
|
|||
use shared::core::texture::{SpectrumType, TexCoord2D, TextureEvalContext, TextureMapping2D};
|
||||
use shared::spectra::{
|
||||
RGBAlbedoSpectrum, RGBIlluminantSpectrum, RGBUnboundedSpectrum, SampledSpectrum,
|
||||
SampledWavelengths,
|
||||
SampledWavelengths
|
||||
};
|
||||
use shared::utils::Transform;
|
||||
use shared::Float;
|
||||
|
|
@ -28,7 +27,7 @@ pub struct ImageTextureBase {
|
|||
pub filename: String,
|
||||
pub scale: Float,
|
||||
pub invert: bool,
|
||||
pub mipmap: Arc<MIPMap>,
|
||||
pub mipmap: Arc<MIPMap>
|
||||
}
|
||||
|
||||
impl ImageTextureBase {
|
||||
|
|
@ -45,7 +44,7 @@ impl ImageTextureBase {
|
|||
filename: filename.clone(),
|
||||
filter_options,
|
||||
wrap_mode,
|
||||
encoding,
|
||||
encoding
|
||||
};
|
||||
|
||||
let cache_mutex = get_texture_cache();
|
||||
|
|
@ -58,7 +57,7 @@ impl ImageTextureBase {
|
|||
filename,
|
||||
scale,
|
||||
invert,
|
||||
mipmap: mipmap.clone(),
|
||||
mipmap: mipmap.clone()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +78,7 @@ impl ImageTextureBase {
|
|||
filename,
|
||||
scale,
|
||||
invert,
|
||||
mipmap: stored_mipmap.clone(),
|
||||
mipmap: stored_mipmap.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,7 +96,7 @@ impl ImageTextureBase {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct SpectrumImageTexture {
|
||||
pub base: ImageTextureBase,
|
||||
pub spectrum_type: SpectrumType,
|
||||
pub spectrum_type: SpectrumType
|
||||
}
|
||||
|
||||
impl SpectrumImageTexture {
|
||||
|
|
@ -124,58 +123,18 @@ impl SpectrumImageTexture {
|
|||
|
||||
Self {
|
||||
base,
|
||||
spectrum_type,
|
||||
spectrum_type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumImageTexture {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
static PATH_IMG_COUNT: AtomicU32 = AtomicU32::new(0);
|
||||
let pn = PATH_IMG_COUNT.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
let mut c = self.base.mapping.map(ctx);
|
||||
c.st[1] = 1. - c.st[1];
|
||||
let dst0 = Vector2f::new(c.dsdx, c.dtdx);
|
||||
let dst1 = Vector2f::new(c.dsdy, c.dtdy);
|
||||
let raw_rgb = self.base.mipmap.filter::<RGB>(c.st, dst0, dst1);
|
||||
let rgb_unclamp = self.base.scale * raw_rgb;
|
||||
let rgb = RGB::clamp_zero(&rgb_unclamp);
|
||||
|
||||
if pn < 5 {
|
||||
eprintln!("PATH_IMG[{pn}] scale={:.6} raw_rgb[0]={:.6} rgb_after_scale[0]={:.6} \
|
||||
st={:?} dst0={:?} dst1={:?} has_cs={}",
|
||||
self.base.scale, raw_rgb[0], rgb_unclamp[0],
|
||||
c.st, dst0, dst1,
|
||||
self.base.mipmap.get_rgb_colorspace().is_some());
|
||||
}
|
||||
|
||||
if let Some(cs) = self.base.mipmap.get_rgb_colorspace() {
|
||||
match self.spectrum_type {
|
||||
SpectrumType::Unbounded => {
|
||||
return RGBUnboundedSpectrum::new(&cs, rgb).sample(lambda);
|
||||
}
|
||||
SpectrumType::Albedo => {
|
||||
return RGBAlbedoSpectrum::new(&cs, rgb.clamp(0., 1.)).sample(lambda);
|
||||
}
|
||||
_ => return RGBIlluminantSpectrum::new(&cs, rgb).sample(lambda),
|
||||
}
|
||||
}
|
||||
let result = SampledSpectrum::new(rgb[0]);
|
||||
if pn < 5 {
|
||||
eprintln!("PATH_IMG[{pn}] no-cs branch result[0]={:.6}", result[0]);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumImageTexture {
|
||||
fn create(
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
let mapping = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||
|
||||
|
|
@ -190,7 +149,7 @@ impl CreateSpectrumTexture for SpectrumImageTexture {
|
|||
"repeat" => WrapMode::Repeat,
|
||||
"clamp" => WrapMode::Clamp,
|
||||
"black" => WrapMode::Black,
|
||||
_ => WrapMode::Repeat,
|
||||
_ => WrapMode::Repeat
|
||||
};
|
||||
|
||||
let encoding = ColorEncoding::SRGB(SRGBEncoding);
|
||||
|
|
@ -212,7 +171,7 @@ impl CreateSpectrumTexture for SpectrumImageTexture {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FloatImageTexture {
|
||||
pub base: ImageTextureBase,
|
||||
pub base: ImageTextureBase
|
||||
}
|
||||
|
||||
impl FloatImageTexture {
|
||||
|
|
@ -234,26 +193,7 @@ impl FloatImageTexture {
|
|||
scale,
|
||||
invert,
|
||||
encoding,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for FloatImageTexture {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let mut c: TexCoord2D = self.base.mapping.map(ctx);
|
||||
c.st[1] = 1. - c.st[1];
|
||||
let v: Float = self.base.scale
|
||||
* self.base.mipmap.filter::<Float>(
|
||||
c.st,
|
||||
Vector2f::new(c.dsdx, c.dtdx),
|
||||
Vector2f::new(c.dsdy, c.dtdy),
|
||||
);
|
||||
|
||||
if self.base.invert {
|
||||
(1. - v).max(0.)
|
||||
} else {
|
||||
v
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -271,10 +211,10 @@ impl CreateFloatTexture for FloatImageTexture {
|
|||
let mut filter_options = MIPMapFilterOptions::default();
|
||||
filter_options.max_anisotropy = max_aniso;
|
||||
|
||||
let ff = FilterFunction::parse(&filter)?;
|
||||
let ff = FilterFunction::parse(&filter).with_context(|| format!("{:?}", filter))?;
|
||||
filter_options.filter = ff;
|
||||
let wrap_string = parameters.get_one_string("wrap", "repeat")?;
|
||||
let wrap_mode = WrapMode::parse(&wrap_string)?;
|
||||
let wrap_mode = WrapMode::parse(&wrap_string).with_context(|| format!("{:?}", wrap_string))?;
|
||||
let scale = parameters.get_one_float("scale", 1.)?;
|
||||
let invert = parameters.get_one_bool("invert", false)?;
|
||||
let filename = resolve_filename(¶meters.get_one_string("filename", "")?);
|
||||
|
|
@ -287,7 +227,8 @@ impl CreateFloatTexture for FloatImageTexture {
|
|||
"linear"
|
||||
};
|
||||
let encoding_str = parameters.get_one_string("encoding", default_encoding)?;
|
||||
let encoding = ColorEncoding::from_name(&encoding_str)?;
|
||||
let encoding =
|
||||
ColorEncoding::from_name(&encoding_str).with_context(|| format!("{:?}", encoding_str))?;
|
||||
|
||||
let tex = FloatImageTexture::new(
|
||||
mapping,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,19 @@
|
|||
use crate::core::texture::{CreateSpectrumTexture, SpectrumTexture, SpectrumTextureTrait};
|
||||
use crate::core::texture::{CreateSpectrumTexture, SpectrumTexture};
|
||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
||||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
use shared::Transform;
|
||||
use shared::core::texture::SpectrumType;
|
||||
use shared::textures::MarbleTexture;
|
||||
|
||||
impl SpectrumTextureTrait for MarbleTexture {
|
||||
fn evaluate(
|
||||
&self,
|
||||
_ctx: &shared::core::texture::TextureEvalContext,
|
||||
_lambda: &shared::spectra::SampledWavelengths,
|
||||
) -> shared::spectra::SampledSpectrum {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for MarbleTexture {
|
||||
fn create(
|
||||
_render_from_texture: shared::utils::Transform,
|
||||
_parameters: crate::utils::TextureParameterDictionary,
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: crate::utils::FileLoc,
|
||||
) -> anyhow::Result<SpectrumTexture> {
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use crate::core::texture::{
|
||||
CreateSpectrumTexture, FloatTexture, FloatTextureTrait, SpectrumTexture, SpectrumTextureTrait,
|
||||
};
|
||||
CreateSpectrumTexture, FloatTexture, SpectrumTexture };
|
||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
||||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
|
|
@ -15,7 +14,7 @@ use std::sync::Arc;
|
|||
pub struct FloatMixTexture {
|
||||
pub tex1: Arc<FloatTexture>,
|
||||
pub tex2: Arc<FloatTexture>,
|
||||
pub amount: Arc<FloatTexture>,
|
||||
pub amount: Arc<FloatTexture>
|
||||
}
|
||||
|
||||
impl FloatMixTexture {
|
||||
|
|
@ -41,26 +40,11 @@ impl FloatMixTexture {
|
|||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for FloatMixTexture {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let amt = self.amount.evaluate(ctx);
|
||||
let mut t1 = 0.;
|
||||
let mut t2 = 0.;
|
||||
if amt != 1. {
|
||||
t1 = self.tex1.evaluate(ctx);
|
||||
}
|
||||
if amt != 0. {
|
||||
t2 = self.tex2.evaluate(ctx);
|
||||
}
|
||||
(1. - amt) * t1 + amt * t2
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FloatDirectionMixTexture {
|
||||
pub tex1: Arc<FloatTexture>,
|
||||
pub tex2: Arc<FloatTexture>,
|
||||
pub dir: Vector3f,
|
||||
pub dir: Vector3f
|
||||
}
|
||||
|
||||
impl FloatDirectionMixTexture {
|
||||
|
|
@ -83,17 +67,11 @@ impl FloatDirectionMixTexture {
|
|||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for FloatDirectionMixTexture {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext) -> Float {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpectrumMixTexture {
|
||||
pub tex1: Arc<SpectrumTexture>,
|
||||
pub tex2: Arc<SpectrumTexture>,
|
||||
pub amount: Arc<FloatTexture>,
|
||||
pub amount: Arc<FloatTexture>
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumMixTexture {
|
||||
|
|
@ -102,22 +80,17 @@ impl CreateSpectrumTexture for SpectrumMixTexture {
|
|||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumMixTexture {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpectrumDirectionMixTexture {
|
||||
pub tex1: Arc<SpectrumTexture>,
|
||||
pub tex2: Arc<SpectrumTexture>,
|
||||
pub dir: Vector3f,
|
||||
pub dir: Vector3f
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumDirectionMixTexture {
|
||||
|
|
@ -126,13 +99,9 @@ impl CreateSpectrumTexture for SpectrumDirectionMixTexture {
|
|||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumDirectionMixTexture {
|
||||
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ mod scaled;
|
|||
mod windy;
|
||||
mod wrinkled;
|
||||
|
||||
pub use bilerp::*;
|
||||
pub use image::*;
|
||||
pub use mix::*;
|
||||
pub use scaled::*;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::core::texture::{CreateSpectrumTexture, FloatTexture, SpectrumTexture};
|
||||
use crate::core::texture::{FloatTextureTrait, SpectrumTextureTrait};
|
||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
||||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
|
|
@ -13,7 +12,7 @@ use std::sync::Arc;
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct FloatScaledTexture {
|
||||
pub tex: Arc<FloatTexture>,
|
||||
pub scale: Arc<FloatTexture>,
|
||||
pub scale: Arc<FloatTexture>
|
||||
}
|
||||
|
||||
impl FloatScaledTexture {
|
||||
|
|
@ -52,20 +51,10 @@ impl FloatScaledTexture {
|
|||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for FloatScaledTexture {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let sc = self.scale.evaluate(ctx);
|
||||
if sc == 0. {
|
||||
return 0.;
|
||||
}
|
||||
self.tex.evaluate(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpectrumScaledTexture {
|
||||
pub tex: Arc<SpectrumTexture>,
|
||||
pub scale: Arc<FloatTexture>,
|
||||
pub scale: Arc<FloatTexture>
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumScaledTexture {
|
||||
|
|
@ -74,6 +63,7 @@ impl CreateSpectrumTexture for SpectrumScaledTexture {
|
|||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.0));
|
||||
let tex = parameters
|
||||
|
|
@ -95,17 +85,8 @@ impl CreateSpectrumTexture for SpectrumScaledTexture {
|
|||
|
||||
Ok(SpectrumTexture::Scaled(SpectrumScaledTexture {
|
||||
tex,
|
||||
scale,
|
||||
scale
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl SpectrumTextureTrait for SpectrumScaledTexture {
|
||||
fn evaluate(&self, ctx: &TextureEvalContext, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
let sc = self.scale.evaluate(ctx);
|
||||
if sc == 0. {
|
||||
return SampledSpectrum::new(0.);
|
||||
}
|
||||
self.tex.evaluate(ctx, lambda) * sc
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use anyhow::Result;
|
|||
use shared::{textures::WindyTexture, utils::Transform};
|
||||
|
||||
use crate::{
|
||||
core::texture::{CreateFloatTexture, FloatTexture, FloatTextureTrait},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
core::texture::{CreateFloatTexture, FloatTexture },
|
||||
utils::{FileLoc, TextureParameterDictionary}
|
||||
};
|
||||
|
||||
impl CreateFloatTexture for WindyTexture {
|
||||
|
|
@ -18,8 +18,3 @@ impl CreateFloatTexture for WindyTexture {
|
|||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for WindyTexture {
|
||||
fn evaluate(&self, _ctx: &shared::core::texture::TextureEvalContext) -> shared::Float {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use anyhow::Result;
|
|||
use shared::{textures::WrinkledTexture, utils::Transform};
|
||||
|
||||
use crate::{
|
||||
core::texture::{CreateFloatTexture, FloatTexture, FloatTextureTrait},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
core::texture::{CreateFloatTexture, FloatTexture },
|
||||
utils::{FileLoc, TextureParameterDictionary}
|
||||
};
|
||||
|
||||
impl CreateFloatTexture for WrinkledTexture {
|
||||
|
|
@ -18,8 +18,3 @@ impl CreateFloatTexture for WrinkledTexture {
|
|||
}
|
||||
}
|
||||
|
||||
impl FloatTextureTrait for WrinkledTexture {
|
||||
fn evaluate(&self, _ctx: &shared::core::texture::TextureEvalContext) -> shared::Float {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use thiserror::Error;
|
||||
use anyhow::Result;
|
||||
use flate2::read::GzDecoder;
|
||||
use memmap2::Mmap;
|
||||
|
|
@ -247,17 +248,39 @@ impl Token {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ParserError {
|
||||
#[error("{0}")]
|
||||
Io(String),
|
||||
#[error("unexpected end of file")]
|
||||
UnexpectedEof,
|
||||
#[error("invalid UTF-8: {0}")]
|
||||
InvalidUtf8(String),
|
||||
#[error("{1}: {0}")]
|
||||
Generic(String, FileLoc),
|
||||
#[error("{1}: expected an integer: {0}")]
|
||||
ParseIntError(String, FileLoc),
|
||||
#[error("{1}: expected a float: {0}")]
|
||||
ParseFloatError(String, FileLoc),
|
||||
#[error("{1}: numeric overflow: {0}")]
|
||||
NumericOverflow(String, FileLoc),
|
||||
}
|
||||
|
||||
/// Attach a source location to any foreign error, converting it into a
|
||||
/// `ParserError`. This is the only sanctioned direction: typed errors are
|
||||
/// produced *at* the boundary that knows the `FileLoc`, never recovered from an
|
||||
/// erased `anyhow::Error` after the fact.
|
||||
pub trait AtLoc<T> {
|
||||
fn at(self, loc: &FileLoc) -> Result<T, ParserError>;
|
||||
}
|
||||
|
||||
impl<T, E: std::fmt::Display> AtLoc<T> for Result<T, E> {
|
||||
fn at(self, loc: &FileLoc) -> Result<T, ParserError> {
|
||||
// `{:#}` renders anyhow's full context chain; harmless for plain errors.
|
||||
self.map_err(|e| ParserError::Generic(format!("{e:#}"), loc.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum TokenizerBuffer {
|
||||
Ram(String),
|
||||
Mapped(Mmap),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use super::CpuAggregate;
|
||||
use crate::globals::get_options;
|
||||
use crate::lights::sampler::create_light_sampler;
|
||||
use crate::Arena;
|
||||
use crate::ParameterDictionary;
|
||||
use crate::PbrtProgress;
|
||||
use crate::globals::get_options;
|
||||
use crate::lights::sampler::create_light_sampler;
|
||||
use log::debug;
|
||||
use rayon::prelude::*;
|
||||
use shared::core::LightIdx;
|
||||
use shared::core::bxdf::{FArgs, TransportMode};
|
||||
use shared::core::camera::{Camera, CameraTrait};
|
||||
use shared::core::film::VisibleSurface;
|
||||
|
|
@ -18,24 +19,23 @@ use shared::core::interaction::InteractionTrait;
|
|||
use shared::core::light::{Light, LightSampleContext, LightTrait};
|
||||
use shared::core::material::{Material, MaterialEvalContext, MaterialTrait};
|
||||
use shared::core::primitive::{Primitive, PrimitiveTrait};
|
||||
use shared::core::sampler::{get_camera_sample, CameraSample, Sampler, SamplerTrait};
|
||||
use shared::core::sampler::{CameraSample, Sampler, SamplerTrait, get_camera_sample};
|
||||
use shared::core::texture::{BasicTextureEvaluator, TextureEvalContext, UniversalTextureEvaluator};
|
||||
use shared::core::LightIdx;
|
||||
use shared::lights::sampler::{LightSampler, LightSamplerTrait};
|
||||
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
||||
use shared::textures::image::{
|
||||
DIAG_IMG_COUNT, DIAG_IMG_PIXEL0_BITS, DIAG_IMG_RESULT0_BITS, DIAG_IMG_RGB0_BITS,
|
||||
DIAG_IMG_SCALE_BITS,
|
||||
};
|
||||
use shared::utils::math::square;
|
||||
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, gvec_from_slice, GVec, Ptr, SHADOW_EPSILON};
|
||||
use shared::textures::image::{
|
||||
DIAG_IMG_COUNT, DIAG_IMG_SCALE_BITS, DIAG_IMG_PIXEL0_BITS,
|
||||
DIAG_IMG_RGB0_BITS, DIAG_IMG_RESULT0_BITS,
|
||||
};
|
||||
use shared::{GVec, Ptr, SHADOW_EPSILON, gvec, gvec_from_slice};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
static DIAG_EVAL_ENTER: AtomicU32 = AtomicU32::new(0);
|
||||
static DIAG_BSDF_EMPTY: AtomicU32 = AtomicU32::new(0);
|
||||
|
|
@ -232,23 +232,39 @@ impl CpuWavefrontRenderer {
|
|||
eprintln!("=== DIAG s=0 y0={} depth={} ===", y0, depth);
|
||||
eprintln!(" eval_enter={}", DIAG_EVAL_ENTER.load(Ordering::Relaxed));
|
||||
eprintln!(" bsdf_empty={}", DIAG_BSDF_EMPTY.load(Ordering::Relaxed));
|
||||
eprintln!(" non_specular_skip={}", DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed));
|
||||
eprintln!(" sample_light_none={}", DIAG_SAMPLE_LIGHT_NONE.load(Ordering::Relaxed));
|
||||
eprintln!(" sample_li_none={}", DIAG_SAMPLE_LI_NONE.load(Ordering::Relaxed));
|
||||
eprintln!(
|
||||
" non_specular_skip={}",
|
||||
DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed)
|
||||
);
|
||||
eprintln!(
|
||||
" sample_light_none={}",
|
||||
DIAG_SAMPLE_LIGHT_NONE.load(Ordering::Relaxed)
|
||||
);
|
||||
eprintln!(
|
||||
" sample_li_none={}",
|
||||
DIAG_SAMPLE_LI_NONE.load(Ordering::Relaxed)
|
||||
);
|
||||
eprintln!(" ls_l_black={}", DIAG_LS_L_BLACK.load(Ordering::Relaxed));
|
||||
eprintln!(" ls_pdf_zero={}", DIAG_LS_PDF_ZERO.load(Ordering::Relaxed));
|
||||
eprintln!(" f_none={}", DIAG_F_NONE.load(Ordering::Relaxed));
|
||||
eprintln!(" f_black={}", DIAG_F_BLACK.load(Ordering::Relaxed));
|
||||
eprintln!(" shadow_push={}", DIAG_SHADOW_PUSH.load(Ordering::Relaxed));
|
||||
eprintln!(" shadow_unoccluded={}", super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed));
|
||||
eprintln!(
|
||||
" shadow_unoccluded={}",
|
||||
super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed)
|
||||
);
|
||||
let img_n = DIAG_IMG_COUNT.load(Ordering::Relaxed);
|
||||
if img_n > 0 {
|
||||
let scale = f32::from_bits(DIAG_IMG_SCALE_BITS.load(Ordering::Relaxed));
|
||||
let pixel0 = f32::from_bits(DIAG_IMG_PIXEL0_BITS.load(Ordering::Relaxed));
|
||||
let pixel0 =
|
||||
f32::from_bits(DIAG_IMG_PIXEL0_BITS.load(Ordering::Relaxed));
|
||||
let rgb0 = f32::from_bits(DIAG_IMG_RGB0_BITS.load(Ordering::Relaxed));
|
||||
let result0 = f32::from_bits(DIAG_IMG_RESULT0_BITS.load(Ordering::Relaxed));
|
||||
eprintln!(" img_tex_calls={} scale={:.6} pixel0={:.6} rgb0_pre_scale={:.6} result[0]={:.6}",
|
||||
img_n, scale, pixel0, rgb0, result0);
|
||||
let result0 =
|
||||
f32::from_bits(DIAG_IMG_RESULT0_BITS.load(Ordering::Relaxed));
|
||||
eprintln!(
|
||||
" img_tex_calls={} scale={:.6} pixel0={:.6} rgb0_pre_scale={:.6} result[0]={:.6}",
|
||||
img_n, scale, pixel0, rgb0, result0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -263,15 +279,27 @@ impl CpuWavefrontRenderer {
|
|||
eprintln!("=== NEE DIAG COUNTS ===");
|
||||
eprintln!("eval_enter={}", DIAG_EVAL_ENTER.load(Ordering::Relaxed));
|
||||
eprintln!("bsdf_empty={}", DIAG_BSDF_EMPTY.load(Ordering::Relaxed));
|
||||
eprintln!("non_specular_skip={}", DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed));
|
||||
eprintln!("sample_light_none={}", DIAG_SAMPLE_LIGHT_NONE.load(Ordering::Relaxed));
|
||||
eprintln!("sample_li_none={}", DIAG_SAMPLE_LI_NONE.load(Ordering::Relaxed));
|
||||
eprintln!(
|
||||
"non_specular_skip={}",
|
||||
DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed)
|
||||
);
|
||||
eprintln!(
|
||||
"sample_light_none={}",
|
||||
DIAG_SAMPLE_LIGHT_NONE.load(Ordering::Relaxed)
|
||||
);
|
||||
eprintln!(
|
||||
"sample_li_none={}",
|
||||
DIAG_SAMPLE_LI_NONE.load(Ordering::Relaxed)
|
||||
);
|
||||
eprintln!("ls_l_black={}", DIAG_LS_L_BLACK.load(Ordering::Relaxed));
|
||||
eprintln!("ls_pdf_zero={}", DIAG_LS_PDF_ZERO.load(Ordering::Relaxed));
|
||||
eprintln!("f_none={}", DIAG_F_NONE.load(Ordering::Relaxed));
|
||||
eprintln!("f_black={}", DIAG_F_BLACK.load(Ordering::Relaxed));
|
||||
eprintln!("shadow_push={}", DIAG_SHADOW_PUSH.load(Ordering::Relaxed));
|
||||
eprintln!("shadow_unoccluded={}", super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed));
|
||||
eprintln!(
|
||||
"shadow_unoccluded={}",
|
||||
super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed)
|
||||
);
|
||||
}
|
||||
|
||||
fn generate_camera_rays(
|
||||
|
|
@ -464,11 +492,19 @@ impl CpuWavefrontRenderer {
|
|||
dpdu={:?} dpdv={:?} \
|
||||
dpdus={:?} dpdvs={:?} \
|
||||
uv={:?} material={:?} area_light={:?} face_index={}",
|
||||
w.pixel_index, w.depth,
|
||||
w.p, w.n, w.ns,
|
||||
w.dpdu, w.dpdv,
|
||||
w.dpdus, w.dpdvs,
|
||||
w.uv, w.material, w.area_light, w.face_index,
|
||||
w.pixel_index,
|
||||
w.depth,
|
||||
w.p,
|
||||
w.n,
|
||||
w.ns,
|
||||
w.dpdu,
|
||||
w.dpdv,
|
||||
w.dpdus,
|
||||
w.dpdvs,
|
||||
w.uv,
|
||||
w.material,
|
||||
w.area_light,
|
||||
w.face_index,
|
||||
);
|
||||
}
|
||||
DIAG_EVAL_ENTER.fetch_add(1, Ordering::Relaxed);
|
||||
|
|
@ -500,12 +536,12 @@ impl CpuWavefrontRenderer {
|
|||
dpdus: w.dpdus,
|
||||
};
|
||||
|
||||
let lambda = w.lambda;
|
||||
let mut lambda = w.lambda;
|
||||
|
||||
let mut bsdf = if use_universal {
|
||||
material.get_bsdf(&UniversalTextureEvaluator, &ctx, &lambda)
|
||||
material.get_bsdf(&UniversalTextureEvaluator, &ctx, &mut lambda)
|
||||
} else {
|
||||
material.get_bsdf(&BasicTextureEvaluator, &ctx, &lambda)
|
||||
material.get_bsdf(&BasicTextureEvaluator, &ctx, &mut lambda)
|
||||
};
|
||||
|
||||
if lambda.secondary_terminated() {
|
||||
|
|
@ -658,8 +694,16 @@ impl CpuWavefrontRenderer {
|
|||
"NEE_D0[{n}] pixel={:?} ls.l={:?} ls.pdf={:.6} f={:?} \
|
||||
beta={:?} light_pdf={:.6} bsdf_pdf={:.6} \
|
||||
r_u={:?} r_l={:?} l_d={:?}",
|
||||
w.pixel_index, ls.l, ls.pdf, f, beta,
|
||||
light_pdf, bsdf_pdf, r_u, r_l, l_d
|
||||
w.pixel_index,
|
||||
ls.l,
|
||||
ls.pdf,
|
||||
f,
|
||||
beta,
|
||||
light_pdf,
|
||||
bsdf_pdf,
|
||||
r_u,
|
||||
r_l,
|
||||
l_d
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue