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 "transport.h"
00026 #include "scene.h"
00027
00028 Integrator::~Integrator() {
00029 }
00030
00031 COREDLL Spectrum UniformSampleAllLights(const Scene *scene,
00032 const Point &p, const Normal &n, const Vector &wo,
00033 BSDF *bsdf, const Sample *sample,
00034 int *lightSampleOffset, int *bsdfSampleOffset,
00035 int *bsdfComponentOffset) {
00036 Spectrum L(0.);
00037 for (u_int i = 0; i < scene->lights.size(); ++i) {
00038 Light *light = scene->lights[i];
00039 int nSamples = (sample && lightSampleOffset) ?
00040 sample->n2D[lightSampleOffset[i]] : 1;
00041
00042 Spectrum Ld(0.);
00043 for (int j = 0; j < nSamples; ++j)
00044 Ld += EstimateDirect(scene, light, p, n, wo, bsdf,
00045 sample, lightSampleOffset[i], bsdfSampleOffset[i],
00046 bsdfComponentOffset[i], j);
00047 L += Ld / nSamples;
00048 }
00049 return L;
00050 }
00051 COREDLL Spectrum UniformSampleOneLight(const Scene *scene,
00052 const Point &p, const Normal &n,
00053 const Vector &wo, BSDF *bsdf, const Sample *sample,
00054 int lightSampleOffset, int lightNumOffset,
00055 int bsdfSampleOffset, int bsdfComponentOffset) {
00056
00057 int nLights = int(scene->lights.size());
00058 int lightNum;
00059 if (lightNumOffset != -1)
00060 lightNum = Floor2Int(sample->oneD[lightNumOffset][0] *
00061 nLights);
00062 else
00063 lightNum = Floor2Int(RandomFloat() * nLights);
00064 lightNum = min(lightNum, nLights-1);
00065 Light *light = scene->lights[lightNum];
00066 return (float)nLights *
00067 EstimateDirect(scene, light, p, n, wo, bsdf, sample,
00068 lightSampleOffset, bsdfSampleOffset,
00069 bsdfComponentOffset, 0);
00070 }
00071 COREDLL Spectrum WeightedSampleOneLight(const Scene *scene,
00072 const Point &p, const Normal &n,
00073 const Vector &wo, BSDF *bsdf,
00074 const Sample *sample, int lightSampleOffset,
00075 int lightNumOffset, int bsdfSampleOffset,
00076 int bsdfComponentOffset, float *&avgY,
00077 float *&avgYsample, float *&cdf,
00078 float &overallAvgY) {
00079 int nLights = int(scene->lights.size());
00080
00081 if (!avgY) {
00082 avgY = new float[nLights];
00083 avgYsample = new float[nLights];
00084 cdf = new float[nLights+1];
00085 for (int i = 0; i < nLights; ++i)
00086 avgY[i] = avgYsample[i] = 0.;
00087 }
00088 Spectrum L(0.);
00089 if (overallAvgY == 0.) {
00090
00091 L = UniformSampleOneLight(scene, p, n,
00092 wo, bsdf, sample, lightSampleOffset,
00093 lightNumOffset, bsdfSampleOffset,
00094 bsdfComponentOffset);
00095 float luminance = L.y();
00096 overallAvgY = luminance;
00097 for (int i = 0; i < nLights; ++i)
00098 avgY[i] = luminance;
00099 }
00100 else {
00101
00102 float c, lightSampleWeight;
00103 for (int i = 0; i < nLights; ++i)
00104 avgYsample[i] = max(avgY[i], .1f * overallAvgY);
00105 ComputeStep1dCDF(avgYsample, nLights, &c, cdf);
00106 float t = SampleStep1d(avgYsample, cdf, c, nLights,
00107 sample->oneD[lightNumOffset][0], &lightSampleWeight);
00108 int lightNum = min(Float2Int(nLights * t), nLights-1);
00109 Light *light = scene->lights[lightNum];
00110 L = EstimateDirect(scene, light, p, n, wo, bsdf,
00111 sample, lightSampleOffset, bsdfSampleOffset,
00112 bsdfComponentOffset, 0);
00113
00114 float luminance = L.y();
00115 avgY[lightNum] =
00116 ExponentialAverage(avgY[lightNum], luminance, .99f);
00117 overallAvgY =
00118 ExponentialAverage(overallAvgY, luminance, .999f);
00119 L /= lightSampleWeight;
00120 }
00121 return L;
00122 }
00123 Spectrum EstimateDirect(const Scene *scene,
00124 const Light *light, const Point &p,
00125 const Normal &n, const Vector &wo,
00126 BSDF *bsdf, const Sample *sample, int lightSamp,
00127 int bsdfSamp, int bsdfComponent, u_int sampleNum) {
00128 Spectrum Ld(0.);
00129
00130 float ls1, ls2, bs1, bs2, bcs;
00131 if (lightSamp != -1 && bsdfSamp != -1 &&
00132 sampleNum < sample->n2D[lightSamp] &&
00133 sampleNum < sample->n2D[bsdfSamp]) {
00134 ls1 = sample->twoD[lightSamp][2*sampleNum];
00135 ls2 = sample->twoD[lightSamp][2*sampleNum+1];
00136 bs1 = sample->twoD[bsdfSamp][2*sampleNum];
00137 bs2 = sample->twoD[bsdfSamp][2*sampleNum+1];
00138 bcs = sample->oneD[bsdfComponent][sampleNum];
00139 }
00140 else {
00141 ls1 = RandomFloat();
00142 ls2 = RandomFloat();
00143 bs1 = RandomFloat();
00144 bs2 = RandomFloat();
00145 bcs = RandomFloat();
00146 }
00147
00148 Vector wi;
00149 float lightPdf, bsdfPdf;
00150 VisibilityTester visibility;
00151 Spectrum Li = light->Sample_L(p, n,
00152 ls1, ls2, &wi, &lightPdf, &visibility);
00153 if (lightPdf > 0. && !Li.Black()) {
00154 Spectrum f = bsdf->f(wo, wi);
00155 if (!f.Black() && visibility.Unoccluded(scene)) {
00156
00157 Li *= visibility.Transmittance(scene);
00158 if (light->IsDeltaLight())
00159 Ld += f * Li * AbsDot(wi, n) / lightPdf;
00160 else {
00161 bsdfPdf = bsdf->Pdf(wo, wi);
00162 float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);
00163 Ld += f * Li * AbsDot(wi, n) * weight / lightPdf;
00164 }
00165 }
00166 }
00167
00168 if (!light->IsDeltaLight()) {
00169 BxDFType flags = BxDFType(BSDF_ALL & ~BSDF_SPECULAR);
00170 Spectrum f = bsdf->Sample_f(wo, &wi,
00171 bs1, bs2, bcs, &bsdfPdf, flags);
00172 if (!f.Black() && bsdfPdf > 0.) {
00173 lightPdf = light->Pdf(p, n, wi);
00174 if (lightPdf > 0.) {
00175
00176 float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);
00177 Intersection lightIsect;
00178 Spectrum Li(0.f);
00179 RayDifferential ray(p, wi);
00180 if (scene->Intersect(ray, &lightIsect)) {
00181 if (lightIsect.primitive->GetAreaLight() == light)
00182 Li = lightIsect.Le(-wi);
00183 }
00184 else
00185 Li = light->Le(ray);
00186 if (!Li.Black()) {
00187 Li *= scene->Transmittance(ray);
00188 Ld += f * Li * AbsDot(wi, n) * weight / bsdfPdf;
00189 }
00190 }
00191 }
00192 }
00193 return Ld;
00194 }