1.3 pbrt:系统综述(1.3.1-1.3.3)

来源:互联网 发布:英雄无敌3恐怖骑士知乎 编辑:程序博客网 时间:2024/05/17 00:01

(ps:1.3实在太长,打算分三节来发。系统综述对理解结构十分有帮助,虽然还没看全,但是也能猜想出系统的大致情况了)


1.3 pbrt: SYSTEM OVERVIEW

1.3 pbrt:系统综述

 

pbrt is structured using standardobject-oriented techniques: abstract base classes are defined for importantentities (for example, a Shape abstract base class defines the interface that all geometricshapes must implement, the Light abstract base class acts similarly for lights, etc.). The majorityof the system is implemented purely in terms of the interfaces provided bythese abstract base classes; for example, the code that checks for occludingobjects between a light source and a point being shaded calls the Shape intersection methods and doesn’t need toconsider the particular types of shapes that are present in the scene. Thisapproach makes it easy to extend the system, as adding a new shape only requiresimplementing a class that implements the Shape interface and linking it into the system.pbrt is written using a total of 13 keyabstract base classes, summarized in Table 1.1. Adding a new implementation ofone of these types to the system is straightforward; the implementation mustinherit from the appropriate base class, be compiled and linked into theexecutable, and the object creation routines in Appendix B must be modified to createinstances of the object as needed as the scene description file is parsed.Section B.4 discusses extending the system in this manner in more detail.

 

pbrt使用标准的面相对象技术来进行构建的:数个定义重要概念对象的抽象基类(abstract base classes)(如Shape抽象类定义了所有几何形状应该实现的接口,Light抽象类则定义了所有光源可进行的操作)。整个系统的关键部分是由这些抽象基类提供的接口来进行实现的;例如检查光源和一个点之间是否有阻碍,我们调用的是Shape类提供的相交检测函数,而不需要关心场景里具体是哪种类型的Shape子类(比如Sphere,Cube,Cyline)。这种手法让整个系统易于扩展,比如添加一种新的形状只需要实现Shape类规定的接口,然后添加到项目里参与编译。pbrt使用了13种关键抽象类进行编写,在表1.1中做了总结。为这些类型添加一个新的实现是非常简单明了的;新实现必须选择一个恰当的基类进行继承,编译和链接到可执行程序里,然后附录B中描述的对象创建流程中需要添加这个新类的修改。附录B.4章节讨论了扩展系统时的更多细节。

 

Table 1.1: Main Interface Types. Most ofpbrt is implemented in terms of 13 key abstractbase classes, listed here. Implementations of each of these can easily be addedto the system to extend its functionality.

1.1:主要接口类。pbrt的主要部分使用13种关键抽象类来实现,如下表。可以很容易的给它们各自添加实现子类以便扩展系统的能力。

Base class

Directory

Section

Shape(几何对象)

shapes/

3.1

Aggregate(聚合体)

accelerators/

4.2

Camera(摄像机)

cameras/

6.1

Sampler(采样器)

samplers/

7.2

Filter(筛选器)

filters/

7.7

Film(幕布)

film/

7.8

Material(材质)

materials/

9.2

Texture(贴图)

textures/

10.3

VolumeRegion(体空间)

volumes/

11.3

Light(光源)

lights/

12.1

Renderer(渲染器)

renderers/

1.3.3

SurfaceIntegrator(表面积分器)

integrators/

Ch. 15 intro

VolumeIntegrator(体积积分器)

integrators/

16.2

 

The source code to pbrt is distributed across a small directory hierarchy that can be foundin the pbrt distribution, available frompbrt.org/downloads.php. Allof the code for the pbrt core is in the src/core/ directory, and the main() function is contained in the short file src/main/pbrt.cpp. Various implementations ofinstances of the abstract base classes are in separate directories: src/shapes/ has implementations of the Shape base class, src/materials/ has implementations of Material, and so forth. Throughoutthis section are a number of images rendered with extended versions of pbrt. Of them, Figures 1.11 through 1.14 arenotable: not only are they visually impressive, but each of them was created bya student in a rendering course where the final class project was to extend pbrt with new functionality in order to renderan interesting image. These images are among the best from those courses.Figures 1.15 and 1.16 were rendered with LuxRender, a GPL-licensed rendering system originally based on the pbrt source code from the first edition of thebook. (Seewww.luxrender.net for more informationabout LuxRender.)

 

