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
00026 #include "stdafx.h"
00027 #include "light.h"
00028 #include "scene.h"
00029 #include "montecarlo.h"
00030 #include "paramset.h"
00031 #include "sh.h"
00032
00033
00034 Light::~Light() {
00035 }
00036
00037
00038 bool VisibilityTester::Unoccluded(const Scene *scene) const {
00039 return !scene->IntersectP(r);
00040 }
00041
00042
00043 Spectrum VisibilityTester::Transmittance(const Scene *scene,
00044 const Renderer *renderer, const Sample *sample,
00045 RNG &rng, MemoryArena &arena) const {
00046 return renderer->Transmittance(scene, RayDifferential(r), sample,
00047 rng, arena);
00048 }
00049
00050
00051 Spectrum Light::Le(const RayDifferential &) const {
00052 return Spectrum(0.);
00053 }
00054
00055
00056 LightSampleOffsets::LightSampleOffsets(int count, Sample *sample) {
00057 nSamples = count;
00058 componentOffset = sample->Add1D(nSamples);
00059 posOffset = sample->Add2D(nSamples);
00060 }
00061
00062
00063 LightSample::LightSample(const Sample *sample,
00064 const LightSampleOffsets &offsets, uint32_t n) {
00065 Assert(n < sample->n2D[offsets.posOffset]);
00066 Assert(n < sample->n1D[offsets.componentOffset]);
00067 uPos[0] = sample->twoD[offsets.posOffset][2*n];
00068 uPos[1] = sample->twoD[offsets.posOffset][2*n+1];
00069 uComponent = sample->oneD[offsets.componentOffset][n];
00070 Assert(uPos[0] >= 0.f && uPos[0] < 1.f);
00071 Assert(uPos[1] >= 0.f && uPos[1] < 1.f);
00072 Assert(uComponent >= 0.f && uComponent < 1.f);
00073 }
00074
00075
00076 void Light::SHProject(const Point &p, float pEpsilon, int lmax,
00077 const Scene *scene, bool computeLightVisibility, float time,
00078 RNG &rng, Spectrum *coeffs) const {
00079 for (int i = 0; i < SHTerms(lmax); ++i)
00080 coeffs[i] = 0.f;
00081 uint32_t ns = RoundUpPow2(nSamples);
00082 uint32_t scramble1D = rng.RandomUInt();
00083 uint32_t scramble2D[2] = { rng.RandomUInt(), rng.RandomUInt() };
00084 float *Ylm = ALLOCA(float, SHTerms(lmax));
00085 for (uint32_t i = 0; i < ns; ++i) {
00086
00087 float u[2], pdf;
00088 Sample02(i, scramble2D, u);
00089 LightSample lightSample(u[0], u[1], VanDerCorput(i, scramble1D));
00090 Vector wi;
00091 VisibilityTester vis;
00092 Spectrum Li = Sample_L(p, pEpsilon, lightSample, time, &wi, &pdf, &vis);
00093 if (!Li.IsBlack() && pdf > 0.f &&
00094 (!computeLightVisibility || vis.Unoccluded(scene))) {
00095
00096 SHEvaluate(wi, lmax, Ylm);
00097 for (int j = 0; j < SHTerms(lmax); ++j)
00098 coeffs[j] += Li * Ylm[j] / (pdf * ns);
00099 }
00100 }
00101 }
00102
00103
00104
00105
00106 ShapeSet::ShapeSet(const Reference<Shape> &s) {
00107 vector<Reference<Shape> > todo;
00108 todo.push_back(s);
00109 while (todo.size()) {
00110 Reference<Shape> sh = todo.back();
00111 todo.pop_back();
00112 if (sh->CanIntersect())
00113 shapes.push_back(sh);
00114 else
00115 sh->Refine(todo);
00116 }
00117 if (shapes.size() > 64)
00118 Warning("Area light geometry turned into %d shapes; "
00119 "may be very inefficient.", (int)shapes.size());
00120
00121
00122 sumArea = 0.f;
00123 for (uint32_t i = 0; i < shapes.size(); ++i) {
00124 float a = shapes[i]->Area();
00125 areas.push_back(a);
00126 sumArea += a;
00127 }
00128 areaDistribution = new Distribution1D(&areas[0], areas.size());
00129 }
00130
00131
00132 ShapeSet::~ShapeSet() {
00133 delete areaDistribution;
00134 }
00135
00136
00137 Point ShapeSet::Sample(const Point &p, const LightSample &ls,
00138 Normal *Ns) const {
00139 int sn = areaDistribution->SampleDiscrete(ls.uComponent, NULL);
00140 Point pt = shapes[sn]->Sample(p, ls.uPos[0], ls.uPos[1], Ns);
00141
00142 Ray r(p, pt-p, 1e-3f, INFINITY);
00143 float rayEps, thit = 1.f;
00144 bool anyHit = false;
00145 DifferentialGeometry dg;
00146 for (uint32_t i = 0; i < shapes.size(); ++i)
00147 anyHit |= shapes[i]->Intersect(r, &thit, &rayEps, &dg);
00148 if (anyHit) *Ns = dg.nn;
00149 return r(thit);
00150 }
00151
00152
00153 Point ShapeSet::Sample(const LightSample &ls, Normal *Ns) const {
00154 int sn = areaDistribution->SampleDiscrete(ls.uComponent, NULL);
00155 return shapes[sn]->Sample(ls.uPos[0], ls.uPos[1], Ns);
00156 }
00157
00158
00159 float ShapeSet::Pdf(const Point &p, const Vector &wi) const {
00160 float pdf = 0.f;
00161 for (uint32_t i = 0; i < shapes.size(); ++i)
00162 pdf += areas[i] * shapes[i]->Pdf(p, wi);
00163 return pdf / sumArea;
00164 }
00165
00166
00167 float ShapeSet::Pdf(const Point &p) const {
00168 float pdf = 0.f;
00169 for (uint32_t i = 0; i < shapes.size(); ++i)
00170 pdf += areas[i] * shapes[i]->Pdf(p);
00171 return pdf / sumArea;
00172 }
00173
00174