PBRT_V2 总结记录 <20> Sampler

总结一下:

1. 采样器作用:

整个 Film Plane 上的 incident radiance 实际上是一个连续函数 ,但是Pixel是离散的,这些离散的Pixel其实是从incident radiance 连续函数中采样计算出来, 而最终的目的就是利用离散的Pixel去重新构建一个新的函数,逼近 原来的连续函数,采样器就是为了从incident radiance 连续函数采样出来的更好的Pixel出来。

Sampler 类


// Sampling Declarations
class Sampler {
public:
	// Sampler Interface
	virtual ~Sampler();
	Sampler(int xstart, int xend, int ystart, int yend,
		int spp, float sopen, float sclose);

	
	virtual int GetMoreSamples(Sample *sample, RNG &rng) = 0;

	
	virtual int MaximumSampleCount() = 0;

	
	virtual bool ReportResults(Sample *samples, const RayDifferential *rays,
		const Spectrum *Ls, const Intersection *isects, int count);

	
	virtual Sampler *GetSubSampler(int num, int count) = 0;

	
	virtual int RoundSize(int size) const = 0;

	// Sampler Public Data
	const int xPixelStart, xPixelEnd, yPixelStart, yPixelEnd;
	const int samplesPerPixel;
	const float shutterOpen, shutterClose;
protected:
	
	void ComputeSubWindow(int num, int count, int *xstart, int *xend, int *ystart, int *yend) const;
};

类的作用:

(好的采样模式可以大幅度地改善光线追踪器的效率,可以用少量的射线就可以创建一个高质量的图片)

We can now describe the operation of a few classes that generate good image sampling
patterns. It may be surprising to see that some of them have a significant amount of
complexity behind them. In practice, creating good sample patterns can substantially
improve a ray tracer’s efficiency, allowing it to create a high-quality image with fewer
rays than if a lower-quality pattern was used. Because the run time expense for using
the best sampling patterns is approximately the same as for lower-quality patterns, and
because evaluating the radiance for each image sample is expensive, doing this work pays
dividends
(做这个工作是值得的).

All of the sampler implementations inherit from an abstract Sampler class that defines
their interface. The task of Samplers is to generate a sequence of multidimensional sample
positions. Two dimensions give the raster space image sample position, and another gives
the time at which the sample should be taken; this ranges from zero to one, and is scaled
by the camera to cover the time period that the shutter is open. Two more sample values
give a (u, v) lens position for depth of field; these also vary from zero to one.

Just as well-placed sample points can help conquer the complexity of the 2D image
function, most of the light transport algorithms in Chapters 15 and 16 use sample points
for tasks like choosing positions on area light sources when estimating illumination.
Choosing these points is also the job of the Sampler, since it is able to take the sample
points chosen for adjacent image samples into account when selecting samples at new
points. Doing so can improve the quality of the results of the light transport algorithms

1. 构造函数

Sampler::Sampler(int xstart, int xend, int ystart, int yend, int spp,
float sopen, float sclose)
: xPixelStart(xstart), xPixelEnd(xend), yPixelStart(ystart),
yPixelEnd(yend), samplesPerPixel(spp), shutterOpen(sopen),
shutterClose(sclose) { }

作用:

(构造函数中保存 整一副图片的分辨率,一个Pixel需要多少个采样点,和相机快门时间,采样器生成采样点的范围就是:【xPixelStart ,xPixelEnd-1】,【yPixelStart ,yPixelEnd-1】)

All of the Sampler implementations take a few common parameters that must be passed
to the base class’s constructor. These include the overall image resolution in the x and
y dimensions
, the number of samples the implementation expects to generate for each
pixel in the final image
, and the range of time over which the camera’s shutter is open.
These values are stored in member variables for later use.

The Sampler implementation should generate samples for pixels with x coordinates ranging
from xPixelStart to xPixelEnd-1, inclusive, and analogously(类似) for y coordinates. The
time values for samples should similarly be in the range shutterOpen to shutterClose.

2. virtual int GetMoreSamples(Sample *sample, RNG &rng) = 0;

作用:

