00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "speculartransmission.h"
00025 #include "color.h"
00026 #include "spectrum.h"
00027 #include "spectrumwavelengths.h"
00028 #include "mc.h"
00029 #include "sampling.h"
00030 #include <stdarg.h>
00031
00032 #include <boost/thread/tss.hpp>
00033
00034 using namespace lux;
00035
00036 extern boost::thread_specific_ptr<SpectrumWavelengths> thread_wavelengths;
00037
00038 SWCSpectrum SpecularTransmission::Sample_f(const Vector &wo,
00039 Vector *wi, float u1, float u2, float *pdf, float *pdfBack) const {
00040
00041 const bool entering = CosTheta(wo) > 0.f;
00042 float ei = etai, et = etat;
00043
00044 if(cb != 0.f) {
00045
00046 const float w = thread_wavelengths->SampleSingle();
00047 et += (cb * 1000000.f) / (w * w);
00048 }
00049
00050 if (!entering && !architectural)
00051 swap(ei, et);
00052
00053 const float sini2 = SinTheta2(wo);
00054 const float eta = ei / et;
00055 const float eta2 = eta * eta;
00056 const float sint2 = eta2 * sini2;
00057
00058 if (sint2 > 1.) {
00059 *pdf = 0.f;
00060 if (pdfBack)
00061 *pdfBack = 0.f;
00062 return 0.;
00063 }
00064 float cost = sqrtf(max(0.f, 1.f - sint2));
00065 if (entering) cost = -cost;
00066 if (architectural)
00067 *wi = -wo;
00068 else
00069 *wi = Vector(-eta * wo.x, -eta * wo.y, cost);
00070 *pdf = 1.f;
00071 if (pdfBack)
00072 *pdfBack = 1.f;
00073 if (!architectural) {
00074 SWCSpectrum F = fresnel.Evaluate(CosTheta(wo));
00075 return (SWCSpectrum(1.f) - F) * T / (fabsf(cost) * eta2);
00076 } else {
00077 SWCSpectrum F = fresnel.Evaluate(-cost);
00078 if (entering)
00079 return (SWCSpectrum(1.f) - F) * T / (fabsf(wi->z) * eta2);
00080 else
00081 return (SWCSpectrum(1.f) - F) * T * (eta2 / fabsf(wi->z));
00082 }
00083 }
00084 SWCSpectrum SpecularTransmission::f(const Vector &wo, const Vector &wi) const
00085 {
00086 if (!(architectural && wi == -wo))
00087 return 0.f;
00088
00089 const bool entering = CosTheta(wo) > 0.f;
00090 float ei = etai, et = etat;
00091
00092 if(cb != 0.f) {
00093
00094 const float w = thread_wavelengths->SampleSingle();
00095 et += (cb * 1000000.f) / (w * w);
00096 }
00097
00098
00099 const float sini2 = SinTheta2(wo);
00100 const float eta = ei / et;
00101 const float eta2 = eta * eta;
00102 const float sint2 = eta2 * sini2;
00103
00104 if (sint2 > 1.) {
00105 return 0.;
00106 }
00107 float cost = sqrtf(max(0.f, 1.f - sint2));
00108 if (entering) cost = -cost;
00109 SWCSpectrum F = fresnel.Evaluate(-cost);
00110 if (entering)
00111 return (SWCSpectrum(1.f) - F) * T / (fabsf(wi.z) * eta2);
00112 else
00113 return (SWCSpectrum(1.f) - F) * T * (eta2 / fabsf(wi.z));
00114 }