Skip to content

Commit

Permalink
Implement diffuse reflectance for most BSDFs
Browse files Browse the repository at this point in the history
  • Loading branch information
njroussel committed Oct 24, 2022
1 parent 31271c9 commit 59af884
Show file tree
Hide file tree
Showing 16 changed files with 138 additions and 21 deletions.
4 changes: 2 additions & 2 deletions include/mitsuba/python/docstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,8 @@ Parameter ``si``:
Parameter ``wo``:
The outgoing direction)doc";

static const char *__doc_mitsuba_BSDF_eval_diffuse_reflectance = R"doc(Return the diffuse reflectance value)doc";

static const char *__doc_mitsuba_BSDF_eval_null_transmission =
R"doc(Evaluate un-scattered transmission component of the BSDF
Expand Down Expand Up @@ -798,8 +800,6 @@ static const char *__doc_mitsuba_BSDF_flags = R"doc(Flags for all components com

static const char *__doc_mitsuba_BSDF_flags_2 = R"doc(Flags for a specific component of this BSDF.)doc";

static const char *__doc_mitsuba_BSDF_get_diffuse_reflectance = R"doc(Return the diffuse reflectance value (if any))doc";

static const char *__doc_mitsuba_BSDF_id = R"doc(Return a string identifier)doc";

static const char *__doc_mitsuba_BSDF_m_components = R"doc(Flags for each component of this BSDF.)doc";
Expand Down
21 changes: 17 additions & 4 deletions include/mitsuba/render/bsdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,22 @@ class MI_EXPORT_LIB BSDF : public Object {
/// Set a string identifier
void set_id(const std::string& id) override { m_id = id; };

/// Return the diffuse reflectance value (if any)
virtual Spectrum get_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active = true) const;
/**
* \brief Evaluate the diffuse reflectance
*
* This method approximates the total diffuse reflectance for a given
* direction. For some materials, an exact value can be computed
* inexpensively.
* When this is not possible, the value is approximated by
* evaluating the BSDF for a normal outgoing direction and returning this
* value multiplied by pi. This is the default behaviour of this method.
*
* \param si
* A surface interaction data structure describing the underlying
* surface position.
*/
virtual Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active = true) const;

