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 "volume.h"
00026 #include "transport.h"
00027 #include "scene.h"
00028
00029 class EmissionIntegrator : public VolumeIntegrator {
00030 public:
00031
00032 EmissionIntegrator(float ss) { stepSize = ss; }
00033 void RequestSamples(Sample *sample, const Scene *scene);
00034 Spectrum Transmittance(const Scene *, const Ray &ray, const Sample *sample, float *alpha) const;
00035 Spectrum Li(const Scene *, const RayDifferential &ray, const Sample *sample, float *alpha) const;
00036 private:
00037
00038 float stepSize;
00039 int tauSampleOffset, scatterSampleOffset;
00040 };
00041
00042 void EmissionIntegrator::RequestSamples(Sample *sample,
00043 const Scene *scene) {
00044 tauSampleOffset = sample->Add1D(1);
00045 scatterSampleOffset = sample->Add1D(1);
00046 }
00047 Spectrum
00048 EmissionIntegrator::Transmittance(const Scene *scene,
00049 const Ray &ray, const Sample *sample,
00050 float *alpha) const {
00051 if (!scene->volumeRegion) return Spectrum(1.f);
00052 float step = sample ? stepSize : 4.f * stepSize;
00053 float offset =
00054 sample ? sample->oneD[tauSampleOffset][0] :
00055 RandomFloat();
00056 Spectrum tau =
00057 scene->volumeRegion->Tau(ray, step, offset);
00058 return Exp(-tau);
00059 }
00060 Spectrum EmissionIntegrator::Li(const Scene *scene,
00061 const RayDifferential &ray, const Sample *sample,
00062 float *alpha) const {
00063 VolumeRegion *vr = scene->volumeRegion;
00064 float t0, t1;
00065 if (!vr || !vr->IntersectP(ray, &t0, &t1)) return 0.f;
00066
00067 Spectrum Lv(0.);
00068
00069 int N = Ceil2Int((t1-t0) / stepSize);
00070 float step = (t1 - t0) / N;
00071 Spectrum Tr(1.f);
00072 Point p = ray(t0), pPrev;
00073 Vector w = -ray.d;
00074 if (sample)
00075 t0 += sample->oneD[scatterSampleOffset][0] * step;
00076 else
00077 t0 += RandomFloat() * step;
00078 for (int i = 0; i < N; ++i, t0 += step) {
00079
00080 pPrev = p;
00081 p = ray(t0);
00082 Spectrum stepTau = vr->Tau(Ray(pPrev, p - pPrev, 0, 1),
00083 .5f * stepSize, RandomFloat());
00084 Tr *= Exp(-stepTau);
00085
00086 if (Tr.y() < 1e-3) {
00087 const float continueProb = .5f;
00088 if (RandomFloat() > continueProb) break;
00089 Tr /= continueProb;
00090 }
00091
00092 Lv += Tr * vr->Lve(p, w);
00093 }
00094 return Lv * step;
00095 }
00096 extern "C" DLLEXPORT VolumeIntegrator *CreateVolumeIntegrator(const ParamSet ¶ms) {
00097 float stepSize = params.FindOneFloat("stepsize", 1.f);
00098 return new EmissionIntegrator(stepSize);
00099 }