可以通过pbrt.org/downloads.php找到pbrt的目录结构描述。pbrt的核心代码都在src/core/ 目录下了,main()函数则在src/main/pbrt.cpp 文件中。src/shapes/ 是Shape类的子类实现,src/materials/ 是Material类的子类实现,其他目录诸如此类。本章节会展示许多由pbrt扩展版本渲染出的图像。其中值得注意的是图1.11到图1.14:它们不单单在视觉上印象深刻,而且每一张图都是出自学生之手,他们通过课程学习如何扩展pbrt的功能来创造一些有趣的图像。这些图像是课程作品中最好的。图1.15和1.16由LuxRender渲染引擎进行渲染,一个GPL版权的渲染系统,基于本书第一版的源码。(有关LuxRender可以访问www.luxrender.net获取更多信息。)

 

1.3.1 PHASES OFEXECUTION

1.3.1 各执行阶段

 

pbrt can be conceptually divided into twophases of execution. First, it parses the scene description file provided bythe user. The scene description is a text file that specifies the geometricshapes that make up the scene, their material properties, the lights that illuminatethem, where the virtual camera is positioned in the scene, and parameters to allof the individual algorithms used throughout the system. Each statement in theinput file has a direct mapping to one of the routines in Appendix B; theseroutines comprise the procedural interface for describing a scene to pbrt. A number of example scenes are providedin the scenes/ directory in the pbrt distribution. The scene file format is specifiedin the file docs/fileformat.pdf and a user’s guide to thefile format is in the file docs/usersguide.pdf.

 

pbrt从概念上可以分为两个执行阶段。第一个,它解析用户提供的场景描述文件。场景描述是一个文本文件,该文件指出构建场景的各种几何对象、它们的材质属性、它们的光照信息、摄像机的位置、以及整个系统中各个算法需要用到的参数。描述文件中的每一个部分在附录B中都有对照。这些阶段构成了pbrt描述场景的结构范式。在pbrt目录结构中scenes/ directory 目录下提供了一些场景描述文件的例子。这些文件的格式定义在 docs/fileformat.pdf 文件中,说明则在docs/usersguide.pdf 文件中。

 

 

Figure 1.11: Guillaume Poncin and PramodSharma extended pbrt in numerous ways, implementing a number of complex renderingalgorithms, to make this prize-winning image for Stanford’s cs348b renderingcompetition. The trees are modeled procedurally with L-systems, a glow imageprocessing filter increases the apparent realism of the lights on the tree,snow was modeled procedurally with metaballs, and a subsurface scatteringalgorithm gave the snow its realistic appearance by accounting for the effectof light that travels beneath the snow for some distance before leaving it.

1.11: Guillaume Poncin and PramodSharma 用多种方式扩展了pbrt,实现了多种复杂的渲染算法,制作出了这张图像,并获得斯坦福大学cs348b 渲染比赛的冠军。这些树根据L-System进行建模(一种分形(fractal)模型),一个图像发光处理筛选器(image effect, pixel shader)增强了树上这些光源的真实度,雪堆是根据metaball方案进行建模,一个次表面散射算法计算了光线在雪堆内部的传播一段距离后才离开的情况,这给了雪逼真的视觉效果。(个人感觉屌炸了,果然是冠军图像)

【L-System:https://en.wikipedia.org/wiki/L-system】

【Metaball:http://jamie-wong.com/2014/08/19/metaballs-and-marching-squares/  和https://en.wikipedia.org/wiki/Metaballs】

 