/// Return a human-readable representation of the BSDF
std::string to_string() const override = 0;
Expand Down Expand Up @@ -545,7 +558,7 @@ DRJIT_VCALL_TEMPLATE_BEGIN(mitsuba::BSDF)
DRJIT_VCALL_METHOD(eval_null_transmission)
DRJIT_VCALL_METHOD(pdf)
DRJIT_VCALL_METHOD(eval_pdf)
DRJIT_VCALL_METHOD(get_diffuse_reflectance)
DRJIT_VCALL_METHOD(eval_diffuse_reflectance)
DRJIT_VCALL_GETTER(flags, uint32_t)
auto needs_differentials() const {
return has_flag(flags(), mitsuba::BSDFFlags::NeedsDifferentials);
Expand Down
7 changes: 7 additions & 0 deletions src/bsdfs/blendbsdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,13 @@ class BlendBSDF final : public BSDF<Float, Spectrum> {
return dr::clamp(m_weight->eval_1(si, active), 0.f, 1.f);
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
Float weight = eval_weight(si, active);
return m_nested_bsdf[0]->eval_diffuse_reflectance(si, active) * (1 - weight) +
m_nested_bsdf[1]->eval_diffuse_reflectance(si, active) * weight;
}

std::string to_string() const override {
std::ostringstream oss;
oss << "BlendBSDF[" << std::endl
Expand Down
5 changes: 5 additions & 0 deletions src/bsdfs/bumpmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ class BumpMap final : public BSDF<Float, Spectrum> {
return result;
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_nested_bsdf->eval_diffuse_reflectance(si, active);
}

std::string to_string() const override {
std::ostringstream oss;
oss << "BumpMap[" << std::endl
Expand Down
5 changes: 5 additions & 0 deletions src/bsdfs/circular.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ class CircularPolarizer final : public BSDF<Float, Spectrum> {
}
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_transmittance->eval(si, active);
}

std::string to_string() const override {
std::ostringstream oss;
oss << "CircularPolarizer[" << std::endl
Expand Down
4 changes: 2 additions & 2 deletions src/bsdfs/diffuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ class SmoothDiffuse final : public BSDF<Float, Spectrum> {
return { depolarizer<Spectrum>(value) & active, dr::select(active, pdf, 0.f) };
}

/// Return the diffuse reflectance value (if any)
Spectrum get_diffuse_reflectance(const SurfaceInteraction3f &si, Mask active) const override {
Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_reflectance->eval(si, active);
}

Expand Down
5 changes: 5 additions & 0 deletions src/bsdfs/mask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ class MaskBSDF final : public BSDF<Float, Spectrum> {
return dr::clamp(m_opacity->eval_1(si, active), 0.f, 1.f);
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_nested_bsdf->eval_diffuse_reflectance(si, active);
}

std::string to_string() const override {
std::ostringstream oss;
oss << "Mask[" << std::endl
Expand Down
3 changes: 2 additions & 1 deletion src/bsdfs/plastic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ class SmoothPlastic final : public BSDF<Float, Spectrum> {
dr::select(active, hemi_pdf * prob_diffuse, 0.f) };
}

Spectrum get_diffuse_reflectance(const SurfaceInteraction3f &si, Mask active) const override {
Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_diffuse_reflectance->eval(si, active);
}

Expand Down
5 changes: 5 additions & 0 deletions src/bsdfs/principled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,11 @@ class Principled final : public BSDF<Float, Spectrum> {
return pdf;
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_base_color->eval(si, active);
}

std::string to_string() const override {
std::ostringstream oss;
oss << "Principled BSDF :" << std::endl
Expand Down
5 changes: 5 additions & 0 deletions src/bsdfs/principledthin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,11 @@ class PrincipledThin final : public BSDF<Float, Spectrum> {
return pdf;
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_base_color->eval(si, active);
}

std::string to_string() const override {
std::ostringstream oss;
oss << "The Thin Principled BSDF :" << std::endl
Expand Down
4 changes: 2 additions & 2 deletions src/bsdfs/roughplastic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ class RoughPlastic final : public BSDF<Float, Spectrum> {
return { depolarizer<Spectrum>(value) & active, pdf };
}

/// Return the diffuse reflectance value (if any)
Spectrum get_diffuse_reflectance(const SurfaceInteraction3f &si, Mask active) const override {
Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
return m_diffuse_reflectance->eval(si, active);
}

Expand Down
43 changes: 43 additions & 0 deletions src/bsdfs/tests/test_twosided.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,46 @@ def test03_sample_eval_pdf(variant_scalar_rgb):
v_eval_pdf = bsdf.eval_pdf(ctx, si, bs.wo)
assert dr.allclose(e_value, v_eval_pdf[0])
assert dr.allclose(p_pdf, v_eval_pdf[1])

def test03_eval_diffuse_reflectance(variants_vec_rgb):
bsdf_front = mi.load_dict({
'type': 'diffuse',
'reflectance': {
'type': 'rgb',
'value': [0.1, 0.1, 0.1]
}
})
bsdf_back = mi.load_dict({
'type': 'diffuse',
'reflectance': {
'type': 'rgb',
'value': [0.9, 0.9, 0.9]
}
})
bsdf = mi.load_dict({
'type': 'twosided',
'a': bsdf_front,
'b': bsdf_back,
})

si = mi.SurfaceInteraction3f()
si.t = 0.1
si.p = [0, 0, 0]
si.n = [0, 0, 1]
si.sh_frame = mi.Frame3f(si.n)

n = 5
epsilon = 0.0001
for u in dr.linspace(mi.Float, epsilon, 1 - epsilon, n):
for v in dr.linspace(mi.Float, epsilon, 1 - epsilon, n):
si.wi = mi.warp.square_to_uniform_sphere([u / float(n-1),
v / float(n-1)])
up = mi.Frame3f.cos_theta(si.wi) > 0.0

value = bsdf.eval_diffuse_reflectance(si)
value_front = bsdf_front.eval_diffuse_reflectance(si)
si.wi.z *= -1
value_back = bsdf_back.eval_diffuse_reflectance(si)

assert dr.allclose(dr.select(up, value - value_front, 0), 0.0)
assert dr.allclose(dr.select(up, 0, value - value_back), 0.0)
25 changes: 25 additions & 0 deletions src/bsdfs/twosided.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,31 @@ class TwoSidedBRDF final : public BSDF<Float, Spectrum> {
return { value, pdf };
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si_,
Mask active) const override {
SurfaceInteraction3f si(si_);

if (m_brdf[0] == m_brdf[1]) {
si.wi.z() = dr::abs(si.wi.z());
return m_brdf[0]->eval_diffuse_reflectance(si, active);
} else {
Spectrum result = 0.f;
Mask front_side = Frame3f::cos_theta(si.wi) > 0.f && active,
back_side = Frame3f::cos_theta(si.wi) < 0.f && active;

if (dr::any_or<true>(front_side))
result = m_brdf[0]->eval_diffuse_reflectance(si, front_side);

if (dr::any_or<true>(back_side)) {
si.wi.z() *= -1.f;
dr::masked(result, back_side) =
m_brdf[1]->eval_diffuse_reflectance(si, back_side);
}

return result;
}
}

std::string to_string() const override {
std::ostringstream oss;
oss << "TwoSided[" << std::endl
Expand Down
5 changes: 4 additions & 1 deletion src/integrators/aov.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ Note that integer-valued AOVs (e.g. :monosp:`prim_index`, :monosp:`shape_index`)
are meaningless whenever there is only partial pixel coverage or when using a
wide pixel reconstruction filter as it will result in fractional values.

The :monosp:`albedo` AOV will evaluate the diffuse reflectance
(\ref BSDF::eval_diffuse_reflectance) of the material. Note that depending on
the material, this value might only be an approximation.
*/

template <typename Float, typename Spectrum>
Expand Down Expand Up @@ -209,7 +212,7 @@ class AOVIntegrator final : public SamplingIntegrator<Float, Spectrum> {
switch (m_aov_types[i]) {
case Type::Albedo: {
BSDFPtr bsdf = si.bsdf(ray);
Spectrum spec = bsdf->get_diffuse_reflectance(si, active);
Spectrum spec = bsdf->eval_diffuse_reflectance(si, active);
Color3f color;
if constexpr (is_spectral_v<Spectrum>)
color = spectrum_to_srgb(spec, ray.wavelengths, active);
Expand Down
6 changes: 3 additions & 3 deletions src/render/bsdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ MI_VARIANT Spectrum BSDF<Float, Spectrum>::eval_null_transmission(
return 0.f;
}

MI_VARIANT Spectrum BSDF<Float, Spectrum>::get_diffuse_reflectance(
MI_VARIANT Spectrum BSDF<Float, Spectrum>::eval_diffuse_reflectance(
const SurfaceInteraction3f &si, Mask active) const {
Vector3f placeholder = Vector3f(0.0f, 0.0f, 1.0f);
Vector3f wo = Vector3f(0.0f, 0.0f, 1.0f);
BSDFContext ctx;
return eval(ctx, si, placeholder, active) * dr::Pi<Float>;
return eval(ctx, si, wo, active) * dr::Pi<Float>;
}

template <typename Index>
Expand Down
12 changes: 6 additions & 6 deletions src/render/python/bsdf_v.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ MI_VARIANT class PyBSDF : public BSDF<Float, Spectrum> {
PYBIND11_OVERRIDE_PURE(Return, BSDF, eval_pdf, ctx, si, wo, active);
}

Spectrum get_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
PYBIND11_OVERRIDE_PURE(Spectrum, BSDF, get_diffuse_reflectance, si, active);
Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Mask active) const override {
PYBIND11_OVERRIDE_PURE(Spectrum, BSDF, eval_diffuse_reflectance, si, active);
}

std::string to_string() const override {
Expand Down Expand Up @@ -101,10 +101,10 @@ template <typename Ptr, typename Cls> void bind_bsdf_generic(Cls &cls) {
[](Ptr bsdf, const SurfaceInteraction3f &si, Mask active) {
return bsdf->eval_null_transmission(si, active);
}, "si"_a, "active"_a = true, D(BSDF, eval_null_transmission))
.def("get_diffuse_reflectance",
.def("eval_diffuse_reflectance",
[](Ptr bsdf, const SurfaceInteraction3f &si, Mask active) {
return bsdf->get_diffuse_reflectance(si, active);
}, "si"_a, "active"_a = true)
return bsdf->eval_diffuse_reflectance(si, active);
}, "si"_a, "active"_a = true, D(BSDF, eval_diffuse_reflectance))
.def("flags", [](Ptr bsdf) { return bsdf->flags(); }, D(BSDF, flags))
.def("needs_differentials",
[](Ptr bsdf) { return bsdf->needs_differentials(); },
Expand Down

0 comments on commit 59af884

Please sign in to comment.