BSDF.h

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @class  BSDF
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Abstract representation of a BSDF defined at a single point on a 
00009    surface in 3-space.
00010    
00011       A BSDF (or Bidirectional Scattering Distribution Function) is a function 
00012    defining the fraction of light propagated after hitting a surface in a 
00013    given exitent direction, wo, from a given incident direction, wi. It 
00014    represents the observed radiance leaving in direction wo, per unit of 
00015    irradiance arriving from wi. A BSDF is commonly denoted by the notation 
00016    fs(wi->wo).
00017       It is much more common in computer graphics to hear one speak about 
00018    BRDFs (or Bidirectional Reflectance Distribution Functions), the difference 
00019    being that BSDFs are defined over the entire sphere of solid angles and 
00020    therefore include transmission (transparency), whereas BRDFs are defined 
00021    only on the positive hemisphere at a surface point with respect to its 
00022    local geometric normal.  BRDFs represent a subset of allowable BSDFs, and 
00023    they suffice in simulating the majority of real world materials. The 
00024    added complexity / generality of BSDFs, however, is important to any 
00025    physically based rendering engine such as Milton. A BRDF is commonly 
00026    denoted by fr(wi->wo).
00027    
00028       Physically valid BRDFs have several basic properties or consraints, 
00029    namely reciprocity and conservation of energy.
00030       Reciprocity means that BRDFs are symmetric: fr(wi->wo) = fr(wo->wi). 
00031    For this reason, it is common to make the symmetric explicit in the notation
00032    by instead writing fr(wi<->wo) in the case of BRDFs or fs(wi<->wo) in the 
00033    case of BSDFs.
00034       Conservation of energy states that a surface should not reflect more 
00035    energy than it receives. Formally this can be stated as the integral of 
00036    fr(wi->wo) over the positive hemisphere at any point with respect to a 
00037    projected solid angle measure has to be less than or equal to one for 
00038    all possible incident vectors, wi.
00039    
00040    @htmlonly
00041    Example usage:
00042    <pre><code>
00043       SurfacePoint pt;
00044       const real_t t = m_scene->getIntersection(ray, pt);
00045       
00046       // lazily initialize SurfacePoint and return if no intersection
00047       if (!pt.init(ray, t))
00048          return; // ray didn't hit anything (t == INFINITY)
00049       
00050       // sample the BSDF for an exitant direction
00051       const Event &event = pt.bsdf->sample();
00052       const Vector3 &wo  = event;
00053       
00054       if (wo == Vector3::zero())
00055          return; // invalid exitant direction
00056       
00057       // evaluate BSDF in the given exitant direction and divide by probability
00058       // with which we sampled that direction
00059       const real_t pdf = pt.bsdf->getPdf(event);
00060       const SpectralSampleSet &fs = pt.bsdf->getBSDF(wo) / pdf;
00061       
00062       // ... trace another ray in direction 'wo' ...
00063    </code></pre>
00064    @endhtmlonly
00065    <!-------------------------------------------------------------------->**/
00066 
00067 #ifndef BSDF_H_
00068 #define BSDF_H_
00069 
00070 #include <core/SurfacePoint.h>
00071 #include <utils/SpectralSampleSet.h>
00072 #include <stats/Sampler.h>
00073 #include <shapes/Shape.h>
00074 #include <common/image/Image.h>
00075 
00076 class Material;
00077 
00078 class BSDF : public Sampler, public SSEAligned {
00079    public:
00080       ///@name Constructors
00081       //@{-----------------------------------------------------------------
00082       
00083       inline explicit BSDF(SurfacePoint &pt, Material *parent = NULL)
00084          : Sampler(), m_wi(1, 0, 0), m_pt(pt), m_parent(parent)
00085       { }
00086       
00087       virtual ~BSDF()
00088       { }
00089       
00090       
00091       //@}-----------------------------------------------------------------
00092       ///@name Initialization
00093       //@{-----------------------------------------------------------------
00094       
00095       /**
00096        * @brief
00097        *    Performs any initialization that may be necessary before beginning 
00098        * to sample this BSDF
00099        * 
00100        * @note default implementation is empty
00101        */
00102       virtual void init()
00103       { }
00104       
00105       
00106       //@}-----------------------------------------------------------------
00107       ///@name Main usage interface
00108       //@{-----------------------------------------------------------------
00109       
00110       /**
00111        * @brief
00112        *    Sets the incident vector, wi, for this BSDF. All BSDF sampling 
00113        * is with respect to the current value of wi.
00114        */
00115       virtual void setWi(const Vector3 &wi) {
00116          m_wi = wi;
00117       }
00118       
00119       /**
00120        * @brief
00121        *    Samples an exitent vector at the given surface point
00122        * 
00123        * @returns the sampled vector as a Vector3 wrapped in an Event object
00124        * @note returns Vector3::zero() if no exitent vector was sampled
00125        *    (to model a certain probability of absorption, for instance)
00126        * 
00127        * @htmlonly
00128        * Example usage:
00129        * <pre><code>
00130        *    const Event &event = bsdf.sample();
00131        *    const Vector3 &wo  = event.getValue<Vector3>();
00132        *    const real_t pd    = bsdf.getPdf(event);        // p(x) probability
00133        *    const SpectralSampleSet &fs = bsdf.getBSDF(wo); // f(x) reflectivity
00134        * </code></pre>
00135        * @endhtmlonly
00136        */
00137       virtual Event sample() = 0;
00138       
00139       /**
00140        * @returns the probability density of having sampled the given out 
00141        *    out vector @p event with respect to whatever underlying sampling 
00142        *    strategy is being used to sample the BSDF
00143        * 
00144        * @note probability density is assumed to be with respect to projected 
00145        *    solid angle (the conversion from solid angle to projected solid 
00146        *    angle involves dividing the solid angle density by the absolute 
00147        *    value of the cosine of the angle between the local surface normal 
00148        *    and the exitant vector in @p event)
00149        */
00150       virtual real_t getPdf(const Event &event) = 0;
00151       
00152       /**
00153        * @brief
00154        *    Evaluates the spectral BSDF at the given surface point with respect 
00155        * to the out vector, 'wo', at the underlying surface point and given 
00156        * incident vector, 'wi'
00157        * 
00158        * @returns the spectral radiance leaving in direction wo, per unit of 
00159        *    irradiance arriving from wi (unitless fraction in [0, 1])
00160        * 
00161        * @note uses the currently set m_wi for the incident vector
00162        */
00163       inline SpectralSampleSet getBSDF(const Vector3 &wo) {
00164          return getBSDF(m_wi, wo);
00165       }
00166       
00167       /**
00168        * @brief
00169        *    Evaluates the spectral BSDF at the given surface point with respect 
00170        * to the out vector, 'wo', at the underlying surface point and given 
00171        * incident vector, 'wi'
00172        * 
00173        * @returns the spectral radiance leaving in direction wo, per unit of 
00174        *    irradiance arriving from wi (unitless fraction in [0, 1])
00175        */
00176       virtual SpectralSampleSet getBSDF(const Vector3 &wi, 
00177                                         const Vector3 &wo) = 0;
00178       
00179       /**
00180        * @returns true iff this BSDF is non-zero over a set of solid angles 
00181        *    with measure zero (measured with respect to solid angle)
00182        * 
00183        * @note a perfectly specular material has a dirac distribution for its 
00184        *    reflectance, and therefore needs special consideration when 
00185        *    sampling the BRDF for simulation purposes
00186        * @note the default implementation returns false because perfectly
00187        *    specular surfaces don't occur that often in real life, though they 
00188        *    abound in computer graphics (due to their ease of simulation)
00189        */
00190       inline bool isSpecular() const {
00191          Event e;
00192          return isSpecular(e);
00193       }
00194       
00195       /**
00196        * @returns true iff this BSDF is non-zero over a set of solid angles 
00197        *    with measure zero (measured with respect to solid angle)
00198        * 
00199        * @note a perfectly specular material has a dirac distribution for its 
00200        *    reflectance, and therefore needs special consideration when 
00201        *    sampling the BRDF for simulation purposes
00202        * @note the default implementation returns false because perfectly
00203        *    specular surfaces don't occur that often in real life, though they 
00204        *    abound in computer graphics (due to their ease of simulation)
00205        * @note implementations are free to use the given Event's metadata 
00206        *    to determine whether or not it represents a specular event
00207        */
00208       virtual bool isSpecular(Event &/* event unused*/) const {
00209          return false;
00210       }
00211       
00212       /**
00213        * @brief
00214        *    Sets up OpenGL material state (color properties, etc.) to enable 
00215        * a crude/fast preview of geometry to which this BSDF is applied
00216        *
00217        * @note default implementation sets the current glColor
00218        * @param shape is the Shape which this BSDF will preview itself on
00219        */
00220       virtual void preview(Shape *shape);
00221       
00222       
00223       //@}-----------------------------------------------------------------
00224       ///@name Accessors/Mutators
00225       //@{-----------------------------------------------------------------
00226       
00227       /**
00228        * @returns the SurfacePoint at which this BSDF instance is defined
00229        */
00230       inline SurfacePoint &getSurfacePoint() {
00231          return m_pt;
00232       }
00233       
00234       /**
00235        * @returns the current incident vector, wi, for which this BSDF will 
00236        *    be sampled
00237        */
00238       inline const Vector3 &getWi() const {
00239          return m_wi;
00240       }
00241       
00242       /**
00243        * @returns the parent Material which instantiated this BSDF
00244        * 
00245        * @note the parent Material is also a PropertyMap and contians all 
00246        *    key-value inputs to this BSDF
00247        */
00248       inline Material *getParent() {
00249          return m_parent;
00250       }
00251       
00252       /**
00253        * @returns the perfect specularly reflected direction given the current
00254        *    incident vector, wi, which is defined to be wi rotated about the 
00255        *    local surface normal
00256        * 
00257        * @see also Vector::reflectVector
00258        */
00259       inline Vector3 getSpecularReflection() const {
00260          return m_wi.reflectVector(m_pt.normalS);
00261       }
00262       
00263       
00264       //@}-----------------------------------------------------------------
00265       
00266    protected:
00267       Vector3       m_wi;
00268       SurfacePoint &m_pt;
00269       Material     *m_parent;
00270 };
00271 
00272 #endif // BSDF_H_
00273 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6