wahn / rs_pbrt

Rust crate to implement a counterpart to the PBRT book's (3rd edition) C++ code. See also https://www.rs-pbrt.org/about ...
https://www.rs-pbrt.org
Other
811 stars 59 forks source link

Implement GonioPhotometricLight #117

Closed wahn closed 5 years ago

wahn commented 5 years ago

Even though the book describes the GonioPhotometricLight, e.g. here:

http://www.pbr-book.org/3ed-2018/Light_Sources/Point_Lights.html#GoniophotometricDiagramLights

I was not able to find another example, except the one shipping with PBRTForMaya:

pbrt

> ~/builds/pbrt/release/pbrt pbrt_feature_demo_light_goniometric.pbrt

The image above was rendered by the C++ version of PBRT and we need to implement the counterpart to the C++ class GonioPhotometricLight:

// GonioPhotometricLight Declarations
class GonioPhotometricLight : public Light {
  public:
    // GonioPhotometricLight Public Methods
    Spectrum Sample_Li(const Interaction &ref, const Point2f &u, Vector3f *wi,
                       Float *pdf, VisibilityTester *vis) const;
    GonioPhotometricLight(const Transform &LightToWorld,
                          const MediumInterface &mediumInterface,
                          const Spectrum &I, const std::string &texname)
        : Light((int)LightFlags::DeltaPosition, LightToWorld, mediumInterface),
          pLight(LightToWorld(Point3f(0, 0, 0))),
          I(I) {
        // Create _mipmap_ for _GonioPhotometricLight_
        Point2i resolution;
        std::unique_ptr<RGBSpectrum[]> texels = ReadImage(texname, &resolution);
        if (texels)
            mipmap.reset(new MIPMap<RGBSpectrum>(resolution, texels.get()));
    }
    Spectrum Scale(const Vector3f &w) const {
        Vector3f wp = Normalize(WorldToLight(w));
        std::swap(wp.y, wp.z);
        Float theta = SphericalTheta(wp);
        Float phi = SphericalPhi(wp);
        Point2f st(phi * Inv2Pi, theta * InvPi);
        return !mipmap ? RGBSpectrum(1.f)
                       : Spectrum(mipmap->Lookup(st), SpectrumType::Illuminant);
    }
    Spectrum Power() const;
    Float Pdf_Li(const Interaction &, const Vector3f &) const;
    Spectrum Sample_Le(const Point2f &u1, const Point2f &u2, Float time,
                       Ray *ray, Normal3f *nLight, Float *pdfPos,
                       Float *pdfDir) const;
    void Pdf_Le(const Ray &, const Normal3f &, Float *pdfPos,
                Float *pdfDir) const;

  private:
    // GonioPhotometricLight Private Data
    const Point3f pLight;
    const Spectrum I;
    std::unique_ptr<MIPMap<RGBSpectrum>> mipmap;
};
wahn commented 5 years ago

After commit 94642784a6ac1b6b194258d5464bfde182f99504 the test scene renders 100% the same between the Rust and the C++ version:

> imf_diff pbrt_rust.png pbrt_cpp.png
pbrt_rust.png pbrt_cpp.png: no differences.
== "pbrt_rust.png" and "pbrt_cpp.png" are identical