The end results of the parsing phase are an instance of the Scene class and an instance of the Renderer class. The Scene specifies the contents of the scene(geometric objects, lights, etc.), and the Renderer implements an algorithm torender it. Once the scene has been specified, the second phase of executionbegins and the main rendering loop executes. This phase is where pbrt usually spends the majority of its runningtime, and most of this book describes code that executes during this phase. Therendering loop is implemented in an implementation of the Renderer::Render() method, which is the focus ofSection 1.3.4. For the SamplerRenderer described in this chapter, the Render() method determines the lightarriving at a virtual film plane for a large number of rays in order to modelthe process of image formation. After the contributions of all of these filmsamples have been computed, the final image is written to disk. The scenedescription data in memory are deallocated and the renderer then resumesprocessing statements from the scene description file until no more remain,allowing the user to specify another scene to be rendered, if desired.

 

解析阶段的最终结果就是一个Scene实例对象和一个Renderer实例对象。Scene对象指出了场景中的内容(几何体对象、光源和其他),Renderer对象实现了某种渲染算法去渲染场景。一旦场景确定下来,执行的第二阶段就开始了,渲染的主循环也启动了。pbrt的主要时间开销都花在这个阶段,本书描述的大部分代码也是在这个阶段执行的。The Rendering Loop(渲染循环)是Renderer:Render()方法的某个具体实现,1.3.4章节会讲到。本章会介绍SamplerRenderer,它使用Render()方法检测大量的到达film(虚拟幕布)的光线,并形成最终图像。综合幕布上全部点的渲染结果后,最终图像会保存到磁盘上。内存中的场景描述数据会被释放,渲染器随后会从处理场景描述文件的阶段恢复,等待用户指定其他的场景进行渲染—如果需要的话。

 

Figure 1.12: Abe Davis, David Jacobs, andJongmin Baek rendered this amazing image of an ice cave to take the grand prizein the 2009 Stanford CS348b rendering competition. They first implemented a simulationof the physical process of glaciation, the process where snow falls, melts, andrefreezes over the course of many years, forming stratified layers of ice. Theythen simulated erosion of the ice due to melted water runoff before generatinga geometric model of the ice. Scattering of light inside the volume wassimulated with volumetric photon mapping; the blue color of the ice is entirelydue to modeling the wavelength-dependent absorption of light in the ice volume

图 1.12:Abe Davis,David Jacobs,和Jongmin Baek渲染的这个冰洞的图像在2009斯坦福cs348b渲染比赛中获得了最高成就奖。他们首先实现了一个模拟的冰川作用的物理过程,瀑布、雪在融化的过程,并经历多年冻结,形成(冰川冰的)分层结构。然后,他们模拟的冰融化的水径流的侵蚀,然后产生一个几何模型的冰(参考【冰川学-冰川冰】)。散射的体积内的光进行了模拟与体积光子映射;冰的蓝色的颜色是完全由对波长建模,并由冰本体对光波的吸收产生的。(orz,他们是准备去南极的过程中顺便渲了一张图吗?)

 

1.3.2 SCENEREPRESENTATION

1.3.2 场景表达

 

pbrt’s main() function can be found in the file main/pbrt.cpp. This function is quite simple;it first loops over the provided command-line arguments in argv, initializing values in the Options structure and storing thefilenames provided in the arguments. Running pbrt with --help as a command line argument prints all ofthe options that can be specified on the command line. The fragment that parsesthe command-line arguments,Process command-line arguments, is straightforward and therefore not included in the book here.

 

pbrt的main()函数在main/pbrt.cpp 文件中。此函数非常简单:它先遍历一遍通过变量argv传递的命令行参数,然后用这些参数初始化Options结构体中的变量值以及保存传递进来的场景文件名称。使用--help参数运行pbrt可以看到所有的可选命令。关于解析命令行参数的实现部分很普通很直接,也不属于本书的主要目的,没有包含在本书中。

 

Figure 1.13: Lingfeng Yang implemented abidirectional texture function to simulate the appearance of cloth, adding ananalytic self-shadowing model, to render this image that took first prize inthe 2009 Stanford CS348b rendering competition.

1.13: Lingfeng Yang 实现了一个双向贴图函数,该函数模拟了布料的外观,并在其中添加了一种自我阴影的解析模型。这张渲染图获得了2009斯坦福CS348b渲染比赛的第一名。

 

