391 lines
13 KiB
C++
391 lines
13 KiB
C++
/*
|
|
This file is part of Mitsuba, a physically based rendering system.
|
|
|
|
Copyright (c) 2007-2011 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#if !defined(__LUMINAIRE_H)
|
|
#define __LUMINAIRE_H
|
|
|
|
#include <mitsuba/render/shape.h>
|
|
#include <mitsuba/render/shader.h>
|
|
|
|
MTS_NAMESPACE_BEGIN
|
|
|
|
/**
|
|
* \brief Data structure used by the direct illumination / shadow ray
|
|
* sampling methods in the class \ref Luminaire.
|
|
*/
|
|
struct MTS_EXPORT_RENDER LuminaireSamplingRecord {
|
|
public:
|
|
/// Create an invalid shadow ray sampling record
|
|
inline LuminaireSamplingRecord() : luminaire(NULL) { }
|
|
|
|
/// Create a shadow ray sampling record based on a surface intersection
|
|
inline LuminaireSamplingRecord(const Intersection &its, const Vector &direction);
|
|
|
|
/// Return a string representation
|
|
std::string toString() const;
|
|
public:
|
|
/// Associated luminaire
|
|
const Luminaire *luminaire;
|
|
|
|
/// Data record of the associated shape sample
|
|
ShapeSamplingRecord sRec;
|
|
|
|
/// Direction vector pointing away from the light source
|
|
Vector d;
|
|
|
|
/**
|
|
* \brief Probability density (wrt. solid angle) of the sampled
|
|
* point on the luminaire
|
|
*/
|
|
Float pdf;
|
|
|
|
/**
|
|
* \brief Emitted radiance at \c p into direction \c d divided by
|
|
* the associated probability. Already contains the geometric term
|
|
* and optionally also transmittance when generated via
|
|
* \ref Scene::sampleAttenuatedLuminaire.
|
|
*/
|
|
Spectrum value;
|
|
};
|
|
|
|
/**
|
|
* \brief Data structure used to record information associated with
|
|
* emission sampling in the class \ref Luminaire.
|
|
*/
|
|
struct MTS_EXPORT_RENDER EmissionRecord {
|
|
public:
|
|
/**
|
|
* \brief This class supports a special \a preview mode when
|
|
* sampling emissions for use in a VPL-style rendering algorithm
|
|
*/
|
|
enum ESamplingType {
|
|
ENormal,
|
|
EPreview
|
|
};
|
|
|
|
/// Construct a luminaire sampling record that can be used to query a luminaire
|
|
inline EmissionRecord(const Luminaire *luminaire,
|
|
const ShapeSamplingRecord &sRec, const Vector &d)
|
|
: luminaire(luminaire), type(ENormal), sRec(sRec), d(d) { }
|
|
|
|
inline EmissionRecord() : luminaire(NULL), type(ENormal) { }
|
|
|
|
/// Return a string representation
|
|
std::string toString() const;
|
|
public:
|
|
/// Associated luminaire
|
|
const Luminaire *luminaire;
|
|
|
|
ESamplingType type;
|
|
|
|
/// Data record of the associated shape sample
|
|
ShapeSamplingRecord sRec;
|
|
|
|
/// Direction vector pointing away from the light source
|
|
Vector d;
|
|
|
|
/**
|
|
* \brief Stores the spatial component of the radiant
|
|
* emittance
|
|
*
|
|
* When the record was populated using Scene::sampleEmission(),
|
|
* \c P will also be modulated by the directional scattering
|
|
* distribution and divided by the associated sampling densities.
|
|
*/
|
|
Spectrum value;
|
|
|
|
/// Area probability density
|
|
Float pdfArea;
|
|
|
|
/// Directional probability density (wrt. solid angle)
|
|
Float pdfDir;
|
|
};
|
|
|
|
/**
|
|
* \brief Abstract implementation of a luminaire. Supports emission and
|
|
* direct illumination sampling strategies, and computes related probabilities.
|
|
*/
|
|
class MTS_EXPORT_RENDER Luminaire : public ConfigurableObject, public HWResource {
|
|
public:
|
|
/**
|
|
* \brief Non-exhaustive list of flags that can be used to characterize
|
|
* light sources in \ref getType()
|
|
*/
|
|
enum EType {
|
|
/// The light source has a degenerate directional density
|
|
EDeltaDirection = 0x1,
|
|
|
|
/// The light source is perfectly diffuse with respect to direction.
|
|
EDiffuseDirection = 0x02,
|
|
|
|
/// The light source is associated with a surface
|
|
EOnSurface = 0x04,
|
|
|
|
/// The light source has a degenerate spatial density
|
|
EDeltaPosition = 0x8,
|
|
|
|
/// The light source has a degenerate spatial \a or directional density
|
|
EDelta = EDeltaDirection | EDeltaPosition
|
|
};
|
|
|
|
// =============================================================
|
|
//! @{ \name General information
|
|
// =============================================================
|
|
|
|
/// Return the name of this luminaire
|
|
inline const std::string &getName() const { return m_name; }
|
|
|
|
/// Return the luminaire type (a combination of the properties in \ref EType)
|
|
inline int getType() const { return m_type; }
|
|
|
|
/**
|
|
* \brief Return an estimate of the total amount of power emitted
|
|
* by this luminaire.
|
|
*/
|
|
virtual Spectrum getPower() const = 0;
|
|
|
|
/// Is this luminaire intersectable (e.g. can it be encountered by a tracing a ray)?
|
|
inline bool isIntersectable() const { return m_intersectable; }
|
|
|
|
/// Specify the medium that surrounds the luminaire
|
|
inline void setMedium(Medium *medium) { m_medium = medium; }
|
|
|
|
/// Return a pointer to the medium that surrounds the luminaire
|
|
inline Medium *getMedium() { return m_medium.get(); }
|
|
|
|
/// Return a pointer to the medium that surrounds the luminaire (const version)
|
|
inline const Medium *getMedium() const { return m_medium.get(); }
|
|
|
|
/**
|
|
* \brief Return the luminaire's sampling weight
|
|
*
|
|
* This is used by the luminaire importance sampling
|
|
* routines in \ref Scene.
|
|
*/
|
|
inline Float getSamplingWeight() const { return m_samplingWeight; }
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Direct illumination sampling strategies
|
|
// =============================================================
|
|
|
|
/**
|
|
* \brief Shadow ray sampling routine: Given an arbitrary 3D position,
|
|
* generate a sample point on the luminaire and fill the supplied sampling
|
|
* record with relevant information.
|
|
*
|
|
* Sampling is ideally done with respect to solid angle at \c p.
|
|
*/
|
|
virtual void sample(const Point &p,
|
|
LuminaireSamplingRecord &lRec, const Point2 &sample) const = 0;
|
|
|
|
/**
|
|
* \brief Calculate the solid angle density for generating this sample
|
|
* using the luminaire sampling strategy implemented by this class.
|
|
*
|
|
* When \c delta is set to true, only components with a Dirac delta density
|
|
* are considered in the query. Otherwise, they are left out.
|
|
*/
|
|
virtual Float pdf(const Point &p,
|
|
const LuminaireSamplingRecord &lRec, bool delta) const = 0;
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Emission sampling strategies
|
|
// =============================================================
|
|
|
|
/**
|
|
* \brief Sample a particle leaving this luminaire and return a ray
|
|
* describing its path as well as record containing detailed probability
|
|
* density information.
|
|
*
|
|
* Two uniformly distributed 2D samples are required. This method does
|
|
* exactly the same as calling \c sampleEmissionArea and
|
|
* \c sampleEmissionDirection in sequence, modulating \c eRec.Le
|
|
* by the return value of the latter and dividing by the product
|
|
* of the spatial and directional sampling densities.
|
|
*/
|
|
virtual void sampleEmission(EmissionRecord &eRec,
|
|
const Point2& areaSample, const Point2 &dirSample) const = 0;
|
|
|
|
/**
|
|
* \brief Sample only the spatial part of the emission sampling strategy
|
|
* implemented in \c sampleEmission.
|
|
*
|
|
* An examplary use of this method is bidirectional path tracing or MLT,
|
|
* where the area and direction sampling steps take place in different
|
|
* vertices.
|
|
*
|
|
* After the function call terminates, the area density as well as the
|
|
* spatially dependent emittance component will be stored in \c eRec.
|
|
*/
|
|
virtual void sampleEmissionArea(EmissionRecord &lRec,
|
|
const Point2 &sample) const = 0;
|
|
|
|
/**
|
|
* \brief Sample only the directional part of the emission sampling strategy
|
|
* implemented in \c sampleEmission.
|
|
*
|
|
* Can only be called \a after a preceding invocation of
|
|
* \ref sampleEmissionArea() with the same emission sampling record.
|
|
*
|
|
* The return value of this function should be used to modulate the spatial
|
|
* component of the radiant emittance obtained in \ref sampleEmissionArea.
|
|
*/
|
|
virtual Spectrum sampleEmissionDirection(EmissionRecord &lRec,
|
|
const Point2 &sample) const = 0;
|
|
|
|
/**
|
|
* \brief Given an emitted particle, populate the emission record with the
|
|
* relevant probability densities.
|
|
*
|
|
* When \c delta is set to true, only components with a Dirac delta density
|
|
* are considered in the query. Otherwise, they are left out.
|
|
*/
|
|
virtual void pdfEmission(EmissionRecord &eRec, bool delta) const = 0;
|
|
|
|
/**
|
|
* \brief Evaluate the spatial component of the radiant emittance at a
|
|
* point on the luminaire (ignoring any directional variations).
|
|
*/
|
|
virtual Spectrum evalArea(const EmissionRecord &eRec) const = 0;
|
|
|
|
/**
|
|
* \brief Evaluate the directional emission distribution of this light source
|
|
* at a given point (ignoring the spatial component).
|
|
*
|
|
* This function is normalized so that it integrates to one.
|
|
*/
|
|
virtual Spectrum evalDirection(const EmissionRecord &eRec) const = 0;
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Area luminaire support
|
|
// =============================================================
|
|
|
|
/**
|
|
* \brief This function is specific to area luminaires (i.e. luminaires
|
|
* that can be intersected by a \ref Scene::rayIntersect). It returns the
|
|
* radiant emittance into a given direction.
|
|
*
|
|
* This is function is used when an area light source has been hit by a
|
|
* ray in a path tracing-style integrator, and it subsequently needs to
|
|
* be queried for the emitted radiance along the negative ray direction.
|
|
|
|
* The default implementation throws an exception, which states that
|
|
* the method is not implemented.
|
|
*/
|
|
virtual Spectrum Le(const ShapeSamplingRecord &sRec,
|
|
const Vector &d) const;
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Background luminaire support
|
|
// =============================================================
|
|
|
|
/// Is this a background luminaire (e.g. an environment map?)
|
|
virtual bool isBackgroundLuminaire() const;
|
|
|
|
/**
|
|
* \brief Return the radiant emittance along a ray which does not
|
|
* intersect any scene objects.
|
|
*
|
|
* The default implementation throws an exception, which states that
|
|
* the method is not implemented.
|
|
*/
|
|
virtual Spectrum Le(const Ray &ray) const;
|
|
|
|
/**
|
|
* \brief This function fills an emission sampling record with relevant
|
|
* information for the supplied ray (which doesn't intersect \a any
|
|
* scene objects).
|
|
*
|
|
* The record will be populated with the radiant emittance, as well as
|
|
* the spatial and directional densities for sampling an emitted ray along
|
|
* the opposite ray direction.
|
|
*
|
|
* This function is only relevant to background luminaires. The
|
|
* default implementation throws an exception, which states that
|
|
* the method is not implemented.
|
|
*
|
|
* \return \c true upon success
|
|
*/
|
|
virtual bool createEmissionRecord(EmissionRecord &eRec, const Ray &ray) const;
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
// =============================================================
|
|
//! @{ \name Miscellaneous
|
|
// =============================================================
|
|
|
|
/// Is this a compound luminaire consisting of several sub-objects?
|
|
virtual bool isCompound() const;
|
|
|
|
/**
|
|
* \brief Return a sub-element of a compound luminaire.
|
|
*
|
|
* When expanding luminaires, the scene will repeatedly call this
|
|
* function with increasing indices. Returning \a NULL indicates
|
|
* that no more are available.
|
|
*/
|
|
virtual Luminaire *getElement(int i);
|
|
|
|
/// Serialize this luminaire to a binary data stream
|
|
virtual void serialize(Stream *stream, InstanceManager *manager) const;
|
|
|
|
/// Optional pre-process step before rendering starts
|
|
virtual void preprocess(const Scene *scene);
|
|
|
|
/// Add a child (e.g. a medium reference) to this luminaire
|
|
void addChild(const std::string &name, ConfigurableObject *child);
|
|
|
|
//! @}
|
|
// =============================================================
|
|
|
|
MTS_DECLARE_CLASS()
|
|
protected:
|
|
/// Create a new luminaire
|
|
Luminaire(const Properties &props);
|
|
|
|
/// Unserialize a luminaire
|
|
Luminaire(Stream *stream, InstanceManager *manager);
|
|
|
|
/// Virtual destructor
|
|
virtual ~Luminaire();
|
|
protected:
|
|
Transform m_worldToLuminaire, m_luminaireToWorld;
|
|
Float m_samplingWeight;
|
|
ref<Medium> m_medium;
|
|
int m_type;
|
|
bool m_intersectable;
|
|
std::string m_name;
|
|
};
|
|
|
|
MTS_NAMESPACE_END
|
|
|
|
#endif /* __LUMINAIRE_H */
|