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”章节。
- Q108:浅析PBRT-V3的代码结构
- Q110:PBRT-V3十大基类对应的继承关系
- Q114:阅读PBRT-V3官方源代码的正确姿势
- Q133:PBRT-V3,BSSRDF的采样(15.4章节)
- Q137:PBRT-V3,各种采样(Sampling)之间的逻辑
- Q111:PBRT-V3系统概述
- Q116:PBRT-V3场景描述文件.pbrt格式解析
- Q123:PBRT-V3,各种形式的“光传播方程”的推导依据
- Q113:PBRT-V3分别在Linux和Mac下的编译与调试(汇总)
- Q118:PBRT-V3材质及其对应的反射模型(笔记)
- Q125:PBRT-V3,对比VolPathIntegrator::Li()和EstimateDirect()判断Medium的方式
- Q127:PBRT-V3,理解“体渲染”积分器的关键竟然是这张图
- Q128:PBRT-V3,“体渲染”积分器的“传播方程”(15.1章节)
- Q129:PBRT-V3,均匀介质的采样(15.2.1章节)
- Q130:PBRT-V3,非均匀介质的采样(11.3.3章节、15.2.2章节)
- Q141:PBRT-V3,交点处各种微分的求解(球面,3.2章节)
- Q142:PBRT-V3,交点处各种微分的求解(三角形,3.6章节)
- Q146:PBRT-V3,对系统进行拓展(以添加一个新的Integrator为例)
- 黑客马拉松活动如何搞
- Java大数类解决大数加法
- java数组初始化
- 51 Nod 1021 石子归并
- 信号处理第二课:矩阵的 Fantastic Four
- Q108:浅析PBRT-V3的代码结构
- 开通博客,记录以后的知识积累
- 【C#】设计模式-创建型模式
- js 小数取整的函数
- HandlerInterceptor
- Spark之RDD的属性
- http慢速连接攻击
- Unity中SLua、Tolua、XLua和ILRuntime效率评测
- java基础--for循环嵌套实现九九乘法表