The options structure is then passed pbrtInit(), which does systemwideinitialization. The main() function then parses the given scene description(s), leading tothe creation of a Scene object that represents all of the elements (shapes, lights, etc.)that make up the scene and a Renderer object that implements an algorithm to render the scene. Because theinput file can specify multiple scenes to be rendered, rendering actuallybegins as soon as the appropriate input directive is parsed. After allrendering is done, pbrtCleanup() does final cleanup before the system exits. The pbrtInit() and pbrtCleanup() functions appear in amini-index in the page margin, alongwith the number of the page where they are actually defined. The mini-indiceshave pointers to the definitions of almost all of the functions, classes,methods, and member variables used or referred to on each page.

 

Options结构体随后被传给pbrtInit()函数,它负责系统级的初始化工作。然后main()函数开始解析场景描述文件,这些描述文件会指导创建一个SceneObject,用来展现各种组成场景的元素(如物体,灯光之类),同时也创建一个RendererObject,它使用某种指定的渲染算法来渲染场景。因为输入文件可以指定多个场景进行渲染,所以只要解析完指令(全部?还是任意一个?)就会立即开始渲染。在所有的渲染完成后,pbrtCleanup()函数会做一些清理操作,然后整个应用程序才关闭。本书在调用pbrtInit()和pbrtCleanup()函数的页边距空白处有小字体显示的页面索引,用来指出这两个函数的实现部分在哪一页。小索引是一种定位规则,适用于查找各种函数、类、方法、成员变量的引用来源。

 

Figure 1.14: Jared Jacobs and MichaelTuritzin added an implementation of Kajiya and Kay’s texelbased fur renderingalgorithm (Kajiya and Kay 1989) to pbrt and rendered this image, where both the fur on the dog and theshag carpet are rendered with the texel fur algorithm.

图1.14: JaredJacobs 和Michael Turitzin在pbrt中加入了Kajiya 和 Kay的基于贴图的毛皮渲染算法(Kajiyaand Kay 1989),渲染出了这张图片。狗和粗毛地毯都应用了这种基于贴图的毛皮渲染算法。

 

<main program>

int main(int argc, char *argv[]) {

Options options;

vector<string> filenames;

<Process command-line arguments>

pbrtInit(options);
<Process scene description 21>

pbrtCleanup();

return 0;

}

 

函数主体:

1、解析参数

2、设置options

3、pbrtInit(options)

4、处理场景渲染

5、pbrtCleanup();

6、退出程序

 

If pbrt is run with no input filenames provided, then the scenedescription is read from standard input. Otherwise it loops through the providedfilenames, processing each file in turn.

 

如果运行pbrt时没有指定输入文件,那么它将会从standardinput(标准输入流)中读取场景描述参数。否则会遍历所有输入文件,每次处理一个。

 

Figure 1.15: This contemporary indoor scenewas modeled and rendered by Florent Boyer (www.florentboyer.com). The image was rendered usingLuxRender, a GPL licensed physicallybased rendering system originally basedon pbrt’s source code. Modelling and texturingwas done using Blender.

 

1.15这个现代室内场景由Florent Boyer建模和渲染。渲染这张图用到了LuxRender软件,一个GPL协议、由pbrt源代码演化而成的基于物理的渲染系统。建模和纹理绘制使用了Blender软件。

 

<Process scene description


> ≡ 20

if (filenames.size() == 0) {

<Parse scene from standard input 21>

} else {

<Parse scene from input files 21>

}

 

<处理场景描述文件>

如果没文件{

         <从标准输入流中解析场景参数>

}否则{

         <从文件中解析场景参数>

}

 

The ParseFile() function parses a scene description file, either from standardinput or from a file on disk; it returns false if it was unable to open the file. Themechanics of parsing scene description files will not be described in thisbook; the parser implementation can be found in the lex and yacc files core/pbrtlex.ll and core/pbrtparse.yy, respectively. Readers whowant to understand the parsing subsystem but are not familiar with these toolsmay wish to consult Levine, Mason, and Brown (1992).

 

