Closed wahn closed 6 years ago
Commit ea3f0c7133103a4b921d183b914027f3e96200a4 starts to work on this issue and provides a skeleton for FourierMaterial
and FourierBSDFTable
.
We have to implement the Rust counterpart to FourierBSDFTable::Read(...)
next ...
Let's check the header first (see commit 88b0971a9857718576b41fa7fa50a1f6473b46c2):
$ cd /home/jan/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van
$ ~/git/self_hosted/Rust/pbrt/target/release/examples/rs_pbrt -i vw-van.pbrt
...
thread 'main' panicked at 'WORK: Header found', src/core/reflection.rs:60:17
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Since commit ddd1b6cc7ecc75ac2893bd31d6d6dbe4924f62b2 we use the byteorder
crate (to read 6 little endian i32 values):
$ cd /home/jan/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van
$ ~/git/self_hosted/Rust/pbrt/target/release/examples/rs_pbrt -i vw-van.pbrt
...
WORK: flags = 1
WORK: n_mu = 852
WORK: n_coeffs = 24360150
WORK: m_max = 1599
WORK: n_channels = 3
WORK: n_bases = 1
reading "bsdfs/ceramic.bsdf" returns false
...
With gdb
and the C++ version you can confirm those values:
(gdb) p flags
$7 = 1
(gdb) p bsdfTable->nMu
$8 = 852
(gdb) p nCoeffs
$9 = 24360150
(gdb) p bsdfTable->mMax
$10 = 1599
(gdb) p bsdfTable->nChannels
$11 = 3
(gdb) p nBases
$12 = 1
Since commit 363ee05cd35a367aa9eb29cd626096ea99a6c827 we can read the entire *.bsdf
file:
$ cd /home/jan/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van
$ ~/git/self_hosted/Rust/pbrt/target/release/examples/rs_pbrt -i vw-van.pbrt
...
WORK: flags = 1
WORK: n_mu = 852
WORK: n_coeffs = 24360150
WORK: m_max = 1599
WORK: n_channels = 3
WORK: n_bases = 1
WORK: eta = 1.0
WORK: 852 f32 values read for mu
WORK: 725904 f32 values read for cdf
WORK: 1451808 f32 values read for offset_and_length
WORK: 24360150 f32 values read for a
reading "bsdfs/ceramic.bsdf" returns true
...
But the values stored in FourierBSDFTable
are not used yet.
Since commit b33f0f86db4c6b2f06e5e670e64a7dbe87fa881d we store the FourierBSDFTable
within the FourierMaterial
, but we need a FourierBSDF
now:
> rg -tcpp "class FourierBSDF"
core/reflection.h
500:class FourierBSDF : public BxDF {
In C++ the class looks like this:
class FourierBSDF : public BxDF {
public:
// FourierBSDF Public Methods
Spectrum f(const Vector3f &wo, const Vector3f &wi) const;
FourierBSDF(const FourierBSDFTable &bsdfTable, TransportMode mode)
: BxDF(BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_GLOSSY)),
bsdfTable(bsdfTable),
mode(mode) {}
Spectrum Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &u,
Float *pdf, BxDFType *sampledType) const;
Float Pdf(const Vector3f &wo, const Vector3f &wi) const;
std::string ToString() const;
private:
// FourierBSDF Private Data
const FourierBSDFTable &bsdfTable;
const TransportMode mode;
};
Commit ed6ecc598c1394e9d2600c046dfaf7e8a73d9fcc leaves us a couple of functions to implement:
I started to work on FourierBSDF::f(...)
, needed FourierBSDFTable::get_weights_and_offset(...)
, and the next task to do is to implement catmull_rom_weights(...)
:
> rg -tcpp "bool CatmullRomWeights\(" -A 1
core/interpolation.h
48:bool CatmullRomWeights(int size, const Float *nodes, Float x, int *offset,
49- Float *weights);
core/interpolation.cpp
61:bool CatmullRomWeights(int size, const Float *nodes, Float x, int *offset,
62- Float *weights) {
The C++ counterpart looks like this:
bool CatmullRomWeights(int size, const Float *nodes, Float x, int *offset,
Float *weights) {
// Return _false_ if _x_ is out of bounds
if (!(x >= nodes[0] && x <= nodes[size - 1])) return false;
// Search for the interval _idx_ containing _x_
int idx = FindInterval(size, [&](int i) { return nodes[i] <= x; });
*offset = idx - 1;
Float x0 = nodes[idx], x1 = nodes[idx + 1];
// Compute the $t$ parameter and powers
Float t = (x - x0) / (x1 - x0), t2 = t * t, t3 = t2 * t;
// Compute initial node weights $w_1$ and $w_2$
weights[1] = 2 * t3 - 3 * t2 + 1;
weights[2] = -2 * t3 + 3 * t2;
// Compute first node weight $w_0$
if (idx > 0) {
Float w0 = (t3 - 2 * t2 + t) * (x1 - x0) / (x1 - nodes[idx - 1]);
weights[0] = -w0;
weights[2] += w0;
} else {
Float w0 = t3 - 2 * t2 + t;
weights[0] = 0;
weights[1] -= w0;
weights[2] += w0;
}
// Compute last node weight $w_3$
if (idx + 2 < size) {
Float w3 = (t3 - t2) * (x1 - x0) / (nodes[idx + 2] - x0);
weights[1] -= w3;
weights[3] = w3;
} else {
Float w3 = t3 - t2;
weights[1] -= w3;
weights[2] += w3;
weights[3] = 0;
}
return true;
}
Since commit 4c8b7599de1f8aada30cbb55cb3c5a0bb5c2728f FourierBSDF::f(...)
is finished, but there are still two functions left to do:
FourierBSDF::sample_f(...)
FourierBSDF::pdf(...)
In theory all the Bxdf
functions are fully implemented for FourierBSDF
(since commit fe8752a03435ddad6393904b7f993b506a838499), but we have to debug why the scene panics:
$ pwd
/home/jan/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van
$ ~/git/self_hosted/Rust/pbrt/target/release/examples/rs_pbrt -i vw-van.pbrt
pbrt version 0.4.2 [Detected 4 cores]
...
thread '<unnamed>' panicked at 'assertion failed: !ret.has_nans()', src/core/spectrum.rs:1622:9
Closing the ticket after commit e7ab8e5036971f0a9bd7da2c8d2f7723d76459e3 removes the source of the panic.
The test scene
~/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van/vw-van.pbrt
uses a fourier material:On the C++ side we have this class:
We have to implement the Rust counterpart ...