/* This file is part of Mitsuba, a physically based rendering system. Copyright (c) 2007-2012 by Wenzel Jakob and others. Mitsuba is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. Mitsuba is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #pragma once #if !defined(__MITSUBA_RENDER_PHASE_H_) #define __MITSUBA_RENDER_PHASE_H_ #include #include MTS_NAMESPACE_BEGIN /** * \brief Data structure, which contains information * required to sample or query a phase function. * * \ingroup librender */ struct MTS_EXPORT_RENDER PhaseFunctionSamplingRecord { /** * \brief Reference to a Medium sampling record created * by \ref Medium::sampleDistance() */ const MediumSamplingRecord &mRec; /** * \brief Normalized incident direction vector, which points away * from the scattering event. * * In Mitsuba, the direction convention for phase functions is the * same as for BSDFs, as opposed to much of the literature, where * \c wi points inwards. */ Vector wi; /// Normalized outgoing direction vector Vector wo; /* Transported mode (radiance or importance) -- required for rendering with non-reciprocal phase functions */ ETransportMode mode; /** * \brief Given a medium interaction and an incident direction, * construct a query record which can be used to sample an outgoing * direction. * * \param mRec * An reference to the underlying medium sampling record * \param wi * An incident direction in world coordinates. This should * be a normalized direction vector that points \a away from * the scattering event. * \param mode * The transported mode (\ref ERadiance or \ref EImportance) */ inline PhaseFunctionSamplingRecord(const MediumSamplingRecord &mRec, const Vector &wi, ETransportMode mode = ERadiance) : mRec(mRec), wi(wi), mode(mode) { } /* * \brief Given a medium interaction an an incident/exitant direction * pair (wi, wo), create a query record to evaluate the phase function * or its sampling density. * * \param mRec * An reference to the underlying medium sampling record * \param wi * An incident direction in world coordinates. This should * be a normalized direction vector that points \a away from * the scattering event. * \param wo * An outgoing direction in world coordinates. This should * be a normalized direction vector that points \a away from * the scattering event. * \param mode * The transported mode (\ref ERadiance or \ref EImportance) */ inline PhaseFunctionSamplingRecord(const MediumSamplingRecord &mRec, const Vector &wi, const Vector &wo, ETransportMode mode = ERadiance) : mRec(mRec), wi(wi), wo(wo), mode(mode) { } /** * \brief Reverse the direction of light transport in the record * * This function essentially swaps \c wi and \c wo and adjusts * \c mode appropriately, so that non-symmetric scattering * models can be queried in the reverse direction. */ inline void reverse() { std::swap(wo, wi); mode = (ETransportMode) (1-mode); } std::string toString() const; }; /** \brief Abstract phase function. * \ingroup librender */ class MTS_EXPORT_RENDER PhaseFunction : public ConfigurableObject { public: enum EPhaseFunctionType { /// Completely isotropic 1/(4 pi) phase function EIsotropic = 0x01, /// The phase function only depends on \c dot(wi,wo) EAngleDependence = 0x04, /// The opposite of \ref EAngleDependence (there is an arbitrary dependence) EAnisotropic = 0x02, /// The phase function is non symmetric, i.e. eval(wi,wo) != eval(wo, wi) ENonSymmetric = 0x08 }; /** * \brief Return information flags of this phase function, * combined binary OR. * \sa EPhaseFunctionType */ inline unsigned int getType() const { return m_type; } /// Configure the material (called after construction by the XML parser) virtual void configure(); /** * \brief Evaluate the phase function for an outward-pointing * pair of directions (wi, wo) */ virtual Float eval(const PhaseFunctionSamplingRecord &pRec) const = 0; /** * \brief Sample the phase function and return the importance weight (i.e. the * value of the phase function divided by the probability density of the sample). * * When the probability density is not explicitly required, this function * should be preferred, since it is potentially faster by making use of * cancellations during the division. * * \param pRec A phase function query record * \param sampler A sample generator * * \return The phase function value divided by the probability * density of the sample */ virtual Float sample(PhaseFunctionSamplingRecord &pRec, Sampler *sampler) const = 0; /** * \brief Sample the phase function and return the probability density \a and the * importance weight of the sample (i.e. the value of the phase function divided * by the probability density) * * \param pRec A phase function query record * \param sampler A sample generator * \param pdf Will record the probability with respect to solid angles * * \return The phase function value divided by the probability * density of the sample */ virtual Float sample(PhaseFunctionSamplingRecord &pRec, Float &pdf, Sampler *sampler) const = 0; /** * \brief Calculate the probability of sampling wo (given wi). * * Assuming that the phase function can be sampled exactly, * the default implementation just evaluates \ref eval() */ virtual Float pdf(const PhaseFunctionSamplingRecord &pRec) const; /** * \brief Does this phase function require directionally varying scattering * and extinction coefficients? * * This is used to implement rendering of media that have an anisotropic * structure (cf. "A radiative transfer framework for rendering materials with * anisotropic structure" by Wenzel Jakob, Adam Arbree, Jonathan T. Moon, * Kavita Bala, and Steve Marschner, SIGGRAPH 2010) */ virtual bool needsDirectionallyVaryingCoefficients() const; /** * \brief For anisotropic media: evaluate the directionally varying component * of the scattering and absorption coefficients. * * \param cosTheta * Angle between the axis of rotational symmetry and the * direction of propagation */ virtual Float sigmaDir(Float cosTheta) const; /** * \brief Returns the maximum value take on on by \ref sigmaDirMax(). * This is useful when implementing Woodcock tracking. */ virtual Float sigmaDirMax() const; /** * \brief Returns the mean cosine (often referred to by * the constant "g") of this phase function * * The default implementation throws an exception */ virtual Float getMeanCosine() const; /// Return a string representation virtual std::string toString() const = 0; MTS_DECLARE_CLASS() protected: /// Create a new phase function instance inline PhaseFunction(const Properties &props) : ConfigurableObject(props) { } /// Unserialize a phase function inline PhaseFunction(Stream *stream, InstanceManager *manager) : ConfigurableObject(stream, manager) { } /// Virtual destructor virtual ~PhaseFunction() { } protected: unsigned int m_type; }; MTS_NAMESPACE_END #endif /* __MITSUBA_RENDER_PHASE_H_ */