New features for Environment integrator. Added environment light features. New integrator depthfield.
1 /***************************************************************************
2 * Copyright (C) 1998-2009 by authors (see AUTHORS.txt ) *
4 * This file is part of LuxRender. *
6 * Lux Renderer is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 3 of the License, or *
9 * (at your option) any later version. *
11 * Lux Renderer is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * This project is based on PBRT ; see http://www.pbrt.org *
20 * Lux Renderer website : http://www.luxrender.net *
21 ***************************************************************************/
23 // initial metropolis light transport sample integrator
26 // TODO: add scaling of output image samples
36 #define SAMPLE_FLOATS 6
38 // mutate a value in the range [0-1]
39 static float mutate(const float x, const float randomValue)
41 static const float s1 = 1.f / 1024.f, s2 = 1.f / 16.f;
42 float dx = s2 * powf(s1 / s2, fabsf(2.f * randomValue - 1.f));
43 if (randomValue < 0.5f) {
45 return (x1 > 1.f) ? x1 - 1.f : x1;
48 return (x1 < 0.f) ? x1 + 1.f : x1;
52 // mutate a value in the range [min-max]
53 static float mutateScaled(const float x, const float randomValue, const float mini, const float maxi, const float range)
55 float dx = range * expf(-logf(2.f * range) * fabsf(2.f * randomValue - 1.f));
56 if (randomValue < 0.5f) {
58 return (x1 > maxi) ? x1 - maxi + mini : x1;
61 return (x1 < mini) ? x1 - mini + maxi : x1;
65 ERPTSampler::ERPTData::ERPTData(const Sample &sample) :
66 numChains(0), chain(0), mutation(~0U), stamp(0), currentStamp(0),
67 baseLY(0.f), quantum(0.f), weight(0.f), LY(0.f), alpha(0.f),
68 totalLY(0.), sampleCount(0.)
71 normalSamples = SAMPLE_FLOATS;
72 for (i = 0; i < sample.n1D.size(); ++i)
73 normalSamples += sample.n1D[i];
74 for (i = 0; i < sample.n2D.size(); ++i)
75 normalSamples += 2 * sample.n2D[i];
76 totalSamples = normalSamples;
77 timeOffset = new u_int[sample.nxD.size()];
78 offset = new u_int[sample.nxD.size()];
80 for (i = 0; i < sample.nxD.size(); ++i) {
81 timeOffset[i] = totalTimes;
82 offset[i] = totalSamples;
83 totalTimes += sample.nxD[i];
84 totalSamples += sample.dxD[i] * sample.nxD[i];
86 sampleImage = AllocAligned<float>(totalSamples);
87 currentImage = AllocAligned<float>(totalSamples);
88 baseImage = AllocAligned<float>(totalSamples);
89 timeImage = AllocAligned<int>(totalTimes);
90 currentTimeImage = AllocAligned<int>(totalTimes);
91 baseTimeImage = AllocAligned<int>(totalTimes);
93 ERPTSampler::ERPTData::~ERPTData()
95 FreeAligned(baseTimeImage);
96 FreeAligned(currentTimeImage);
97 FreeAligned(timeImage);
98 FreeAligned(baseImage);
99 FreeAligned(currentImage);
100 FreeAligned(sampleImage);
105 // Metropolis method definitions
106 ERPTSampler::ERPTSampler(u_int totMutations, float rng, Sampler *sampler) :
107 Sampler(sampler->xPixelStart, sampler->xPixelEnd,
108 sampler->yPixelStart, sampler->yPixelEnd, sampler->samplesPerPixel),
109 totalMutations(totMutations), range(rng), baseSampler(sampler)
113 ERPTSampler::~ERPTSampler() {
117 // interface for new ray/samples from scene
118 bool ERPTSampler::GetNextSample(Sample *sample)
120 const RandomGenerator *rng = sample->rng;
121 ERPTData *data = (ERPTData *)(sample->samplerData);
123 if (data->mutation == ~0U) {
124 // Dade - we are at a valid checkpoint where we can stop the
125 // rendering. Check if we have enough samples per pixel in the film.
126 if (film->enoughSamplesPerPixel)
129 sample->samplerData = data->baseSamplerData;
130 const bool ret = baseSampler->GetNextSample(sample);
131 float *image = data->baseImage;
132 *image++ = sample->imageX;
133 *image++ = sample->imageY;
134 *image++ = sample->lensU;
135 *image++ = sample->lensV;
136 *image++ = sample->time;
137 *image++ = sample->wavelengths;
138 for (u_int i = 0; i < sample->n1D.size(); ++i) {
139 for (u_int j = 0; j < sample->n1D[i]; ++j)
140 *image++ = baseSampler->GetOneD(*sample, i, j);
142 for (u_int i = 0; i < sample->n2D.size(); ++i) {
143 for (u_int j = 0; j < sample->n2D[i]; ++j) {
145 baseSampler->GetTwoD(*sample, i, j, u);
150 sample->samplerData = data;
151 for (u_int i = 0; i < data->totalTimes; ++i)
152 data->baseTimeImage[i] = -1;
153 data->currentStamp = 0;
157 if (data->mutation == 0) {
159 for (u_int i = 0; i < data->totalSamples; ++i)
160 data->currentImage[i] = data->baseImage[i];
161 for (u_int i = 0; i < data->totalTimes; ++i) {
162 data->timeImage[i] = -1;
163 data->currentTimeImage[i] = data->baseTimeImage[i];
165 data->currentStamp = 0;
168 // *** small mutation ***
169 // mutate current sample
170 data->sampleImage[0] = mutateScaled(data->currentImage[0], rng->floatValue(), xPixelStart, xPixelEnd, range);
171 data->sampleImage[1] = mutateScaled(data->currentImage[1], rng->floatValue(), yPixelStart, yPixelEnd, range);
172 for (u_int i = 2; i < data->normalSamples; ++i)
173 data->sampleImage[i] = mutate(data->currentImage[i], rng->floatValue());
174 data->stamp = data->currentStamp + 1;
175 sample->imageX = data->sampleImage[0];
176 sample->imageY = data->sampleImage[1];
177 sample->lensU = data->sampleImage[2];
178 sample->lensV = data->sampleImage[3];
179 sample->time = data->sampleImage[4];
180 sample->wavelengths = data->sampleImage[5];
186 float ERPTSampler::GetOneD(const Sample &sample, u_int num, u_int pos)
188 ERPTData *data = (ERPTData *)(sample.samplerData);
189 u_int offset = SAMPLE_FLOATS;
190 for (u_int i = 0; i < num; ++i)
191 offset += sample.n1D[i];
192 if (data->mutation == ~0U)
193 return data->baseImage[offset + pos];
195 return data->sampleImage[offset + pos];
198 void ERPTSampler::GetTwoD(const Sample &sample, u_int num, u_int pos, float u[2])
200 ERPTData *data = (ERPTData *)(sample.samplerData);
201 u_int offset = SAMPLE_FLOATS;
202 for (u_int i = 0; i < sample.n1D.size(); ++i)
203 offset += sample.n1D[i];
204 for (u_int i = 0; i < num; ++i)
205 offset += sample.n2D[i] * 2;
206 if (data->mutation == ~0U) {
207 u[0] = data->baseImage[offset + pos * 2];
208 u[1] = data->baseImage[offset + pos * 2 + 1];
210 u[0] = data->sampleImage[offset + pos * 2];
211 u[1] = data->sampleImage[offset + pos * 2 + 1];
215 float *ERPTSampler::GetLazyValues(const Sample &sample, u_int num, u_int pos)
217 ERPTData *data = (ERPTData *)(sample.samplerData);
218 const u_int size = sample.dxD[num];
219 const u_int first = data->offset[num] + pos * size;
220 int &baseTime(data->baseTimeImage[data->timeOffset[num] + pos]);
221 if (baseTime == -1) {
222 const_cast<Sample&>(sample).samplerData = data->baseSamplerData;
223 float *base = baseSampler->GetLazyValues(sample, num, pos);
224 const_cast<Sample&>(sample).samplerData = data;
225 for (u_int i = 0; i < size; ++i)
226 data->baseImage[first + i] = base[i];
229 if (data->mutation == ~0U)
230 return data->baseImage + first;
231 int &time(data->timeImage[data->timeOffset[num] + pos]);
232 const int stampLimit = data->stamp;
233 if (time != stampLimit) {
234 int ¤tTime(data->currentTimeImage[data->timeOffset[num] + pos]);
235 if (currentTime == -1) {
236 for (u_int i = first; i < first + size; ++i)
237 data->currentImage[i] = data->baseImage[i];
240 for (u_int i = first; i < first + size; ++i) {
241 data->sampleImage[i] = data->currentImage[i];
242 for (time = currentTime; time < stampLimit; ++time)
243 data->sampleImage[i] = mutate(data->sampleImage[i], sample.rng->floatValue());
246 return data->sampleImage + first;
249 // interface for adding/accepting a new image sample.
250 void ERPTSampler::AddSample(const Sample &sample)
252 ERPTData *data = (ERPTData *)(sample.samplerData);
253 vector<Contribution> &newContributions(sample.contributions);
255 for(u_int i = 0; i < newContributions.size(); ++i)
256 newLY += newContributions[i].color.Y();
257 if (data->mutation == 0U || data->mutation == ~0U) {
258 if (data->weight > 0.f) {
259 // Add accumulated contribution of previous reference sample
260 data->weight *= data->quantum / data->LY;
261 if (!isinf(data->weight) && data->LY > 0.f) {
262 for(u_int i = 0; i < data->oldContributions.size(); ++i)
263 sample.contribBuffer->Add(data->oldContributions[i], data->weight);
267 if (data->mutation == ~0U) {
268 if (!(newLY > 0.f)) {
269 newContributions.clear();
272 sample.contribBuffer->AddSampleCount(1.f);
273 ++(data->sampleCount);
274 data->totalLY += newLY;
275 const float meanIntensity = data->totalLY > 0. ? static_cast<float>(data->totalLY / data->sampleCount) : 1.f;
276 // calculate the number of chains on a new seed
277 data->quantum = newLY / meanIntensity;
278 data->numChains = max(1U, Floor2UInt(data->quantum + .5f));
279 // The following line avoids to block on a pixel
280 // if the initial sample is extremely bright
281 data->numChains = min(data->numChains, totalMutations);
282 data->quantum /= data->numChains;
283 data->baseLY = newLY;
284 data->baseContributions = newContributions;
286 newContributions.clear();
289 data->LY = data->baseLY;
290 data->oldContributions = data->baseContributions;
292 // calculate accept probability from old and new image sample
295 accProb = min(1.f, newLY / data->LY);
298 float newWeight = accProb;
299 data->weight += 1.f - accProb;
301 // try accepting of the new sample
302 if (accProb == 1.f || sample.rng->floatValue() < accProb) {
303 // Add accumulated contribution of previous reference sample
304 data->weight *= data->quantum / data->LY;
305 if (!isinf(data->weight) && data->LY > 0.f) {
306 for(u_int i = 0; i < data->oldContributions.size(); ++i)
307 sample.contribBuffer->Add(data->oldContributions[i], data->weight);
309 data->weight = newWeight;
311 data->oldContributions = newContributions;
313 // Save new contributions for reference
314 swap(data->sampleImage, data->currentImage);
315 swap(data->timeImage, data->currentTimeImage);
316 data->currentStamp = data->stamp;
318 // Add contribution of new sample before rejecting it
319 newWeight *= data->quantum / newLY;
320 if (!isinf(newWeight) && newLY > 0.f) {
321 for(u_int i = 0; i < newContributions.size(); ++i)
322 sample.contribBuffer->Add(newContributions[i], newWeight);
325 data->stamp = data->currentStamp;
327 if (++(data->mutation) >= totalMutations) {
329 if (++(data->chain) >= data->numChains) {
331 data->mutation = ~0U;
334 newContributions.clear();
337 Sampler* ERPTSampler::CreateSampler(const ParamSet ¶ms, const Film *film)
339 int xStart, xEnd, yStart, yEnd;
340 film->GetSampleExtent(&xStart, &xEnd, &yStart, &yEnd);
341 int totMutations = params.FindOneInt("chainlength", 100); // number of mutations from a given seed
342 float range = params.FindOneFloat("mutationrange", (xEnd - xStart + yEnd - yStart) / 50.f); // maximum distance in pixel for a small mutation
343 string base = params.FindOneString("basesampler", "random"); // sampler for new chain seed
344 Sampler *sampler = MakeSampler(base, params, film);
345 if (sampler == NULL) {
346 LOG( LUX_SEVERE,LUX_SYSTEM)<< "ERPTSampler: Could not obtain a valid sampler";
349 return new ERPTSampler(max(totMutations, 0), range, sampler);
352 static DynamicLoader::RegisterSampler<ERPTSampler> r("erpt");