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 "path.h"
00025
00026 using namespace lux;
00027
00028
00029 PathIntegrator* PathIntegrator::clone() const
00030 {
00031 PathIntegrator *path = new PathIntegrator(*this);
00032 path->lightPositionOffset = new int[maxDepth];
00033 path->lightNumOffset = new int[maxDepth];
00034 path->bsdfDirectionOffset = new int[maxDepth];
00035 path->bsdfComponentOffset = new int[maxDepth];
00036 path->continueOffset = new int[maxDepth];
00037 path->outgoingDirectionOffset = new int[maxDepth];
00038 path->outgoingComponentOffset = new int[maxDepth];
00039 for (int i = 0; i < maxDepth; ++i) {
00040 path->lightPositionOffset[i] = lightPositionOffset[i];
00041 path->lightNumOffset[i] = lightNumOffset[i];
00042 path->bsdfDirectionOffset[i] = bsdfDirectionOffset[i];
00043 path->bsdfComponentOffset[i] = bsdfComponentOffset[i];
00044 path->continueOffset[i] = continueOffset[i];
00045 path->outgoingDirectionOffset[i] = outgoingDirectionOffset[i];
00046 path->outgoingComponentOffset[i] = outgoingComponentOffset[i];
00047 }
00048 return path;
00049 }
00050
00051 void PathIntegrator::RequestSamples(Sample *sample,
00052 const Scene *scene) {
00053 for (int i = 0; i < maxDepth; ++i) {
00054 lightPositionOffset[i] = sample->Add2D(1);
00055 lightNumOffset[i] = sample->Add1D(1);
00056 bsdfDirectionOffset[i] = sample->Add2D(1);
00057 bsdfComponentOffset[i] = sample->Add1D(1);
00058 continueOffset[i] = sample->Add1D(1);
00059 outgoingDirectionOffset[i] = sample->Add2D(1);
00060 outgoingComponentOffset[i] = sample->Add1D(1);
00061 }
00062 }
00063
00064 IntegrationSampler* PathIntegrator::HasIntegrationSampler(IntegrationSampler *is) {
00065 IntegrationSampler *isa = NULL;
00066 if(useMlt) {
00067 isa = new Metropolis();
00068 isa->SetParams(maxReject, pLarge);
00069 mltIntegrationSampler = isa;
00070 }
00071 return isa;
00072 }
00073
00074 Spectrum PathIntegrator::Li(const Scene *scene,
00075 const RayDifferential &r, const Sample *sample,
00076 float *alpha) const {
00077
00078 Spectrum pathThroughput = 1., L = 0.;
00079 RayDifferential ray(r);
00080 bool specularBounce = false;
00081 for (int pathLength = 0; ; ++pathLength) {
00082
00083 Intersection isect;
00084 if (!scene->Intersect(ray, &isect)) {
00085
00086
00087
00088 if (pathLength == 0 || specularBounce)
00089 for (u_int i = 0; i < scene->lights.size(); ++i)
00090 L += pathThroughput * scene->lights[i]->Le(ray);
00091
00092
00093
00094
00095
00096 break;
00097 }
00098 if (pathLength == 0) {
00099 r.maxt = ray.maxt;
00100 if (alpha) *alpha = 1.;
00101 }
00102 else
00103 pathThroughput *= scene->Transmittance(ray);
00104
00105 if (pathLength == 0 || specularBounce)
00106 L += pathThroughput * isect.Le(-ray.d);
00107
00108 BSDF *bsdf = isect.GetBSDF(ray);
00109
00110 const Point &p = bsdf->dgShading.p;
00111 const Normal &n = bsdf->dgShading.nn;
00112 Vector wo = -ray.d;
00113 if (pathLength < maxDepth && !useMlt)
00114 L += pathThroughput *
00115 UniformSampleOneLight(scene, p, n,
00116 wo, bsdf, sample,
00117 lightPositionOffset[pathLength],
00118 lightNumOffset[pathLength],
00119 bsdfDirectionOffset[pathLength],
00120 bsdfComponentOffset[pathLength]);
00121 else
00122 L += pathThroughput *
00123 UniformSampleOneLight(scene, p, n,
00124 wo, bsdf, sample);
00125
00126
00127 if (pathLength == maxDepth)
00128 break;
00129 if (pathLength > 3) {
00130 if (sample->oneD[continueOffset[pathLength]][0] > continueProbability)
00131 break;
00132
00133
00134 pathThroughput /= continueProbability;
00135 }
00136
00137
00138 float bs1, bs2, bcs;
00139 if (!useMlt) {
00140 bs1 = sample->twoD[outgoingDirectionOffset[pathLength]][0];
00141 bs2 = sample->twoD[outgoingDirectionOffset[pathLength]][1];
00142 bcs = sample->oneD[outgoingComponentOffset[pathLength]][0];
00143 }
00144 else {
00145 bs1 = lux::random::floatValue();
00146 bs2 = lux::random::floatValue();
00147 bcs = lux::random::floatValue();
00148
00149 mltIntegrationSampler->GetNext(bs1, bs2, bcs, pathLength);
00150 }
00151 Vector wi;
00152 float pdf;
00153 BxDFType flags;
00154 Spectrum f = bsdf->Sample_f(wo, &wi, bs1, bs2, bcs,
00155 &pdf, BSDF_ALL, &flags);
00156 if (f.Black() || pdf == 0.)
00157 break;
00158 specularBounce = (flags & BSDF_SPECULAR) != 0;
00159 pathThroughput *= f * AbsDot(wi, n) / pdf;
00160
00161 ray = RayDifferential(p, wi);
00162 }
00163 return L;
00164 }
00165 SurfaceIntegrator* PathIntegrator::CreateSurfaceIntegrator(const ParamSet ¶ms) {
00166
00167 int maxDepth = params.FindOneInt("maxdepth", 16);
00168 float RRcontinueProb = params.FindOneFloat("rrcontinueprob", .65f);
00169
00170 bool mlt = params.FindOneBool("metropolis", true);
00171 int MaxConsecRejects = params.FindOneInt("maxconsecrejects", 512);
00172 float LargeMutationProb = params.FindOneFloat("largemutationprob", .4f);
00173
00174 return new PathIntegrator(maxDepth, RRcontinueProb, mlt, MaxConsecRejects, LargeMutationProb);
00175
00176 }