1.1 --- a/samplers/erpt.cpp Thu Oct 15 00:38:46 2009 +0200
1.2 +++ b/samplers/erpt.cpp Mon Mar 22 21:55:10 2010 +0100
1.3 @@ -52,7 +52,7 @@
1.4 // mutate a value in the range [min-max]
1.5 static float mutateScaled(const float x, const float randomValue, const float mini, const float maxi, const float range)
1.6 {
1.7 - float dx = range * exp(-log(2.f * range) * fabsf(2.f * randomValue - 1.f));
1.8 + float dx = range * expf(-logf(2.f * range) * fabsf(2.f * randomValue - 1.f));
1.9 if (randomValue < 0.5f) {
1.10 float x1 = x + dx;
1.11 return (x1 > maxi) ? x1 - maxi + mini : x1;
1.12 @@ -63,15 +63,15 @@
1.13 }
1.14
1.15 // Metropolis method definitions
1.16 -ERPTSampler::ERPTSampler(int totMutations, float microProb, float rng,
1.17 +ERPTSampler::ERPTSampler(u_int totMutations, float rng,
1.18 Sampler *sampler) :
1.19 Sampler(sampler->xPixelStart, sampler->xPixelEnd,
1.20 sampler->yPixelStart, sampler->yPixelEnd, sampler->samplesPerPixel),
1.21 normalSamples(0), totalSamples(0), totalTimes(0), totalMutations(totMutations),
1.22 - pMicro(microProb), range(rng), baseSampler(sampler),
1.23 + range(rng), baseSampler(sampler),
1.24 baseImage(NULL), sampleImage(NULL), currentImage(NULL),
1.25 baseTimeImage(NULL), timeImage(NULL), currentTimeImage(NULL), offset(NULL),
1.26 - numChains(0), chain(0), mutation(-1), stamp(0), numMicro(-1), posMicro(-1),
1.27 + numChains(0), chain(0), mutation(~0U), stamp(0),
1.28 baseLY(0.f), quantum(0.f), weight(0.f), LY(0.f), alpha(0.f),
1.29 totalLY(0.), sampleCount(0.)
1.30 {
1.31 @@ -104,7 +104,7 @@
1.32 for (i = 0; i < sample->n2D.size(); ++i)
1.33 sampler->normalSamples += 2 * sample->n2D[i];
1.34 sampler->totalSamples = sampler->normalSamples;
1.35 - sampler->offset = new int[sample->nxD.size()];
1.36 + sampler->offset = new u_int[sample->nxD.size()];
1.37 sampler->totalTimes = 0;
1.38 for (i = 0; i < sample->nxD.size(); ++i) {
1.39 sampler->offset[i] = sampler->totalSamples;
1.40 @@ -117,7 +117,7 @@
1.41 sampler->baseTimeImage = AllocAligned<int>(sampler->totalTimes);
1.42 sampler->baseSampler->SetTsPack(sampler->tspack);
1.43 sampler->baseSampler->SetFilm(sampler->film);
1.44 - sampler->mutation = -1;
1.45 + sampler->mutation = ~0U;
1.46
1.47 // Fetch first contribution buffer from pool
1.48 sampler->contribBuffer = sampler->film->scene->contribPool->Next(NULL);
1.49 @@ -131,7 +131,7 @@
1.50 initERPT(this, sample);
1.51 }
1.52
1.53 - if (mutation == -1) {
1.54 + if (mutation == ~0U) {
1.55 // Dade - we are at a valid checkpoint where we can stop the
1.56 // rendering. Check if we have enough samples per pixel in the film.
1.57 if (film->enoughSamplePerPixel)
1.58 @@ -139,18 +139,17 @@
1.59
1.60 const bool ret = baseSampler->GetNextSample(sample, use_pos);
1.61 sample->sampler = this;
1.62 - for (int i = 0; i < totalTimes; ++i)
1.63 + for (u_int i = 0; i < totalTimes; ++i)
1.64 sample->timexD[0][i] = -1;
1.65 sample->stamp = 0;
1.66 currentImage = baseImage;
1.67 currentTimeImage = baseTimeImage;
1.68 stamp = 0;
1.69 - numMicro = -1;
1.70 return ret;
1.71 } else {
1.72 if (mutation == 0) {
1.73 // *** new chain ***
1.74 - for (int i = 0; i < totalTimes; ++i)
1.75 + for (u_int i = 0; i < totalTimes; ++i)
1.76 sample->timexD[0][i] = baseTimeImage[i];
1.77 sample->stamp = 0;
1.78 currentImage = baseImage;
1.79 @@ -159,47 +158,31 @@
1.80 }
1.81 // *** small mutation ***
1.82 // mutate current sample
1.83 - float mutationSelector = tspack->rng->floatValue();
1.84 - if (mutationSelector < pMicro)
1.85 - numMicro = min<int>(sample->nxD.size(), Float2Int(mutationSelector / pMicro * (sample->nxD.size() + 1)));
1.86 - else
1.87 - numMicro = -1;
1.88 - if (numMicro > 0) {
1.89 - u_int maxPos = 0;
1.90 - for(; maxPos < sample->nxD[numMicro - 1]; ++maxPos)
1.91 - if (sample->timexD[numMicro - 1][maxPos] < sample->stamp)
1.92 - break;
1.93 - posMicro = min<int>(sample->nxD[numMicro - 1] - 1, Float2Int(tspack->rng->floatValue() * maxPos));
1.94 - } else {
1.95 - posMicro = -1;
1.96 - sample->imageX = mutateScaled(currentImage[0], tspack->rng->floatValue(), xPixelStart, xPixelEnd, range);
1.97 - sample->imageY = mutateScaled(currentImage[1], tspack->rng->floatValue(), yPixelStart, yPixelEnd, range);
1.98 - sample->lensU = mutate(currentImage[2], tspack->rng->floatValue());
1.99 - sample->lensV = mutate(currentImage[3], tspack->rng->floatValue());
1.100 - sample->time = mutate(currentImage[4], tspack->rng->floatValue());
1.101 - sample->wavelengths = mutate(currentImage[5], tspack->rng->floatValue());
1.102 - for (int i = SAMPLE_FLOATS; i < normalSamples; ++i)
1.103 + sample->imageX = mutateScaled(currentImage[0], tspack->rng->floatValue(), xPixelStart, xPixelEnd, range);
1.104 + sample->imageY = mutateScaled(currentImage[1], tspack->rng->floatValue(), yPixelStart, yPixelEnd, range);
1.105 + sample->lensU = mutate(currentImage[2], tspack->rng->floatValue());
1.106 + sample->lensV = mutate(currentImage[3], tspack->rng->floatValue());
1.107 + sample->time = mutate(currentImage[4], tspack->rng->floatValue());
1.108 + sample->wavelengths = mutate(currentImage[5], tspack->rng->floatValue());
1.109 + for (u_int i = SAMPLE_FLOATS; i < normalSamples; ++i)
1.110 sample->oneD[0][i - SAMPLE_FLOATS] = mutate(currentImage[i], tspack->rng->floatValue());
1.111 - }
1.112 ++(sample->stamp);
1.113 }
1.114
1.115 - return true;
1.116 + return true;
1.117 }
1.118
1.119 float *ERPTSampler::GetLazyValues(Sample *sample, u_int num, u_int pos)
1.120 {
1.121 const u_int size = sample->dxD[num];
1.122 float *data = sample->xD[num] + pos * size;
1.123 - int stampLimit = sample->stamp;
1.124 - if (numMicro >= 0 && num != u_int(numMicro - 1) && pos != u_int(posMicro))
1.125 - --stampLimit;
1.126 + const int stampLimit = sample->stamp;
1.127 if (sample->timexD[num][pos] != stampLimit) {
1.128 if (sample->timexD[num][pos] == -1) {
1.129 baseSampler->GetLazyValues(sample, num, pos);
1.130 sample->timexD[num][pos] = 0;
1.131 } else {
1.132 - int start = offset[num] + pos * size;
1.133 + const u_int start = offset[num] + pos * size;
1.134 float *image = currentImage + start;
1.135 for (u_int i = 0; i < size; ++i)
1.136 data[i] = image[i];
1.137 @@ -219,7 +202,7 @@
1.138 float newLY = 0.0f;
1.139 for(u_int i = 0; i < newContributions.size(); ++i)
1.140 newLY += newContributions[i].color.Y();
1.141 - if (mutation <= 0) {
1.142 + if (mutation == 0U || mutation == ~0U) {
1.143 if (weight > 0.f) {
1.144 // Add accumulated contribution of previous reference sample
1.145 weight *= quantum / LY;
1.146 @@ -234,7 +217,7 @@
1.147 }
1.148 weight = 0.f;
1.149 }
1.150 - if (mutation == -1) {
1.151 + if (mutation == ~0U) {
1.152 contribBuffer->AddSampleCount(1.f);
1.153 ++sampleCount;
1.154 if (!(newLY > 0.f)) {
1.155 @@ -242,10 +225,10 @@
1.156 return;
1.157 }
1.158 totalLY += newLY;
1.159 - const float meanIntensity = totalLY > 0.f ? totalLY / sampleCount : 1.f;
1.160 + const float meanIntensity = totalLY > 0. ? static_cast<float>(totalLY / sampleCount) : 1.f;
1.161 // calculate the number of chains on a new seed
1.162 quantum = newLY / meanIntensity;
1.163 - numChains = max(1, Floor2Int(quantum + .5f));
1.164 + numChains = max(1U, Floor2UInt(quantum + .5f));
1.165 if (numChains > 100) {
1.166 printf("%d chains -> %d\n", numChains, totalMutations);
1.167 numChains = totalMutations;
1.168 @@ -259,9 +242,9 @@
1.169 baseImage[3] = sample.lensV;
1.170 baseImage[4] = sample.time;
1.171 baseImage[5] = sample.wavelengths;
1.172 - for (int i = SAMPLE_FLOATS; i < totalSamples; ++i)
1.173 + for (u_int i = SAMPLE_FLOATS; i < totalSamples; ++i)
1.174 baseImage[i] = sample.oneD[0][i - SAMPLE_FLOATS];
1.175 - for (int i = 0 ; i < totalTimes; ++i)
1.176 + for (u_int i = 0 ; i < totalTimes; ++i)
1.177 baseTimeImage[i] = sample.timexD[0][i];
1.178 mutation = 0;
1.179 newContributions.clear();
1.180 @@ -303,9 +286,9 @@
1.181 sampleImage[3] = sample.lensV;
1.182 sampleImage[4] = sample.time;
1.183 sampleImage[5] = sample.wavelengths;
1.184 - for (int i = SAMPLE_FLOATS; i < totalSamples; ++i)
1.185 + for (u_int i = SAMPLE_FLOATS; i < totalSamples; ++i)
1.186 sampleImage[i] = sample.oneD[0][i - SAMPLE_FLOATS];
1.187 - for (int i = 0 ; i < totalTimes; ++i)
1.188 + for (u_int i = 0 ; i < totalTimes; ++i)
1.189 timeImage[i] = sample.timexD[0][i];
1.190 stamp = sample.stamp;
1.191 currentImage = sampleImage;
1.192 @@ -324,7 +307,7 @@
1.193 }
1.194
1.195 // Restart from previous reference
1.196 - for (int i = 0; i < totalTimes; ++i)
1.197 + for (u_int i = 0; i < totalTimes; ++i)
1.198 sample.timexD[0][i] = currentTimeImage[i];
1.199 sample.stamp = stamp;
1.200 }
1.201 @@ -332,7 +315,7 @@
1.202 mutation = 0;
1.203 if (++chain >= numChains) {
1.204 chain = 0;
1.205 - mutation = -1;
1.206 + mutation = ~0U;
1.207 }
1.208 }
1.209 newContributions.clear();
1.210 @@ -343,15 +326,14 @@
1.211 int xStart, xEnd, yStart, yEnd;
1.212 film->GetSampleExtent(&xStart, &xEnd, &yStart, &yEnd);
1.213 int totMutations = params.FindOneInt("chainlength", 100); // number of mutations from a given seed
1.214 - float microMutationProb = params.FindOneFloat("micromutationprob", .5f); //probability of generating a micro sample mutation
1.215 - float range = params.FindOneFloat("mutationrange", (xEnd - xStart + yEnd - yStart) / 50.); // maximum distance in pixel for a small mutation
1.216 + float range = params.FindOneFloat("mutationrange", (xEnd - xStart + yEnd - yStart) / 50.f); // maximum distance in pixel for a small mutation
1.217 string base = params.FindOneString("basesampler", "random"); // sampler for new chain seed
1.218 Sampler *sampler = MakeSampler(base, params, film);
1.219 if (sampler == NULL) {
1.220 luxError(LUX_SYSTEM, LUX_SEVERE, "ERPTSampler: Could not obtain a valid sampler");
1.221 return NULL;
1.222 }
1.223 - return new ERPTSampler(totMutations, microMutationProb, range, sampler);
1.224 + return new ERPTSampler(max(totMutations, 0), range, sampler);
1.225 }
1.226
1.227 static DynamicLoader::RegisterSampler<ERPTSampler> r("erpt");