DielectricBSDF.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   DielectricBSDF.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Wavelength-dependent, thin dielectric BSDF defined at a single point on 
00009    a surface in 3-space. The opacity input controls the transmittance versus 
00010    reflectance of different wavelengths. A pure specular mirror may be obtained
00011    by creating a dielectric BSDF with zero opacity. Conversely, a purely 
00012    transparent surface may be obtained by creating a dielectric with full 
00013    opacity. Note that a completely transparent surface will still reflect some 
00014    light (in proportion to Fresnel's Laws) because refraction is undefined past 
00015    a critical angle when light is traveling between a lighter and denser 
00016    medium. When this happens, some light is reflected regardless of the opacity 
00017    parameter, and this is typically known as total internal reflection.
00018    
00019    @param
00020       opacity - SpectralSampleSet which specifies the transmittance of the 
00021    material
00022    
00023    @param
00024       ks      - SpectralSampleSet which scales / attenuates the overall 
00025    reflectance of the material (specular albedo)
00026    <!-------------------------------------------------------------------->**/
00027 
00028 #include "DielectricBSDF.h"
00029 #include <IndexOfRefraction.h>
00030 #include <Material.h>
00031 #include <Fresnel.h>
00032 #include <Random.h>
00033 
00034 void DielectricBSDF::init() {
00035    m_ior = m_parent->getSpectralSampleSet("ior", IndexOfRefraction::AIR, m_pt);
00036    
00037    m_transparency    = m_parent->getSpectralSampleSet("transparency", 1.0, m_pt);
00038    m_avgTransparency = m_transparency.getAverage();
00039 }
00040 
00041 Event DielectricBSDF::sample() {
00042    const Vector3 &N  = 
00043       (m_pt.normal.dot(m_wi) > 0 ? -m_pt.normalS : m_pt.normalS);
00044    const unsigned index = Random::sampleInt(0, m_ior.getN());
00045    const real_t ior = m_ior[index].value;
00046    const Vector3 &wt = m_wi.refractVector(m_pt.normalS, m_pt.ior1, ior);
00047    
00048    if (wt != Vector3::zero()) {
00049       const real_t Fr = Fresnel::getFr(m_wi, m_pt.normalS, m_pt.ior1, ior);
00050       ASSERT(Fr >= 0 && Fr <= 1);
00051       
00052       // attenuate normal Fresnel transmission coefficient, Fs, by the average 
00053       // transparency of the surface
00054       const real_t Fs = m_avgTransparency * (1 - Fr);
00055       ASSERT(Fs >= 0 && Fs <= 1);
00056       
00057       // refract with probability Fs
00058       if (Random::sample() < Fs)
00059          return Event(wt, this, index);
00060    }
00061    
00062    return Event(m_wi.reflectVector(N), this);
00063 }
00064 
00065 real_t DielectricBSDF::getPdf(const Event &event) {
00066    const Vector3 &wo = event.getValue<const Vector3&>();
00067    const Vector3 &N  = 
00068       (m_pt.normal.dot(m_wi) > 0 ? -m_pt.normalS : m_pt.normalS);
00069    
00070    if (wo.dot(N) < 0) {
00071       //const Vector3 &wt = m_wi.refractVector(m_pt.normalS, m_pt.ior1, m_pt.ior2);
00072       real_t n = 0;
00073       for(unsigned i = m_ior.getN(); i--;) {
00074          const Vector3 &wt = m_wi.refractVector(m_pt.normalS, m_pt.ior1, m_ior[i].value);
00075          
00076          n += (wo == wt);
00077       }
00078       
00079       return n / m_ior.getN();
00080       //return (wo == wt ? 1 : 0);
00081    }
00082    
00083    return (wo == m_wi.reflectVector(N) ? 1 : 0);
00084 }
00085 
00086 SpectralSampleSet DielectricBSDF::getBSDF(const Vector3 &wi, const Vector3 &wo) {
00087    const SpectralSampleSet &ks = 
00088       m_parent->getSpectralSampleSet("ks", SpectralSampleSet::fill(1.0), m_pt);
00089    const Vector3 &N   = 
00090       (m_pt.normal.dot(wi) > 0 ? -m_pt.normalS : m_pt.normalS);
00091    
00092    if (wo.dot(N) < 0) {
00093       SpectralSampleSet s(m_ior);
00094       for(unsigned i = m_ior.getN(); i--;) {
00095          const Vector3 &wt = wi.refractVector(m_pt.normalS, m_pt.ior1, m_ior[i].value);
00096          
00097          s[i].value = (wo == wt);
00098       }
00099       
00100       return ks * s;
00101       //return ks * (wo == wt);
00102    }
00103    
00104    return ks * (wo == wi.reflectVector(N));
00105 }
00106 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6