(返回0 表示所有的 采样点已经生成完毕,否则,就会生成一个或者多个采样点,同时返回采样点的数目和把这些采样点填充到Sample *sample 参数中,一个采样点的里面保存的数据的范围应该是[0,1], 但是除了CameraSample::imageX and CameraSample::imageY,这两个是相对于 图片的 大小。

函数思路: 遍历图片的 【xPixelStart ,yPixelStart 】->【xPixelEnd,yPixelEnd】区域中的所有的Pixel,每一个Pixel就生成一个或者多个采样点,如果这个区域所有的Pixel 都生成完采样点的话,就直接返回0,如果还没有,就直接返回当前这个Pixel的采样点数量)

Samplers must implement the Sampler::GetMoreSamples() method, which is a pure
virtual function. The SamplerRendererTask::Run() method calls this function until it
returns zero, which signifies that all samples have been generated. Otherwise, it generates
one or more samples, returning the number of samples generated and filling
in sample values in the array pointed to by the sample parameter. All of the dimensions
of the sample values it generates should have values in the range [0, 1], except for
CameraSample::imageX and CameraSample::imageY, which are specified with respect to
the image size in raster coordinates.

3. virtual int MaximumSampleCount() = 0;

作用:

(MaximumSampleCount 表示的就是,返回最大的 采样点 数量,就一个Pixel最多可以生成多少个采样点)

The MaximumSampleCount() method returns the maximum number of sample values
that the Sampler will ever return from its implementation of the GetMoreSamples()
method.
It allows the renderer to preallocate memory for the array of Samples passed
into GetMoreSamples().

4. virtual bool ReportResults(Sample *samples, const RayDifferential *rays,
        const Spectrum *Ls, const Intersection *isects, int count);

作用:

(这个函数就是 分析目前生成的 samplers, ray,Radiance, Intersction 来判断是否需要更加多的数据,或者是抛弃现在这些数据,决定生成的 Radiance 是否可以贡献给最终的图片,这个方法主要用于 adaptive sampling)

Samplers may implement the ReportResults() method; it allows the renderer to report
back to the sampler which rays were generated, what radiance values were computed,
and the intersection points found for a collection of samples originally from
GetMoreSamples(). The sampler may use this information for adaptive sampling algorithms,
deciding to take more samples close to the ones that were returned here.
The return value indicates whether or not the sample values should be added to the image
being generated. For some adaptive sampling algorithms, the sampler may want to cause
an initial collection of samples (and their results) to be discarded, generating a new set to
replace them completely.
Because most of the Samplers in this chapter do not implement
adaptive sampling, a default implementation of this method just returns true.

5. 

virtual Sampler *GetSubSampler(int num, int count) = 0;

void ComputeSubWindow(int num, int count, int *xstart, int *xend, int *ystart, int *yend) const;

作用:

(GetSubSampler 的主要的思路就是,把 一整个图片分成count块(平铺), num 代表的是第num块,那么GetSubSampler   会生成  第 num 块 的 SubSampler,这个 SubSampler 只会负责 第 num 块区域的所有Pixel。

ComputeSubWindow()  就是负责计算,第 num 块对应的图片的 像素区域【xPixelStart, yPxielStart】->【xPixelEnd, yPixelEnd】)

The GetSubSampler() method returns a new Sampler that is responsible for
generating samples for a subset of the image;
its num parameter ranges from 0 to count-1,
where count is the total number of subsamplers being used.

Most implementations of the GetSubSampler() method decompose the image into rectangular
tiles and have each subsampler generate samples for a single tile.

ComputeSubWindow() is a utility function that computes a pixel sampling range given a tile number
num and a total number of tiles count.

6. virtual int RoundSize(int size) const = 0;

作用:

(返回这个采样器最合适的 采样点 数目)

Most Samplers can do a better job of generating particular quantities of these additional
samples than others. For example, the LDSampler can generate extremely good patterns,
although theymust have a size that is a power of two. The Sampler::RoundSize() method
helps communicate(传达) this information. Integrators should call this method with the desired
number of samples to be taken, giving the Sampler an opportunity to adjust the
number of samples to a more convenient one.
The integrator should then use the returned
value as the number of samples to request from the Sampler.

猜你喜欢

转载自blog.csdn.net/aa20274270/article/details/83176439
今日推荐