Q108:浅析PBRT-V3的代码结构

来源:互联网 发布:java变量类型怎么赋值 编辑:程序博客网 时间:2024/05/17 07:35


前续知识:

Q106:Linux系统下安装编译PBRT-V3
Q107:Linux系统下GDB对PBRT-V3进行debug


108.1 理论介绍

咱这篇文章要讲的内容不是如下这些基类,当然这些绝对时系统的核心结构。

这篇文章的主要内容是:从.pbrt场景描述文件到render()循环前的这个过程。


PBRT中的场景描述文件相当于《Ray Tracing from the Ground Up》中的world::build()。


接下来,咱以Q106:Linux系统下安装编译PBRT-V3中用到的sharp.pbrt为例来进行说明。


场景描述文件,即配置文件。描述场景所包含的:shapes、material等等信息。

比如:场景中有两个球、球的材质时matte。


sharp.pbrt的功能相当于《Ray Tracing from the Ground Up》中的World::build(),即构建场景。

《Ray Tracing from the Ground Up》中的World::build()直接用C++写的,所以系统“认识”。

但是,sharp.pbrt是如下这个鬼样子,系统怎么认识呢?

#sharp.pbrt -- a simple pbrt input file that displays a cone, sphere#              and refletive plane#Richard P. Sharp - CIS782 Fall 2004#first we set up the eyeLookAt 1 1 10   0 0 -1  0 1 0 #ex ey ez lx ly lz ux uy uz#the cameraCamera "perspective" "float fov" [30]#this is the filter used for antialiasingPixelFilter "mitchell" "float xwidth" [2] "float ywidth" [2]#name the fileFilm "image" "string filename" ["sharp.exr"]     "integer xresolution" [400] "integer yresolution" [400]#begin describing sceneWorldBegin#light sourceAttributeBegin  CoordSysTransform "camera"  LightSource "distant"               "point from" [0 0 0] "point to"   [0 0 1]              "color L"    [3 3 3]AttributeEnd#transform the worldAttributeBegin  Translate 0 -1 0  Rotate 35 0 1 0  #define an orangish sphere  AttributeBegin    Translate -1 .75 -1.5    Rotate -90 1 0 0      Material "matte" "color Kd" [0.1 0.9 0.1]    Shape "sphere" "float radius" [.75]   AttributeEnd  #define a blue cone  AttributeBegin    Translate 0 0 2.5    Rotate -90 1 0 0    #this describes the material properties    Material "matte" "color Kd" [0.9 0.1 0.1]        #this is the shape    Shape "cone" "float radius" [.75] "float height" [2]  AttributeEnd  #define a reflective ground plane  AttributeBegin    Scale 20 20 20    Material "uber" "color Kd" [0.1 0.1 0.9] "color Kr" [0.9 0.9 0.9] "color Ks" [0.1 0.1 0.1] "float roughness" [0.9] "float index" [1.34]    #this is a triangle mesh, the first set of points define four xyz     #coordinates, the second set defines the mesh by indexing into    #those points    Shape "trianglemesh" "point P" [ -1 0 -1  1 0 -1  1 0 1  -1 0 1 ]     "integer indices" [ 0 1 2 2 3 0 ]  AttributeEndAttributeEndWorldEnd

