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 "spectrum.h"
00026 #include "spectrumwavelengths.h"
00027
00028 using namespace lux;
00029
00030 bool SpecularTransmission::Sample_f(const TsPack *tspack, const Vector &wo,
00031 Vector *wi, float u1, float u2, SWCSpectrum *const f_, float *pdf, float *pdfBack, bool reverse) const {
00032
00033 const bool entering = CosTheta(wo) > 0.f;
00034
00035
00036 if (dispersive)
00037 tspack->swl->SampleSingle();
00038
00039
00040 const float sini2 = SinTheta2(wo);
00041 const float eta = (entering || architectural) ? 1.f / fresnel->Index(tspack) : fresnel->Index(tspack);
00042 const float eta2 = eta * eta;
00043 const float sint2 = eta2 * sini2;
00044
00045 if (sint2 >= 1.f) {
00046 *f_ = 0.f;
00047 *pdf = 0.f;
00048 if (pdfBack)
00049 *pdfBack = 0.f;
00050 return false;
00051 }
00052 float cost = sqrtf(max(0.f, 1.f - sint2));
00053 if (entering) cost = -cost;
00054 if (architectural)
00055 *wi = -wo;
00056 else
00057 *wi = Vector(-eta * wo.x, -eta * wo.y, cost);
00058 *pdf = 1.f;
00059 if (pdfBack)
00060 *pdfBack = 1.f;
00061 SWCSpectrum F;
00062 if (!architectural) {
00063 if (reverse) {
00064 fresnel->Evaluate(tspack, cost, &F);
00065 *f_ = (SWCSpectrum(1.f) - F) * T / (eta2 * fabsf(cost));
00066 } else {
00067 fresnel->Evaluate(tspack, CosTheta(wo), &F);
00068 *f_ = (SWCSpectrum(1.f) - F) * T / fabsf(cost);
00069 }
00070 } else {
00071 if (reverse) {
00072 if (entering)
00073 F = SWCSpectrum(0.f);
00074 else
00075 fresnel->Evaluate(tspack, -CosTheta(wo), &F);
00076 } else {
00077 if (entering)
00078 fresnel->Evaluate(tspack, CosTheta(wo), &F);
00079 else
00080 F = SWCSpectrum(0.f);
00081 }
00082 *f_ = (SWCSpectrum(1.f) - F) * T / fabsf(-CosTheta(wo));
00083 }
00084 return true;
00085 }
00086 float SpecularTransmission::Weight(const TsPack *tspack, const Vector &wo) const
00087 {
00088 if (architectural)
00089 return 1.f;
00090 SWCSpectrum F;
00091 fresnel->Evaluate(tspack, CosTheta(wo), &F);
00092 return (1.f - F.Filter(tspack)) / fabsf(CosTheta(wo));
00093 }
00094 void SpecularTransmission::f(const TsPack *tspack, const Vector &wo,
00095 const Vector &wi, SWCSpectrum *const f_) const
00096 {
00097 if (!(architectural && Dot(wo, wi) < MachineEpsilon::E(1.f) - 1.f))
00098 return;
00099
00100 const bool entering = CosTheta(wo) > 0.f;
00101
00102
00103 if (dispersive)
00104 tspack->swl->SampleSingle();
00105
00106
00107 const float sini2 = SinTheta2(wo);
00108 const float eta = 1.f / fresnel->Index(tspack);
00109 const float eta2 = eta * eta;
00110 const float sint2 = eta2 * sini2;
00111
00112 if (sint2 >= 1.f)
00113 return;
00114 SWCSpectrum F;
00115 if (entering)
00116 fresnel->Evaluate(tspack, CosTheta(wo), &F);
00117 else
00118 F = SWCSpectrum(0.f);
00119 f_->AddWeighted(1.f / fabsf(CosTheta(wi)), (SWCSpectrum(1.f) - F) * T);
00120 }