00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_SAMPLING_H
00024 #define LUX_SAMPLING_H
00025
00026 #include "lux.h"
00027 #include "memory.h"
00028 #include "randomgen.h"
00029 #include "contribution.h"
00030 #include "film.h"
00031
00032 namespace lux
00033 {
00034
00035
00036 enum SamplingType {
00037 SAMPLING_DIRECT = 1 << 0,
00038 SAMPLING_INDIRECT = 1 << 1,
00039 SAMPLING_EYETOLIGHT = 1 << 2,
00040 SAMPLING_LIGHTTOEYE = 1 << 3,
00041 SAMPLING_ALL = (1 << 4) - 1
00042 };
00043
00044 class Sample {
00045 public:
00046
00047 Sample(SurfaceIntegrator *surf, VolumeIntegrator *vol,
00048 const Scene *scene);
00049
00050 u_int Add1D(u_int num) {
00051 n1D.push_back(num);
00052 return n1D.size()-1;
00053 }
00054 u_int Add2D(u_int num) {
00055 n2D.push_back(num);
00056 return n2D.size()-1;
00057 }
00058 u_int AddxD(vector<u_int> &structure, u_int num) {
00059 nxD.push_back(num);
00060 sxD.push_back(structure);
00061 u_int d = 0;
00062 for (u_int i = 0; i < structure.size(); ++i)
00063 d += structure[i];
00064 dxD.push_back(d);
00065 return nxD.size()-1;
00066 }
00067 void AddContribution(float x, float y, const XYZColor &c, float a, float zd = 0,
00068 int b = 0, int g = 0) const {
00069 contributions.push_back(Contribution(x, y, c, a, zd, 0.f, b, g));
00070 }
00071 void AddContribution(float x, float y, const XYZColor &c, float a, float zd,
00072 float v, int b = 0, int g = 0) const {
00073 contributions.push_back(Contribution(x, y, c, a, zd, v, b, g));
00074 }
00075 ~Sample() {
00076 if (oneD != NULL) {
00077 FreeAligned(oneD[0]);
00078 FreeAligned(oneD);
00079 }
00080 if (timexD != NULL) {
00081 FreeAligned(timexD[0]);
00082 FreeAligned(timexD);
00083 }
00084 }
00085
00086
00087
00088 Sampler *sampler;
00089 SamplingType sampling;
00090
00091
00092
00093 mutable float imageX, imageY;
00094 float lensU, lensV;
00095 float time;
00096 float wavelengths, singleWavelength;
00097
00098 mutable int stamp;
00099 vector<u_int> n1D, n2D, nxD, dxD;
00100 vector<vector<u_int> > sxD;
00101 float **oneD, **twoD, **xD;
00102 int **timexD;
00103 mutable vector<Contribution> contributions;
00104 };
00105
00106 class Sampler {
00107 public:
00108
00109 virtual ~Sampler() {}
00110 Sampler(int xstart, int xend, int ystart, int yend, int spp);
00111 virtual bool GetNextSample(Sample *sample, u_int *use_pos) = 0;
00112 virtual float *GetLazyValues(Sample *sample, u_int num, u_int pos);
00113 virtual u_int GetTotalSamplePos() = 0;
00114 int TotalSamples() const {
00115 return samplesPerPixel * (xPixelEnd - xPixelStart) * (yPixelEnd - yPixelStart);
00116 }
00117 virtual int RoundSize(int size) const = 0;
00118 void SetFilm(Film* f) { film = f; }
00119 virtual void GetBufferType(BufferType *t) { }
00120 virtual void AddSample(const Sample &sample);
00121 virtual Sampler* clone() const = 0;
00122
00123 virtual bool IsMutating() { return false; }
00124
00125 void SetContributionPool(ContributionPool *p) { contribPool = p; }
00126
00127 void Cleanup() {
00128 contribPool->End(contribBuffer);
00129 contribBuffer = NULL;
00130 }
00131
00132 void SetTsPack(TsPack *t) { tspack = t; }
00133 TsPack *tspack;
00134
00135
00136 int xPixelStart, xPixelEnd, yPixelStart, yPixelEnd;
00137 int samplesPerPixel;
00138 Film *film;
00139 ContributionPool *contribPool;
00140 ContributionBuffer *contribBuffer;
00141 };
00142
00143
00144 struct PxLoc {
00145 short x;
00146 short y;
00147 };
00148 class PixelSampler {
00149 public:
00150 PixelSampler() : renderingDone(false) {}
00151 virtual ~PixelSampler() {}
00152
00153 virtual u_int GetTotalPixels() = 0;
00154 virtual bool GetNextPixel(int &xPos, int &yPos, u_int *use_pos) = 0;
00155
00156
00157
00158 bool renderingDone;
00159 };
00160
00161 void StratifiedSample1D(const TsPack *tspack, float *samples, int nsamples, bool jitter = true);
00162 void StratifiedSample2D(const TsPack *tspack, float *samples, int nx, int ny, bool jitter = true);
00163 void Shuffle(const TsPack *tspack, float *samp, int count, int dims);
00164 void LatinHypercube(const TsPack *tspack, float *samples, int nSamples, int nDim);
00165
00166
00167 inline double RadicalInverse(int n, int base)
00168 {
00169 double val = 0.;
00170 double invBase = 1. / base, invBi = invBase;
00171 while (n > 0) {
00172
00173 int d_i = (n % base);
00174 val += d_i * invBi;
00175 n /= base;
00176 invBi *= invBase;
00177 }
00178 return val;
00179 }
00180 inline double FoldedRadicalInverse(int n, int base)
00181 {
00182 double val = 0.;
00183 double invBase = 1. / base, invBi = invBase;
00184 int modOffset = 0;
00185 while (val + base * invBi != val) {
00186
00187 int digit = ((n + modOffset) % base);
00188 val += digit * invBi;
00189 n /= base;
00190 invBi *= invBase;
00191 ++modOffset;
00192 }
00193 return val;
00194 }
00195 inline float VanDerCorput(u_int n, u_int scramble = 0)
00196 {
00197 n = (n << 16) | (n >> 16);
00198 n = ((n & 0x00ff00ff) << 8) | ((n & 0xff00ff00) >> 8);
00199 n = ((n & 0x0f0f0f0f) << 4) | ((n & 0xf0f0f0f0) >> 4);
00200 n = ((n & 0x33333333) << 2) | ((n & 0xcccccccc) >> 2);
00201 n = ((n & 0x55555555) << 1) | ((n & 0xaaaaaaaa) >> 1);
00202 n ^= scramble;
00203 return (float)n / (float)0x100000000LL;
00204 }
00205 inline float Sobol2(u_int n, u_int scramble = 0)
00206 {
00207 for (u_int v = 1u << 31; n != 0; n >>= 1, v ^= v >> 1)
00208 if (n & 0x1) scramble ^= v;
00209 return (float)scramble / (float)0x100000000LL;
00210 }
00211 inline float LarcherPillichshammer2(u_int n, u_int scramble = 0)
00212 {
00213 for (u_int v = 1u << 31; n != 0; n >>= 1, v |= v >> 1)
00214 if (n & 0x1) scramble ^= v;
00215 return (float)scramble / (float)0x100000000LL;
00216 }
00217 inline float Halton(u_int n, u_int scramble = 0)
00218 {
00219 float s = FoldedRadicalInverse(n, 2);
00220 u_int s0 = (u_int) (s * (float)0x100000000LL);
00221 s0 ^= scramble;
00222 return (float)s0 / (float)0x100000000LL;
00223 }
00224 inline float Halton2(u_int n, u_int scramble = 0)
00225 {
00226 float s = FoldedRadicalInverse(n, 3);
00227 u_int s0 = (u_int) (s * (float)0x100000000LL);
00228 s0 ^= scramble;
00229 return (float)s0 / (float)0x100000000LL;
00230 }
00231 inline void SampleHalton(u_int n, u_int scramble[2], float sample[2])
00232 {
00233 sample[0] = FoldedRadicalInverse(n, 2);
00234 sample[1] = FoldedRadicalInverse(n, 3);
00235 u_int s0 = (u_int) (sample[0] * (float)0x100000000LL);
00236 u_int s1 = (u_int) (sample[1] * (float)0x100000000LL);
00237 s0 ^= scramble[0];
00238 s1 ^= scramble[1];
00239 sample[0] = (float)s0 / (float)0x100000000LL;
00240 sample[1] = (float)s1 / (float)0x100000000LL;
00241 }
00242 inline void Sample02(u_int n, u_int scramble[2], float sample[2])
00243 {
00244 sample[0] = VanDerCorput(n, scramble[0]);
00245 sample[1] = Sobol2(n, scramble[1]);
00246 }
00247
00248 inline void LDShuffleScrambled1D(const TsPack *tspack, int nSamples,
00249 int nPixel, float *samples) {
00250 u_int scramble = tspack->rng->uintValue();
00251 for (int i = 0; i < nSamples * nPixel; ++i)
00252 samples[i] = VanDerCorput(i, scramble);
00253 for (int i = 0; i < nPixel; ++i)
00254 Shuffle(tspack, samples + i * nSamples, nSamples, 1);
00255 Shuffle(tspack, samples, nPixel, nSamples);
00256 }
00257 inline void LDShuffleScrambled2D(const TsPack *tspack, int nSamples,
00258 int nPixel, float *samples) {
00259 u_int scramble[2] = { tspack->rng->uintValue(), tspack->rng->uintValue() };
00260 for (int i = 0; i < nSamples * nPixel; ++i)
00261 Sample02(i, scramble, &samples[2*i]);
00262 for (int i = 0; i < nPixel; ++i)
00263 Shuffle(tspack, samples + 2 * i * nSamples, nSamples, 2);
00264 Shuffle(tspack, samples, nPixel, 2 * nSamples);
00265 }
00266 inline void HaltonShuffleScrambled1D(const TsPack *tspack, int nSamples,
00267 int nPixel, float *samples) {
00268 u_int scramble = tspack->rng->uintValue();
00269 for (int i = 0; i < nSamples * nPixel; ++i)
00270 samples[i] = Halton(i, scramble);
00271 for (int i = 0; i < nPixel; ++i)
00272 Shuffle(tspack, samples + i * nSamples, nSamples, 1);
00273 Shuffle(tspack, samples, nPixel, nSamples);
00274 }
00275 inline void HaltonShuffleScrambled2D(const TsPack *tspack, int nSamples,
00276 int nPixel, float *samples) {
00277 u_int scramble[2] = { tspack->rng->uintValue(), tspack->rng->uintValue() };
00278 for (int i = 0; i < nSamples * nPixel; ++i)
00279 SampleHalton(i, scramble, &samples[2*i]);
00280 for (int i = 0; i < nPixel; ++i)
00281 Shuffle(tspack, samples + 2 * i * nSamples, nSamples, 2);
00282 Shuffle(tspack, samples, nPixel, 2 * nSamples);
00283 }
00284
00285 }
00286
00287 #endif // LUX_SAMPLING_H