Skip to content

Commit

Permalink
Add textured alpha for roughconductor and roughdielectric
Browse files Browse the repository at this point in the history
  • Loading branch information
Speierers committed Mar 4, 2020
1 parent e61a353 commit cac8741
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 62 deletions.
48 changes: 24 additions & 24 deletions include/mitsuba/core/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,47 +263,47 @@ class MTS_EXPORT_CORE Properties {
/// Retrieve a color (use default value if no entry exists)
const Color3f& color(const std::string &name, const Color3f &def_val) const;

/// Retrieve a texture
/// Retrieve a texture (if the property is a float, create a uniform texture instead)
template <typename Texture>
ref<Texture> texture(const std::string &name) const {
ref<Object> object = find_object(name);
if (!object)
if (!has_property(name))
Throw("Property \"%s\" has not been specified!", name);
if (!object->class_()->derives_from(MTS_CLASS(Texture)))

auto p_type = type(name);
if (p_type == Properties::Type::Object) {
ref<Object> object = find_object(name);
if (!object->class_()->derives_from(MTS_CLASS(Texture)))
Throw("The property \"%s\" has the wrong type (expected "
" <spectrum> or <texture>).", name);
mark_queried(name);
return (Texture *) object.get();
} else if (p_type == Properties::Type::Float) {
Properties props("uniform");
props.set_float("value", float_(name));
return (Texture *) PluginManager::instance()->create_object<Texture>(props).get();
} else {
Throw("The property \"%s\" has the wrong type (expected "
" <spectrum> or <texture>).", name);
mark_queried(name);
return (Texture *) object.get();
" <spectrum> or <texture>).", name);
}
}


/// Retrieve a texture (use the provided spectrum if no entry exists)
/// Retrieve a texture (use the provided texture if no entry exists)
template <typename Texture>
ref<Texture> texture(const std::string &name, ref<Texture> def_val) const {
ref<Object> object = find_object(name);
if (!object)
if (!has_property(name))
return def_val;
if (!object->class_()->derives_from(MTS_CLASS(Texture)))
Throw("The property \"%s\" has the wrong type (expected "
" <spectrum> or <texture>).", name);
mark_queried(name);
return (Texture *) object.get();
return texture<Texture>(name);
}

/// Retrieve a continuous spectrum (or create flat spectrum with default value)
/// Retrieve a texture (or create uniform texture with default value)
template <typename Texture>
ref<Texture> texture(const std::string &name, Float def_val) const {
ref<Object> object = find_object(name);
if (!object) {
if (!has_property(name)) {
Properties props("uniform");
props.set_float("value", def_val);
return (Texture *) PluginManager::instance()->create_object<Texture>(props).get();
}
if (!object->class_()->derives_from(MTS_CLASS(Texture)))
Throw("The property \"%s\" has the wrong type (expected "
" <spectrum> or <texture>).", name);
mark_queried(name);
return (Texture *) object.get();
return texture<Texture>(name);
}

/// Retrieve a 3D texture
Expand Down
61 changes: 45 additions & 16 deletions src/bsdfs/roughconductor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Rough conductor material (:monosp:`roughconductor`)
tails observed in measurements of ground surfaces, which are not modeled by the Beckmann
distribution.
* - alpha, alpha_u, alpha_v
- |float|
- |texture| or |float|
- Specifies the roughness of the unresolved surface micro-geometry along the tangent and
bitangent directions. When the Beckmann distribution is used, this parameter is equal to the
**root mean square** (RMS) slope of the microfacets. :monosp:`alpha` is a convenience
Expand All @@ -57,6 +57,8 @@ rough conducting materials, such as metals.
:caption: Rough copper (Beckmann, :math:`\alpha=0.1`)
.. subfigure:: ../../resources/data/docs/images/render/bsdf_roughconductor_anisotropic_aluminium.jpg
:caption: Vertically brushed aluminium (Anisotropic Beckmann, :math:`\alpha_u=0.05,\ \alpha_v=0.3`)
.. subfigure:: ../../resources/data/docs/images/render/bsdf_roughconductor_textured_carbon.jpg
:caption: Carbon fiber using two inverted checkerboard textures for ``alpha_u`` and ``alpha_v``
.. subfigend::
:label: fig-bsdf-roughconductor
Expand Down Expand Up @@ -153,20 +155,40 @@ class RoughConductor final : public BSDF<Float, Spectrum> {
std::tie(m_eta, m_k) = complex_ior_from_file<Spectrum, Texture>(props.string("material", "Cu"));
}

mitsuba::MicrofacetDistribution<ScalarFloat, Spectrum> distr(props);
m_type = distr.type();
m_sample_visible = distr.sample_visible();
if (props.has_property("distribution")) {
std::string distr = string::to_lower(props.string("distribution"));
if (distr == "beckmann")
m_type = MicrofacetType::Beckmann;
else if (distr == "ggx")
m_type = MicrofacetType::GGX;
else
Throw("Specified an invalid distribution \"%s\", must be "
"\"beckmann\" or \"ggx\"!", distr.c_str());
} else {
m_type = MicrofacetType::Beckmann;
}

m_alpha_u = distr.alpha_u();
m_alpha_v = distr.alpha_v();
m_sample_visible = props.bool_("sample_visible", true);

if (props.has_property("alpha_u") || props.has_property("alpha_v")) {
if (!props.has_property("alpha_u") || !props.has_property("alpha_v"))
Throw("Microfacet model: both 'alpha_u' and 'alpha_v' must be specified.");
if (props.has_property("alpha"))
Throw("Microfacet model: please specify"
"either 'alpha' or 'alpha_u'/'alpha_v'.");
m_alpha_u = props.texture<Texture>("alpha_u");
m_alpha_v = props.texture<Texture>("alpha_v");
} else {
m_alpha_u = m_alpha_v = props.texture<Texture>("alpha", 0.1f);
}

parameters_changed();
}

void parameters_changed() override {
m_flags = BSDFFlags::GlossyReflection | BSDFFlags::FrontSide;

if (m_alpha_u != m_alpha_v)
if (any(neq(m_alpha_u, m_alpha_v)))
m_flags = m_flags | BSDFFlags::Anisotropic;

m_components.clear();
Expand All @@ -189,8 +211,10 @@ class RoughConductor final : public BSDF<Float, Spectrum> {

/* Construct a microfacet distribution matching the
roughness values at the current surface position. */
MicrofacetDistribution distr(m_type, m_alpha_u, m_alpha_v,
m_sample_visible);
MicrofacetDistribution distr(m_type,
m_alpha_u->eval_1(si, active),
m_alpha_v->eval_1(si, active),
m_sample_visible);

// Sample M, the microfacet normal
Normal3f m;
Expand Down Expand Up @@ -271,7 +295,9 @@ class RoughConductor final : public BSDF<Float, Spectrum> {

/* Construct a microfacet distribution matching the
roughness values at the current surface position. */
MicrofacetDistribution distr(m_type, m_alpha_u, m_alpha_v,
MicrofacetDistribution distr(m_type,
m_alpha_u->eval_1(si, active),
m_alpha_v->eval_1(si, active),
m_sample_visible);

// Evaluate the microfacet normal distribution
Expand Down Expand Up @@ -346,7 +372,10 @@ class RoughConductor final : public BSDF<Float, Spectrum> {

/* Construct a microfacet distribution matching the
roughness values at the current surface position. */
MicrofacetDistribution distr(m_type, m_alpha_u, m_alpha_v, m_sample_visible);
MicrofacetDistribution distr(m_type,
m_alpha_u->eval_1(si, active),
m_alpha_v->eval_1(si, active),
m_sample_visible);

Float result;
if (likely(m_sample_visible))
Expand All @@ -359,8 +388,8 @@ class RoughConductor final : public BSDF<Float, Spectrum> {
}

void traverse(TraversalCallback *callback) override {
callback->put_parameter("alpha_u", m_alpha_u);
callback->put_parameter("alpha_v", m_alpha_v);
callback->put_object("alpha_u", m_alpha_u.get());
callback->put_object("alpha_v", m_alpha_v.get());
callback->put_object("eta", m_eta.get());
callback->put_object("k", m_k.get());
}
Expand All @@ -370,8 +399,8 @@ class RoughConductor final : public BSDF<Float, Spectrum> {
oss << "RoughConductor[" << std::endl
<< " distribution = " << m_type << "," << std::endl
<< " sample_visible = " << m_sample_visible << "," << std::endl
<< " alpha_u = " << m_alpha_u << "," << std::endl
<< " alpha_v = " << m_alpha_v << "," << std::endl
<< " alpha_u = " << string::indent(m_alpha_u) << "," << std::endl
<< " alpha_v = " << string::indent(m_alpha_v) << "," << std::endl
<< " eta = " << string::indent(m_eta) << "," << std::endl
<< " k = " << string::indent(m_k) << std::endl
<< "]";
Expand All @@ -383,7 +412,7 @@ class RoughConductor final : public BSDF<Float, Spectrum> {
/// Specifies the type of microfacet distribution
MicrofacetType m_type;
/// Anisotropic roughness values
ScalarFloat m_alpha_u, m_alpha_v;
ref<Texture> m_alpha_u, m_alpha_v;
/// Importance sample the distribution of visible normals?
bool m_sample_visible;
/// Relative refractive index (real component)
Expand Down
63 changes: 46 additions & 17 deletions src/bsdfs/roughdielectric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Rough dielectric material (:monosp:`roughdielectric`)
tails observed in measurements of ground surfaces, which are not modeled by the Beckmann
distribution.
* - alpha, alpha_u, alpha_v
- |float|
- |texture| or |float|
- Specifies the roughness of the unresolved surface micro-geometry along the tangent and
bitangent directions. When the Beckmann distribution is used, this parameter is equal to the
*root mean square* (RMS) slope of the microfacets. :monosp:`alpha` is a convenience
Expand All @@ -68,6 +68,8 @@ materials.
:caption: Anti-glare glass (Beckmann, :math:`\alpha=0.02`)
.. subfigure:: ../../resources/data/docs/images/render/bsdf_roughdielectric_rough.jpg
:caption: Rough glass (Beckmann, :math:`\alpha=0.1`)
.. subfigure:: ../../resources/data/docs/images/render/bsdf_roughdielectric_textured.jpg
:caption: Rough glass with textured alpha
.. subfigend::
:label: fig-bsdf-roughdielectric
Expand Down Expand Up @@ -154,13 +156,34 @@ class RoughDielectric final : public BSDF<Float, Spectrum> {
m_eta = int_ior / ext_ior;
m_inv_eta = ext_ior / int_ior;

mitsuba::MicrofacetDistribution<ScalarFloat, Spectrum> distr(props);
m_type = distr.type();
m_sample_visible = distr.sample_visible();
m_alpha_u = distr.alpha_u();
m_alpha_v = distr.alpha_v();
if (props.has_property("distribution")) {
std::string distr = string::to_lower(props.string("distribution"));
if (distr == "beckmann")
m_type = MicrofacetType::Beckmann;
else if (distr == "ggx")
m_type = MicrofacetType::GGX;
else
Throw("Specified an invalid distribution \"%s\", must be "
"\"beckmann\" or \"ggx\"!", distr.c_str());
} else {
m_type = MicrofacetType::Beckmann;
}

m_sample_visible = props.bool_("sample_visible", true);

if (props.has_property("alpha_u") || props.has_property("alpha_v")) {
if (!props.has_property("alpha_u") || !props.has_property("alpha_v"))
Throw("Microfacet model: both 'alpha_u' and 'alpha_v' must be specified.");
if (props.has_property("alpha"))
Throw("Microfacet model: please specify"
"either 'alpha' or 'alpha_u'/'alpha_v'.");
m_alpha_u = props.texture<Texture>("alpha_u");
m_alpha_v = props.texture<Texture>("alpha_v");
} else {
m_alpha_u = m_alpha_v = props.texture<Texture>("alpha", 0.1f);
}

BSDFFlags extra = (m_alpha_u == m_alpha_v) ? BSDFFlags::Anisotropic : BSDFFlags(0);
BSDFFlags extra = all(eq(m_alpha_u, m_alpha_v)) ? BSDFFlags::Anisotropic : BSDFFlags(0);
m_components.push_back(BSDFFlags::GlossyReflection | BSDFFlags::FrontSide |
BSDFFlags::BackSide | extra);
m_components.push_back(BSDFFlags::GlossyTransmission | BSDFFlags::FrontSide |
Expand Down Expand Up @@ -193,7 +216,10 @@ class RoughDielectric final : public BSDF<Float, Spectrum> {
active &= neq(cos_theta_i, 0.f);

/* Construct the microfacet distribution matching the roughness values at the current surface position. */
MicrofacetDistribution distr(m_type, m_alpha_u, m_alpha_v, m_sample_visible);
MicrofacetDistribution distr(m_type,
m_alpha_u->eval_1(si, active),
m_alpha_v->eval_1(si, active),
m_sample_visible);

/* Trick by Walter et al.: slightly scale the roughness values to
reduce importance sampling weights. Not needed for the
Expand Down Expand Up @@ -305,7 +331,10 @@ class RoughDielectric final : public BSDF<Float, Spectrum> {

/* Construct the microfacet distribution matching the
roughness values at the current surface position. */
MicrofacetDistribution distr(m_type, m_alpha_u, m_alpha_v, m_sample_visible);
MicrofacetDistribution distr(m_type,
m_alpha_u->eval_1(si, active),
m_alpha_v->eval_1(si, active),
m_sample_visible);

// Evaluate the microfacet normal distribution
Float D = distr.eval(m);
Expand Down Expand Up @@ -389,8 +418,8 @@ class RoughDielectric final : public BSDF<Float, Spectrum> {
roughness values at the current surface position. */
MicrofacetDistribution sample_distr(
m_type,
m_alpha_u,
m_alpha_v,
m_alpha_u->eval_1(si, active),
m_alpha_v->eval_1(si, active),
m_sample_visible
);

Expand All @@ -412,8 +441,8 @@ class RoughDielectric final : public BSDF<Float, Spectrum> {
}

void traverse(TraversalCallback *callback) override {
callback->put_parameter("alpha_u", m_alpha_u);
callback->put_parameter("alpha_v", m_alpha_v);
callback->put_object("alpha_u", m_alpha_u.get());
callback->put_object("alpha_v", m_alpha_v.get());
callback->put_parameter("eta", m_eta);
callback->put_object("specular_reflectance", m_specular_reflectance.get());
callback->put_object("specular_transmittance", m_specular_transmittance.get());
Expand All @@ -424,10 +453,10 @@ class RoughDielectric final : public BSDF<Float, Spectrum> {
oss << "RoughDielectric[" << std::endl
<< " distribution = " << m_type << "," << std::endl
<< " sample_visible = " << m_sample_visible << "," << std::endl
<< " alpha_u = " << m_alpha_u << "," << std::endl
<< " alpha_v = " << m_alpha_v << "," << std::endl
<< " alpha_u = " << string::indent(m_alpha_u) << "," << std::endl
<< " alpha_v = " << string::indent(m_alpha_v) << "," << std::endl
<< " eta = " << m_eta << "," << std::endl
<< " specular_reflectance = " << string::indent(m_specular_reflectance) << "," << std::endl
<< " specular_reflectance = " << string::indent(m_specular_reflectance) << "," << std::endl
<< " specular_transmittance = " << string::indent(m_specular_transmittance) << std::endl
<< "]";
return oss.str();
Expand All @@ -438,7 +467,7 @@ class RoughDielectric final : public BSDF<Float, Spectrum> {
ref<Texture> m_specular_reflectance;
ref<Texture> m_specular_transmittance;
MicrofacetType m_type;
ScalarFloat m_alpha_u, m_alpha_v;
ref<Texture> m_alpha_u, m_alpha_v;
ScalarFloat m_eta, m_inv_eta;
bool m_sample_visible;
};
Expand Down
5 changes: 3 additions & 2 deletions src/libcore/python/spectrum_v.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ MTS_PY_EXPORT(Spectrum) {
.def("pdf_uniform_spectrum", vectorize(&pdf_uniform_spectrum<Spectrum>),
"wavelengths"_a, D(pdf_uniform_spectrum));

m.def("xyz_to_srgb", vectorize(&xyz_to_srgb<Float>),
"rgb"_a, "active"_a = true, D(xyz_to_srgb));

if constexpr (is_rgb_v<Spectrum>) {
m.def("srgb_to_xyz", vectorize(&srgb_to_xyz<Float>),
"rgb"_a, "active"_a = true, D(srgb_to_xyz));
m.def("xyz_to_srgb", vectorize(&xyz_to_srgb<Float>),
"rgb"_a, "active"_a = true, D(xyz_to_srgb));
}

if constexpr (is_spectral_v<Spectrum>) {
Expand Down
4 changes: 4 additions & 0 deletions src/spectra/blackbody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class BlackBodySpectrum final : public Texture<Float, Spectrum> {

BlackBodySpectrum(const Properties &props) : Texture(props) {
m_temperature = props.float_("temperature");
parameters_changed();
}

void parameters_changed() override {
m_integral_min = cdf_and_pdf(ScalarFloat(MTS_WAVELENGTH_MIN)).first;
m_integral = cdf_and_pdf(ScalarFloat(MTS_WAVELENGTH_MAX)).first - m_integral_min;
}
Expand Down
4 changes: 2 additions & 2 deletions src/spectra/uniform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class UniformSpectrum final : public Texture<Float, Spectrum> {
}
}

ScalarFloat mean() const override { return m_value; }
ScalarFloat mean() const override { return scalar_cast(hmean(m_value)); }

void traverse(TraversalCallback *callback) override {
callback->put_parameter("value", m_value);
Expand All @@ -83,7 +83,7 @@ class UniformSpectrum final : public Texture<Float, Spectrum> {

MTS_DECLARE_CLASS()
private:
ScalarFloat m_value;
Float m_value;
};

MTS_IMPLEMENT_CLASS_VARIANT(UniformSpectrum, Texture)
Expand Down

0 comments on commit cac8741

Please sign in to comment.