ParseFile()函数负责解析场景描述文件,同时也负责从输入流中解析场景参数;如果无法打开文件它就会返回false。想看实现的自己去看源码core/pbrtlex.ll和core/pbrtparse.yy。想问细节的去问Levine, Mason, and Brown (1992)。

 

We use the common UNIX idiom that a file named “-” represents standard input:

 

我们使用UNIX的惯用方式“-”作为文件名来代表从标准输入流读入参数:

 

Parse scene from standard input


 ≡ 21
ParseFile("-");

 

If a particular input file can’t be opened, the Error() routine reports thisinformation to the user. Error() uses the same format string semantics as printf().

 

如果指定的输入文件打开失败,会通过Error()函数通知用户。Error()函数使用和printf()相同的字符串格式化语法。

 

Parse scene from input files


 ≡ 21
for (u_int i = 0; i < filenames.size(); i++)
if (!ParseFile(filenames[i]))
Error("Couldn’t open scene file \"%s\"",filenames[i].c_str());

 

Figure 1.16: Martin Lubich modeled thisscene of the Austrian Imperial Crown and rendered it usingLuxRender, an open-source fork of the pbrt codebase. The scene was modeled in Blenderand consists of approximately 1.8 million vertices. It is illuminated by sixarea light sources with emission spectra based on measured data from areal-world light source and was rendered with 1280 samples per pixel in 73hours of computation on a quad-core CPU. See Martin’s Web site,www.loramel.net, for more information, including downloadable Blender scenefiles.

 

As the scene file is parsed, objects are created that representthe lights and geometric primitives in the scene. These are all stored in the Scene object, which is created by the RenderOptions::MakeScene() methodin Section B.3.7 in Appendix B. The Scene class is declared in core/scene.hand defined in core/scene.cpp. We will not include the implementation of the Scene constructor here; it just stores copies ofits arguments in the various member variables inside the class.

 

在场景文件解析完成后,就会创建场景中的光源、几何体等对象。这些元素都由Scene对象进行存储和管理,Scene对象由RenderOptions::MakeScene()函数创建(详见附录B.3.7)。Scene类的代码是core/scene.h和core/scene.cpp。我们在这里就不把整个Scene的代码弄过来了,只摘出成员变量进行讲解。

 

Scene Declarations


 ≡
class Scene {
public:
Scene Public Methods 23
Scene Public Data 23
};

 

Scene的声明

class Scene {

public:

ScenePublic方法

ScenePublic 数据字段

(我简直无语了….233333)

}

 

Each geometric object in the scene is represented by a Primitive, which combines two objects:a Shape that specifies its geometry, and a Material that describes its appearance(e.g., the object’s color, whether it has a dull or glossy finish). All ofthese geometric primitives are collected into a single aggregate Primitive in the Scene member variable Scene::aggregate. This aggregate is a specialkind of primitive that itself holds references to many other primitives.Because it implements the Primitive interface it appears no different than a single primitive to therest of the system. The specific class used to implement Scene::aggregate stores all the scene’sprimitives in an acceleration data structure that reduces the number ofunnecessary ray intersection tests with primitives that a given ray doesn’tpass near.

 

场景中的每个几何体都对应一个Primitive对象。它整合了两个部分:几何体的Shape(也可称Mesh)和使用到的Material(如物体的颜色,阴暗或有光泽)。所有的这些几何体原始信息都保存在Scene对象的一个名为aggregate的指针中,Scene::aggregate。Aggregate比较特别,它负责保存对其他所有原始信息的引用。由于它其实也实现了Primitive接口,所以它对系统来说其实没啥特别之处。这个特别的类只负责保存其他primitive,不过使用的是一个经过优化的结构体,这样在做场景查询的时候,可以快速剔除不会和指定光线产生相交的几何体。(比如K-DTree)

 

Scene Public Data


 ≡ 22
Primitive *aggregate;

 

