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 "particletracing.h"
00025 #include "lux.h"
00026 #include "transport.h"
00027 #include "scene.h"
00028 #include "light.h"
00029 #include "camera.h"
00030 #include "film.h"
00031 #include "bxdf.h"
00032 #include "paramset.h"
00033
00034 using namespace lux;
00035
00036
00037 void ParticleTracingIntegrator::RequestSamples(Sample *sample, const Scene *scene)
00038 {
00039
00040 vector<u_int> structure;
00041
00042 structure.push_back(1);
00043 structure.push_back(2);
00044 structure.push_back(2);
00045
00046 structure.push_back(2);
00047 structure.push_back(1);
00048 sampleOffset = sample->AddxD(structure, maxDepth + 1);
00049 }
00050 void ParticleTracingIntegrator::Preprocess(const Scene *scene)
00051 {
00052 int i,id;
00053 char postfix[64];
00054 bufferIds.clear();
00055 for(i=0; i<=maxDepth; ++i)
00056 {
00057 sprintf(postfix,"_%02d",i);
00058 id = scene->camera->film->RequestBuffer(BUF_TYPE_PER_SCREEN,(BufferOutputConfig)(BUF_FRAMEBUFFER|BUF_STANDALONE),postfix);
00059 bufferIds.push_back(id);
00060 }
00061 scene->camera->film->CreateBuffers();
00062 numOfLights = scene->lights.size();
00063 }
00064
00065 SWCSpectrum ParticleTracingIntegrator::Li(const Scene *scene,
00066 const RayDifferential &r, const Sample *sample,
00067 float *alpha) const
00068 {
00069 SampleGuard guard(sample->sampler, sample);
00070 Sample &sample_gen = const_cast<Sample &>(*sample);
00071 Ray ray_gen;
00072
00073 bool isDeltaCamera = scene->camera->IsDelta();
00074 bool specularBounce = false;
00075 SWCSpectrum pathThroughput(1.0f);
00076 Point p;
00077 Normal n;
00078 Vector wi;
00079 Point lenP;
00080 float lenPdf;
00081 float *data = sample->sampler->GetLazyValues(const_cast<Sample *>(sample), sampleOffset, 0);
00082
00083
00084 int lightNum = Floor2Int(data[0] * numOfLights);
00085 lightNum = min(lightNum, numOfLights - 1);
00086 Light *light = scene->lights[lightNum];
00087
00088
00089 SWCSpectrum F;
00090 double G,pdf,g;
00091
00092 Normal lastNormal;
00093
00094 SWCSpectrum Le;
00095 Point lightPoint;
00096 Normal lightNormal;
00097 Vector lightDir;
00098 float lightPdf1,lightPdf2,lightPdf;
00099
00100 light->SamplePosition(data[1], data[2], &lightPoint, &lightNormal, &lightPdf1);
00101 lightPdf = lightPdf1 / numOfLights;
00102
00103 scene->camera->SamplePosition(sample->lensU, sample->lensV, &lenP, &lenPdf);
00104 if (scene->camera->IsVisibleFromEyes(scene, lenP, lightPoint, &sample_gen, &ray_gen))
00105 {
00106
00107 Vector wo1 = Normalize(-ray_gen.d);
00108 Le = light->Eval(lightNormal,wo1);
00109
00110 G = scene->camera->GetConnectingFactor(lenP, lightPoint, wo1, lightNormal);
00111 Le *= G / lightPdf;
00112
00113 assert(!Le.IsNaN());
00114
00115 sample->AddContribution(sample_gen.imageX, sample_gen.imageY, Le.ToXYZ(), 1.f, 0);
00116 }
00117
00118 light->SampleDirection(data[3],data[4],lightNormal,&lightDir,&lightPdf2);
00119 lightPdf *= lightPdf2;
00120 if (lightPdf == 0.)
00121 {
00122 printf("P \n");
00123 return 0.f;
00124 }
00125 Le = light->Eval(lightNormal,lightDir);
00126
00127 Ray lightRay(lightPoint,lightDir);
00128
00129 RayDifferential ray(lightRay);
00130 Intersection isect;
00131
00132 F = Le;
00133 wi = -ray.d;
00134
00135 lastNormal = lightNormal;
00136 pdf = lightPdf;
00137
00138 bool lensIntersected, objectsIntersected;
00139 for (int pathLength = 0; ; ++pathLength)
00140 {
00141 if (pathLength!=0)
00142 data = sample->sampler->GetLazyValues(const_cast<Sample *>(sample), sampleOffset, pathLength);
00143
00144 lensIntersected = !isDeltaCamera && specularBounce && scene->camera->Intersect(ray, &isect);
00145
00146
00147
00148 objectsIntersected = scene->Intersect(ray, &isect);
00149 if (!objectsIntersected && lensIntersected)
00150 {
00151 float selectPdf = 0.9f;
00152 if (random::floatValue() < selectPdf)
00153 {
00154 pdf *= selectPdf;
00155 lenP = isect.dg.p;
00156 if (scene->camera->IsVisibleFromEyes(scene, lenP, ray.o, &sample_gen, &ray_gen))
00157 {
00158 Vector wo1 = Normalize(-ray_gen.d);
00159 Vector wi1 = Normalize(wi);
00160
00161
00162 g = 1.0;
00163 G = AbsDot(wi1,lastNormal)*g;
00164 pdf *= g;
00165 SWCSpectrum F1 = F;
00166 F1 *= G / pdf;
00167
00168
00169 F1 *= lenPdf;
00170
00171
00172 sample->AddContribution(sample_gen.imageX, sample_gen.imageY, F1.ToXYZ(), 1.f, pathLength);
00173 }
00174 return SWCSpectrum(-1.0f);
00175 }
00176 lensIntersected = false;
00177 pdf *= 1 - selectPdf ;
00178 }
00179 if (!objectsIntersected)
00180 break;
00181 if (pathLength == maxDepth)
00182 break;
00183
00184
00185
00186 BSDF *bsdf = isect.GetBSDF(ray, fabsf(2.f * data[7] - 1.f));
00187
00188 p = bsdf->dgShading.p;
00189 n = bsdf->dgShading.nn;
00190 wi = -ray.d;
00191
00192
00193 g = 1.0;
00194 G = AbsDot(wi,lastNormal)*g;
00195 pdf *= g;
00196 F *= G;
00197
00198 scene->camera->SamplePosition(sample->lensU, sample->lensV, &lenP, &lenPdf);
00199 if (scene->camera->IsVisibleFromEyes(scene, lenP, p, &sample_gen, &ray_gen))
00200 {
00201 Vector wo1 = Normalize(-ray_gen.d);
00202 Vector wi1 = Normalize(wi);
00203 SWCSpectrum F1 = F;
00204 G = scene->camera->GetConnectingFactor(lenP, p, wo1, n);
00205 F1 *= bsdf->f(wo1,wi1)*(G / pdf);
00206
00207 sample->AddContribution(sample_gen.imageX, sample_gen.imageY, F1.ToXYZ(), 1.f, pathLength + 1);
00208 }
00209
00210 Vector wo;
00211 float bsdf_pdf;
00212 BxDFType flags;
00213 SWCSpectrum f = bsdf->Sample_f(wi, &wo, data[5], data[6], data[7],
00214 &bsdf_pdf, BSDF_ALL, &flags);
00215 if (f.Black() || bsdf_pdf == 0.)
00216 break;
00217 specularBounce = (flags & BSDF_SPECULAR) != 0;
00218 F *= f;
00219 pdf *= bsdf_pdf;
00220
00221
00222
00223 {
00224 if (random::floatValue() > continueProbability)
00225 {
00226 break;
00227 }
00228 pdf *= continueProbability;
00229 }
00230
00231 ray = RayDifferential(p, wo);
00232
00233
00234 lastNormal = n;
00235 }
00236
00237 return SWCSpectrum(-1.0f);
00238 }
00239 SurfaceIntegrator* ParticleTracingIntegrator::CreateSurfaceIntegrator(const ParamSet ¶ms)
00240 {
00241 int maxDepth = params.FindOneInt("maxdepth", 5);
00242 float RRcontinueProb = params.FindOneFloat("rrcontinueprob", .65f);
00243 return new ParticleTracingIntegrator(maxDepth, RRcontinueProb);
00244 }