samplers/erpt.cpp
changeset 2081 43981caab6b9
parent 1643 eac52d5c6a9e
child 2174 4476a60abb5a
     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");