Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement FourierMaterial #61

Closed
wahn opened this issue Sep 7, 2018 · 10 comments
Closed

Implement FourierMaterial #61

wahn opened this issue Sep 7, 2018 · 10 comments
Assignees
Labels

Comments

@wahn
Copy link
Owner

wahn commented Sep 7, 2018

The test scene ~/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van/vw-van.pbrt uses a fourier material:

$ rg fourier /home/jan/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van
/home/jan/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_vw_van/vw-van.pbrt
55:    "string type" "fourier" "string bsdffile" "bsdfs/ceramic.bsdf"

On the C++ side we have this class:

// FourierMaterial Declarations
class FourierMaterial : public Material {
  public:
    // FourierMaterial Public Methods
    FourierMaterial(const std::string &filename,
                    const std::shared_ptr<Texture<Float>> &bump);
    void ComputeScatteringFunctions(SurfaceInteraction *si, MemoryArena &arena,
                                    TransportMode mode,
                                    bool allowMultipleLobes) const;

  private:
    // FourierMaterial Private Data
    FourierBSDFTable *bsdfTable;
    std::shared_ptr<Texture<Float>> bumpMap;
    static std::map<std::string, std::unique_ptr<FourierBSDFTable>> loadedBSDFs;
};

We have to implement the Rust counterpart ...

@wahn wahn self-assigned this Sep 7, 2018
@wahn wahn added the task label Sep 7, 2018
@wahn
Copy link
Owner Author

wahn commented Sep 7, 2018

Commit ea3f0c7 starts to work on this issue and provides a skeleton for FourierMaterial and FourierBSDFTable.

@wahn
Copy link
Owner Author

wahn commented Sep 7, 2018

We have to implement the Rust counterpart to FourierBSDFTable::Read(...) next ...

@wahn
Copy link
Owner Author

wahn commented Sep 19, 2018

Let's check the header first (see commit 88b0971):

$ 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.

@wahn
Copy link
Owner Author

wahn commented Sep 19, 2018

Since commit ddd1b6c 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

@wahn
Copy link
Owner Author

wahn commented Sep 20, 2018

Since commit 363ee05 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.

@wahn
Copy link
Owner Author

wahn commented Sep 21, 2018

Since commit b33f0f8 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;
};

@wahn
Copy link
Owner Author

wahn commented Sep 21, 2018

Commit ed6ecc5 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;
}

@wahn
Copy link
Owner Author

wahn commented Sep 25, 2018

Since commit 4c8b759 FourierBSDF::f(...) is finished, but there are still two functions left to do:

  1. FourierBSDF::sample_f(...)
  2. FourierBSDF::pdf(...)

@wahn
Copy link
Owner Author

wahn commented Sep 26, 2018

In theory all the Bxdf functions are fully implemented for FourierBSDF (since commit fe8752a), 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

@wahn
Copy link
Owner Author

wahn commented Oct 4, 2018

Closing the ticket after commit e7ab8e5 removes the source of the panic.

@wahn wahn closed this as completed Oct 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant