BSDF::getFrame/BSDF::getFrameDerivative functions, Shape::adjustTime() feature

metadata
Wenzel Jakob 2014-06-06 01:10:15 +02:00
parent 27a17f3bf7
commit eae7a55eac
15 changed files with 182 additions and 14 deletions

View File

@ -26,6 +26,7 @@
#define EIGEN_NO_DEBUG #define EIGEN_NO_DEBUG
#include <Eigen/Core> #include <Eigen/Core>
#include <Eigen/Geometry>
#include <cmath> #include <cmath>
#include <stdexcept> #include <stdexcept>

View File

@ -336,6 +336,11 @@ public:
/// Return the diffuse reflectance value (if any) /// Return the diffuse reflectance value (if any)
virtual Spectrum getDiffuseReflectance(const Intersection &its) const; virtual Spectrum getDiffuseReflectance(const Intersection &its) const;
/// Return the specular reflectance value (if any)
virtual Spectrum getSpecularReflectance(const Intersection &its) const {
return Spectrum(0.0f);
}
/** /**
* \brief Sample the BSDF and return the importance weight (i.e. the * \brief Sample the BSDF and return the importance weight (i.e. the
* value of the BSDF divided by the probability density of the sample). * value of the BSDF divided by the probability density of the sample).
@ -462,6 +467,15 @@ public:
*/ */
virtual Frame getFrame(const Intersection &its) const; virtual Frame getFrame(const Intersection &its) const;
/**
* \brief Sometimes, BSDF models make use of a perturbed frame for
* internal shading computations (e.g. bump maps). This function
* computes the derivative of this frame with respect to the UV
* parameterization of the underlying shape.
*/
virtual void getFrameDerivative(const Intersection &its,
Frame &du, Frame &dv) const;
// ============================================================= // =============================================================
//! @{ \name ConfigurableObject interface //! @{ \name ConfigurableObject interface
// ============================================================= // =============================================================

View File

@ -92,6 +92,24 @@ inline const Medium *Intersection::getTargetMedium(Float cosTheta) const {
return shape->getInteriorMedium(); return shape->getInteriorMedium();
} }
void Intersection::adjustTime(Float time) {
if (instance)
instance->adjustTime(*this, time);
else if (shape)
shape->adjustTime(*this, time);
else
this->time = time;
}
void Intersection::getNormalDerivative(Vector &dndu, Vector &dndv,
bool shadingFrame) const {
if (instance)
instance->getNormalDerivative(*this, dndu, dndv, shadingFrame);
else if (shape)
shape->getNormalDerivative(*this, dndu, dndv, shadingFrame);
}
inline const PhaseFunction *MediumSamplingRecord::getPhaseFunction() const { inline const PhaseFunction *MediumSamplingRecord::getPhaseFunction() const {
return medium->getPhaseFunction(); return medium->getPhaseFunction();
} }

View File

@ -118,6 +118,13 @@ public:
/// Computes texture coordinate partials /// Computes texture coordinate partials
void computePartials(const RayDifferential &ray); void computePartials(const RayDifferential &ray);
/// Move the intersection forward or backward through time
inline void adjustTime(Float time);
/// Calls the suitable implementaiton of \ref Shape::getNormalDerivative()
inline void getNormalDerivative(Vector &dndu, Vector &dndv,
bool shadingFrame = true) const;
/// Return a string representation /// Return a string representation
std::string toString() const; std::string toString() const;
public: public:
@ -316,6 +323,11 @@ public:
void getCurvature(const Intersection &its, Float &H, Float &K, void getCurvature(const Intersection &its, Float &H, Float &K,
bool shadingFrame = true) const; bool shadingFrame = true) const;
/**
* Adjust an intersection record to a different time value
*/
virtual void adjustTime(Intersection &its, Float time) const;
/** /**
* \brief Return the internal kd-tree of this shape (if any) * \brief Return the internal kd-tree of this shape (if any)
* *

View File

@ -80,12 +80,13 @@ public:
TriMesh(Stream *stream, InstanceManager *manager); TriMesh(Stream *stream, InstanceManager *manager);
/** /**
* Unserialize a triangle mesh - this is an alternative * \brief Unserialize a triangle mesh
* routine, which only loads triangle data (no BSDF, *
* Sub-surface integrator, etc.) in a format that * This is an alternative routine, which only loads triangle data
* will remain stable as Mitsuba evolves. The files * (no BSDF, Sub-surface integrator, etc.) in a format that will
* can optionally contain multiple meshes -- in that case, * remain stable as Mitsuba evolves. The files can optionally contain
* the specified index determines which one to load. * multiple meshes -- in that case, the specified index determines
* which one to load.
*/ */
TriMesh(Stream *stream, int idx = 0); TriMesh(Stream *stream, int idx = 0);

View File

@ -105,6 +105,14 @@ public:
manager->serialize(stream, m_displacement.get()); manager->serialize(stream, m_displacement.get());
} }
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_nested->getDiffuseReflectance(its);
}
Spectrum getSpecularReflectance(const Intersection &its) const {
return m_nested->getSpecularReflectance(its);
}
void addChild(const std::string &name, ConfigurableObject *child) { void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) { if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) {
if (m_nested != NULL) if (m_nested != NULL)

View File

@ -22,7 +22,7 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/*!\plugin{mask}{Opacity mask} /*!\plugin{mask}{Opacity mask}
* \order{18} * \order{19}
* \parameters{ * \parameters{
* \parameter{opacity}{\Spectrum\Or\Texture}{ * \parameter{opacity}{\Spectrum\Or\Texture}{
* Specifies the per-channel opacity (where $1=$ completely opaque)\default{0.5}. * Specifies the per-channel opacity (where $1=$ completely opaque)\default{0.5}.

View File

@ -77,6 +77,14 @@ public:
manager->serialize(stream, m_normals.get()); manager->serialize(stream, m_normals.get());
} }
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_nested->getDiffuseReflectance(its);
}
Spectrum getSpecularReflectance(const Intersection &its) const {
return m_nested->getSpecularReflectance(its);
}
void addChild(const std::string &name, ConfigurableObject *child) { void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) { if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) {
if (m_nested != NULL) if (m_nested != NULL)
@ -97,23 +105,65 @@ public:
} }
Frame getFrame(const Intersection &its) const { Frame getFrame(const Intersection &its) const {
Frame result;
Normal n; Normal n;
m_normals->eval(its, false).toLinearRGB(n.x, n.y, n.z); m_normals->eval(its, false).toLinearRGB(n.x, n.y, n.z);
for (int i=0; i<3; ++i) for (int i=0; i<3; ++i)
n[i] = 2 * n[i] - 1; n[i] = 2 * n[i] - 1;
Frame result; Frame frame = BSDF::getFrame(its);
result.n = normalize(its.shFrame.toWorld(n)); result.n = normalize(frame.toWorld(n));
result.s = normalize(its.dpdu - result.n result.s = normalize(its.dpdu - result.n
* dot(result.n, its.dpdu)); * dot(result.n, its.dpdu));
result.t = cross(result.n, result.s); result.t = cross(result.n, result.s);
if (dot(result.n, its.geoFrame.n) < 0)
result.n *= -1;
return result; return result;
} }
void getFrameDerivative(const Intersection &its, Frame &du, Frame &dv) const {
Vector n;
m_normals->eval(its, false).toLinearRGB(n.x, n.y, n.z);
for (int i=0; i<3; ++i)
n[i] = 2 * n[i] - 1;
Spectrum dn[2];
Vector dndu, dndv;
m_normals->evalGradient(its, dn);
Spectrum(2*dn[0]).toLinearRGB(dndu.x, dndu.y, dndu.z);
Spectrum(2*dn[1]).toLinearRGB(dndv.x, dndv.y, dndv.z);
Frame base_du, base_dv;
Frame base = BSDF::getFrame(its);
BSDF::getFrameDerivative(its, base_du, base_dv);
Vector worldN = base.toWorld(n);
Float invLength_n = 1/worldN.length();
worldN *= invLength_n;
du.n = invLength_n * (base.toWorld(dndu) + base_du.toWorld(n));
dv.n = invLength_n * (base.toWorld(dndv) + base_dv.toWorld(n));
du.n -= dot(du.n, worldN) * worldN;
dv.n -= dot(dv.n, worldN) * worldN;
Vector s = its.dpdu - worldN * dot(worldN, its.dpdu);
Float invLen_s = 1.0f / s.length();
s *= invLen_s;
du.s = invLen_s * (-du.n * dot(worldN, its.dpdu) - worldN * dot(du.n, its.dpdu));
dv.s = invLen_s * (-dv.n * dot(worldN, its.dpdu) - worldN * dot(dv.n, its.dpdu));
du.s -= s * dot(du.s, s);
dv.s -= s * dot(dv.s, s);
du.t = cross(du.n, s) + cross(worldN, du.s);
dv.t = cross(dv.n, s) + cross(worldN, dv.s);
}
Spectrum eval(const BSDFSamplingRecord &bRec, EMeasure measure) const { Spectrum eval(const BSDFSamplingRecord &bRec, EMeasure measure) const {
const Intersection& its = bRec.its; const Intersection& its = bRec.its;
Intersection perturbed(its); Intersection perturbed(its);
@ -283,5 +333,5 @@ Shader *NormalMap::createShader(Renderer *renderer) const {
MTS_IMPLEMENT_CLASS(NormalMapShader, false, Shader) MTS_IMPLEMENT_CLASS(NormalMapShader, false, Shader)
MTS_IMPLEMENT_CLASS_S(NormalMap, false, BSDF) MTS_IMPLEMENT_CLASS_S(NormalMap, false, BSDF)
MTS_EXPORT_PLUGIN(NormalMap, "Smooth dielectric coating"); MTS_EXPORT_PLUGIN(NormalMap, "Normal map modifier");
MTS_NAMESPACE_END MTS_NAMESPACE_END

View File

@ -110,6 +110,10 @@ public:
return m_diffuseReflectance->eval(its); return m_diffuseReflectance->eval(its);
} }
Spectrum getSpecularReflectance(const Intersection &its) const {
return m_specularReflectance->eval(its);
}
/// Reflection in local coordinates /// Reflection in local coordinates
inline Vector reflect(const Vector &wi) const { inline Vector reflect(const Vector &wi) const {
return Vector(-wi.x, -wi.y, wi.z); return Vector(-wi.x, -wi.y, wi.z);

View File

@ -220,6 +220,9 @@ public:
return m_diffuseReflectance->eval(its) * (1-m_fdrExt); return m_diffuseReflectance->eval(its) * (1-m_fdrExt);
} }
Spectrum getSpecularReflectance(const Intersection &its) const {
return m_specularReflectance->eval(its);
}
void addChild(const std::string &name, ConfigurableObject *child) { void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) {

View File

@ -311,6 +311,10 @@ public:
return m_diffuseReflectance->eval(its) * Ftr; return m_diffuseReflectance->eval(its) * Ftr;
} }
Spectrum getSpecularReflectance(const Intersection &its) const {
return m_specularReflectance->eval(its);
}
/// Helper function: reflect \c wi with respect to a given surface normal /// Helper function: reflect \c wi with respect to a given surface normal
inline Vector reflect(const Vector &wi, const Normal &m) const { inline Vector reflect(const Vector &wi, const Normal &m) const {
return 2 * dot(wi, m) * Vector(m) - wi; return 2 * dot(wi, m) * Vector(m) - wi;

View File

@ -64,7 +64,32 @@ Float BSDF::getEta() const {
} }
Frame BSDF::getFrame(const Intersection &its) const { Frame BSDF::getFrame(const Intersection &its) const {
return its.shFrame; Frame result;
result.n = its.shFrame.n;
result.s = normalize(its.dpdu - result.n
* dot(result.n, its.dpdu));
result.t = cross(result.n, result.s);
return result;
}
void BSDF::getFrameDerivative(const Intersection &its, Frame &du, Frame &dv) const {
(its.instance ? its.instance : its.shape)->getNormalDerivative(its, du.n, dv.n, true);
Vector n = its.shFrame.n;
Vector s = its.dpdu - n * dot(n, its.dpdu);
Float invLen_s = 1.0f / s.length();
s *= invLen_s;
du.s = invLen_s * (-du.n * dot(n, its.dpdu) - n * dot(du.n, its.dpdu));
dv.s = invLen_s * (-dv.n * dot(n, its.dpdu) - n * dot(dv.n, its.dpdu));
du.s -= s * dot(du.s, s);
dv.s -= s * dot(dv.s, s);
du.t = cross(du.n, s) + cross(n, du.s);
dv.t = cross(dv.n, s) + cross(n, dv.s);
} }
Float BSDF::getRoughness(const Intersection &its, int component) const { Float BSDF::getRoughness(const Intersection &its, int component) const {

View File

@ -73,6 +73,11 @@ void Shape::configure() {
"emitter/sensor/subsurface attachment. This is not allowed!", getName().c_str()); "emitter/sensor/subsurface attachment. This is not allowed!", getName().c_str());
} }
void Shape::adjustTime(Intersection &its, Float time) const {
its.time = time;
/* Do nothing else by default */
}
bool Shape::isCompound() const { bool Shape::isCompound() const {
return false; return false;
} }

View File

@ -129,6 +129,24 @@ bool Instance::rayIntersect(const Ray &_ray, Float mint, Float maxt) const {
return kdtree->rayIntersect(ray, mint, maxt); return kdtree->rayIntersect(ray, mint, maxt);
} }
void Instance::adjustTime(Intersection &its, Float time) const {
Transform trafo = m_transform->eval(its.time).inverse();
trafo = m_transform->eval(time) * trafo;
Vector s = trafo(its.shFrame.s);
its.shFrame.n = normalize(trafo(its.shFrame.n));
its.shFrame.s = normalize(s - its.shFrame.n
* dot(its.shFrame.n, s));
its.shFrame.t = cross(its.shFrame.n, its.shFrame.s);
its.geoFrame = Frame(normalize(trafo(its.geoFrame.n)));
its.dpdu = trafo(its.dpdu);
its.dpdv = trafo(its.dpdv);
its.p = trafo(its.p);
its.wi = normalize(trafo(its.wi));
its.instance = this;
its.time = time;
}
void Instance::fillIntersectionRecord(const Ray &_ray, void Instance::fillIntersectionRecord(const Ray &_ray,
const void *temp, Intersection &its) const { const void *temp, Intersection &its) const {
const ShapeKDTree *kdtree = m_shapeGroup->getKDTree(); const ShapeKDTree *kdtree = m_shapeGroup->getKDTree();

View File

@ -51,6 +51,9 @@ public:
/// Return a pointer to the associated \ref ShapeGroup (const version) /// Return a pointer to the associated \ref ShapeGroup (const version)
inline const ShapeGroup* getShapeGroup() const { return m_shapeGroup.get(); } inline const ShapeGroup* getShapeGroup() const { return m_shapeGroup.get(); }
/// Return the underlying animated transformation
inline const AnimatedTransform *getAnimatedTransform() const { return m_transform.get(); }
// ============================================================= // =============================================================
//! @{ \name Implementation of the Shape interface //! @{ \name Implementation of the Shape interface
// ============================================================= // =============================================================
@ -72,6 +75,8 @@ public:
size_t getEffectivePrimitiveCount() const; size_t getEffectivePrimitiveCount() const;
void adjustTime(Intersection &its, Float time) const;
//! @} //! @}
// ============================================================= // =============================================================