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 #include "pbrt.h"
00026 #include "transport.h"
00027 #include "scene.h"
00028
00029 class PathIntegrator : public SurfaceIntegrator {
00030 public:
00031
00032 Spectrum Li(const Scene *scene, const RayDifferential &ray, const Sample *sample, float *alpha) const;
00033 void RequestSamples(Sample *sample, const Scene *scene);
00034 PathIntegrator(int md) { maxDepth = md; }
00035 private:
00036
00037 int maxDepth;
00038 #define SAMPLE_DEPTH 3
00039 int lightPositionOffset[SAMPLE_DEPTH];
00040 int lightNumOffset[SAMPLE_DEPTH];
00041 int bsdfDirectionOffset[SAMPLE_DEPTH];
00042 int bsdfComponentOffset[SAMPLE_DEPTH];
00043 int outgoingDirectionOffset[SAMPLE_DEPTH];
00044 int outgoingComponentOffset[SAMPLE_DEPTH];
00045 };
00046
00047 void PathIntegrator::RequestSamples(Sample *sample,
00048 const Scene *scene) {
00049 for (int i = 0; i < SAMPLE_DEPTH; ++i) {
00050 lightPositionOffset[i] = sample->Add2D(1);
00051 lightNumOffset[i] = sample->Add1D(1);
00052 bsdfDirectionOffset[i] = sample->Add2D(1);
00053 bsdfComponentOffset[i] = sample->Add1D(1);
00054 outgoingDirectionOffset[i] = sample->Add2D(1);
00055 outgoingComponentOffset[i] = sample->Add1D(1);
00056 }
00057 }
00058 Spectrum PathIntegrator::Li(const Scene *scene,
00059 const RayDifferential &r, const Sample *sample,
00060 float *alpha) const {
00061
00062 Spectrum pathThroughput = 1., L = 0.;
00063 RayDifferential ray(r);
00064 bool specularBounce = false;
00065 for (int pathLength = 0; ; ++pathLength) {
00066
00067 Intersection isect;
00068 if (!scene->Intersect(ray, &isect)) {
00069
00070 if (pathLength == 0) {
00071 for (u_int i = 0; i < scene->lights.size(); ++i)
00072 L += scene->lights[i]->Le(ray);
00073 if (alpha) {
00074 if (L != 0.) *alpha = 1.;
00075 else *alpha = 0.;
00076 }
00077 }
00078 else if (pathLength > 0 && alpha && specularBounce) {
00079 for (u_int i = 0; i < scene->lights.size(); ++i)
00080 L += pathThroughput * scene->lights[i]->Le(ray);
00081 }
00082 break;
00083 }
00084 if (pathLength == 0) {
00085 r.maxt = ray.maxt;
00086 if (alpha) *alpha = 1.;
00087 }
00088 else
00089 pathThroughput *= scene->Transmittance(ray);
00090
00091 if (pathLength == 0 || specularBounce)
00092 L += pathThroughput * isect.Le(-ray.d);
00093
00094 BSDF *bsdf = isect.GetBSDF(ray);
00095
00096 const Point &p = bsdf->dgShading.p;
00097 const Normal &n = bsdf->dgShading.nn;
00098 Vector wo = -ray.d;
00099 if (pathLength < SAMPLE_DEPTH)
00100 L += pathThroughput *
00101 UniformSampleOneLight(scene, p, n,
00102 wo, bsdf, sample,
00103 lightPositionOffset[pathLength],
00104 lightNumOffset[pathLength],
00105 bsdfDirectionOffset[pathLength],
00106 bsdfComponentOffset[pathLength]);
00107 else
00108 L += pathThroughput *
00109 UniformSampleOneLight(scene, p, n,
00110 wo, bsdf, sample);
00111
00112
00113 float bs1, bs2, bcs;
00114 if (pathLength < SAMPLE_DEPTH) {
00115 bs1 = sample->twoD[outgoingDirectionOffset[pathLength]][0];
00116 bs2 = sample->twoD[outgoingDirectionOffset[pathLength]][1];
00117 bcs = sample->oneD[outgoingComponentOffset[pathLength]][0];
00118 }
00119 else {
00120 bs1 = RandomFloat();
00121 bs2 = RandomFloat();
00122 bcs = RandomFloat();
00123 }
00124 Vector wi;
00125 float pdf;
00126 BxDFType flags;
00127 Spectrum f = bsdf->Sample_f(wo, &wi, bs1, bs2, bcs,
00128 &pdf, BSDF_ALL, &flags);
00129 if (f.Black() || pdf == 0.)
00130 break;
00131 specularBounce = (flags & BSDF_SPECULAR) != 0;
00132 pathThroughput *= f * AbsDot(wi, n) / pdf;
00133 ray = RayDifferential(p, wi);
00134
00135 if (pathLength > 3) {
00136 float continueProbability = .5f;
00137 if (RandomFloat() > continueProbability)
00138 break;
00139 pathThroughput /= continueProbability;
00140 }
00141 if (pathLength == maxDepth)
00142 break;
00143 }
00144 return L;
00145 }
00146 extern "C" DLLEXPORT SurfaceIntegrator *CreateSurfaceIntegrator(const ParamSet ¶ms) {
00147 int maxDepth = params.FindOneInt("maxdepth", 5);
00148 return new PathIntegrator(maxDepth);
00149 }