Each light source in the scene is represented by a Light object, which specifies the shape of alight and the distribution of energy that it emits. The Scene stores all of the lights in a vector class from the C++ standard library.While some renderers support separate light lists per geometric object, allowinga light to illuminate only some of the objects in the scene, this idea does notmap well to the physically based rendering approach taken in pbrt, so we use only this per-scene list.

 

光源信息都存在Scene:: vector<Light *> lights里。有些渲染系统允许指定特定对象接受特定光源的光照,从而提供了多组光源列表,这个想法不符合基于真实物理的路子,所以我们只有一个列表。

 

Scene Public Data


 +≡ 22
vector<Light *> lights;

 

In addition to geometric primitives, pbrt also supports participating media, orvolumetric primitives. These types ofprimitives are supported through the VolumeRegioninterface. The system’s support for participating media isdescribed in Chapter 11. Like Primitives, multiple VolumeRegions are all stored together in a single aggregate region, Scene::volumeRegion.

 

除了支持几何对象描述外,pbrt也支持传播介质对象的表达,或者叫做体对象描述。这些类型的对象描述通过VolumeRegion接口进行定义。在第11章里介绍了系统支持的传播介质种类。多个体对象描述统一由Scene::volumeRegion指针进行保存。

 

Scene Public Data


 +≡ 22
VolumeRegion *volumeRegion;

 

The Scene class provides a handful of additional methods. Its Intersect() method traces the given rayinto the scene and returns a Boolean value indicating whether the ray intersectedany of the primitives. If so, it fills in the provided Intersection structure with informationabout the closest intersection point along the ray. The Intersection structure is defined inSection 4.1.

 

Scene类还提供一个十分有用的函数Intersect()。这个函数的功能是检测是否有任意对象和指定射线相交,并将结果填充到Intersection结构体中。Intersection结构体在小节4.1中定义。

 

Scene Public Methods


 ≡ 22

bool Intersect(const Ray &ray, Intersection *isect) const {

bool hit = aggregate->Intersect(ray, isect);

return hit;

}

 

A closely related method is Scene::IntersectP(), which checks for theexistence of intersections along the ray, but does not return any informationabout those intersections. Because this routine doesn’t need to search for theclosest intersection or compute any additional information about theintersections, it is generally more efficient than Scene::Intersect(). This routine is used forshadow rays.

 

有个类似的函数Scene::IntersectP(),它只返回是否相交,而不进行其他附加信息的计算,比如找出最近的几何体或者其他额外的相交信息,它比Scene::Intersect()效率更高。比较常见的是用它来参与阴影的实现。

 

Scene Public Methods


 +≡ 22

bool IntersectP(const Ray &ray) const {

bool hit = aggregate->IntersectP(ray);

return hit;

}

 

Finally, Scene::WorldBound()returns a 3D box that bounds all of the geometry in the scene,which is simply the bounding box of Scene::aggregate. The Scene class caches this bound to avoid having to repeatedly compute it.

 

最后,Scene::WorldBound()负责返回所有场景内对象的最小包围盒。Scene对象会缓存结果,避免总是重复计算它。

 

Scene Constructor Implementation


 ≡

bound = aggregate->WorldBound();

if (volumeRegion) bound = Union(bound,volumeRegion->WorldBound());

 

Scene Public Data


 +≡ 22

BBox bound;

 

Scene Method Definitions


 ≡

const BBox &Scene::WorldBound() const {

return bound;

}

 

 

1.3.3 RENDERER INTERFACE AND SamplerRenderer

1.3.3渲染器接口和采样-渲染器

 

Rendering an image of thescene is handled by an instance of a class that implements the Renderer interface. Renderer is an abstract base classthat defines a few methods that must be provided by all renderers. It isdefined in the files core/renderer.h and core/renderer.cpp. In this section, we will define both the interface that all Renderers must provide as well asthe start of one instance of a Renderer, the SamplerRenderer.

 

将场景渲染成一张图片的任务由一个实现了Renderer(渲染器)接口的类的实例对象来完成。渲染器是一个抽象类,它规定了一些必须实现的接口。它定义在文件core/renderer.h和core/renderer.cpp中。在这一小节中,我们将定义Renderer的接口,同时将介绍第一个Renderer的例子,SamplerRenderer类。

 

