00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdafx.h"
00027 #include "samplers/adaptive.h"
00028 #include "paramset.h"
00029 #include "film.h"
00030 #include "primitive.h"
00031 #include "intersection.h"
00032 #include "camera.h"
00033 #include "montecarlo.h"
00034
00035
00036 AdaptiveSampler::AdaptiveSampler(int xstart, int xend,
00037 int ystart, int yend, int mins, int maxs, const string &m,
00038 float sopen, float sclose)
00039 : Sampler(xstart, xend, ystart, yend, RoundUpPow2(max(mins, maxs)),
00040 sopen, sclose) {
00041 xPos = xPixelStart;
00042 yPos = yPixelStart;
00043 supersamplePixel = false;
00044 if (mins > maxs) std::swap(mins, maxs);
00045
00046 if (!IsPowerOf2(mins)) {
00047 Warning("Minimum pixel samples being rounded up to power of 2");
00048 minSamples = RoundUpPow2(mins);
00049 }
00050 else
00051 minSamples = mins;
00052 if (!IsPowerOf2(maxs)) {
00053 Warning("Maximum pixel samples being rounded up to power of 2");
00054 maxSamples = RoundUpPow2(maxs);
00055 }
00056 else
00057 maxSamples = maxs;
00058
00059 if (minSamples < 2) {
00060 Warning("Adaptive sampler needs at least two initial pixel samples. Using two.");
00061 minSamples = 2;
00062 }
00063 if (minSamples == maxSamples) {
00064 maxSamples *= 2;
00065 Warning("Adaptive sampler must have more maximum samples than minimum. Using %d - %d",
00066 minSamples, maxSamples);
00067 }
00068 if (m == "contrast") method = ADAPTIVE_CONTRAST_THRESHOLD;
00069 else if (m == "shapeid") method = ADAPTIVE_COMPARE_SHAPE_ID;
00070 else {
00071 Warning("Adaptive sampling metric \"%s\" unknown. Using \"contrast\".",
00072 m.c_str());
00073 method = ADAPTIVE_CONTRAST_THRESHOLD;
00074 }
00075 sampleBuf = NULL;
00076 }
00077
00078
00079 AdaptiveSampler::~AdaptiveSampler() {
00080 delete[] sampleBuf;
00081 }
00082
00083
00084 Sampler *AdaptiveSampler::GetSubSampler(int num, int count) {
00085 int x0, x1, y0, y1;
00086 ComputeSubWindow(num, count, &x0, &x1, &y0, &y1);
00087 if (x0 == x1 || y0 == y1) return NULL;
00088 return new AdaptiveSampler(x0, x1, y0, y1, minSamples, maxSamples,
00089 method == ADAPTIVE_CONTRAST_THRESHOLD ? "contrast" : "shapeid",
00090 shutterOpen, shutterClose);
00091 }
00092
00093
00094 int AdaptiveSampler::GetMoreSamples(Sample *samples, RNG &rng) {
00095 if (!sampleBuf)
00096 sampleBuf = new float[LDPixelSampleFloatsNeeded(samples,
00097 maxSamples)];
00098 if (supersamplePixel) {
00099 LDPixelSample(xPos, yPos, shutterOpen, shutterClose, maxSamples,
00100 samples, sampleBuf, rng);
00101 return maxSamples;
00102 }
00103 else {
00104 if (yPos == yPixelEnd) return 0;
00105 LDPixelSample(xPos, yPos, shutterOpen, shutterClose, minSamples,
00106 samples, sampleBuf, rng);
00107 return minSamples;
00108 }
00109 }
00110
00111
00112 bool AdaptiveSampler::ReportResults(Sample *samples,
00113 const RayDifferential *rays, const Spectrum *Ls,
00114 const Intersection *isects, int count) {
00115 if (supersamplePixel) {
00116 supersamplePixel = false;
00117
00118 if (++xPos == xPixelEnd) {
00119 xPos = xPixelStart;
00120 ++yPos;
00121 }
00122 return true;
00123 }
00124 else if (needsSupersampling(samples, rays, Ls, isects, count)) {
00125 PBRT_SUPERSAMPLE_PIXEL_YES(xPos, yPos);
00126 supersamplePixel = true;
00127 return false;
00128 }
00129
00130 else {
00131 PBRT_SUPERSAMPLE_PIXEL_NO(xPos, yPos);
00132
00133 if (++xPos == xPixelEnd) {
00134 xPos = xPixelStart;
00135 ++yPos;
00136 }
00137 return true;
00138 }
00139 }
00140
00141
00142 bool AdaptiveSampler::needsSupersampling(Sample *samples,
00143 const RayDifferential *rays, const Spectrum *Ls,
00144 const Intersection *isects, int count) {
00145 switch (method) {
00146 case ADAPTIVE_COMPARE_SHAPE_ID:
00147
00148 for (int i = 0; i < count-1; ++i)
00149 if (isects[i].shapeId != isects[i+1].shapeId ||
00150 isects[i].primitiveId != isects[i+1].primitiveId)
00151 return true;
00152 return false;
00153 case ADAPTIVE_CONTRAST_THRESHOLD:
00154
00155 float Lavg = 0.f;
00156 for (int i = 0; i < count; ++i)
00157 Lavg += Ls[i].y();
00158 Lavg /= count;
00159 const float maxContrast = 0.5f;
00160 for (int i = 0; i < count; ++i)
00161 if (fabsf(Ls[i].y() - Lavg) / Lavg > maxContrast)
00162 return true;
00163 return false;
00164 }
00165 return false;
00166 }
00167
00168
00169 AdaptiveSampler *CreateAdaptiveSampler(const ParamSet ¶ms, const Film *film,
00170 const Camera *camera) {
00171
00172 int xstart, xend, ystart, yend;
00173 film->GetSampleExtent(&xstart, &xend, &ystart, ¥d);
00174 int minsamp = params.FindOneInt("minsamples", 4);
00175 int maxsamp = params.FindOneInt("maxsamples", 32);
00176 if (PbrtOptions.quickRender) { minsamp = 2; maxsamp = 4; }
00177 string method = params.FindOneString("method", "contrast");
00178 return new AdaptiveSampler(xstart, xend, ystart, yend, minsamp, maxsamp, method,
00179 camera->shutterOpen, camera->shutterClose);
00180 }
00181
00182