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