RendererDeclarations


 ≡

class Renderer {

public:

Renderer Interface 24

};

 

The main method that Renderers must provide is Render();the Renderer is passed a pointer to a Scene and computes an image of the scene or more generally, a setof measurements of the scene lighting. For example, in Section 17.3, we definea completely different kind of Renderer thatcomputes measurements of incident illumination at a set of points in the sceneand writes the results to a text file, without generating an image at all.These measurements can then be used for interactive rendering of the scene,among other applications.

 

Renderer的主要接口是Render();渲染器接受一个Scene对象指针,然后计算一个场景的图片,或者更一般化的讲,计算对场景中的光照的测量结果。举个例子,在章节17.3中,我们定义了一个非常特别的Renderer,它负责计算所有入射光的入射点并将这些点集写入一个文本,但不生成图像。这些信息可以提供给其他应用程序使用,参与渲染场景。

 

RendererInterface


 ≡ 24

virtual void Render(const Scene*scene) = 0;

 

Renderers are also required to provide methods that computeinformation about the illumination along rays in the scene. Li() returns the incident radiance along the given ray. Inaddition to the ray and the scene, it takes a number of additional parameters:the Sample (which may be NULL) providesrandom sample values for Monte Carlo integration computationsin the integrator, and the RNG is a pseudo-random number generator that is also available forthis purpose. The MemoryArena performs efficient allocation of small temporary amounts of memorythat may be needed while computing radiance along the ray. Finally, informationabout the ray’s geometric intersection point can be returned via the Intersection, if its pointer is non-NULL, and the volumetric transmittance alongthe ray is returned via the T parameter, also if non-NULL.

 

同时渲染器需要提供计算场景中的光线的照明信息的接口。Li() 函数返回指定光线的入射辐射量。除了ray和scene参数,还需要几个额外的参数:Sample(采样器)(可以为NULL)为集成了蒙特卡洛方法的积分器提供随机样本,RNG是一个伪随机数生成器,也是给积分器用的。MemoryArena为计算射线的辐射量时需要频繁申请临时的零散小内存时提供高效的分配方法(内存管理)。最后是关于射线相交的几何信息,通过Intersection来返回交点----如果不为NULL的话,通过Spectrum来返回射线方向上的光能量传输率。

 

Renderer Interface


 +≡ 24
virtual Spectrum  Li (

const Scene *scene, constRayDifferential &ray,

const Sample *sample, RNG &rng,MemoryArena &arena,

Intersection *isect = NULL, Spectrum*T = NULL)  const = 0;

 

Transmittance() returns the fraction of light thatis attenuated by volumetric scattering along the ray.Renderer implementations will generally dispatch to Integrators (defined in Chapters 15 and 16) to compute the valuesreturned by Li() and Transmittance().

 

Transmittance()函数返回射线方向上的由物体表面散射引起的光能量衰减比率。

Renderer在实现Li()和Transmittance()的计算过程时通常会用上积分器(在第15和第16章定义)。

 

RendererInterface


 +≡ 24
virtual Spectrum  Transmittance(const Scene *scene,

const RayDifferential &ray,const Sample *sample,

RNG &rng, MemoryArena&arena) const = 0;

 

Now we will define the SamplerRenderer implementation of the Renderer interface and show how its Render() method computes an image of the scene. SamplerRenderer is so named because its renderingprocess is driven by a stream ofsamplesfrom a Sampler; each such sample identifies a point on the image at whichto compute the arriving light to form the image. The definition of SamplerRenderer is in the files renderers/samplerrenderer.h and renderers/samplerrenderer.cpp.

 

现在我们将定义SamplerRenderer的实现,并来看一看它的Render()函数是如何将一个场景渲染成图片的。SamplerRenderer(采样渲染器)的名字由来是因为它的渲染过程由一个Sampler(采样器)提供的样本流来进行主导的;每一个样本都代表了光线到达最终渲染图像上的一个像素点。SamplerRenderer定义在文件renderers/samplerrenderer.h 和 renderers/samplerrenderer.cpp中。

 

