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 "transport.h"
00025 #include "scene.h"
00026 #include "bxdf.h"
00027 #include "light.h"
00028 #include "mc.h"
00029
00030 namespace lux
00031 {
00032
00033
00034 Integrator::~Integrator() {
00035 }
00036
00037 SWCSpectrum UniformSampleAllLights(const TsPack *tspack, const Scene *scene,
00038 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00039 const Sample *sample,
00040 float *lightSample, float *lightNum,
00041 float *bsdfSample, float *bsdfComponent)
00042 {
00043 SWCSpectrum L(0.f);
00044 for (u_int i = 0; i < scene->lights.size(); ++i) {
00045 L += EstimateDirect(tspack, scene, scene->lights[i], p, n, wo, bsdf,
00046 sample, lightSample[0], lightSample[1], *lightNum,
00047 bsdfSample[0], bsdfSample[1], *bsdfComponent);
00048 }
00049 return L;
00050 }
00051
00052 int UniformSampleOneLight(const TsPack *tspack, const Scene *scene,
00053 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00054 const Sample *sample,
00055 float *lightSample, float *lightNum,
00056 float *bsdfSample, float *bsdfComponent, SWCSpectrum *L)
00057 {
00058
00059 int nLights = scene->lights.size();
00060 if (nLights == 0) {
00061 *L = 0.f;
00062 return 0;
00063 }
00064 int lightNumber;
00065 float ls3 = *lightNum * nLights;
00066 lightNumber = min(Floor2Int(ls3), nLights - 1);
00067 ls3 -= lightNumber;
00068 Light *light = scene->lights[lightNumber];
00069 *L = (float)nLights *
00070 EstimateDirect(tspack, scene, light, p, n, wo, bsdf,
00071 sample, lightSample[0], lightSample[1], ls3,
00072 bsdfSample[0], bsdfSample[1], *bsdfComponent);
00073 return scene->lights[lightNumber]->group;
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 SWCSpectrum EstimateDirect(const TsPack *tspack, const Scene *scene, const Light *light,
00141 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf, const Sample *sample,
00142 float &ls1, float &ls2, float &ls3, float &bs1, float &bs2, float &bcs)
00143 {
00144 SWCSpectrum Ld(0.);
00145
00146
00147 BxDFType noDiffuse = BxDFType(BSDF_ALL & ~(BSDF_DIFFUSE));
00148 if (light->IsDeltaLight() || (bsdf->NumComponents(noDiffuse) == 0)) {
00149
00150
00151 Vector wi;
00152 float lightPdf;
00153 VisibilityTester visibility;
00154 SWCSpectrum Li = light->Sample_L(tspack, p, n,
00155 ls1, ls2, ls3, &wi, &lightPdf, &visibility);
00156 if (lightPdf > 0. && !Li.Black()) {
00157 SWCSpectrum f = bsdf->f(tspack, wi, wo);
00158 SWCSpectrum fO(1.f);
00159 if (!f.Black() && visibility.TestOcclusion(tspack, scene, &fO)) {
00160
00161 visibility.Transmittance(tspack, scene, sample, &Li);
00162 Li *= fO;
00163 Ld += f * Li * (AbsDot(wi, n) / lightPdf);
00164 }
00165 }
00166 } else {
00167
00168
00169 const BxDFType noSpecular = BxDFType(BSDF_ALL & ~BSDF_SPECULAR);
00170 Vector wi;
00171 float lightPdf, bsdfPdf;
00172 VisibilityTester visibility;
00173 SWCSpectrum Li = light->Sample_L(tspack, p, n,
00174 ls1, ls2, ls3, &wi, &lightPdf, &visibility);
00175 if (lightPdf > 0. && !Li.Black()) {
00176 SWCSpectrum f = bsdf->f(tspack, wi, wo, noSpecular);
00177 SWCSpectrum fO(1.f);
00178 if (!f.Black() && visibility.TestOcclusion(tspack, scene, &fO)) {
00179
00180 visibility.Transmittance(tspack, scene, sample, &Li);
00181 Li *= fO;
00182
00183 bsdfPdf = bsdf->Pdf(tspack, wi, wo, noSpecular);
00184 float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);
00185 Ld += f * Li * (AbsDot(wi, n) * weight / lightPdf);
00186 }
00187
00188
00189 SWCSpectrum fBSDF;
00190 if (bsdf->Sample_f(tspack, wo, &wi, bs1, bs2, bcs, &fBSDF, &bsdfPdf, noSpecular, NULL, NULL, true)) {
00191 lightPdf = light->Pdf(p, n, wi);
00192 if (lightPdf > 0.) {
00193
00194 float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);
00195 Intersection lightIsect;
00196 Li = SWCSpectrum(1.f);
00197 RayDifferential ray(p, wi);
00198 ray.time = tspack->time;
00199 const BxDFType flags(BxDFType(BSDF_SPECULAR | BSDF_TRANSMISSION));
00200 for (u_int i = 0; i < 10000; ++i) {
00201 if (!scene->Intersect(ray, &lightIsect)) {
00202 Li *= light->Le(tspack, ray);
00203 break;
00204 } else if (lightIsect.arealight == light) {
00205 Li *= lightIsect.Le(tspack, -wi);
00206 break;
00207 }
00208 BSDF *ibsdf = lightIsect.GetBSDF(tspack, ray);
00209
00210 Li *= ibsdf->f(tspack, wi, -wi, flags);
00211 if (Li.Black())
00212 break;
00213 Li *= AbsDot(ibsdf->dgShading.nn, wi);
00214
00215 ray.mint = ray.maxt + MachineEpsilon::E(ray.maxt);
00216 ray.maxt = INFINITY;
00217 }
00218 if (!Li.Black()) {
00219 scene->Transmittance(tspack, ray, sample, &Li);
00220 Ld += fBSDF * Li * (AbsDot(wi, n) * weight / bsdfPdf);
00221 }
00222 }
00223 }
00224 }
00225 }
00226
00227 return Ld;
00228 }
00229
00230
00231 }