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 "single.h"
00025 #include "randomgen.h"
00026 #include "light.h"
00027 #include "paramset.h"
00028 #include "dynload.h"
00029
00030 using namespace lux;
00031
00032
00033 void SingleScattering::RequestSamples(Sample *sample,
00034 const Scene *scene) {
00035 tauSampleOffset = sample->Add1D(1);
00036 scatterSampleOffset = sample->Add1D(1);
00037 }
00038
00039 void SingleScattering::Transmittance(const TsPack *tspack, const Scene *scene,
00040 const Ray &ray, const Sample *sample, float *alpha, SWCSpectrum *const L) const {
00041 if (!scene->volumeRegion)
00042 return;
00043
00044 float step = stepSize;
00045 float offset = sample->oneD[tauSampleOffset][0];
00046 SWCSpectrum tau = SWCSpectrum(tspack, scene->volumeRegion->Tau(ray, step, offset));
00047 *L *= Exp(-tau);
00048 }
00049
00050 int SingleScattering::Li(const TsPack *tspack, const Scene *scene,
00051 const RayDifferential &ray, const Sample *sample,
00052 SWCSpectrum *Lv, float *alpha) const {
00053 VolumeRegion *vr = scene->volumeRegion;
00054 float t0, t1;
00055 if (!vr || !vr->IntersectP(ray, &t0, &t1)) return 0.f;
00056
00057 *Lv = 0.f;
00058
00059 int N = Ceil2Int((t1-t0) / stepSize);
00060 float step = (t1 - t0) / N;
00061 SWCSpectrum Tr(1.f);
00062 Point p = ray(t0), pPrev;
00063 Vector w = -ray.d;
00064 t0 += sample->oneD[scatterSampleOffset][0] * step;
00065 int nLights = scene->lights.size();
00066 int lightNum = min(Floor2Int(tspack->rng->floatValue() * nLights), nLights-1);
00067 Light *light = scene->lights[lightNum];
00068
00069
00070 float *samp = (float *)alloca(3 * N * sizeof(float));
00071 LatinHypercube(tspack, samp, N, 3);
00072 int sampOffset = 0;
00073 for (int i = 0; i < N; ++i, t0 += step) {
00074
00075 pPrev = p;
00076 p = ray(t0);
00077
00078 SWCSpectrum stepTau = SWCSpectrum(tspack, vr->Tau(Ray(pPrev, p - pPrev, 0, 1),
00079 .5f * stepSize, tspack->rng->floatValue()));
00080 Tr *= Exp(-stepTau);
00081
00082 if (Tr.Filter(tspack) < 1e-3f) {
00083 const float continueProb = .5f;
00084 if (tspack->rng->floatValue() > continueProb) break;
00085 Tr /= continueProb;
00086 }
00087
00088
00089 *Lv += Tr * SWCSpectrum(tspack, vr->Lve(p, w));
00090
00091 SWCSpectrum ss = SWCSpectrum(tspack, vr->sigma_s(p, w));
00092 if (!ss.Black() && scene->lights.size() > 0) {
00093
00094 float pdf;
00095 VisibilityTester vis;
00096 Vector wo;
00097 float u1 = samp[sampOffset], u2 = samp[sampOffset+1], u3 = samp[sampOffset+2];
00098 SWCSpectrum L = light->Sample_L(tspack, p, u1, u2, u3, &wo, &pdf, &vis);
00099
00100
00101 SWCSpectrum occlusion(1.f);
00102 if ((!L.Black()) && (pdf > 0.0f) && vis.TestOcclusion(tspack, scene, &occlusion)) {
00103 SWCSpectrum Ld = L * occlusion;
00104 vis.Transmittance(tspack, scene, sample, &Ld);
00105 *Lv += Tr * ss * vr->P(p, w, -wo) *
00106 Ld * float(nLights) / pdf;
00107 }
00108 }
00109 sampOffset += 3;
00110 }
00111 *Lv *= step;
00112 return light->group;
00113 }
00114
00115 VolumeIntegrator* SingleScattering::CreateVolumeIntegrator(const ParamSet ¶ms) {
00116 float stepSize = params.FindOneFloat("stepsize", 1.f);
00117 return new SingleScattering(stepSize);
00118 }
00119
00120 static DynamicLoader::RegisterVolumeIntegrator<SingleScattering> r("single");