Compare commits
No commits in common. "7c35f9b1805dcf8862757fb99caf995cc3cde344" and "1b8ca71b0ebba1d7a57736ccc2a90e6a9ce14f77" have entirely different histories.
7c35f9b180
...
1b8ca71b0e
42 changed files with 557 additions and 910 deletions
14
Cargo.toml
14
Cargo.toml
|
|
@ -76,17 +76,3 @@ wrong_self_convention = "allow"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
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,8 +4,9 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.100"
|
||||||
bitflags = "2.10.0"
|
bitflags = "2.10.0"
|
||||||
half = { version = "2.7.1", default-features = false }
|
half = "2.7.1"
|
||||||
bytemuck = { version = "1.24.0", features = ["derive"] }
|
bytemuck = { version = "1.24.0", features = ["derive"] }
|
||||||
enum_dispatch = "0.3.13"
|
enum_dispatch = "0.3.13"
|
||||||
ash = { version = "0.38", optional = true }
|
ash = { version = "0.38", optional = true }
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::core::bsdf::BSDFSample;
|
use crate::core::bsdf::BSDFSample;
|
||||||
use crate::core::bxdf::{BxDFFlags, BxDFReflTransFlags, BxDFTrait, FArgs, TransportMode};
|
use crate::core::bxdf::{BxDFFlags, BxDFReflTransFlags, BxDFTrait, FArgs, TransportMode};
|
||||||
use crate::core::geometry::{
|
use crate::core::geometry::{
|
||||||
Normal3f, Point2f, Vector3f, VectorLike, abs_cos_theta, cos_theta, same_hemisphere,
|
abs_cos_theta, cos_theta, same_hemisphere, Normal3f, Point2f, Vector3f, VectorLike,
|
||||||
};
|
};
|
||||||
use crate::core::scattering::{
|
use crate::core::scattering::{
|
||||||
TrowbridgeReitzDistribution, fr_complex_from_spectrum, fr_dielectric, reflect, refract,
|
fr_complex_from_spectrum, fr_dielectric, reflect, refract, TrowbridgeReitzDistribution,
|
||||||
};
|
};
|
||||||
use crate::spectra::SampledSpectrum;
|
use crate::spectra::SampledSpectrum;
|
||||||
use crate::utils::math::square;
|
use crate::utils::math::square;
|
||||||
|
|
@ -362,6 +362,7 @@ impl BxDFTrait for ThinDielectricBxDF {
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
fn regularize(&mut self) {
|
||||||
fn regularize(&mut self) {}
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,118 +73,4 @@ impl BxDFTrait for DiffuseBxDF {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[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,7 +146,6 @@ pub trait BxDFTrait: Any {
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum BxDF {
|
pub enum BxDF {
|
||||||
Diffuse(DiffuseBxDF),
|
Diffuse(DiffuseBxDF),
|
||||||
DiffuseTransmission(DiffuseTransmissionBxDF),
|
|
||||||
Dielectric(DielectricBxDF),
|
Dielectric(DielectricBxDF),
|
||||||
ThinDielectric(ThinDielectricBxDF),
|
ThinDielectric(ThinDielectricBxDF),
|
||||||
Conductor(ConductorBxDF),
|
Conductor(ConductorBxDF),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use core::fmt;
|
||||||
use core::ops::{
|
use core::ops::{
|
||||||
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
||||||
};
|
};
|
||||||
use crate::utils::error::{Error, Result};
|
use anyhow::{Result, bail};
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use num_traits::Float as NumFloat;
|
use num_traits::Float as NumFloat;
|
||||||
|
|
||||||
|
|
@ -686,7 +686,7 @@ impl ColorEncoding {
|
||||||
match name {
|
match name {
|
||||||
"sRGB" | "srgb" => Ok(ColorEncoding::SRGB(SRGBEncoding)),
|
"sRGB" | "srgb" => Ok(ColorEncoding::SRGB(SRGBEncoding)),
|
||||||
"linear" => Ok(ColorEncoding::Linear(LinearEncoding)),
|
"linear" => Ok(ColorEncoding::Linear(LinearEncoding)),
|
||||||
_ => Err(Error::UnknownColorEncoding),
|
_ => bail!("Unknown color encoding: {}", name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::core::color::{ColorEncoding, ColorEncodingTrait, LINEAR};
|
||||||
use crate::core::geometry::{Bounds2f, Point2f, Point2fi, Point2i};
|
use crate::core::geometry::{Bounds2f, Point2f, Point2fi, Point2i};
|
||||||
use crate::utils::math::{f16_to_f32_software, lerp, square};
|
use crate::utils::math::{f16_to_f32_software, lerp, square};
|
||||||
use crate::{gvec_with_capacity, Float, GVec, Ptr};
|
use crate::{gvec_with_capacity, Float, GVec, Ptr};
|
||||||
use crate::utils::error::{Error, Result};
|
use anyhow::{bail, Result};
|
||||||
use core::hash;
|
use core::hash;
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use num_traits::Float as NumFloat;
|
use num_traits::Float as NumFloat;
|
||||||
|
|
@ -23,7 +23,7 @@ impl WrapMode {
|
||||||
"black" => Ok(WrapMode::Black),
|
"black" => Ok(WrapMode::Black),
|
||||||
"repeat" => Ok(WrapMode::Repeat),
|
"repeat" => Ok(WrapMode::Repeat),
|
||||||
"octahedralsphere" => Ok(WrapMode::OctahedralSphere),
|
"octahedralsphere" => Ok(WrapMode::OctahedralSphere),
|
||||||
_ => Err(Error::UnknownWrapMode),
|
_ => bail!("{:?}: wrap mode unknown", name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -503,7 +503,7 @@ impl FilterFunction {
|
||||||
"trilinear" => Ok(FilterFunction::Trilinear),
|
"trilinear" => Ok(FilterFunction::Trilinear),
|
||||||
"bilinear" => Ok(FilterFunction::Bilinear),
|
"bilinear" => Ok(FilterFunction::Bilinear),
|
||||||
"point" => Ok(FilterFunction::Point),
|
"point" => Ok(FilterFunction::Point),
|
||||||
_ => Err(Error::UnknownFilterFunction),
|
_ => bail!("Filter function unknown"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ use crate::materials::*;
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
|
|
||||||
use crate::Float;
|
|
||||||
use crate::bxdfs::{
|
use crate::bxdfs::{
|
||||||
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF,
|
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF,
|
||||||
};
|
};
|
||||||
|
|
@ -14,12 +13,15 @@ use crate::core::image::{Image, WrapMode, WrapMode2D};
|
||||||
use crate::core::interaction::{Interaction, InteractionTrait, ShadingGeom, SurfaceInteraction};
|
use crate::core::interaction::{Interaction, InteractionTrait, ShadingGeom, SurfaceInteraction};
|
||||||
use crate::core::scattering::TrowbridgeReitzDistribution;
|
use crate::core::scattering::TrowbridgeReitzDistribution;
|
||||||
use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
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::materials::*;
|
||||||
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::Ptr;
|
|
||||||
use crate::utils::hash::hash_float;
|
use crate::utils::hash::hash_float;
|
||||||
use crate::utils::math::clamp;
|
use crate::utils::math::clamp;
|
||||||
|
use crate::utils::Ptr;
|
||||||
|
use crate::Float;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, Copy)]
|
#[derive(Clone, Debug, Copy)]
|
||||||
|
|
@ -160,7 +162,7 @@ pub trait MaterialTrait {
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> BSDF;
|
) -> BSDF;
|
||||||
|
|
||||||
fn get_bssrdf<T: TextureEvaluator>(
|
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::geometry::{Bounds2f, Point2f, Point2i, Vector2f};
|
||||||
use crate::core::pbrt::{Float, ONE_MINUS_EPSILON, PI, PI_OVER_2, PI_OVER_4};
|
use crate::core::pbrt::{Float, ONE_MINUS_EPSILON, PI, PI_OVER_2, PI_OVER_4};
|
||||||
use crate::utils::math::{
|
use crate::utils::math::{
|
||||||
BinaryPermuteScrambler, DigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler,
|
clamp, encode_morton_2, inverse_radical_inverse, lerp, log2_int,
|
||||||
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,
|
owen_scrambled_radical_inverse, permutation_element, radical_inverse, round_up_pow2,
|
||||||
scrambled_radical_inverse, sobol_interval_to_index, sobol_sample,
|
scrambled_radical_inverse, sobol_interval_to_index, sobol_sample, BinaryPermuteScrambler,
|
||||||
|
DigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler, Scrambler, PRIME_TABLE_SIZE,
|
||||||
};
|
};
|
||||||
use crate::utils::rng::Rng;
|
use crate::utils::rng::Rng;
|
||||||
use crate::utils::sobol::N_SOBOL_DIMENSIONS;
|
use crate::utils::sobol::N_SOBOL_DIMENSIONS;
|
||||||
use crate::utils::{hash::*, sobol};
|
use crate::utils::{hash::*, sobol};
|
||||||
use crate::{GVec, Ptr, gvec};
|
use crate::{gvec, GVec, Ptr};
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -530,18 +530,6 @@ pub struct ZSobolSampler {
|
||||||
dim: u32,
|
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 {
|
impl ZSobolSampler {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
samples_per_pixel: i32,
|
samples_per_pixel: i32,
|
||||||
|
|
@ -549,12 +537,10 @@ impl ZSobolSampler {
|
||||||
randomize: RandomizeStrategy,
|
randomize: RandomizeStrategy,
|
||||||
seed: Option<u64>,
|
seed: Option<u64>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// pbrt calls the integer Log2Int overload; the float one disagrees for
|
let log2_samples_per_pixel = log2_int(samples_per_pixel as Float) as u32;
|
||||||
// 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 res = round_up_pow2(full_resolution.x().max(full_resolution.y()));
|
||||||
let log4_samples_per_pixel = log2_samples_per_pixel.div_ceil(2);
|
let log4_samples_per_pixel = log2_samples_per_pixel.div_ceil(2);
|
||||||
let n_base4_digits = (res.max(1) as u32).ilog2() + log4_samples_per_pixel;
|
let n_base4_digits = log2_int(res as Float) as u32 + log4_samples_per_pixel as u32;
|
||||||
Self {
|
Self {
|
||||||
randomize,
|
randomize,
|
||||||
seed: seed.unwrap_or(0),
|
seed: seed.unwrap_or(0),
|
||||||
|
|
@ -604,7 +590,7 @@ impl ZSobolSampler {
|
||||||
|
|
||||||
let higher_digits = self.morton_index >> (digit_shift + 2);
|
let higher_digits = self.morton_index >> (digit_shift + 2);
|
||||||
|
|
||||||
let mix_input = higher_digits ^ scramble_seed(self.dim);
|
let mix_input = higher_digits ^ (0x55555555 * self.dim as u64);
|
||||||
let p = (mix_bits(mix_input) >> 24) % 24;
|
let p = (mix_bits(mix_input) >> 24) % 24;
|
||||||
|
|
||||||
digit = PERMUTATIONS[p as usize][digit as usize] as u64;
|
digit = PERMUTATIONS[p as usize][digit as usize] as u64;
|
||||||
|
|
@ -613,9 +599,8 @@ impl ZSobolSampler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if pow2_samples {
|
if pow2_samples {
|
||||||
let digit = self.morton_index & 1;
|
let lsb = self.morton_index & 1;
|
||||||
sample_index |=
|
sample_index |= lsb;
|
||||||
digit ^ (mix_bits((self.morton_index >> 1) ^ scramble_seed(self.dim)) & 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sample_index
|
sample_index
|
||||||
|
|
@ -624,9 +609,8 @@ impl ZSobolSampler {
|
||||||
|
|
||||||
impl SamplerTrait for ZSobolSampler {
|
impl SamplerTrait for ZSobolSampler {
|
||||||
fn samples_per_pixel(&self) -> i32 {
|
fn samples_per_pixel(&self) -> i32 {
|
||||||
1 << self.log2_samples_per_pixel
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_pixel_sample(&mut self, p: Point2i, sample_index: i32, dim: Option<u32>) {
|
fn start_pixel_sample(&mut self, p: Point2i, sample_index: i32, dim: Option<u32>) {
|
||||||
self.dim = dim.unwrap_or(0);
|
self.dim = dim.unwrap_or(0);
|
||||||
self.morton_index = (encode_morton_2(p.x() as u32, p.y() as u32)
|
self.morton_index = (encode_morton_2(p.x() as u32, p.y() as u32)
|
||||||
|
|
@ -636,25 +620,31 @@ impl SamplerTrait for ZSobolSampler {
|
||||||
|
|
||||||
fn get1d(&mut self) -> Float {
|
fn get1d(&mut self) -> Float {
|
||||||
let sample_index = self.get_sample_index();
|
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;
|
self.dim += 1;
|
||||||
let hash = dim_seed_hash(self.dim, self.seed) as u32;
|
if self.randomize == RandomizeStrategy::None {
|
||||||
// Always Sobol dimension 0 -- decorrelation comes from the hash.
|
return sobol_sample(sample_index, self.dim, NoRandomizer);
|
||||||
|
}
|
||||||
match self.randomize {
|
match self.randomize {
|
||||||
RandomizeStrategy::None => sobol_sample(sample_index, 0, NoRandomizer),
|
|
||||||
RandomizeStrategy::PermuteDigits => {
|
RandomizeStrategy::PermuteDigits => {
|
||||||
sobol_sample(sample_index, 0, BinaryPermuteScrambler::new(hash))
|
sobol_sample(sample_index, self.dim, BinaryPermuteScrambler::new(hash))
|
||||||
}
|
}
|
||||||
RandomizeStrategy::FastOwen => {
|
RandomizeStrategy::FastOwen => {
|
||||||
sobol_sample(sample_index, 0, FastOwenScrambler::new(hash))
|
sobol_sample(sample_index, self.dim, FastOwenScrambler::new(hash))
|
||||||
}
|
}
|
||||||
RandomizeStrategy::Owen => sobol_sample(sample_index, 0, OwenScrambler::new(hash)),
|
RandomizeStrategy::Owen => {
|
||||||
|
sobol_sample(sample_index, self.dim, OwenScrambler::new(hash))
|
||||||
|
}
|
||||||
|
RandomizeStrategy::None => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get2d(&mut self) -> Point2f {
|
fn get2d(&mut self) -> Point2f {
|
||||||
let sample_index = self.get_sample_index();
|
let sample_index = self.get_sample_index();
|
||||||
self.dim += 2;
|
self.dim += 2;
|
||||||
let hash = dim_seed_hash(self.dim, self.seed);
|
let hash_input = [self.dim as u64, self.seed];
|
||||||
|
let hash = hash_buffer(&hash_input, 0);
|
||||||
let sample_hash = [hash as u32, (hash >> 32) as u32];
|
let sample_hash = [hash as u32, (hash >> 32) as u32];
|
||||||
if self.randomize == RandomizeStrategy::None {
|
if self.randomize == RandomizeStrategy::None {
|
||||||
return Point2f::new(
|
return Point2f::new(
|
||||||
|
|
@ -685,92 +675,16 @@ impl SamplerTrait for ZSobolSampler {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
struct PrimarySample {
|
pub struct MLTSampler;
|
||||||
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 {
|
impl SamplerTrait for MLTSampler {
|
||||||
fn samples_per_pixel(&self) -> i32 {
|
fn samples_per_pixel(&self) -> i32 {
|
||||||
self.mutations_per_pixel
|
todo!()
|
||||||
}
|
}
|
||||||
|
fn start_pixel_sample(&mut self, _p: Point2i, _sample_index: i32, _dim: Option<u32>) {
|
||||||
fn start_pixel_sample(&mut self, p: Point2i, sample_index: i32, dim: Option<u32>) {
|
todo!()
|
||||||
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 {
|
fn get1d(&mut self) -> Float {
|
||||||
#[cfg(not(any(feature = "cuda", feature = "vulkan")))]
|
todo!()
|
||||||
{
|
|
||||||
return 0.;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ind = self.get_next_index();
|
|
||||||
}
|
}
|
||||||
fn get2d(&mut self) -> Point2f {
|
fn get2d(&mut self) -> Point2f {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ impl MaterialTrait for CoatedDiffuseMaterial {
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
let r = SampledSpectrum::clamp(
|
let r = SampledSpectrum::clamp(
|
||||||
&tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda),
|
&tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda),
|
||||||
|
|
@ -220,7 +220,7 @@ impl MaterialTrait for CoatedConductorMaterial {
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
let mut iurough = tex_eval.evaluate_float(&self.interface_uroughness, ctx);
|
let mut iurough = tex_eval.evaluate_float(&self.interface_uroughness, ctx);
|
||||||
let mut ivrough = tex_eval.evaluate_float(&self.interface_vroughness, ctx);
|
let mut ivrough = tex_eval.evaluate_float(&self.interface_vroughness, ctx);
|
||||||
|
|
@ -234,6 +234,7 @@ impl MaterialTrait for CoatedConductorMaterial {
|
||||||
|
|
||||||
let mut ieta = self.interface_eta.evaluate(lambda[0]);
|
let mut ieta = self.interface_eta.evaluate(lambda[0]);
|
||||||
if self.interface_eta.is_constant() {
|
if self.interface_eta.is_constant() {
|
||||||
|
let mut lambda = *lambda;
|
||||||
lambda.terminate_secondary_inplace();
|
lambda.terminate_secondary_inplace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ impl MaterialTrait for HairMaterial {
|
||||||
&self,
|
&self,
|
||||||
_tex_eval: &T,
|
_tex_eval: &T,
|
||||||
_ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
_lambda: &mut SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ impl MaterialTrait for MeasuredMaterial {
|
||||||
&self,
|
&self,
|
||||||
_tex_eval: &T,
|
_tex_eval: &T,
|
||||||
_ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
_lambda: &mut SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
// MeasuredBxDF::new(&self.brdf, lambda)
|
// MeasuredBxDF::new(&self.brdf, lambda)
|
||||||
todo!()
|
todo!()
|
||||||
|
|
@ -157,7 +157,7 @@ impl MaterialTrait for SubsurfaceMaterial {
|
||||||
&self,
|
&self,
|
||||||
_tex_eval: &T,
|
_tex_eval: &T,
|
||||||
_ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
_lambda: &mut SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ use crate::core::scattering::TrowbridgeReitzDistribution;
|
||||||
use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
||||||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
||||||
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::Ptr;
|
|
||||||
use crate::utils::math::clamp;
|
use crate::utils::math::clamp;
|
||||||
|
use crate::utils::Ptr;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|
@ -55,7 +55,7 @@ impl MaterialTrait for ConductorMaterial {
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
let mut u_rough = tex_eval.evaluate_float(&self.u_roughness, ctx);
|
let mut u_rough = tex_eval.evaluate_float(&self.u_roughness, ctx);
|
||||||
let mut v_rough = tex_eval.evaluate_float(&self.v_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>(
|
fn get_bssrdf<T>(
|
||||||
&self,
|
&self,
|
||||||
_tex_eval: &T,
|
tex_eval: &T,
|
||||||
_ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
_lambda: &SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> Option<BSSRDF> {
|
) -> Option<BSSRDF> {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::Ptr;
|
|
||||||
use crate::bxdfs::{
|
use crate::bxdfs::{
|
||||||
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF, HairBxDF,
|
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF, HairBxDF,
|
||||||
ThinDielectricBxDF,
|
|
||||||
};
|
};
|
||||||
use crate::core::bsdf::BSDF;
|
use crate::core::bsdf::BSDF;
|
||||||
use crate::core::bssrdf::BSSRDF;
|
use crate::core::bssrdf::BSSRDF;
|
||||||
|
|
@ -13,6 +11,7 @@ use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
||||||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
||||||
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::math::clamp;
|
use crate::utils::math::clamp;
|
||||||
|
use crate::Ptr;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|
@ -30,11 +29,11 @@ impl MaterialTrait for DielectricMaterial {
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
let mut sampled_eta = self.eta.evaluate(lambda[0]);
|
let mut sampled_eta = self.eta.evaluate(lambda[0]);
|
||||||
if !self.eta.is_constant() {
|
if !self.eta.is_constant() {
|
||||||
lambda.terminate_secondary_inplace();
|
lambda.terminate_secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
if sampled_eta == 0.0 {
|
if sampled_eta == 0.0 {
|
||||||
|
|
@ -93,29 +92,18 @@ impl MaterialTrait for ThinDielectricMaterial {
|
||||||
fn get_bsdf<T: TextureEvaluator>(
|
fn get_bsdf<T: TextureEvaluator>(
|
||||||
&self,
|
&self,
|
||||||
_tex_eval: &T,
|
_tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
let mut sampled_eta = self.eta.evaluate(lambda[0]);
|
todo!()
|
||||||
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>(
|
fn get_bssrdf<T>(
|
||||||
&self,
|
&self,
|
||||||
_tex_eval: &T,
|
_tex_eval: &T,
|
||||||
_ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
_lambda: &SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> Option<BSSRDF> {
|
) -> Option<BSSRDF> {
|
||||||
None
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_evaluate_textures(&self, _tex_eval: &dyn TextureEvaluator) -> bool {
|
fn can_evaluate_textures(&self, _tex_eval: &dyn TextureEvaluator) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
use crate::Float;
|
|
||||||
use crate::Ptr;
|
|
||||||
use crate::bxdfs::{
|
use crate::bxdfs::{
|
||||||
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF,
|
CoatedConductorBxDF, CoatedDiffuseBxDF, ConductorBxDF, DielectricBxDF, DiffuseBxDF, HairBxDF,
|
||||||
DiffuseTransmissionBxDF, HairBxDF,
|
|
||||||
};
|
};
|
||||||
use crate::core::bsdf::BSDF;
|
use crate::core::bsdf::BSDF;
|
||||||
use crate::core::bssrdf::BSSRDF;
|
use crate::core::bssrdf::BSSRDF;
|
||||||
|
|
@ -14,6 +11,8 @@ use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
||||||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvaluator};
|
||||||
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::math::clamp;
|
use crate::utils::math::clamp;
|
||||||
|
use crate::Float;
|
||||||
|
use crate::Ptr;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|
@ -28,7 +27,7 @@ impl MaterialTrait for DiffuseMaterial {
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
let spec = tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda);
|
let spec = tex_eval.evaluate_spectrum(&self.reflectance, ctx, lambda);
|
||||||
let r = SampledSpectrum::clamp(&spec, 0., 1.);
|
let r = SampledSpectrum::clamp(&spec, 0., 1.);
|
||||||
|
|
@ -42,7 +41,7 @@ impl MaterialTrait for DiffuseMaterial {
|
||||||
_ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
_lambda: &SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> Option<BSSRDF> {
|
) -> Option<BSSRDF> {
|
||||||
None
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_evaluate_textures(&self, tex_eval: &dyn TextureEvaluator) -> bool {
|
fn can_evaluate_textures(&self, tex_eval: &dyn TextureEvaluator) -> bool {
|
||||||
|
|
@ -65,33 +64,21 @@ impl MaterialTrait for DiffuseMaterial {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct DiffuseTransmissionMaterial {
|
pub struct DiffuseTransmissionMaterial {
|
||||||
pub normal_map: Ptr<Image>,
|
pub image: Ptr<Image>,
|
||||||
pub displacement: Ptr<FloatTexture>,
|
pub displacement: Ptr<FloatTexture>,
|
||||||
pub reflectance: Ptr<SpectrumTexture>,
|
pub reflectance: Ptr<FloatTexture>,
|
||||||
pub transmittance: Ptr<SpectrumTexture>,
|
pub transmittance: Ptr<FloatTexture>,
|
||||||
pub scale: Float,
|
pub scale: Float,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaterialTrait for DiffuseTransmissionMaterial {
|
impl MaterialTrait for DiffuseTransmissionMaterial {
|
||||||
fn get_bsdf<T: TextureEvaluator>(
|
fn get_bsdf<T: TextureEvaluator>(
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
_tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
let r = SampledSpectrum::clamp(
|
todo!()
|
||||||
&(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>(
|
fn get_bssrdf<T>(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -99,15 +86,15 @@ impl MaterialTrait for DiffuseTransmissionMaterial {
|
||||||
_ctx: &MaterialEvalContext,
|
_ctx: &MaterialEvalContext,
|
||||||
_lambda: &SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
) -> Option<BSSRDF> {
|
) -> Option<BSSRDF> {
|
||||||
None
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_evaluate_textures(&self, tex_eval: &dyn TextureEvaluator) -> bool {
|
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> {
|
fn get_normal_map(&self) -> Option<&Image> {
|
||||||
self.normal_map.get()
|
self.image.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_displacement(&self) -> Ptr<FloatTexture> {
|
fn get_displacement(&self) -> Ptr<FloatTexture> {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ impl MaterialTrait for MixMaterial {
|
||||||
&self,
|
&self,
|
||||||
tex_eval: &T,
|
tex_eval: &T,
|
||||||
ctx: &MaterialEvalContext,
|
ctx: &MaterialEvalContext,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> BSDF {
|
) -> BSDF {
|
||||||
if let Some(mat) = self.choose_material(tex_eval, ctx) {
|
if let Some(mat) = self.choose_material(tex_eval, ctx) {
|
||||||
mat.get_bsdf(tex_eval, ctx, lambda)
|
mat.get_bsdf(tex_eval, ctx, lambda)
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,14 @@ use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::{Ptr, math::square};
|
use crate::utils::{Ptr, math::square};
|
||||||
use num_traits::Float as NumFloat;
|
use num_traits::Float as NumFloat;
|
||||||
|
|
||||||
#[repr(C)]
|
fn checkerboard(
|
||||||
#[derive(Debug, Copy, Clone)]
|
ctx: &TextureEvalContext,
|
||||||
pub enum CheckerMap {
|
map2d: Ptr<TextureMapping2D>,
|
||||||
D2(TextureMapping2D),
|
map3d: Ptr<TextureMapping3D>,
|
||||||
D3(TextureMapping3D),
|
) -> Float {
|
||||||
}
|
|
||||||
|
|
||||||
fn checkerboard(ctx: &TextureEvalContext, checker_map: CheckerMap) -> Float {
|
|
||||||
let d = |x: Float| -> Float {
|
let d = |x: Float| -> Float {
|
||||||
let y = x / 2. - (x / 2.).floor() - 0.5;
|
let y = x / 2. - (x / 2.).floor() - 0.5;
|
||||||
x / 2. + y * (1. - 2. * y.abs())
|
return x / 2. + y * (1. - 2. * y.abs());
|
||||||
};
|
};
|
||||||
|
|
||||||
let bf = |x: Float, r: Float| -> Float {
|
let bf = |x: Float, r: Float| -> Float {
|
||||||
|
|
@ -27,53 +24,49 @@ fn checkerboard(ctx: &TextureEvalContext, checker_map: CheckerMap) -> Float {
|
||||||
(d(x + r) - 2. * d(x) + d(x - r)) / square(r)
|
(d(x + r) - 2. * d(x) + d(x - r)) / square(r)
|
||||||
};
|
};
|
||||||
|
|
||||||
match checker_map {
|
if !map2d.is_null() {
|
||||||
CheckerMap::D2(map) => {
|
assert!(map3d.is_null());
|
||||||
let c = map.map(ctx);
|
let c = map2d.map(&ctx);
|
||||||
let ds = 1.5 * c.dsdx.abs().max(c.dsdy.abs());
|
let ds = 1.5 * c.dsdx.abs().max(c.dsdy.abs());
|
||||||
let dt = 1.5 * c.dtdx.abs().max(c.dtdy.abs());
|
let dt = 1.5 * c.dtdx.abs().max(c.dtdy.abs());
|
||||||
// Integrate product of 2D checkerboard function and triangle filter
|
// Integrate product of 2D checkerboard function and triangle filter
|
||||||
0.5 - bf(c.st[0], ds) * bf(c.st[1], dt) / 2.
|
0.5 - bf(c.st[0], ds) * bf(c.st[1], dt) / 2.
|
||||||
}
|
} else {
|
||||||
CheckerMap::D3(map) => {
|
assert!(!map3d.is_null());
|
||||||
let c = map.map(ctx);
|
let c = map3d.map(&ctx);
|
||||||
let dx = 1.5 * c.dpdx.x().abs().max(c.dpdy.x().abs());
|
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 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());
|
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)
|
0.5 - bf(c.p.x(), dx) * bf(c.p.y(), dy) * bf(c.p.z(), dz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct FloatCheckerboardTexture {
|
pub struct FloatCheckerboardTexture {
|
||||||
pub map: CheckerMap,
|
pub map2d: Ptr<TextureMapping2D>,
|
||||||
|
pub map3d: Ptr<TextureMapping3D>,
|
||||||
pub tex: [Ptr<FloatTexture>; 2],
|
pub tex: [Ptr<FloatTexture>; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatCheckerboardTexture {
|
impl FloatCheckerboardTexture {
|
||||||
pub fn new(map: CheckerMap, tex: [Ptr<FloatTexture>; 2]) -> Self {
|
|
||||||
Self { map, tex }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||||
let w = checkerboard(ctx, self.map);
|
let w = checkerboard(&ctx, self.map2d, self.map3d);
|
||||||
|
|
||||||
let mut t0 = 0.0;
|
let mut t0 = 0.0;
|
||||||
let mut t1 = 0.0;
|
let mut t1 = 0.0;
|
||||||
|
|
||||||
if w != 1.0
|
if w != 1.0 {
|
||||||
&& let Some(tex) = self.tex[0].get()
|
if let Some(tex) = self.tex[0].get() {
|
||||||
{
|
|
||||||
t0 = tex.evaluate(ctx);
|
t0 = tex.evaluate(ctx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if w != 0.0
|
if w != 0.0 {
|
||||||
&& let Some(tex) = self.tex[1].get()
|
if let Some(tex) = self.tex[1].get() {
|
||||||
{
|
|
||||||
t1 = tex.evaluate(ctx);
|
t1 = tex.evaluate(ctx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(1.0 - w) * t0 + w * t1
|
(1.0 - w) * t0 + w * t1
|
||||||
}
|
}
|
||||||
|
|
@ -82,34 +75,31 @@ impl FloatCheckerboardTexture {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct SpectrumCheckerboardTexture {
|
pub struct SpectrumCheckerboardTexture {
|
||||||
pub map: CheckerMap,
|
pub map2d: Ptr<TextureMapping2D>,
|
||||||
|
pub map3d: Ptr<TextureMapping3D>,
|
||||||
pub tex: [Ptr<SpectrumTexture>; 2],
|
pub tex: [Ptr<SpectrumTexture>; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpectrumCheckerboardTexture {
|
impl SpectrumCheckerboardTexture {
|
||||||
pub fn new(map: CheckerMap, tex: [Ptr<SpectrumTexture>; 2]) -> Self {
|
|
||||||
Self { map, tex }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn evaluate(
|
pub fn evaluate(
|
||||||
&self,
|
&self,
|
||||||
ctx: &TextureEvalContext,
|
ctx: &TextureEvalContext,
|
||||||
lambda: &SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
) -> SampledSpectrum {
|
) -> SampledSpectrum {
|
||||||
let w = checkerboard(ctx, self.map);
|
let w = checkerboard(ctx, self.map2d, self.map3d);
|
||||||
let mut t0 = SampledSpectrum::new(0.);
|
let mut t0 = SampledSpectrum::new(0.);
|
||||||
let mut t1 = SampledSpectrum::new(0.);
|
let mut t1 = SampledSpectrum::new(0.);
|
||||||
if w != 1.0
|
if w != 1.0 {
|
||||||
&& let Some(tex) = self.tex[0].get()
|
if let Some(tex) = self.tex[0].get() {
|
||||||
{
|
|
||||||
t0 = tex.evaluate(ctx, lambda);
|
t0 = tex.evaluate(ctx, lambda);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if w != 0.0
|
if w != 0.0 {
|
||||||
&& let Some(tex) = self.tex[1].get()
|
if let Some(tex) = self.tex[1].get() {
|
||||||
{
|
|
||||||
t1 = tex.evaluate(ctx, lambda);
|
t1 = tex.evaluate(ctx, lambda);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
t0 * (1.0 - w) + t1 * w
|
t0 * (1.0 - w) + t1 * w
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::Float;
|
use crate::Float;
|
||||||
use crate::core::geometry::{Point2f, VectorLike};
|
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::spectra::sampled::{SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::Ptr;
|
use crate::utils::Ptr;
|
||||||
use crate::utils::math::square;
|
use crate::utils::math::square;
|
||||||
|
|
@ -20,30 +22,18 @@ fn inside_polka_dot(st: Point2f) -> bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct FloatDotsTexture {
|
pub struct FloatDotsTexture {
|
||||||
pub mapping: TextureMapping2D,
|
pub mapping: TextureMapping2D,
|
||||||
pub inside_dot: Ptr<FloatTexture>,
|
|
||||||
pub outside_dot: Ptr<FloatTexture>,
|
pub outside_dot: Ptr<FloatTexture>,
|
||||||
|
pub inside_dot: Ptr<FloatTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatDotsTexture {
|
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 {
|
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||||
let c = self.mapping.map(ctx);
|
let c = self.mapping.map(ctx);
|
||||||
let target_texture = if inside_polka_dot(c.st) {
|
let target_texture = if inside_polka_dot(c.st) {
|
||||||
|
|
@ -64,22 +54,11 @@ impl FloatDotsTexture {
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct SpectrumDotsTexture {
|
pub struct SpectrumDotsTexture {
|
||||||
pub mapping: TextureMapping2D,
|
pub mapping: TextureMapping2D,
|
||||||
pub inside_dot: Ptr<SpectrumTexture>,
|
|
||||||
pub outside_dot: Ptr<SpectrumTexture>,
|
pub outside_dot: Ptr<SpectrumTexture>,
|
||||||
|
pub inside_dot: Ptr<SpectrumTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpectrumDotsTexture {
|
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(
|
pub fn evaluate(
|
||||||
&self,
|
&self,
|
||||||
ctx: &TextureEvalContext,
|
ctx: &TextureEvalContext,
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,11 @@ use crate::utils::noise::fbm;
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct FBmTexture {
|
pub struct FBmTexture {
|
||||||
pub mapping: TextureMapping3D,
|
pub mapping: TextureMapping3D,
|
||||||
pub octaves: u32,
|
|
||||||
pub omega: Float,
|
pub omega: Float,
|
||||||
|
pub octaves: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FBmTexture {
|
impl FBmTexture {
|
||||||
pub fn new(mapping: TextureMapping3D, octaves: u32, omega: Float) -> Self {
|
|
||||||
Self {
|
|
||||||
mapping,
|
|
||||||
omega,
|
|
||||||
octaves,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||||
let c = self.mapping.map(ctx);
|
let c = self.mapping.map(ctx);
|
||||||
fbm(c.p, c.dpdx, c.dpdy, self.omega, self.octaves)
|
fbm(c.p, c.dpdx, c.dpdy, self.omega, self.octaves)
|
||||||
|
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
//! 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,7 +2,6 @@ pub mod alloc;
|
||||||
pub mod atomic;
|
pub mod atomic;
|
||||||
pub mod complex;
|
pub mod complex;
|
||||||
pub mod containers;
|
pub mod containers;
|
||||||
pub mod error;
|
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
pub mod interval;
|
pub mod interval;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use alloc::string::String;
|
|
||||||
use crate::Float;
|
use crate::Float;
|
||||||
use crate::core::geometry::{Bounds2f, Bounds2i, Point2f, Point2i};
|
use crate::core::geometry::{Bounds2f, Bounds2i, Point2f, Point2i};
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
|
@ -18,7 +17,6 @@ pub struct BasicPBRTOptions {
|
||||||
pub disable_wavelength_jitter: bool,
|
pub disable_wavelength_jitter: bool,
|
||||||
pub disable_texture_filtering: bool,
|
pub disable_texture_filtering: bool,
|
||||||
pub force_diffuse: bool,
|
pub force_diffuse: bool,
|
||||||
pub record_pixel_statistics: bool,
|
|
||||||
pub use_gpu: bool,
|
pub use_gpu: bool,
|
||||||
pub wavefront: bool,
|
pub wavefront: bool,
|
||||||
pub interactive: bool,
|
pub interactive: bool,
|
||||||
|
|
@ -35,7 +33,6 @@ impl Default for BasicPBRTOptions {
|
||||||
disable_wavelength_jitter: false,
|
disable_wavelength_jitter: false,
|
||||||
disable_texture_filtering: false,
|
disable_texture_filtering: false,
|
||||||
force_diffuse: false,
|
force_diffuse: false,
|
||||||
record_pixel_statistics: false,
|
|
||||||
use_gpu: false,
|
use_gpu: false,
|
||||||
wavefront: false,
|
wavefront: false,
|
||||||
interactive: false,
|
interactive: false,
|
||||||
|
|
@ -45,7 +42,7 @@ impl Default for BasicPBRTOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct PBRTOptions {
|
pub struct PBRTOptions {
|
||||||
pub basic: BasicPBRTOptions,
|
pub basic: BasicPBRTOptions,
|
||||||
|
|
||||||
|
|
@ -55,8 +52,8 @@ pub struct PBRTOptions {
|
||||||
pub image_file: &'static str,
|
pub image_file: &'static str,
|
||||||
pub pixel_samples: Option<i32>,
|
pub pixel_samples: Option<i32>,
|
||||||
pub gpu_device: Option<u32>,
|
pub gpu_device: Option<u32>,
|
||||||
pub mse_reference_image: Option<String>,
|
pub mse_reference_image: Option<&'static str>,
|
||||||
pub mse_reference_output: Option<String>,
|
pub mse_reference_output: Option<&'static str>,
|
||||||
pub debug_start: Option<(Point2i, i32)>,
|
pub debug_start: Option<(Point2i, i32)>,
|
||||||
pub quick_render: bool,
|
pub quick_render: bool,
|
||||||
pub upgrade: bool,
|
pub upgrade: bool,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use crate::core::interaction::{
|
||||||
};
|
};
|
||||||
use crate::utils::gpu_array_from_fn;
|
use crate::utils::gpu_array_from_fn;
|
||||||
use crate::{gamma, Float};
|
use crate::{gamma, Float};
|
||||||
use crate::utils::error::{Error, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
|
@ -2125,7 +2125,15 @@ pub fn look_at(
|
||||||
// Initialize first three columns of viewing matrix
|
// Initialize first three columns of viewing matrix
|
||||||
let dir = (look - pos).normalize();
|
let dir = (look - pos).normalize();
|
||||||
if Vector3f::from(up).normalize().cross(dir).norm() == 0. {
|
if Vector3f::from(up).normalize().cross(dir).norm() == 0. {
|
||||||
return Err(Error::DegenerateLookAt);
|
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()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let right = Vector3f::from(up).normalize().cross(dir).normalize();
|
let right = Vector3f::from(up).normalize().cross(dir).normalize();
|
||||||
let new_up = dir.cross(right);
|
let new_up = dir.cross(right);
|
||||||
|
|
@ -2142,6 +2150,8 @@ pub fn look_at(
|
||||||
world_from_camera[2][2] = dir.z();
|
world_from_camera[2][2] = dir.z();
|
||||||
world_from_camera[3][2] = 0.;
|
world_from_camera[3][2] = 0.;
|
||||||
|
|
||||||
let camera_from_world = world_from_camera.inverse().ok_or(Error::SingularMatrix)?;
|
let camera_from_world = world_from_camera
|
||||||
|
.inverse()
|
||||||
|
.context("Failed to inverse viewing matrix")?;
|
||||||
Ok(TransformGeneric::new(camera_from_world, world_from_camera))
|
Ok(TransformGeneric::new(camera_from_world, world_from_camera))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::globals::get_options;
|
use crate::globals::get_options;
|
||||||
use shared::Ptr;
|
|
||||||
use shared::bxdfs::DiffuseBxDF;
|
use shared::bxdfs::DiffuseBxDF;
|
||||||
use shared::core::bsdf::BSDF;
|
use shared::core::bsdf::BSDF;
|
||||||
use shared::core::bssrdf::BSSRDF;
|
use shared::core::bssrdf::BSSRDF;
|
||||||
|
|
@ -11,12 +10,13 @@ use shared::core::material::{Material, MaterialEvalContext, MaterialTrait};
|
||||||
use shared::core::sampler::{Sampler, SamplerTrait};
|
use shared::core::sampler::{Sampler, SamplerTrait};
|
||||||
use shared::core::texture::UniversalTextureEvaluator;
|
use shared::core::texture::UniversalTextureEvaluator;
|
||||||
use shared::spectra::SampledWavelengths;
|
use shared::spectra::SampledWavelengths;
|
||||||
|
use shared::Ptr;
|
||||||
|
|
||||||
pub trait InteractionGetter {
|
pub trait InteractionGetter {
|
||||||
fn get_bsdf(
|
fn get_bsdf(
|
||||||
&mut self,
|
&mut self,
|
||||||
r: &Ray,
|
r: &Ray,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
sampler: &mut Sampler,
|
sampler: &mut Sampler,
|
||||||
materials: &[Material],
|
materials: &[Material],
|
||||||
|
|
@ -35,7 +35,7 @@ impl InteractionGetter for SurfaceInteraction {
|
||||||
fn get_bsdf(
|
fn get_bsdf(
|
||||||
&mut self,
|
&mut self,
|
||||||
r: &Ray,
|
r: &Ray,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
sampler: &mut Sampler,
|
sampler: &mut Sampler,
|
||||||
materials: &[Material],
|
materials: &[Material],
|
||||||
|
|
@ -98,7 +98,7 @@ impl InteractionGetter for MediumInteraction {
|
||||||
fn get_bsdf(
|
fn get_bsdf(
|
||||||
&mut self,
|
&mut self,
|
||||||
_r: &Ray,
|
_r: &Ray,
|
||||||
_lambda: &mut SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
_camera: &Camera,
|
_camera: &Camera,
|
||||||
_sampler: &mut Sampler,
|
_sampler: &mut Sampler,
|
||||||
_materials: &[Material],
|
_materials: &[Material],
|
||||||
|
|
@ -121,7 +121,7 @@ impl InteractionGetter for SimpleInteraction {
|
||||||
fn get_bsdf(
|
fn get_bsdf(
|
||||||
&mut self,
|
&mut self,
|
||||||
_r: &Ray,
|
_r: &Ray,
|
||||||
_lambda: &mut SampledWavelengths,
|
_lambda: &SampledWavelengths,
|
||||||
_camera: &Camera,
|
_camera: &Camera,
|
||||||
_sampler: &mut Sampler,
|
_sampler: &mut Sampler,
|
||||||
_materials: &[Material],
|
_materials: &[Material],
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
use super::BasicScene;
|
|
||||||
use super::entities::*;
|
use super::entities::*;
|
||||||
use crate::Arena;
|
use super::BasicScene;
|
||||||
use crate::spectra::get_colorspace_device;
|
use crate::spectra::get_colorspace_device;
|
||||||
use crate::utils::error::FileLoc;
|
use crate::utils::error::FileLoc;
|
||||||
use crate::utils::parameters::{ParameterDictionary, ParsedParameterVector};
|
use crate::utils::parameters::{ParameterDictionary, ParsedParameterVector};
|
||||||
use crate::utils::parser::{AtLoc, ParserError, ParserTarget};
|
use crate::utils::parser::{ParserError, ParserTarget};
|
||||||
use shared::Float;
|
use crate::Arena;
|
||||||
|
use anyhow::Context;
|
||||||
use shared::core::camera::CameraTransform;
|
use shared::core::camera::CameraTransform;
|
||||||
use shared::core::geometry::Vector3f;
|
use shared::core::geometry::Vector3f;
|
||||||
use shared::spectra::RGBColorSpace;
|
use shared::spectra::RGBColorSpace;
|
||||||
use shared::utils::options::{PBRTOptions, RenderingCoordinateSystem};
|
use shared::utils::options::RenderingCoordinateSystem;
|
||||||
use shared::utils::transform;
|
use shared::utils::transform;
|
||||||
use shared::utils::transform::{AnimatedTransform, Transform};
|
use shared::utils::transform::{AnimatedTransform, Transform};
|
||||||
|
use shared::Float;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -23,16 +24,6 @@ fn normalize_utf8(input: &str) -> String {
|
||||||
input.nfc().collect::<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)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
struct TransformSet {
|
struct TransformSet {
|
||||||
t: [Transform; MAX_TRANSFORMS],
|
t: [Transform; MAX_TRANSFORMS],
|
||||||
|
|
@ -134,11 +125,6 @@ pub struct BasicSceneBuilder {
|
||||||
named_material_names: HashSet<String>,
|
named_material_names: HashSet<String>,
|
||||||
medium_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_camera: Option<CameraSceneEntity>,
|
||||||
current_film: Option<SceneEntity>,
|
current_film: Option<SceneEntity>,
|
||||||
current_integrator: Option<SceneEntity>,
|
current_integrator: Option<SceneEntity>,
|
||||||
|
|
@ -191,7 +177,6 @@ impl BasicSceneBuilder {
|
||||||
spectrum_texture_names: HashSet::new(),
|
spectrum_texture_names: HashSet::new(),
|
||||||
named_material_names: HashSet::new(),
|
named_material_names: HashSet::new(),
|
||||||
medium_names: HashSet::new(),
|
medium_names: HashSet::new(),
|
||||||
pending_options: PBRTOptions::default(),
|
|
||||||
current_camera: Some(CameraSceneEntity {
|
current_camera: Some(CameraSceneEntity {
|
||||||
base: SceneEntity {
|
base: SceneEntity {
|
||||||
name: "perspective".into(),
|
name: "perspective".into(),
|
||||||
|
|
@ -226,12 +211,6 @@ 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)
|
fn for_active_transforms<F>(&mut self, f: F)
|
||||||
where
|
where
|
||||||
F: Fn(&Transform) -> Transform,
|
F: Fn(&Transform) -> Transform,
|
||||||
|
|
@ -275,6 +254,12 @@ 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 {
|
impl ParserTarget for BasicSceneBuilder {
|
||||||
fn reverse_orientation(&mut self, loc: FileLoc) -> Result<(), ParserError> {
|
fn reverse_orientation(&mut self, loc: FileLoc) -> Result<(), ParserError> {
|
||||||
self.verify_world("ReverseOrientation", &loc)?;
|
self.verify_world("ReverseOrientation", &loc)?;
|
||||||
|
|
@ -344,7 +329,8 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
uz: Float,
|
uz: Float,
|
||||||
loc: FileLoc,
|
loc: FileLoc,
|
||||||
) -> Result<(), ParserError> {
|
) -> Result<(), ParserError> {
|
||||||
let t = transform::look_at((ex, ey, ez), (lx, ly, lz), (ux, uy, uz)).at(&loc)?;
|
let t = transform::look_at((ex, ey, ez), (lx, ly, lz), (ux, uy, uz))
|
||||||
|
.with_context(|| format!("at {}", loc))?;
|
||||||
self.for_active_transforms(|cur| cur * &t);
|
self.for_active_transforms(|cur| cur * &t);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -461,65 +447,8 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn option(&mut self, name: &str, value: &str, loc: FileLoc) -> Result<(), ParserError> {
|
fn option(&mut self, _name: &str, _value: &str, _loc: FileLoc) -> Result<(), ParserError> {
|
||||||
let bad = |what: &str| {
|
todo!()
|
||||||
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(
|
fn pixel_filter(
|
||||||
|
|
@ -605,8 +534,7 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
params,
|
params,
|
||||||
&self.graphics_state.medium_attributes,
|
&self.graphics_state.medium_attributes,
|
||||||
self.graphics_state.color_space.clone(),
|
self.graphics_state.color_space.clone(),
|
||||||
)
|
)?;
|
||||||
.at(&loc)?;
|
|
||||||
let render_from_object = self.render_from_object();
|
let render_from_object = self.render_from_object();
|
||||||
let entity = MediumSceneEntity {
|
let entity = MediumSceneEntity {
|
||||||
base: SceneEntity {
|
base: SceneEntity {
|
||||||
|
|
@ -774,8 +702,7 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
params.clone(),
|
params.clone(),
|
||||||
&self.graphics_state.texture_attributes,
|
&self.graphics_state.texture_attributes,
|
||||||
self.graphics_state.color_space.clone(),
|
self.graphics_state.color_space.clone(),
|
||||||
)
|
)?;
|
||||||
.at(&loc)?;
|
|
||||||
|
|
||||||
if type_name != "float" && type_name != "spectrum" {
|
if type_name != "float" && type_name != "spectrum" {
|
||||||
return Err(ParserError::Generic(
|
return Err(ParserError::Generic(
|
||||||
|
|
@ -835,8 +762,7 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
params,
|
params,
|
||||||
&self.graphics_state.material_attributes,
|
&self.graphics_state.material_attributes,
|
||||||
self.graphics_state.color_space.clone(),
|
self.graphics_state.color_space.clone(),
|
||||||
)
|
)?;
|
||||||
.at(&loc)?;
|
|
||||||
let entity = SceneEntity {
|
let entity = SceneEntity {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
loc,
|
loc,
|
||||||
|
|
@ -868,8 +794,7 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
params,
|
params,
|
||||||
&self.graphics_state.material_attributes,
|
&self.graphics_state.material_attributes,
|
||||||
self.graphics_state.color_space.clone(),
|
self.graphics_state.color_space.clone(),
|
||||||
)
|
)?;
|
||||||
.at(&loc)?;
|
|
||||||
|
|
||||||
// pbrt stores an empty entity name here: the material type comes from the
|
// pbrt stores an empty entity name here: the material type comes from the
|
||||||
// "type" parameter (scene.cpp:719).
|
// "type" parameter (scene.cpp:719).
|
||||||
|
|
@ -902,8 +827,7 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
params.clone(),
|
params.clone(),
|
||||||
&self.graphics_state.medium_attributes,
|
&self.graphics_state.medium_attributes,
|
||||||
self.graphics_state.color_space.clone(),
|
self.graphics_state.color_space.clone(),
|
||||||
)
|
)?;
|
||||||
.at(&loc)?;
|
|
||||||
|
|
||||||
let render_from_light = self.render_from_object();
|
let render_from_light = self.render_from_object();
|
||||||
|
|
||||||
|
|
@ -950,8 +874,7 @@ impl ParserTarget for BasicSceneBuilder {
|
||||||
params.clone(),
|
params.clone(),
|
||||||
&self.graphics_state.shape_attributes,
|
&self.graphics_state.shape_attributes,
|
||||||
self.graphics_state.color_space.clone(),
|
self.graphics_state.color_space.clone(),
|
||||||
)
|
)?;
|
||||||
.at(&loc)?;
|
|
||||||
|
|
||||||
let render_from_object = self.render_from_object_at(0);
|
let render_from_object = self.render_from_object_at(0);
|
||||||
let object_from_render = render_from_object.inverse();
|
let object_from_render = render_from_object.inverse();
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,15 @@
|
||||||
use crate::textures::*;
|
use crate::textures::*;
|
||||||
use crate::utils::{MIPMap, MIPMapFilterOptions, TextureParameterDictionary};
|
use crate::utils::{MIPMap, MIPMapFilterOptions, TextureParameterDictionary};
|
||||||
use crate::{Arena, FileLoc};
|
use crate::{Arena, FileLoc};
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{anyhow, Result};
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use shared::Float;
|
|
||||||
use shared::core::color::ColorEncoding;
|
use shared::core::color::ColorEncoding;
|
||||||
use shared::core::geometry::Vector3f;
|
use shared::core::geometry::Vector3f;
|
||||||
use shared::core::image::WrapMode;
|
use shared::core::image::WrapMode;
|
||||||
use shared::core::texture::SpectrumType;
|
use shared::core::texture::SpectrumType;
|
||||||
use shared::core::texture::{
|
use shared::core::texture::{
|
||||||
CylindricalMapping, PlanarMapping, PointTransformMapping, SphericalMapping,
|
CylindricalMapping, PlanarMapping, SphericalMapping, TextureEvalContext, TextureMapping2D,
|
||||||
TextureEvalContext, TextureMapping2D, TextureMapping3D, UVMapping,
|
UVMapping,
|
||||||
};
|
};
|
||||||
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
||||||
use shared::textures::{
|
use shared::textures::{
|
||||||
|
|
@ -19,10 +18,22 @@ use shared::textures::{
|
||||||
SpectrumConstantTexture, SpectrumDotsTexture, WindyTexture, WrinkledTexture,
|
SpectrumConstantTexture, SpectrumDotsTexture, WindyTexture, WrinkledTexture,
|
||||||
};
|
};
|
||||||
use shared::utils::Transform;
|
use shared::utils::Transform;
|
||||||
|
use shared::Float;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex, OnceLock};
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[enum_dispatch(FloatTextureTrait)]
|
||||||
pub enum FloatTexture {
|
pub enum FloatTexture {
|
||||||
Constant(FloatConstantTexture),
|
Constant(FloatConstantTexture),
|
||||||
Checkerboard(FloatCheckerboardTexture),
|
Checkerboard(FloatCheckerboardTexture),
|
||||||
|
|
@ -38,12 +49,19 @@ pub enum FloatTexture {
|
||||||
Bilerp(FloatBilerpTexture),
|
Bilerp(FloatBilerpTexture),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Default for FloatTexture {
|
impl Default for FloatTexture {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
FloatTexture::Constant(FloatConstantTexture::new(1.0))
|
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 {
|
pub trait CreateFloatTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
render_from_texture: Transform,
|
||||||
|
|
@ -83,6 +101,7 @@ impl FloatTexture {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[enum_dispatch(SpectrumTextureTrait)]
|
||||||
pub enum SpectrumTexture {
|
pub enum SpectrumTexture {
|
||||||
Constant(SpectrumConstantTexture),
|
Constant(SpectrumConstantTexture),
|
||||||
Checkerboard(SpectrumCheckerboardTexture),
|
Checkerboard(SpectrumCheckerboardTexture),
|
||||||
|
|
@ -101,7 +120,6 @@ pub trait CreateSpectrumTexture {
|
||||||
parameters: TextureParameterDictionary,
|
parameters: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
spectrum_type: SpectrumType,
|
||||||
loc: FileLoc,
|
loc: FileLoc,
|
||||||
arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture>;
|
) -> Result<SpectrumTexture>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,29 +130,29 @@ impl SpectrumTexture {
|
||||||
params: TextureParameterDictionary,
|
params: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
spectrum_type: SpectrumType,
|
||||||
loc: FileLoc,
|
loc: FileLoc,
|
||||||
arena: &Arena,
|
_arena: &Arena,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
match name {
|
match name {
|
||||||
"constant" => {
|
"constant" => {
|
||||||
SpectrumConstantTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
SpectrumConstantTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||||
}
|
}
|
||||||
"scale" => {
|
"scale" => {
|
||||||
SpectrumScaledTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
SpectrumScaledTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||||
}
|
}
|
||||||
"mix" => SpectrumMixTexture::create(render_from_texture, params, spectrum_type, loc, arena),
|
"mix" => SpectrumMixTexture::create(render_from_texture, params, spectrum_type, loc),
|
||||||
"directionmix" => {
|
"directionmix" => {
|
||||||
SpectrumDirectionMixTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
SpectrumDirectionMixTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||||
}
|
}
|
||||||
"bilerp" => {
|
"bilerp" => {
|
||||||
SpectrumBilerpTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
SpectrumBilerpTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||||
}
|
}
|
||||||
"imagemap" => {
|
"imagemap" => {
|
||||||
SpectrumImageTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
SpectrumImageTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||||
}
|
}
|
||||||
"checkerboard" => {
|
"checkerboard" => {
|
||||||
SpectrumCheckerboardTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
SpectrumCheckerboardTexture::create(render_from_texture, params, spectrum_type, loc)
|
||||||
}
|
}
|
||||||
"dots" => SpectrumDotsTexture::create(render_from_texture, params, spectrum_type, loc, arena),
|
"dots" => SpectrumDotsTexture::create(render_from_texture, params, spectrum_type, loc),
|
||||||
_ => Err(anyhow!(
|
_ => Err(anyhow!(
|
||||||
"Spectrum texture type '{}' unknown at {}",
|
"Spectrum texture type '{}' unknown at {}",
|
||||||
name,
|
name,
|
||||||
|
|
@ -144,6 +162,12 @@ impl SpectrumTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SpectrumTextureTrait for Arc<SpectrumTexture> {
|
||||||
|
fn evaluate(&self, ctx: &TextureEvalContext, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
|
self.as_ref().evaluate(ctx, lambda)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait CreateTextureMapping {
|
pub trait CreateTextureMapping {
|
||||||
fn create(
|
fn create(
|
||||||
params: &TextureParameterDictionary,
|
params: &TextureParameterDictionary,
|
||||||
|
|
@ -197,21 +221,6 @@ 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 static TEXTURE_CACHE: OnceLock<Mutex<HashMap<TexInfo, Arc<MIPMap>>>> = OnceLock::new();
|
||||||
|
|
||||||
pub fn get_texture_cache() -> &'static Mutex<HashMap<TexInfo, Arc<MIPMap>>> {
|
pub fn get_texture_cache() -> &'static Mutex<HashMap<TexInfo, Arc<MIPMap>>> {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ pub trait RayIntegratorTrait {
|
||||||
fn li(
|
fn li(
|
||||||
&self,
|
&self,
|
||||||
ray: Ray,
|
ray: Ray,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
sampler: &mut Sampler,
|
sampler: &mut Sampler,
|
||||||
visible_surface: bool,
|
visible_surface: bool,
|
||||||
arena: &Arena,
|
arena: &Arena,
|
||||||
|
|
@ -69,8 +69,7 @@ impl CreateIntegrator for PathIntegrator {
|
||||||
let _max_depth = parameters.get_one_int("maxdepth", 5)?;
|
let _max_depth = parameters.get_one_int("maxdepth", 5)?;
|
||||||
let _regularize = parameters.get_one_bool("regularize", false)?;
|
let _regularize = parameters.get_one_bool("regularize", false)?;
|
||||||
let light_sampler = create_light_sampler("power", &lights, arena);
|
let light_sampler = create_light_sampler("power", &lights, arena);
|
||||||
let integrator =
|
let integrator = PathIntegrator::new(aggregate, lights, camera, light_sampler, config, materials);
|
||||||
PathIntegrator::new(aggregate, lights, camera, light_sampler, config, materials);
|
|
||||||
Ok(integrator)
|
Ok(integrator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use super::RayIntegratorTrait;
|
|
||||||
use super::base::IntegratorBase;
|
use super::base::IntegratorBase;
|
||||||
use super::constants::*;
|
use super::constants::*;
|
||||||
use super::state::PathState;
|
use super::state::PathState;
|
||||||
use crate::Arena;
|
use super::RayIntegratorTrait;
|
||||||
use crate::core::interaction::InteractionGetter;
|
use crate::core::interaction::InteractionGetter;
|
||||||
use shared::core::bsdf::{BSDF, BSDFSample};
|
use crate::Arena;
|
||||||
|
use shared::core::bsdf::{BSDFSample, BSDF};
|
||||||
use shared::core::bxdf::{BxDFFlags, FArgs, TransportMode};
|
use shared::core::bxdf::{BxDFFlags, FArgs, TransportMode};
|
||||||
use shared::core::camera::Camera;
|
use shared::core::camera::Camera;
|
||||||
use shared::core::film::VisibleSurface;
|
use shared::core::film::VisibleSurface;
|
||||||
|
|
@ -72,6 +72,7 @@ pub struct PathIntegrator {
|
||||||
materials: Vec<Material>,
|
materials: Vec<Material>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl PathIntegrator {
|
impl PathIntegrator {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
aggregate: Arc<Primitive>,
|
aggregate: Arc<Primitive>,
|
||||||
|
|
@ -207,7 +208,7 @@ impl RayIntegratorTrait for PathIntegrator {
|
||||||
fn li(
|
fn li(
|
||||||
&self,
|
&self,
|
||||||
mut ray: Ray,
|
mut ray: Ray,
|
||||||
lambda: &mut SampledWavelengths,
|
lambda: &SampledWavelengths,
|
||||||
sampler: &mut Sampler,
|
sampler: &mut Sampler,
|
||||||
want_visible: bool,
|
want_visible: bool,
|
||||||
_arena: &Arena,
|
_arena: &Arena,
|
||||||
|
|
@ -246,9 +247,7 @@ impl RayIntegratorTrait for PathIntegrator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get BSDF
|
// Get BSDF
|
||||||
let Some(mut bsdf) =
|
let Some(mut bsdf) = isect.get_bsdf(&ray, lambda, &self.camera, sampler, &self.materials) else {
|
||||||
isect.get_bsdf(&ray, lambda, &self.camera, sampler, &self.materials)
|
|
||||||
else {
|
|
||||||
state.specular_bounce = true;
|
state.specular_bounce = true;
|
||||||
isect.skip_intersection(&mut ray, t_hit);
|
isect.skip_intersection(&mut ray, t_hit);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::RayIntegratorTrait;
|
|
||||||
use super::base::IntegratorBase;
|
use super::base::IntegratorBase;
|
||||||
|
use super::RayIntegratorTrait;
|
||||||
use crate::core::camera::InitMetadata;
|
use crate::core::camera::InitMetadata;
|
||||||
use crate::core::film::FilmTrait;
|
use crate::core::film::FilmTrait;
|
||||||
use crate::core::image::{HostImage, ImageIO, ImageMetadata};
|
use crate::core::image::{HostImage, ImageIO, ImageMetadata};
|
||||||
|
|
@ -7,12 +7,12 @@ use crate::globals::get_options;
|
||||||
use crate::spectra::get_spectra_context;
|
use crate::spectra::get_spectra_context;
|
||||||
use crate::{Arena, PbrtProgress};
|
use crate::{Arena, PbrtProgress};
|
||||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use shared::Float;
|
|
||||||
use shared::core::camera::{Camera, CameraTrait};
|
use shared::core::camera::{Camera, CameraTrait};
|
||||||
use shared::core::geometry::{Bounds2i, Point2i};
|
use shared::core::geometry::{Bounds2i, Point2i};
|
||||||
use shared::core::sampler::get_camera_sample;
|
use shared::core::sampler::get_camera_sample;
|
||||||
use shared::core::sampler::{Sampler, SamplerTrait};
|
use shared::core::sampler::{Sampler, SamplerTrait};
|
||||||
use shared::spectra::SampledSpectrum;
|
use shared::spectra::SampledSpectrum;
|
||||||
|
use shared::Float;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
|
@ -214,7 +214,7 @@ pub fn evaluate_pixel_sample<T: RayIntegratorTrait>(
|
||||||
lu = 0.5;
|
lu = 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut lambda = camera.get_film().sample_wavelengths(lu);
|
let lambda = camera.get_film().sample_wavelengths(lu);
|
||||||
let film = camera.get_film();
|
let film = camera.get_film();
|
||||||
let filter = film.get_filter();
|
let filter = film.get_filter();
|
||||||
let camera_sample = get_camera_sample(sampler, pixel, 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 initialize_visible_surface = film.uses_visible_surface();
|
||||||
let (mut l, visible_surface) = integrator.li(
|
let (mut l, visible_surface) = integrator.li(
|
||||||
camera_ray.ray,
|
camera_ray.ray,
|
||||||
&mut lambda,
|
&lambda,
|
||||||
sampler,
|
sampler,
|
||||||
initialize_visible_surface,
|
initialize_visible_surface,
|
||||||
arena,
|
arena,
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,51 @@
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use crate::core::texture::{
|
use crate::core::texture::{
|
||||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture, SpectrumTexture,
|
CreateFloatTexture, CreateSpectrumTexture, FloatTextureTrait, SpectrumTexture,
|
||||||
|
SpectrumTextureTrait,
|
||||||
};
|
};
|
||||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use shared::core::spectrum::Spectrum;
|
use shared::core::texture::{SpectrumType, TextureEvalContext};
|
||||||
use shared::core::texture::{SpectrumType, TextureMapping2D};
|
use shared::{
|
||||||
use shared::spectra::ConstantSpectrum;
|
spectra::{SampledSpectrum, SampledWavelengths},
|
||||||
use shared::textures::{FloatBilerpTexture, SpectrumBilerpTexture};
|
textures::{FloatBilerpTexture, SpectrumBilerpTexture},
|
||||||
use shared::utils::Transform;
|
utils::Transform,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
core::texture::FloatTexture,
|
||||||
|
utils::{FileLoc, TextureParameterDictionary},
|
||||||
|
};
|
||||||
|
|
||||||
impl CreateFloatTexture for FloatBilerpTexture {
|
impl CreateFloatTexture for FloatBilerpTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
loc: FileLoc,
|
_loc: FileLoc,
|
||||||
arena: &Arena,
|
_arena: &Arena,
|
||||||
) -> Result<FloatTexture> {
|
) -> Result<FloatTexture> {
|
||||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let tex = FloatBilerpTexture::new(
|
impl FloatTextureTrait for FloatBilerpTexture {
|
||||||
map,
|
fn evaluate(&self, _ctx: &TextureEvalContext) -> shared::Float {
|
||||||
parameters.get_one_float("v00", 0.)?,
|
todo!()
|
||||||
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 {
|
impl CreateSpectrumTexture for SpectrumBilerpTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
_spectrum_type: SpectrumType,
|
||||||
loc: FileLoc,
|
_loc: FileLoc,
|
||||||
arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
todo!()
|
||||||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
}
|
||||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
}
|
||||||
|
|
||||||
let get = |name: &str, def: Spectrum| {
|
impl SpectrumTextureTrait for SpectrumBilerpTexture {
|
||||||
let s = parameters
|
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
.get_one_spectrum(name, Some(def), spectrum_type)
|
todo!()
|
||||||
.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,79 +1,53 @@
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use anyhow::{Result, bail};
|
use anyhow::Result;
|
||||||
use shared::{
|
use shared::{
|
||||||
core::spectrum::Spectrum,
|
core::texture::SpectrumType,
|
||||||
core::texture::{SpectrumType, TextureMapping2D, TextureMapping3D},
|
textures::{FloatCheckerboardTexture, SpectrumCheckerboardTexture},
|
||||||
spectra::ConstantSpectrum,
|
|
||||||
textures::{CheckerMap, FloatCheckerboardTexture, SpectrumCheckerboardTexture},
|
|
||||||
utils::Transform,
|
utils::Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::texture::{
|
core::texture::{
|
||||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture,
|
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait,
|
||||||
SpectrumTexture,
|
SpectrumTexture, SpectrumTextureTrait,
|
||||||
},
|
},
|
||||||
utils::{ArenaUpload, FileLoc, TextureParameterDictionary},
|
utils::{FileLoc, TextureParameterDictionary},
|
||||||
};
|
};
|
||||||
|
|
||||||
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 CreateFloatTexture for FloatCheckerboardTexture {
|
impl CreateFloatTexture for FloatCheckerboardTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
loc: FileLoc,
|
_loc: FileLoc,
|
||||||
arena: &Arena,
|
_arena: &Arena,
|
||||||
) -> Result<FloatTexture> {
|
) -> Result<FloatTexture> {
|
||||||
let tex1 = arena.upload(parameters.get_float_texture("tex1", 1.)?);
|
todo!()
|
||||||
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 FloatTextureTrait for FloatCheckerboardTexture {
|
||||||
|
fn evaluate(&self, _ctx: &shared::core::texture::TextureEvalContext) -> shared::Float {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateSpectrumTexture for SpectrumCheckerboardTexture {
|
impl CreateSpectrumTexture for SpectrumCheckerboardTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
_spectrum_type: SpectrumType,
|
||||||
loc: FileLoc,
|
_loc: FileLoc,
|
||||||
arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
todo!()
|
||||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
}
|
||||||
let tex = |name: &str, def: Spectrum| {
|
}
|
||||||
arena.upload(
|
|
||||||
parameters
|
impl SpectrumTextureTrait for SpectrumCheckerboardTexture {
|
||||||
.get_spectrum_texture(name, Some(def), spectrum_type)
|
fn evaluate(
|
||||||
.expect("default supplied"),
|
&self,
|
||||||
)
|
_ctx: &shared::core::texture::TextureEvalContext,
|
||||||
};
|
_lambda: &shared::spectra::SampledWavelengths,
|
||||||
|
) -> shared::spectra::SampledSpectrum {
|
||||||
let tex1 = tex("tex1", one);
|
todo!()
|
||||||
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,46 +1,53 @@
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use shared::core::spectrum::Spectrum;
|
|
||||||
use shared::spectra::ConstantSpectrum;
|
|
||||||
use shared::{
|
use shared::{
|
||||||
core::texture::SpectrumType,
|
core::texture::{SpectrumType, TextureEvalContext},
|
||||||
textures::{FloatConstantTexture, SpectrumConstantTexture},
|
textures::{FloatConstantTexture, SpectrumConstantTexture},
|
||||||
utils::Transform,
|
utils::Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::texture::{
|
core::texture::{
|
||||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, SpectrumTexture },
|
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait,
|
||||||
utils::{FileLoc, TextureParameterDictionary}
|
SpectrumTexture, SpectrumTextureTrait,
|
||||||
|
},
|
||||||
|
utils::{FileLoc, TextureParameterDictionary},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl CreateFloatTexture for FloatConstantTexture {
|
impl CreateFloatTexture for FloatConstantTexture {
|
||||||
fn create(
|
fn create(
|
||||||
_render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
_loc: FileLoc,
|
_loc: FileLoc,
|
||||||
_arena: &Arena,
|
_arena: &Arena,
|
||||||
) -> Result<FloatTexture> {
|
) -> Result<FloatTexture> {
|
||||||
let value = parameters.get_one_float("value", 1.)?;
|
todo!()
|
||||||
Ok(FloatTexture::Constant(FloatConstantTexture::new(value)))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FloatTextureTrait for FloatConstantTexture {
|
||||||
|
fn evaluate(&self, _ctx: &TextureEvalContext) -> shared::Float {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateSpectrumTexture for SpectrumConstantTexture {
|
impl CreateSpectrumTexture for SpectrumConstantTexture {
|
||||||
fn create(
|
fn create(
|
||||||
_render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
_spectrum_type: SpectrumType,
|
||||||
_loc: FileLoc,
|
_loc: FileLoc,
|
||||||
_arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
todo!()
|
||||||
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,57 +1,53 @@
|
||||||
use crate::{Arena, ArenaUpload};
|
use crate::Arena;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use shared::{
|
use shared::{
|
||||||
core::spectrum::Spectrum,
|
core::texture::SpectrumType,
|
||||||
core::texture::{SpectrumType, TextureMapping2D},
|
|
||||||
spectra::ConstantSpectrum,
|
|
||||||
textures::{FloatDotsTexture, SpectrumDotsTexture},
|
textures::{FloatDotsTexture, SpectrumDotsTexture},
|
||||||
utils::Transform,
|
utils::Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::texture::{
|
core::texture::{
|
||||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture,
|
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait,
|
||||||
SpectrumTexture,
|
SpectrumTexture, SpectrumTextureTrait,
|
||||||
},
|
},
|
||||||
utils::{FileLoc, TextureParameterDictionary},
|
utils::{FileLoc, TextureParameterDictionary},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
impl FloatTextureTrait for FloatDotsTexture {
|
||||||
|
fn evaluate(&self, _ctx: &shared::core::texture::TextureEvalContext) -> shared::Float {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CreateFloatTexture for FloatDotsTexture {
|
impl CreateFloatTexture for FloatDotsTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
loc: FileLoc,
|
_loc: FileLoc,
|
||||||
arena: &Arena,
|
_arena: &Arena,
|
||||||
) -> Result<FloatTexture> {
|
) -> Result<FloatTexture> {
|
||||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
todo!()
|
||||||
let inside = parameters.get_float_texture("inside", 1.)?;
|
}
|
||||||
let outside = parameters.get_float_texture("outside", 1.)?;
|
}
|
||||||
|
|
||||||
let tex = FloatDotsTexture::new(map, arena.upload(inside), arena.upload(outside));
|
impl SpectrumTextureTrait for SpectrumDotsTexture {
|
||||||
|
fn evaluate(
|
||||||
Ok(FloatTexture::Dots(tex))
|
&self,
|
||||||
|
_ctx: &shared::core::texture::TextureEvalContext,
|
||||||
|
_lambda: &shared::spectra::SampledWavelengths,
|
||||||
|
) -> shared::spectra::SampledSpectrum {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateSpectrumTexture for SpectrumDotsTexture {
|
impl CreateSpectrumTexture for SpectrumDotsTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
_spectrum_type: SpectrumType,
|
||||||
loc: FileLoc,
|
_loc: FileLoc,
|
||||||
arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
todo!()
|
||||||
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 crate::Arena;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use shared::core::texture::{TextureEvalContext, TextureMapping3D};
|
use shared::core::texture::TextureEvalContext;
|
||||||
use shared::{textures::FBmTexture, utils::Transform};
|
use shared::{textures::FBmTexture, utils::Transform};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::texture::{CreateFloatTexture, CreateTextureMapping, FloatTexture},
|
core::texture::{CreateFloatTexture, FloatTexture, FloatTextureTrait},
|
||||||
utils::{FileLoc, TextureParameterDictionary},
|
utils::{FileLoc, TextureParameterDictionary},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl CreateFloatTexture for FBmTexture {
|
impl CreateFloatTexture for FBmTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
_render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
loc: FileLoc,
|
_loc: FileLoc,
|
||||||
arena: &Arena,
|
_arena: &Arena,
|
||||||
) -> Result<FloatTexture> {
|
) -> Result<FloatTexture> {
|
||||||
let map = TextureMapping3D::create(¶meters, &render_from_texture, &loc)?;
|
todo!()
|
||||||
let tex = FBmTexture::new(
|
}
|
||||||
map,
|
}
|
||||||
parameters.get_one_int("octaves", 5)?.try_into().unwrap(),
|
|
||||||
parameters.get_one_float("roughness", 0.5)?,
|
impl FloatTextureTrait for FBmTexture {
|
||||||
);
|
fn evaluate(&self, _ctx: &TextureEvalContext) -> shared::Float {
|
||||||
Ok(FloatTexture::FBm(tex))
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
use crate::core::texture::{get_texture_cache, CreateTextureMapping, TexInfo};
|
use crate::core::texture::{get_texture_cache, CreateTextureMapping, TexInfo};
|
||||||
use crate::core::texture::{
|
use crate::core::texture::{
|
||||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, SpectrumTexture
|
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, FloatTextureTrait, SpectrumTexture,
|
||||||
|
SpectrumTextureTrait,
|
||||||
};
|
};
|
||||||
use crate::utils::mipmap::{MIPMap, MIPMapFilterOptions};
|
use crate::utils::mipmap::{MIPMap, MIPMapFilterOptions};
|
||||||
use crate::utils::{resolve_filename, FileLoc, TextureParameterDictionary};
|
use crate::utils::{resolve_filename, FileLoc, TextureParameterDictionary};
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::Result;
|
||||||
use shared::core::color::RGB;
|
use shared::core::color::RGB;
|
||||||
use shared::core::color::{ColorEncoding, SRGBEncoding};
|
use shared::core::color::{ColorEncoding, SRGBEncoding};
|
||||||
use shared::core::geometry::Vector2f;
|
use shared::core::geometry::Vector2f;
|
||||||
|
|
@ -14,7 +15,7 @@ use shared::core::spectrum::SpectrumTrait;
|
||||||
use shared::core::texture::{SpectrumType, TexCoord2D, TextureEvalContext, TextureMapping2D};
|
use shared::core::texture::{SpectrumType, TexCoord2D, TextureEvalContext, TextureMapping2D};
|
||||||
use shared::spectra::{
|
use shared::spectra::{
|
||||||
RGBAlbedoSpectrum, RGBIlluminantSpectrum, RGBUnboundedSpectrum, SampledSpectrum,
|
RGBAlbedoSpectrum, RGBIlluminantSpectrum, RGBUnboundedSpectrum, SampledSpectrum,
|
||||||
SampledWavelengths
|
SampledWavelengths,
|
||||||
};
|
};
|
||||||
use shared::utils::Transform;
|
use shared::utils::Transform;
|
||||||
use shared::Float;
|
use shared::Float;
|
||||||
|
|
@ -27,7 +28,7 @@ pub struct ImageTextureBase {
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
pub scale: Float,
|
pub scale: Float,
|
||||||
pub invert: bool,
|
pub invert: bool,
|
||||||
pub mipmap: Arc<MIPMap>
|
pub mipmap: Arc<MIPMap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageTextureBase {
|
impl ImageTextureBase {
|
||||||
|
|
@ -44,7 +45,7 @@ impl ImageTextureBase {
|
||||||
filename: filename.clone(),
|
filename: filename.clone(),
|
||||||
filter_options,
|
filter_options,
|
||||||
wrap_mode,
|
wrap_mode,
|
||||||
encoding
|
encoding,
|
||||||
};
|
};
|
||||||
|
|
||||||
let cache_mutex = get_texture_cache();
|
let cache_mutex = get_texture_cache();
|
||||||
|
|
@ -57,7 +58,7 @@ impl ImageTextureBase {
|
||||||
filename,
|
filename,
|
||||||
scale,
|
scale,
|
||||||
invert,
|
invert,
|
||||||
mipmap: mipmap.clone()
|
mipmap: mipmap.clone(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +79,7 @@ impl ImageTextureBase {
|
||||||
filename,
|
filename,
|
||||||
scale,
|
scale,
|
||||||
invert,
|
invert,
|
||||||
mipmap: stored_mipmap.clone()
|
mipmap: stored_mipmap.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +97,7 @@ impl ImageTextureBase {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SpectrumImageTexture {
|
pub struct SpectrumImageTexture {
|
||||||
pub base: ImageTextureBase,
|
pub base: ImageTextureBase,
|
||||||
pub spectrum_type: SpectrumType
|
pub spectrum_type: SpectrumType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpectrumImageTexture {
|
impl SpectrumImageTexture {
|
||||||
|
|
@ -123,18 +124,58 @@ impl SpectrumImageTexture {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
base,
|
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 {
|
impl CreateSpectrumTexture for SpectrumImageTexture {
|
||||||
fn create(
|
fn create(
|
||||||
render_from_texture: Transform,
|
render_from_texture: Transform,
|
||||||
parameters: TextureParameterDictionary,
|
parameters: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
spectrum_type: SpectrumType,
|
||||||
loc: FileLoc,
|
loc: FileLoc,
|
||||||
_arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
let mapping = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
let mapping = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||||
|
|
||||||
|
|
@ -149,7 +190,7 @@ impl CreateSpectrumTexture for SpectrumImageTexture {
|
||||||
"repeat" => WrapMode::Repeat,
|
"repeat" => WrapMode::Repeat,
|
||||||
"clamp" => WrapMode::Clamp,
|
"clamp" => WrapMode::Clamp,
|
||||||
"black" => WrapMode::Black,
|
"black" => WrapMode::Black,
|
||||||
_ => WrapMode::Repeat
|
_ => WrapMode::Repeat,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoding = ColorEncoding::SRGB(SRGBEncoding);
|
let encoding = ColorEncoding::SRGB(SRGBEncoding);
|
||||||
|
|
@ -171,7 +212,7 @@ impl CreateSpectrumTexture for SpectrumImageTexture {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FloatImageTexture {
|
pub struct FloatImageTexture {
|
||||||
pub base: ImageTextureBase
|
pub base: ImageTextureBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatImageTexture {
|
impl FloatImageTexture {
|
||||||
|
|
@ -193,7 +234,26 @@ impl FloatImageTexture {
|
||||||
scale,
|
scale,
|
||||||
invert,
|
invert,
|
||||||
encoding,
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -211,10 +271,10 @@ impl CreateFloatTexture for FloatImageTexture {
|
||||||
let mut filter_options = MIPMapFilterOptions::default();
|
let mut filter_options = MIPMapFilterOptions::default();
|
||||||
filter_options.max_anisotropy = max_aniso;
|
filter_options.max_anisotropy = max_aniso;
|
||||||
|
|
||||||
let ff = FilterFunction::parse(&filter).with_context(|| format!("{:?}", filter))?;
|
let ff = FilterFunction::parse(&filter)?;
|
||||||
filter_options.filter = ff;
|
filter_options.filter = ff;
|
||||||
let wrap_string = parameters.get_one_string("wrap", "repeat")?;
|
let wrap_string = parameters.get_one_string("wrap", "repeat")?;
|
||||||
let wrap_mode = WrapMode::parse(&wrap_string).with_context(|| format!("{:?}", wrap_string))?;
|
let wrap_mode = WrapMode::parse(&wrap_string)?;
|
||||||
let scale = parameters.get_one_float("scale", 1.)?;
|
let scale = parameters.get_one_float("scale", 1.)?;
|
||||||
let invert = parameters.get_one_bool("invert", false)?;
|
let invert = parameters.get_one_bool("invert", false)?;
|
||||||
let filename = resolve_filename(¶meters.get_one_string("filename", "")?);
|
let filename = resolve_filename(¶meters.get_one_string("filename", "")?);
|
||||||
|
|
@ -227,8 +287,7 @@ impl CreateFloatTexture for FloatImageTexture {
|
||||||
"linear"
|
"linear"
|
||||||
};
|
};
|
||||||
let encoding_str = parameters.get_one_string("encoding", default_encoding)?;
|
let encoding_str = parameters.get_one_string("encoding", default_encoding)?;
|
||||||
let encoding =
|
let encoding = ColorEncoding::from_name(&encoding_str)?;
|
||||||
ColorEncoding::from_name(&encoding_str).with_context(|| format!("{:?}", encoding_str))?;
|
|
||||||
|
|
||||||
let tex = FloatImageTexture::new(
|
let tex = FloatImageTexture::new(
|
||||||
mapping,
|
mapping,
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,24 @@
|
||||||
use crate::core::texture::{CreateSpectrumTexture, SpectrumTexture};
|
use crate::core::texture::{CreateSpectrumTexture, SpectrumTexture, SpectrumTextureTrait};
|
||||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
|
||||||
use crate::Arena;
|
|
||||||
use anyhow::Result;
|
|
||||||
use shared::Transform;
|
|
||||||
use shared::core::texture::SpectrumType;
|
use shared::core::texture::SpectrumType;
|
||||||
use shared::textures::MarbleTexture;
|
use shared::textures::MarbleTexture;
|
||||||
|
|
||||||
impl CreateSpectrumTexture for MarbleTexture {
|
impl SpectrumTextureTrait for MarbleTexture {
|
||||||
fn create(
|
fn evaluate(
|
||||||
_render_from_texture: Transform,
|
&self,
|
||||||
_parameters: TextureParameterDictionary,
|
_ctx: &shared::core::texture::TextureEvalContext,
|
||||||
_spectrum_type: SpectrumType,
|
_lambda: &shared::spectra::SampledWavelengths,
|
||||||
_loc: FileLoc,
|
) -> shared::spectra::SampledSpectrum {
|
||||||
_arena: &Arena,
|
todo!()
|
||||||
) -> Result<SpectrumTexture> {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CreateSpectrumTexture for MarbleTexture {
|
||||||
|
fn create(
|
||||||
|
_render_from_texture: shared::utils::Transform,
|
||||||
|
_parameters: crate::utils::TextureParameterDictionary,
|
||||||
|
_spectrum_type: SpectrumType,
|
||||||
|
_loc: crate::utils::FileLoc,
|
||||||
|
) -> anyhow::Result<SpectrumTexture> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::core::texture::{
|
use crate::core::texture::{
|
||||||
CreateSpectrumTexture, FloatTexture, SpectrumTexture };
|
CreateSpectrumTexture, FloatTexture, FloatTextureTrait, SpectrumTexture, SpectrumTextureTrait,
|
||||||
|
};
|
||||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
use crate::utils::{FileLoc, TextureParameterDictionary};
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
@ -14,7 +15,7 @@ use std::sync::Arc;
|
||||||
pub struct FloatMixTexture {
|
pub struct FloatMixTexture {
|
||||||
pub tex1: Arc<FloatTexture>,
|
pub tex1: Arc<FloatTexture>,
|
||||||
pub tex2: Arc<FloatTexture>,
|
pub tex2: Arc<FloatTexture>,
|
||||||
pub amount: Arc<FloatTexture>
|
pub amount: Arc<FloatTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatMixTexture {
|
impl FloatMixTexture {
|
||||||
|
|
@ -40,11 +41,26 @@ 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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct FloatDirectionMixTexture {
|
pub struct FloatDirectionMixTexture {
|
||||||
pub tex1: Arc<FloatTexture>,
|
pub tex1: Arc<FloatTexture>,
|
||||||
pub tex2: Arc<FloatTexture>,
|
pub tex2: Arc<FloatTexture>,
|
||||||
pub dir: Vector3f
|
pub dir: Vector3f,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatDirectionMixTexture {
|
impl FloatDirectionMixTexture {
|
||||||
|
|
@ -67,11 +83,17 @@ impl FloatDirectionMixTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FloatTextureTrait for FloatDirectionMixTexture {
|
||||||
|
fn evaluate(&self, _ctx: &TextureEvalContext) -> Float {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SpectrumMixTexture {
|
pub struct SpectrumMixTexture {
|
||||||
pub tex1: Arc<SpectrumTexture>,
|
pub tex1: Arc<SpectrumTexture>,
|
||||||
pub tex2: Arc<SpectrumTexture>,
|
pub tex2: Arc<SpectrumTexture>,
|
||||||
pub amount: Arc<FloatTexture>
|
pub amount: Arc<FloatTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateSpectrumTexture for SpectrumMixTexture {
|
impl CreateSpectrumTexture for SpectrumMixTexture {
|
||||||
|
|
@ -80,17 +102,22 @@ impl CreateSpectrumTexture for SpectrumMixTexture {
|
||||||
_parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
_spectrum_type: SpectrumType,
|
_spectrum_type: SpectrumType,
|
||||||
_loc: FileLoc,
|
_loc: FileLoc,
|
||||||
_arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SpectrumTextureTrait for SpectrumMixTexture {
|
||||||
|
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SpectrumDirectionMixTexture {
|
pub struct SpectrumDirectionMixTexture {
|
||||||
pub tex1: Arc<SpectrumTexture>,
|
pub tex1: Arc<SpectrumTexture>,
|
||||||
pub tex2: Arc<SpectrumTexture>,
|
pub tex2: Arc<SpectrumTexture>,
|
||||||
pub dir: Vector3f
|
pub dir: Vector3f,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateSpectrumTexture for SpectrumDirectionMixTexture {
|
impl CreateSpectrumTexture for SpectrumDirectionMixTexture {
|
||||||
|
|
@ -99,9 +126,13 @@ impl CreateSpectrumTexture for SpectrumDirectionMixTexture {
|
||||||
_parameters: TextureParameterDictionary,
|
_parameters: TextureParameterDictionary,
|
||||||
_spectrum_type: SpectrumType,
|
_spectrum_type: SpectrumType,
|
||||||
_loc: FileLoc,
|
_loc: FileLoc,
|
||||||
_arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SpectrumTextureTrait for SpectrumDirectionMixTexture {
|
||||||
|
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ mod scaled;
|
||||||
mod windy;
|
mod windy;
|
||||||
mod wrinkled;
|
mod wrinkled;
|
||||||
|
|
||||||
pub use bilerp::*;
|
|
||||||
pub use image::*;
|
pub use image::*;
|
||||||
pub use mix::*;
|
pub use mix::*;
|
||||||
pub use scaled::*;
|
pub use scaled::*;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::core::texture::{CreateSpectrumTexture, FloatTexture, SpectrumTexture};
|
use crate::core::texture::{CreateSpectrumTexture, FloatTexture, SpectrumTexture};
|
||||||
|
use crate::core::texture::{FloatTextureTrait, SpectrumTextureTrait};
|
||||||
use crate::utils::{FileLoc, TextureParameterDictionary};
|
use crate::utils::{FileLoc, TextureParameterDictionary};
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
@ -12,7 +13,7 @@ use std::sync::Arc;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct FloatScaledTexture {
|
pub struct FloatScaledTexture {
|
||||||
pub tex: Arc<FloatTexture>,
|
pub tex: Arc<FloatTexture>,
|
||||||
pub scale: Arc<FloatTexture>
|
pub scale: Arc<FloatTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatScaledTexture {
|
impl FloatScaledTexture {
|
||||||
|
|
@ -51,10 +52,20 @@ 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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SpectrumScaledTexture {
|
pub struct SpectrumScaledTexture {
|
||||||
pub tex: Arc<SpectrumTexture>,
|
pub tex: Arc<SpectrumTexture>,
|
||||||
pub scale: Arc<FloatTexture>
|
pub scale: Arc<FloatTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateSpectrumTexture for SpectrumScaledTexture {
|
impl CreateSpectrumTexture for SpectrumScaledTexture {
|
||||||
|
|
@ -63,7 +74,6 @@ impl CreateSpectrumTexture for SpectrumScaledTexture {
|
||||||
parameters: TextureParameterDictionary,
|
parameters: TextureParameterDictionary,
|
||||||
spectrum_type: SpectrumType,
|
spectrum_type: SpectrumType,
|
||||||
_loc: FileLoc,
|
_loc: FileLoc,
|
||||||
_arena: &Arena,
|
|
||||||
) -> Result<SpectrumTexture> {
|
) -> Result<SpectrumTexture> {
|
||||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.0));
|
let one = Spectrum::Constant(ConstantSpectrum::new(1.0));
|
||||||
let tex = parameters
|
let tex = parameters
|
||||||
|
|
@ -85,8 +95,17 @@ impl CreateSpectrumTexture for SpectrumScaledTexture {
|
||||||
|
|
||||||
Ok(SpectrumTexture::Scaled(SpectrumScaledTexture {
|
Ok(SpectrumTexture::Scaled(SpectrumScaledTexture {
|
||||||
tex,
|
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 shared::{textures::WindyTexture, utils::Transform};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::texture::{CreateFloatTexture, FloatTexture },
|
core::texture::{CreateFloatTexture, FloatTexture, FloatTextureTrait},
|
||||||
utils::{FileLoc, TextureParameterDictionary}
|
utils::{FileLoc, TextureParameterDictionary},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl CreateFloatTexture for WindyTexture {
|
impl CreateFloatTexture for WindyTexture {
|
||||||
|
|
@ -18,3 +18,8 @@ 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 shared::{textures::WrinkledTexture, utils::Transform};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::texture::{CreateFloatTexture, FloatTexture },
|
core::texture::{CreateFloatTexture, FloatTexture, FloatTextureTrait},
|
||||||
utils::{FileLoc, TextureParameterDictionary}
|
utils::{FileLoc, TextureParameterDictionary},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl CreateFloatTexture for WrinkledTexture {
|
impl CreateFloatTexture for WrinkledTexture {
|
||||||
|
|
@ -18,3 +18,8 @@ impl CreateFloatTexture for WrinkledTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FloatTextureTrait for WrinkledTexture {
|
||||||
|
fn evaluate(&self, _ctx: &shared::core::texture::TextureEvalContext) -> shared::Float {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use thiserror::Error;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
use memmap2::Mmap;
|
use memmap2::Mmap;
|
||||||
|
|
@ -248,39 +247,17 @@ impl Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug)]
|
||||||
pub enum ParserError {
|
pub enum ParserError {
|
||||||
#[error("{0}")]
|
|
||||||
Io(String),
|
Io(String),
|
||||||
#[error("unexpected end of file")]
|
|
||||||
UnexpectedEof,
|
UnexpectedEof,
|
||||||
#[error("invalid UTF-8: {0}")]
|
|
||||||
InvalidUtf8(String),
|
InvalidUtf8(String),
|
||||||
#[error("{1}: {0}")]
|
|
||||||
Generic(String, FileLoc),
|
Generic(String, FileLoc),
|
||||||
#[error("{1}: expected an integer: {0}")]
|
|
||||||
ParseIntError(String, FileLoc),
|
ParseIntError(String, FileLoc),
|
||||||
#[error("{1}: expected a float: {0}")]
|
|
||||||
ParseFloatError(String, FileLoc),
|
ParseFloatError(String, FileLoc),
|
||||||
#[error("{1}: numeric overflow: {0}")]
|
|
||||||
NumericOverflow(String, FileLoc),
|
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 {
|
pub enum TokenizerBuffer {
|
||||||
Ram(String),
|
Ram(String),
|
||||||
Mapped(Mmap),
|
Mapped(Mmap),
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
use super::CpuAggregate;
|
use super::CpuAggregate;
|
||||||
|
use crate::globals::get_options;
|
||||||
|
use crate::lights::sampler::create_light_sampler;
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use crate::ParameterDictionary;
|
use crate::ParameterDictionary;
|
||||||
use crate::PbrtProgress;
|
use crate::PbrtProgress;
|
||||||
use crate::globals::get_options;
|
|
||||||
use crate::lights::sampler::create_light_sampler;
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use shared::core::LightIdx;
|
|
||||||
use shared::core::bxdf::{FArgs, TransportMode};
|
use shared::core::bxdf::{FArgs, TransportMode};
|
||||||
use shared::core::camera::{Camera, CameraTrait};
|
use shared::core::camera::{Camera, CameraTrait};
|
||||||
use shared::core::film::VisibleSurface;
|
use shared::core::film::VisibleSurface;
|
||||||
|
|
@ -19,23 +18,24 @@ use shared::core::interaction::InteractionTrait;
|
||||||
use shared::core::light::{Light, LightSampleContext, LightTrait};
|
use shared::core::light::{Light, LightSampleContext, LightTrait};
|
||||||
use shared::core::material::{Material, MaterialEvalContext, MaterialTrait};
|
use shared::core::material::{Material, MaterialEvalContext, MaterialTrait};
|
||||||
use shared::core::primitive::{Primitive, PrimitiveTrait};
|
use shared::core::primitive::{Primitive, PrimitiveTrait};
|
||||||
use shared::core::sampler::{CameraSample, Sampler, SamplerTrait, get_camera_sample};
|
use shared::core::sampler::{get_camera_sample, CameraSample, Sampler, SamplerTrait};
|
||||||
use shared::core::texture::{BasicTextureEvaluator, TextureEvalContext, UniversalTextureEvaluator};
|
use shared::core::texture::{BasicTextureEvaluator, TextureEvalContext, UniversalTextureEvaluator};
|
||||||
|
use shared::core::LightIdx;
|
||||||
use shared::lights::sampler::{LightSampler, LightSamplerTrait};
|
use shared::lights::sampler::{LightSampler, LightSamplerTrait};
|
||||||
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
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::math::square;
|
||||||
use shared::utils::sampling::power_heuristic;
|
use shared::utils::sampling::power_heuristic;
|
||||||
use shared::utils::soa::{SoA, SoAAllocator, WorkQueue};
|
use shared::utils::soa::{SoA, SoAAllocator, WorkQueue};
|
||||||
use shared::wavefront::workitems::*;
|
use shared::wavefront::workitems::*;
|
||||||
use shared::wavefront::{WavefrontAggregate, WavefrontPathIntegrator, WavefrontRenderer};
|
use shared::wavefront::{WavefrontAggregate, WavefrontPathIntegrator, WavefrontRenderer};
|
||||||
use shared::{GVec, Ptr, SHADOW_EPSILON, gvec, gvec_from_slice};
|
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 std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
static DIAG_EVAL_ENTER: AtomicU32 = AtomicU32::new(0);
|
static DIAG_EVAL_ENTER: AtomicU32 = AtomicU32::new(0);
|
||||||
static DIAG_BSDF_EMPTY: AtomicU32 = AtomicU32::new(0);
|
static DIAG_BSDF_EMPTY: AtomicU32 = AtomicU32::new(0);
|
||||||
|
|
@ -232,39 +232,23 @@ impl CpuWavefrontRenderer {
|
||||||
eprintln!("=== DIAG s=0 y0={} depth={} ===", y0, depth);
|
eprintln!("=== DIAG s=0 y0={} depth={} ===", y0, depth);
|
||||||
eprintln!(" eval_enter={}", DIAG_EVAL_ENTER.load(Ordering::Relaxed));
|
eprintln!(" eval_enter={}", DIAG_EVAL_ENTER.load(Ordering::Relaxed));
|
||||||
eprintln!(" bsdf_empty={}", DIAG_BSDF_EMPTY.load(Ordering::Relaxed));
|
eprintln!(" bsdf_empty={}", DIAG_BSDF_EMPTY.load(Ordering::Relaxed));
|
||||||
eprintln!(
|
eprintln!(" non_specular_skip={}", DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed));
|
||||||
" non_specular_skip={}",
|
eprintln!(" sample_light_none={}", DIAG_SAMPLE_LIGHT_NONE.load(Ordering::Relaxed));
|
||||||
DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed)
|
eprintln!(" sample_li_none={}", DIAG_SAMPLE_LI_NONE.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_l_black={}", DIAG_LS_L_BLACK.load(Ordering::Relaxed));
|
||||||
eprintln!(" ls_pdf_zero={}", DIAG_LS_PDF_ZERO.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_none={}", DIAG_F_NONE.load(Ordering::Relaxed));
|
||||||
eprintln!(" f_black={}", DIAG_F_BLACK.load(Ordering::Relaxed));
|
eprintln!(" f_black={}", DIAG_F_BLACK.load(Ordering::Relaxed));
|
||||||
eprintln!(" shadow_push={}", DIAG_SHADOW_PUSH.load(Ordering::Relaxed));
|
eprintln!(" shadow_push={}", DIAG_SHADOW_PUSH.load(Ordering::Relaxed));
|
||||||
eprintln!(
|
eprintln!(" shadow_unoccluded={}", super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed));
|
||||||
" shadow_unoccluded={}",
|
|
||||||
super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed)
|
|
||||||
);
|
|
||||||
let img_n = DIAG_IMG_COUNT.load(Ordering::Relaxed);
|
let img_n = DIAG_IMG_COUNT.load(Ordering::Relaxed);
|
||||||
if img_n > 0 {
|
if img_n > 0 {
|
||||||
let scale = f32::from_bits(DIAG_IMG_SCALE_BITS.load(Ordering::Relaxed));
|
let scale = f32::from_bits(DIAG_IMG_SCALE_BITS.load(Ordering::Relaxed));
|
||||||
let pixel0 =
|
let pixel0 = f32::from_bits(DIAG_IMG_PIXEL0_BITS.load(Ordering::Relaxed));
|
||||||
f32::from_bits(DIAG_IMG_PIXEL0_BITS.load(Ordering::Relaxed));
|
|
||||||
let rgb0 = f32::from_bits(DIAG_IMG_RGB0_BITS.load(Ordering::Relaxed));
|
let rgb0 = f32::from_bits(DIAG_IMG_RGB0_BITS.load(Ordering::Relaxed));
|
||||||
let result0 =
|
let result0 = f32::from_bits(DIAG_IMG_RESULT0_BITS.load(Ordering::Relaxed));
|
||||||
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}",
|
||||||
eprintln!(
|
img_n, scale, pixel0, rgb0, result0);
|
||||||
" img_tex_calls={} scale={:.6} pixel0={:.6} rgb0_pre_scale={:.6} result[0]={:.6}",
|
|
||||||
img_n, scale, pixel0, rgb0, result0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -279,27 +263,15 @@ impl CpuWavefrontRenderer {
|
||||||
eprintln!("=== NEE DIAG COUNTS ===");
|
eprintln!("=== NEE DIAG COUNTS ===");
|
||||||
eprintln!("eval_enter={}", DIAG_EVAL_ENTER.load(Ordering::Relaxed));
|
eprintln!("eval_enter={}", DIAG_EVAL_ENTER.load(Ordering::Relaxed));
|
||||||
eprintln!("bsdf_empty={}", DIAG_BSDF_EMPTY.load(Ordering::Relaxed));
|
eprintln!("bsdf_empty={}", DIAG_BSDF_EMPTY.load(Ordering::Relaxed));
|
||||||
eprintln!(
|
eprintln!("non_specular_skip={}", DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed));
|
||||||
"non_specular_skip={}",
|
eprintln!("sample_light_none={}", DIAG_SAMPLE_LIGHT_NONE.load(Ordering::Relaxed));
|
||||||
DIAG_NON_SPECULAR_SKIP.load(Ordering::Relaxed)
|
eprintln!("sample_li_none={}", DIAG_SAMPLE_LI_NONE.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_l_black={}", DIAG_LS_L_BLACK.load(Ordering::Relaxed));
|
||||||
eprintln!("ls_pdf_zero={}", DIAG_LS_PDF_ZERO.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_none={}", DIAG_F_NONE.load(Ordering::Relaxed));
|
||||||
eprintln!("f_black={}", DIAG_F_BLACK.load(Ordering::Relaxed));
|
eprintln!("f_black={}", DIAG_F_BLACK.load(Ordering::Relaxed));
|
||||||
eprintln!("shadow_push={}", DIAG_SHADOW_PUSH.load(Ordering::Relaxed));
|
eprintln!("shadow_push={}", DIAG_SHADOW_PUSH.load(Ordering::Relaxed));
|
||||||
eprintln!(
|
eprintln!("shadow_unoccluded={}", super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed));
|
||||||
"shadow_unoccluded={}",
|
|
||||||
super::aggregate::DIAG_SHADOW_UNOCCLUDED.load(Ordering::Relaxed)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_camera_rays(
|
fn generate_camera_rays(
|
||||||
|
|
@ -492,19 +464,11 @@ impl CpuWavefrontRenderer {
|
||||||
dpdu={:?} dpdv={:?} \
|
dpdu={:?} dpdv={:?} \
|
||||||
dpdus={:?} dpdvs={:?} \
|
dpdus={:?} dpdvs={:?} \
|
||||||
uv={:?} material={:?} area_light={:?} face_index={}",
|
uv={:?} material={:?} area_light={:?} face_index={}",
|
||||||
w.pixel_index,
|
w.pixel_index, w.depth,
|
||||||
w.depth,
|
w.p, w.n, w.ns,
|
||||||
w.p,
|
w.dpdu, w.dpdv,
|
||||||
w.n,
|
w.dpdus, w.dpdvs,
|
||||||
w.ns,
|
w.uv, w.material, w.area_light, w.face_index,
|
||||||
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);
|
DIAG_EVAL_ENTER.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
@ -536,12 +500,12 @@ impl CpuWavefrontRenderer {
|
||||||
dpdus: w.dpdus,
|
dpdus: w.dpdus,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut lambda = w.lambda;
|
let lambda = w.lambda;
|
||||||
|
|
||||||
let mut bsdf = if use_universal {
|
let mut bsdf = if use_universal {
|
||||||
material.get_bsdf(&UniversalTextureEvaluator, &ctx, &mut lambda)
|
material.get_bsdf(&UniversalTextureEvaluator, &ctx, &lambda)
|
||||||
} else {
|
} else {
|
||||||
material.get_bsdf(&BasicTextureEvaluator, &ctx, &mut lambda)
|
material.get_bsdf(&BasicTextureEvaluator, &ctx, &lambda)
|
||||||
};
|
};
|
||||||
|
|
||||||
if lambda.secondary_terminated() {
|
if lambda.secondary_terminated() {
|
||||||
|
|
@ -694,16 +658,8 @@ impl CpuWavefrontRenderer {
|
||||||
"NEE_D0[{n}] pixel={:?} ls.l={:?} ls.pdf={:.6} f={:?} \
|
"NEE_D0[{n}] pixel={:?} ls.l={:?} ls.pdf={:.6} f={:?} \
|
||||||
beta={:?} light_pdf={:.6} bsdf_pdf={:.6} \
|
beta={:?} light_pdf={:.6} bsdf_pdf={:.6} \
|
||||||
r_u={:?} r_l={:?} l_d={:?}",
|
r_u={:?} r_l={:?} l_d={:?}",
|
||||||
w.pixel_index,
|
w.pixel_index, ls.l, ls.pdf, f, beta,
|
||||||
ls.l,
|
light_pdf, bsdf_pdf, r_u, r_l, l_d
|
||||||
ls.pdf,
|
|
||||||
f,
|
|
||||||
beta,
|
|
||||||
light_pdf,
|
|
||||||
bsdf_pdf,
|
|
||||||
r_u,
|
|
||||||
r_l,
|
|
||||||
l_d
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue