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 "igi.h"
00025
00026 using namespace lux;
00027
00028
00029 IGIIntegrator* IGIIntegrator::clone() const
00030 {
00031 return new IGIIntegrator(*this);
00032 }
00033
00034 IGIIntegrator::IGIIntegrator(int nl, int ns, float md,
00035 float rrt, float is) {
00036 nLightPaths = RoundUpPow2((u_int)nl);
00037 nLightSets = RoundUpPow2((u_int)ns);
00038 minDist2 = md * md;
00039 rrThreshold = rrt;
00040 indirectScale = is;
00041 maxSpecularDepth = 5;
00042 specularDepth = 0;
00043 virtualLights = new vector<VirtualLight>[nLightSets];
00044 }
00045 void IGIIntegrator::RequestSamples(Sample *sample,
00046 const Scene *scene) {
00047
00048 u_int nLights = scene->lights.size();
00049 lightSampleOffset = new int[nLights];
00050 bsdfSampleOffset = new int[nLights];
00051 bsdfComponentOffset = new int[nLights];
00052 for (u_int i = 0; i < nLights; ++i) {
00053 const Light *light = scene->lights[i];
00054 int lightSamples =
00055 scene->sampler->RoundSize(light->nSamples);
00056 lightSampleOffset[i] = sample->Add2D(lightSamples);
00057 bsdfSampleOffset[i] = sample->Add2D(lightSamples);
00058 bsdfComponentOffset[i] = sample->Add1D(lightSamples);
00059 }
00060 lightNumOffset = -1;
00061 vlSetOffset = sample->Add1D(1);
00062 }
00063 void IGIIntegrator::Preprocess(const Scene *scene) {
00064 if (scene->lights.size() == 0) return;
00065
00066 float *lightNum = new float[nLightPaths * nLightSets];
00067 float *lightSamp0 = new float[2 * nLightPaths * nLightSets];
00068 float *lightSamp1 = new float[2 * nLightPaths * nLightSets];
00069 LDShuffleScrambled1D(nLightPaths, nLightSets, lightNum);
00070 LDShuffleScrambled2D(nLightPaths, nLightSets, lightSamp0);
00071 LDShuffleScrambled2D(nLightPaths, nLightSets, lightSamp1);
00072
00073 int nLights = int(scene->lights.size());
00074 float *lightPower = (float *)alloca(nLights * sizeof(float));
00075 float *lightCDF = (float *)alloca((nLights+1) * sizeof(float));
00076 for (int i = 0; i < nLights; ++i)
00077 lightPower[i] = scene->lights[i]->Power(scene).y();
00078 float totalPower;
00079 ComputeStep1dCDF(lightPower, nLights, &totalPower, lightCDF);
00080 for (u_int s = 0; s < nLightSets; ++s) {
00081 for (u_int i = 0; i < nLightPaths; ++i) {
00082
00083 int sampOffset = s*nLightPaths + i;
00084
00085 float lightPdf;
00086 int lNum = Floor2Int(SampleStep1d(lightPower, lightCDF,
00087 totalPower, nLights, lightNum[sampOffset], &lightPdf) * nLights);
00088 fprintf(stderr, "samp %f -> num %d\n", lightNum[sampOffset], lNum);
00089 Light *light = scene->lights[lNum];
00090
00091 RayDifferential ray;
00092 float pdf;
00093 Spectrum alpha =
00094 light->Sample_L(scene, lightSamp0[2*sampOffset],
00095 lightSamp0[2*sampOffset+1],
00096 lightSamp1[2*sampOffset],
00097 lightSamp1[2*sampOffset+1],
00098 &ray, &pdf);
00099 if (pdf == 0.f || alpha.Black()) continue;
00100 alpha /= pdf * lightPdf;
00101 fprintf(stderr, "initial alpha %f, light # %d\n", alpha.y(), lNum);
00102 Intersection isect;
00103 int nIntersections = 0;
00104 while (scene->Intersect(ray, &isect) && !alpha.Black()) {
00105 ++nIntersections;
00106 alpha *= scene->Transmittance(ray);
00107 Vector wo = -ray.d;
00108 MemoryArena arena;
00109 BSDF *bsdf = isect.GetBSDF( ray);
00110
00111
00112
00113 Spectrum Le = alpha * bsdf->rho(wo) / M_PI;
00114 fprintf(stderr, "\tmade light with le y %f\n", Le.y());
00115 virtualLights[s].push_back(VirtualLight(isect.dg.p, isect.dg.nn, Le));
00116
00117 Vector wi;
00118 float pdf;
00119 BxDFType flags;
00120 Spectrum fr = bsdf->Sample_f(wo, &wi, lux::random::floatValue(),
00121 lux::random::floatValue(), lux::random::floatValue(),
00122 &pdf, BSDF_ALL, &flags);
00123 if (fr.Black() || pdf == 0.f)
00124 break;
00125 Spectrum anew = alpha * fr * AbsDot(wi, bsdf->dgShading.nn) / pdf;
00126 float r = anew.y() / alpha.y();
00127 fprintf(stderr, "\tr = %f\n", r);
00128 if (lux::random::floatValue() > r)
00129 break;
00130 alpha = anew / r;
00131 fprintf(stderr, "\tnew alpha %f\n", alpha.y());
00132 ray = RayDifferential(isect.dg.p, wi);
00133 }
00134
00135 }
00136 }
00137 delete[] lightNum;
00138 delete[] lightSamp0;
00139 delete[] lightSamp1;
00140 }
00141 Spectrum IGIIntegrator::Li(const Scene *scene,
00142 const RayDifferential &ray, const Sample *sample,
00143 float *alpha) const {
00144 Spectrum L(0.);
00145 Intersection isect;
00146 if (scene->Intersect(ray, &isect)) {
00147 if (alpha) *alpha = 1.;
00148 Vector wo = -ray.d;
00149
00150 L += isect.Le(wo);
00151
00152 BSDF *bsdf = isect.GetBSDF( ray);
00153 const Point &p = bsdf->dgShading.p;
00154 const Normal &n = bsdf->dgShading.nn;
00155 L += UniformSampleAllLights(scene, p, n,
00156 wo, bsdf, sample,
00157 lightSampleOffset, bsdfSampleOffset,
00158 bsdfComponentOffset);
00159
00160 u_int lSet = min(u_int(sample->oneD[vlSetOffset][0] * nLightSets),
00161 nLightSets-1);
00162 for (u_int i = 0; i < virtualLights[lSet].size(); ++i) {
00163 const VirtualLight &vl = virtualLights[lSet][i];
00164
00165
00166 float d2 = DistanceSquared(p, vl.p);
00167
00168 float distScale = SmoothStep(.8 * minDist2, 1.2 * minDist2, d2);
00169
00170 Vector wi = Normalize(vl.p - p);
00171 Spectrum f = distScale * bsdf->f(wo, wi);
00172 if (f.Black()) continue;
00173 float G = AbsDot(wi, n) * AbsDot(wi, vl.n) / d2;
00174 Spectrum Llight = indirectScale * f * G * vl.Le /
00175 virtualLights[lSet].size();
00176 Llight *= scene->Transmittance(Ray(p, vl.p - p));
00177
00178 if (Llight.y() < rrThreshold) {
00179 float continueProbability = .1f;
00180 if (lux::random::floatValue() > continueProbability)
00181 continue;
00182 Llight /= continueProbability;
00183 }
00184
00185 if (!scene->IntersectP(Ray(p, vl.p - p, RAY_EPSILON,
00186 1.f - RAY_EPSILON)))
00187 L += Llight;
00188 }
00189
00190 if (specularDepth++ < maxSpecularDepth) {
00191 Vector wi;
00192
00193 Spectrum f = bsdf->Sample_f(wo, &wi,
00194 BxDFType(BSDF_REFLECTION | BSDF_SPECULAR));
00195 if (!f.Black()) {
00196
00197 RayDifferential rd(p, wi);
00198 rd.hasDifferentials = true;
00199 rd.rx.o = p + isect.dg.dpdx;
00200 rd.ry.o = p + isect.dg.dpdy;
00201
00202 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx +
00203 bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00204 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy +
00205 bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00206 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00207 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00208 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00209 rd.rx.d = wi -
00210 dwodx + 2 * Vector(Dot(wo, n) * dndx +
00211 dDNdx * n);
00212 rd.ry.d = wi -
00213 dwody + 2 * Vector(Dot(wo, n) * dndy +
00214 dDNdy * n);
00215 L += scene->Li(rd, sample) * f * AbsDot(wi, n);
00216 }
00217 f = bsdf->Sample_f(wo, &wi,
00218 BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR));
00219 if (!f.Black()) {
00220
00221 RayDifferential rd(p, wi);
00222 rd.hasDifferentials = true;
00223 rd.rx.o = p + isect.dg.dpdx;
00224 rd.ry.o = p + isect.dg.dpdy;
00225
00226 float eta = bsdf->eta;
00227 Vector w = -wo;
00228 if (Dot(wo, n) < 0) eta = 1.f / eta;
00229
00230 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx + bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00231 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy + bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00232
00233 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00234 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00235 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00236
00237 float mu = eta * Dot(w, n) - Dot(wi, n);
00238 float dmudx = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdx;
00239 float dmudy = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdy;
00240
00241 rd.rx.d = wi + eta * dwodx - Vector(mu * dndx + dmudx * n);
00242 rd.ry.d = wi + eta * dwody - Vector(mu * dndy + dmudy * n);
00243 L += scene->Li(rd, sample) * f * AbsDot(wi, n);
00244 }
00245 }
00246 --specularDepth;
00247 }
00248 else {
00249
00250 if (alpha) *alpha = 0.;
00251 for (u_int i = 0; i < scene->lights.size(); ++i)
00252 L += scene->lights[i]->Le(ray);
00253 if (alpha && !L.Black()) *alpha = 1.;
00254 return L;
00255 }
00256 return L;
00257 }
00258 SurfaceIntegrator* IGIIntegrator::CreateSurfaceIntegrator(const ParamSet ¶ms)
00259 {
00260 int nLightPaths = params.FindOneInt("nlights", 64);
00261 int nLightSets = params.FindOneInt("nsets", 4);
00262 float minDist = params.FindOneFloat("mindist", .1f);
00263 float rrThresh = params.FindOneFloat("rrthreshold", .05f);
00264 float is = params.FindOneFloat("indirectscale", 1.f);
00265 return new IGIIntegrator(nLightPaths, nLightSets, minDist, rrThresh, is);
00266 }