这个文件的具体内容,咱先不关心。咱现在要知道的是:每一行的第一个“单词”/“变量”可以理解为关键字(#开头的是注释)

比如:Shape、Material、WorldEnd等等。


为了“认识”sharp.pbrt文件中的内容,PBRT-V3借助外部工具flex和bison(后文称“解析工具”)来帮忙解析sharp.pbrt。

为了让解析工具能够解析sharp.pbrt,咱得做一些约定。这个约定就是前面提到的sharp.pbrt中“关键字”。

pbrtparse.y就是告诉解析工具怎么解析sharp.pbrt内容编写的。

pbrtparse.y中会告诉解析工具去解析sharp.pbrt中的每一个关键字。

解析完之后,解析工具还会根据partparse.y生成partparse.cpp。


比如:


为了sharp.pbrt中的如下内容:

   Shape "sphere" "float radius" [.75] 
咱需要在pbrtparse.y中编写:

| SHAPE STRING paramlist{    pbrt::ParamSet params;    pbrt::InitParamSet(params, pbrt::SpectrumType::Reflectance);    pbrt::pbrtShape($2, params);    pbrt::FreeArgs();}
然后,解析工具根据pbrtparse.y中的内容生成pbrtparse.cpp中对应的内容如下:

intyyparse (void){......  case 57:#line 573 "/home/lbzeng/pbrt-v3/src/core/pbrtparse.y" /* yacc.c:1646  */    {    pbrt::ParamSet params;    pbrt::InitParamSet(params, pbrt::SpectrumType::Reflectance);    pbrt::pbrtShape((yyvsp[-1].string), params);    pbrt::FreeArgs();}}
pbrt::pbrtShape()是在~/pbrt-v3/src/core/api.cpp中实现的。

站在PBRT系统的开发者的角度来看:

因为PBRT系统时给大家用的,所以不能像《Ray Tracing from the Ground Up》那样通过在代码中编写World::build()来描述场景。

终端用户要使用咱们的PBRT系统的话,用什么方式来描述他们自己的场景呢?

从而,就有了.pbrt场景描述文件。

我们给终端用户规定一些关键字,让他们根据这些关键字来描述场景。

终端用户提供.pbrt场景描述文件后,系统怎么解析呢?

当然,咱们可以编写C++代码来进行解析。

但是,上面有成熟的解析工具(flex,bison)能够生成解析源代码(by the way,flex和bison被称为“生成解析器的解析工具”),咱直接使用。

为了使用解析工具,咱只需要告诉解析工具:关键字是什么?遇到关键字时应该干什么?(比如:遇到关键字Shape,调用pbrt::pbrtShape())

这些东西就写在pbrtparse.y文件中。

解析工具根据pbrtparse.y生成pbrtparse.cpp(即解析器)。

然后,系统就可直接调用解析器(pbrtparse.cpp)中的函数(yyparse())读取sharp.pbrt文件中的内容了。


图示说明如下:

Shape、Material等关键字的处理类似,最终通过api.cpp中的函数call到具体对应的shape、material。


解析阶段结束时,得到两样东西:Integrator对象、Scene对象



有个问题:场景初始化结束之后,怎么进入渲染循环呢?

这个是在关键字“WorldEnd”的处理函数pbrt::pbrtWorldEnd()中完成的。

该函数中有这么一条语句“integrator->Render(*scene);”。即在场景初始化结束时,开始渲染。


108.2 Callstack

接下来,咱用pbrt.debug来渲染sharp.pbrt。

(pbrt.debug参考:Q107:Linux系统下GDB对PBRT-V3进行debug)


lbzeng@lbzeng-ubuntu:~$ gdb pbrt.debug

//进入debug环境

GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1Copyright (C) 2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "i686-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from pbrt.debug...done.
(gdb) set args --nthreads=1 ~/pbrt/sharp.pbrt
//设置debug参数

(gdb) b /home/lbzeng/pbrt-v3/src/shapes/sphere.h:55
//设置断点(有多个断点需要设置,此处不一一贴出)

(gdb) r
//运行

Starting program: /usr/bin/pbrt.debug --nthreads=1 ~/pbrt/sharp.pbrt [Thread debugging using libthread_db enabled]Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".pbrt version 3 (built May 20 2017 at 08:58:48) [Detected 4 cores]*** DEBUG BUILD ***Copyright (c)1998-2016 Matt Pharr, Greg Humphreys, and Wenzel Jakob.The source code to pbrt (but *not* the book contents) is covered by the BSD License.See the file LICENSE.txt for the conditions of the license.
然后,在“Shape”断点处停住

Breakpoint 5, pbrt::CreateSphereShape (o2w=0xb7b9f040, w2o=0xb7b9f0c0,    reverseOrientation=false, params=...)    at /home/lbzeng/pbrt-v3/src/shapes/sphere.cpp:321321        Float radius = params.FindOneFloat("radius", 1.f);
(gdb) bt
//打印此处Callstack
#0  pbrt::CreateSphereShape (o2w=0xb7b9f040, w2o=0xb7b9f0c0,    reverseOrientation=false, params=...)    at /home/lbzeng/pbrt-v3/src/shapes/sphere.cpp:321#1  0x082c1b7e in pbrt::MakeShapes (name="sphere", object2world=0xb7b9f040,    world2object=0xb7b9f0c0, reverseOrientation=false, paramSet=...)    at /home/lbzeng/pbrt-v3/src/core/api.cpp:304#2  0x082c8ae4 in pbrt::pbrtShape (name="sphere", params=...)    at /home/lbzeng/pbrt-v3/src/core/api.cpp:1171#3  0x084127cc in yyparse () at /home/lbzeng/pbrt-v3/src/core/pbrtparse.y:576#4  0x083283f9 in pbrt::ParseFile (filename="/home/lbzeng/pbrt/sharp.pbrt")    at /home/lbzeng/pbrt-v3/src/core/parser.cpp:63#5  0x082c0592 in main (argc=3, argv=0xbffff104)    at /home/lbzeng/pbrt-v3/src/main/pbrt.cpp:157
(gdb) c
//继续运行
Continuing.
然后,在“材料”断点处停住

Breakpoint 4, pbrt::CreateMatteMaterial (mp=...)    at /home/lbzeng/pbrt-v3/src/materials/matte.cpp:6666            mp.GetSpectrumTexture("Kd", Spectrum(0.5f));
(gdb) bt

//打印此处Callstack

#0  pbrt::CreateMatteMaterial (mp=...)    at /home/lbzeng/pbrt-v3/src/materials/matte.cpp:66#1  0x082c2f31 in pbrt::MakeMaterial (name="matte", mp=...)    at /home/lbzeng/pbrt-v3/src/core/api.cpp:415#2  0x082c9782 in pbrt::GraphicsState::CreateMaterial (    this=0x8a300a0 <pbrt::graphicsState>, params=...)    at /home/lbzeng/pbrt-v3/src/core/api.cpp:1256#3  0x082c8b21 in pbrt::pbrtShape (name="sphere", params=...)    at /home/lbzeng/pbrt-v3/src/core/api.cpp:1173#4  0x084127cc in yyparse () at /home/lbzeng/pbrt-v3/src/core/pbrtparse.y:576#5  0x083283f9 in pbrt::ParseFile (filename="/home/lbzeng/pbrt/sharp.pbrt")    at /home/lbzeng/pbrt-v3/src/core/parser.cpp:63#6  0x082c0592 in main (argc=3, argv=0xbffff104)    at /home/lbzeng/pbrt-v3/src/main/pbrt.cpp:157

(gdb) c

//继续运行

Continuing.
然后在“Integrator”断点处停住

Breakpoint 8, pbrt::SamplerIntegrator::Render (this=0x8a4f480, scene=...)    at /home/lbzeng/pbrt-v3/src/core/integrator.cpp:233233        Bounds2i sampleBounds = camera->film->GetSampleBounds();
(gdb) bt
//打印此处Callstack
#0  pbrt::SamplerIntegrator::Render (this=0x8a4f480, scene=...)    at /home/lbzeng/pbrt-v3/src/core/integrator.cpp:233#1  0x082ca8ad in pbrt::pbrtWorldEnd ()    at /home/lbzeng/pbrt-v3/src/core/api.cpp:1386#2  0x08412b98 in yyparse () at /home/lbzeng/pbrt-v3/src/core/pbrtparse.y:643#3  0x083283f9 in pbrt::ParseFile (filename="/home/lbzeng/pbrt/sharp.pbrt")    at /home/lbzeng/pbrt-v3/src/core/parser.cpp:63#4  0x082c0592 in main (argc=3, argv=0xbffff104)    at /home/lbzeng/pbrt-v3/src/main/pbrt.cpp:157


简单来说,sharp.pbrt中的关键字和api.cpp中的函数相对应


参考:

《Physically Based Rendering_From Theory To Implementation. 3rd. 2016》中“Appendix B: Scene Description Interface”章节。

阅读全文
1 0
原创粉丝点击