SamplerRendererDeclarations


 ≡

class SamplerRenderer : publicRenderer {

public:

SamplerRenderer Public Methods

private:

SamplerRenderer Private Data 25

};

 

The SamplerRenderer stores a pointer to a Sampler. The role of this class is subtle, but its implementationcan substantially affect the quality of the images that the system generates.First, the sampler is responsible for choosing the points on the image planefrom which rays are traced. Second, it is responsible for supplying the samplepositions used by the integrators in their light transport computations; forexample, some integrators need to choose random points on light sources tocompute illumination from area lights. Generating a good distribution of thesesamples is an important part of the rendering process that can substantiallyaffect overall efficiency and is discussed in Chapter 7.

 

SamplerRenderer保存了一个Sampler的指针。这个类比较微妙,它的实现可以极大地影响系统生成的图像的质量。首先Sampler负责定位参与跟踪计算的射线对应最终图像上的点。其次,它

也负责在计算这些光线的传输时给积分器提供位置采样;比如说,一些积分器在处理范围光类型的光源时,需要在光源位置选取随机点。生成一份好的样本分布对渲染流程来说非常重要,这能从根本上影响渲染质量,我们在第7章讨论这些内容。

 

SamplerRendererPrivate Data


 ≡ 25

Sampler *sampler;

 

The Camera object controls the viewing and lens parameters such asposition, orientation, focus, and field of view. A Film member variable inside the Camera class handles image storage. The Camera classes are described in Chapter 6, and Film is described in Section 7.8. The Film is responsible for writing the finalimage to disk and possibly displaying it on the screen as it is being computed.

 

Camera对象控制显示和其他一些变量,如位置,朝向,焦距,和FOV。Camera有一个Film成员变量,负责存储渲染的图像。Camera类的介绍在第6章,File类的介绍在7.8小节。File类负责将渲染的图像保存到磁盘上,当然也很可能在渲染完成后直接用于显示。

 

SamplerRendererPrivate Data


 +≡ 25

Camera *camera;

 

Integrators handle the task ofsimulating the propagation of light in the scene in order to compute how muchlight arrives at image sample positions on the film plane. They are so namedbecause they numerically evaluate the integrals in the surface and volume lighttransport equations that describe the distribution of light in the environment.SurfaceIntegrators compute reflected light fromgeometric surfaces, while VolumeIntegratorshandle the scattering from volumetric primitives. Integrators are described inChapters 15 and 16.

 

积分器负责模拟光线在场景中的传播,以便计算有多少光到位于达投影平面上的图像中对应的采样点。他们之所以叫做积分器,是因为他们对描述环境中的物体表面和体积上的光照分布的光传输方程进行数值上的积分运算。SurfaceIntergrators计算几何表面的反射光,VolumeIntergrators处理基本几何体上的散射。积分器在第15章和第16章介绍。

 

SamplerRendererPrivate Data


 +≡ 25

SurfaceIntegrator *surfaceIntegrator;

VolumeIntegrator *volumeIntegrator;

 

The SamplerRenderer constructor just stores pointers tothese objects in member variables. The SamplerRenderer is created in the RenderOptions::MakeRenderer() method, which is in turn called by pbrtWorldEnd(), which is called by the input fileparser when it is done parsing a scene description from an input file and isready to render the scene.

 

SamplerRenderer的构造函数只是简单的将上述这些对象的指针保存起来。SamplerRenderer可以通过RenderOptions::MakeRenderer()函数进行创建,前序的调用链分别是pbrtWorldEnd()函数、input file parser。调用时机是解释器完成场景描述文件的解析并准备好渲染场景时。

 

SamplerRendererMethod Definitions


 ≡

SamplerRenderer::SamplerRenderer(Sampler*s, Camera *c, SurfaceIntegrator *si, VolumeIntegrator *vi) {

sampler = s;

camera = c;

surfaceIntegrator = si;

volumeIntegrator = vi;

}

0 0
原创粉丝点击