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 "transport.h"
00025 #include "scene.h"
00026 #include "bxdf.h"
00027 #include "light.h"
00028 #include "mc.h"
00029
00030 namespace lux
00031 {
00032
00033
00034 Integrator::~Integrator() {
00035 }
00036
00037 static SWCSpectrum EstimateDirect(const Scene *scene, const Light *light,
00038 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00039 float ls1, float ls2, float ls3, float bs1, float bs2, float bcs);
00040
00041 SWCSpectrum UniformSampleAllLights(const Scene *scene,
00042 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00043 const Sample *sample,
00044 int *lightSampleOffset, int *bsdfSampleOffset, int *bsdfComponentOffset)
00045 {
00046 SWCSpectrum L(0.);
00047 for (u_int i = 0; i < scene->lights.size(); ++i) {
00048 Light *light = scene->lights[i];
00049 int nSamples = (sample && lightSampleOffset) ?
00050 sample->n2D[lightSampleOffset[i]] : 1;
00051
00052 SWCSpectrum Ld(0.);
00053 for (int j = 0; j < nSamples; ++j) {
00054 float ls1, ls2, ls3, bs1, bs2, bcs;
00055 if (sample && lightSampleOffset) {
00056 ls1 = sample->twoD[lightSampleOffset[i]][2 * j];
00057 ls2 = sample->twoD[lightSampleOffset[i]][2 * j + 1];
00058 } else {
00059 ls1 = lux::random::floatValue();
00060 ls2 = lux::random::floatValue();
00061 }
00062 ls3 = lux::random::floatValue();
00063 if (sample && bsdfSampleOffset) {
00064 bs1 = sample->twoD[bsdfSampleOffset[i]][2 * j];
00065 bs2 = sample->twoD[bsdfSampleOffset[i]][2 * j + 1];
00066 } else {
00067 bs1 = lux::random::floatValue();
00068 bs2 = lux::random::floatValue();
00069 }
00070 if (sample && bsdfComponentOffset)
00071 bcs = sample->twoD[bsdfComponentOffset[i]][j];
00072 else
00073 bcs = lux::random::floatValue();
00074 Ld += EstimateDirect(scene, light, p, n, wo, bsdf,
00075 ls1, ls2, ls3, bs1, bs2, bcs);
00076 }
00077 L += Ld / nSamples;
00078 }
00079 return L;
00080 }
00081 SWCSpectrum UniformSampleAllLights(const Scene *scene,
00082 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00083 const Sample *sample,
00084 float *lightSample, float *lightNum,
00085 float *bsdfSample, float *bsdfComponent)
00086 {
00087 float ls1, ls2, ls3, bs1, bs2, bcs;
00088 if (lightNum)
00089 ls3 = *lightNum;
00090 else
00091 ls3 = lux::random::floatValue();
00092 if (lightSample) {
00093 ls1 = lightSample[0];
00094 ls2 = lightSample[1];
00095 } else {
00096 ls1 = lux::random::floatValue();
00097 ls2 = lux::random::floatValue();
00098 }
00099 if (bsdfSample) {
00100 bs1 = bsdfSample[0];
00101 bs2 = bsdfSample[1];
00102 } else {
00103 bs1 = lux::random::floatValue();
00104 bs2 = lux::random::floatValue();
00105 }
00106 if (bsdfComponent)
00107 bcs = *bsdfComponent;
00108 else
00109 bcs = lux::random::floatValue();
00110 SWCSpectrum L(0.f);
00111 for (u_int i = 0; i < scene->lights.size(); ++i) {
00112 L += EstimateDirect(scene, scene->lights[i], p, n, wo, bsdf,
00113 ls1, ls2, ls3, bs1, bs2, bcs);
00114 }
00115 return L;
00116 }
00117 SWCSpectrum UniformSampleOneLight(const Scene *scene,
00118 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00119 const Sample *sample,
00120 float *lightSample, float *lightNum,
00121 float *bsdfSample, float *bsdfComponent)
00122 {
00123
00124 int nLights = int(scene->lights.size());
00125
00126 if (nLights == 0)
00127 return SWCSpectrum(0.f);
00128 int lightNumber;
00129 float ls1, ls2, ls3, bs1, bs2, bcs;
00130 if (lightNum)
00131 ls3 = *lightNum * nLights;
00132 else
00133 ls3 = lux::random::floatValue() * nLights;
00134 lightNumber = min(Floor2Int(ls3), nLights - 1);
00135 ls3 -= lightNumber;
00136 Light *light = scene->lights[lightNumber];
00137 if (lightSample) {
00138 ls1 = lightSample[0];
00139 ls2 = lightSample[1];
00140 } else {
00141 ls1 = lux::random::floatValue();
00142 ls2 = lux::random::floatValue();
00143 }
00144 if (bsdfSample) {
00145 bs1 = bsdfSample[0];
00146 bs2 = bsdfSample[1];
00147 } else {
00148 bs1 = lux::random::floatValue();
00149 bs2 = lux::random::floatValue();
00150 }
00151 if (bsdfComponent)
00152 bcs = *bsdfComponent;
00153 else
00154 bcs = lux::random::floatValue();
00155 return (float)nLights *
00156 EstimateDirect(scene, light, p, n, wo, bsdf,
00157 ls1, ls2, ls3, bs1, bs2, bcs);
00158 }
00159 SWCSpectrum WeightedSampleOneLight(const Scene *scene,
00160 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00161 const Sample *sample,
00162 int lightSampleOffset, int lightNumOffset,
00163 int bsdfSampleOffset, int bsdfComponentOffset,
00164 float *&avgY, float *&avgYsample, float *&cdf, float &overallAvgY)
00165 {
00166 int nLights = int(scene->lights.size());
00167
00168 if (nLights == 0)
00169 return SWCSpectrum(0.f);
00170
00171 if (!avgY) {
00172 avgY = new float[nLights];
00173 avgYsample = new float[nLights];
00174 cdf = new float[nLights+1];
00175 for (int i = 0; i < nLights; ++i)
00176 avgY[i] = avgYsample[i] = 0.;
00177 }
00178 float ls1, ls2, ls3, bs1, bs2, bcs, lightNum;
00179 if (sample && lightSampleOffset!= -1) {
00180 ls1 = sample->twoD[lightSampleOffset][0];
00181 ls2 = sample->twoD[lightSampleOffset][1];
00182 } else {
00183 ls1 = lux::random::floatValue();
00184 ls2 = lux::random::floatValue();
00185 }
00186 if (sample && lightNumOffset != -1)
00187 lightNum = sample->oneD[lightNumOffset][0];
00188 else
00189 lightNum = lux::random::floatValue();
00190 if (sample && bsdfSampleOffset != -1) {
00191 bs1 = sample->twoD[bsdfSampleOffset][0];
00192 bs2 = sample->twoD[bsdfSampleOffset][1];
00193 } else {
00194 bs1 = lux::random::floatValue();
00195 bs2 = lux::random::floatValue();
00196 }
00197 if (sample && bsdfComponentOffset != -1)
00198 bcs = sample->twoD[bsdfComponentOffset][0];
00199 else
00200 bcs = lux::random::floatValue();
00201 SWCSpectrum L(0.);
00202 if (overallAvgY == 0.) {
00203 int lightNumber = min(Float2Int(nLights * lightNum), nLights-1);
00204 ls3 = nLights * lightNum - lightNumber;
00205 Light *light = scene->lights[lightNumber];
00206
00207 L = EstimateDirect(scene, light, p, n, wo, bsdf,
00208 ls1, ls2, ls3, bs1, bs2, bcs);
00209 float luminance = L.y();
00210 overallAvgY = luminance;
00211 for (int i = 0; i < nLights; ++i)
00212 avgY[i] = luminance;
00213 }
00214 else {
00215
00216 float c, lightSampleWeight;
00217 for (int i = 0; i < nLights; ++i)
00218 avgYsample[i] = max(avgY[i], .1f * overallAvgY);
00219 ComputeStep1dCDF(avgYsample, nLights, &c, cdf);
00220 float t = SampleStep1d(avgYsample, cdf, c, nLights,
00221 lightNum, &lightSampleWeight);
00222 int lightNumber = min(Float2Int(nLights * t), nLights-1);
00223 ls3 = nLights * t - lightNumber;
00224 Light *light = scene->lights[lightNumber];
00225 L = EstimateDirect(scene, light, p, n, wo, bsdf,
00226 ls1, ls2, ls3, bs1, bs2, bcs);
00227
00228 float luminance = L.y();
00229 avgY[lightNumber] = Lerp(.99f, luminance, avgY[lightNumber]);
00230 overallAvgY = Lerp(.999f, luminance, overallAvgY);
00231 L /= lightSampleWeight;
00232 }
00233 return L;
00234 }
00235 static SWCSpectrum EstimateDirect(const Scene *scene, const Light *light,
00236 const Point &p, const Normal &n, const Vector &wo, BSDF *bsdf,
00237 float ls1, float ls2, float ls3, float bs1, float bs2, float bcs)
00238 {
00239 SWCSpectrum Ld(0.);
00240
00241 Vector wi;
00242 float lightPdf, bsdfPdf;
00243 VisibilityTester visibility;
00244 SWCSpectrum Li = light->Sample_L(p, n,
00245 ls1, ls2, ls3, &wi, &lightPdf, &visibility);
00246 if (lightPdf > 0. && !Li.Black()) {
00247 SWCSpectrum f = bsdf->f(wo, wi);
00248 SWCSpectrum fO;
00249 if (!f.Black() && visibility.TestOcclusion(scene, &fO)) {
00250
00251 Li *= visibility.Transmittance(scene);
00252 Li *= fO;
00253 if (light->IsDeltaLight())
00254 Ld += f * Li * AbsDot(wi, n) / lightPdf;
00255 else {
00256 bsdfPdf = bsdf->Pdf(wo, wi);
00257 float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);
00258 Ld += f * Li * AbsDot(wi, n) * weight / lightPdf;
00259 }
00260 }
00261 }
00262
00263
00264 if (!light->IsDeltaLight()) {
00265 BxDFType flags = BxDFType(BSDF_ALL & ~BSDF_SPECULAR);
00266 SWCSpectrum f = bsdf->Sample_f(wo, &wi,
00267 bs1, bs2, bcs, &bsdfPdf, flags);
00268 if (!f.Black() && bsdfPdf > 0.) {
00269 lightPdf = light->Pdf(p, n, wi);
00270 if (lightPdf > 0.) {
00271
00272 float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);
00273 Intersection lightIsect;
00274 SWCSpectrum Li(0.f);
00275 RayDifferential ray(p, wi);
00276 if (scene->Intersect(ray, &lightIsect)) {
00277 if (lightIsect.primitive->GetAreaLight() == light)
00278 Li = lightIsect.Le(-wi);
00279 }
00280 else
00281 Li = light->Le(ray);
00282 if (!Li.Black()) {
00283 Li *= scene->Transmittance(ray);
00284 Ld += f * Li * AbsDot(wi, n) * weight / bsdfPdf;
00285 }
00286 }
00287 }
00288 }
00289
00290 return Ld;
00291 }
00292
00293 }
00294