00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "mltpath.h"
00028
00029 using namespace lux;
00030
00031
00032 MLTPathIntegrator* MLTPathIntegrator::clone() const
00033 {
00034 return new MLTPathIntegrator(*this);
00035 }
00036
00037 IntegrationSampler* MLTPathIntegrator::HasIntegrationSampler(IntegrationSampler *is) {
00038 IntegrationSampler *isa = NULL;
00039 isa = new Metropolis();
00040 isa->SetParams(maxReject, pLarge);
00041 mltIntegrationSampler = isa;
00042 return isa;
00043 }
00044
00045 void MLTPathIntegrator::RequestSamples(Sample *sample, const Scene *scene) {
00046 lightNumOffset = sample->Add1D(1);
00047 lightSampOffset = sample->Add2D(1);
00048
00049 }
00050
00051 Spectrum MLTPathIntegrator::Li(const Scene *scene,
00052 const RayDifferential &r, const Sample *sample,
00053 float *alpha) const {
00054 RayDifferential ray(r);
00055 Spectrum pathThroughput = 1., L = 0., Le;
00056 int lightNum;
00057 Light *light;
00058 Vector wi;
00059 float lightWeight, lightPdf, ls1, ls2;
00060 VisibilityTester visibility;
00061
00062
00063 lightNum = Floor2Int(sample->oneD[lightNumOffset][0] * scene->lights.size());
00064 lightNum = min(lightNum, (int)scene->lights.size() - 1);
00065 light = scene->lights[lightNum];
00066 lightWeight = float(scene->lights.size());
00067 ls1 = sample->twoD[lightSampOffset][0];
00068 ls2 = sample->twoD[lightSampOffset][1];
00069
00070 if (alpha) *alpha = 1.;
00071
00072 for (int pathLength = 0; ; ++pathLength) {
00073
00074 Intersection isect;
00075 if (!scene->Intersect(ray, &isect)) {
00076 for (u_int i = 0; i < scene->lights.size(); ++i)
00077 L += pathThroughput * scene->lights[i]->Le(ray);
00078 break;
00079 }
00080
00081
00082 BSDF *bsdf = isect.GetBSDF(ray);
00083 const Point &p = bsdf->dgShading.p;
00084 const Normal &n = bsdf->dgShading.nn;
00085 Vector wo = -ray.d;
00086 Spectrum emittance = isect.Le(wo);
00087
00088 pathThroughput *= scene->Transmittance(ray);
00089
00090 if (emittance != 0.) {
00091
00092 L += pathThroughput * isect.Le(-ray.d);
00093 } else {
00094
00095 Le = light->Sample_L(p, n, ls1, ls2, &wi, &lightPdf, &visibility);
00096 Spectrum f = bsdf->f(wo, wi);
00097 if(lightPdf > 0. && !Le.Black() && !f.Black() && visibility.Unoccluded(scene))
00098 L += pathThroughput * lightWeight * f * Le * AbsDot(wi, n) / lightPdf;
00099 }
00100
00101 if (pathLength == maxDepth)
00102 break;
00103
00104
00105 if (pathLength > 3) {
00106
00107 if (lux::random::floatValue() > continueProbability)
00108 break;
00109
00110 pathThroughput /= continueProbability;
00111 }
00112
00113
00114
00115 float bs1, bs2, bcs;
00116 bs1 = bs2 = bcs = -1.;
00117 mltIntegrationSampler->GetNext(bs1, bs2, bcs, pathLength);
00118
00119 Vector wi;
00120 float pdf;
00121 Spectrum f;
00122 BxDFType flags;
00123
00124
00125 f = bsdf->Sample_f(wo, &wi, bs1, bs2, bcs, &pdf, BSDF_ALL, &flags);
00126 if (f.Black() || pdf == 0.)
00127 break;
00128
00129
00130 ray = RayDifferential(p, wi);
00131
00132 pathThroughput *= f * AbsDot(wi, n) / pdf;
00133 }
00134 return L;
00135 }
00136
00137 SurfaceIntegrator* MLTPathIntegrator::CreateSurfaceIntegrator(const ParamSet ¶ms) {
00138
00139 int maxDepth = params.FindOneInt("maxdepth", 32);
00140 float RRcontinueProb = params.FindOneFloat("rrcontinueprob", .65f);
00141
00142 int MaxConsecRejects = params.FindOneInt("maxconsecrejects", 512);
00143 float LargeMutationProb = params.FindOneFloat("largemutationprob", .4f);
00144
00145 return new MLTPathIntegrator(maxDepth, RRcontinueProb, MaxConsecRejects, LargeMutationProb);
00146
00147 }