前续知识:

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 eye
LookAt 1 1 10   0 0 -1  0 1 0 #ex ey ez lx ly lz ux uy uz#the camera
Camera "perspective" "float fov" [30]#this is the filter used for antialiasing
PixelFilter "mitchell" "float xwidth" [2] "float ywidth" [2]#name the file
Film "image" "string filename" ["sharp.exr"]"integer xresolution" [400] "integer yresolution" [400]#begin describing scene
WorldBegin#light source
AttributeBeginCoordSysTransform "camera"LightSource "distant" "point from" [0 0 0] "point to"   [0 0 1]"color L"    [3 3 3]
AttributeEnd#transform the world
AttributeBeginTranslate 0 -1 0Rotate 35 0 1 0#define an orangish sphereAttributeBeginTranslate -1 .75 -1.5Rotate -90 1 0 0Material "matte" "color Kd" [0.1 0.9 0.1]Shape "sphere" "float radius" [.75] AttributeEnd#define a blue coneAttributeBeginTranslate 0 0 2.5Rotate -90 1 0 0#this describes the material propertiesMaterial "matte" "color Kd" [0.9 0.1 0.1]#this is the shapeShape "cone" "float radius" [.75] "float height" [2]AttributeEnd#define a reflective ground planeAttributeBeginScale 20 20 20Material "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 pointsShape "trianglemesh" "point P" [ -1 0 -1  1 0 -1  1 0 1  -1 0 1 ]"integer indices" [ 0 1 2 2 3 0 ]AttributeEndAttributeEnd
WorldEnd

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

比如: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中对应的内容如下:

int
yyparse (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.1
Copyright (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:321
321        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:66
66            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:233
233        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的代码结构相关推荐

  1. OpenOCD刷写FLASH代码结构浅析(基于RISCV)

    1.配置文件中对应命令的分析 我们一般在使能OpenOCD的刷写功能的时候,需要在OpenOCD的cfg文件中添加如下两条语句: (1) $_TARGETNAME configure -work-ar ...

  2. SPDK代码结构浅析

    最近这三周时间一直因为工作的需要在研究SPDK移植到RISCV平台上,在编译通过的时候,也顺带把SPDK的代码粗粗过了一遍,顺便做了一点笔记. SPDK (Storage Performance De ...

  3. 最全Pycharm教程(43)——Pycharm扩展功能之UML类图使用 代码结构

    版权声明:本文为博主原创文章,转载时麻烦注明源文章链接,谢谢合作 https://blog.csdn.net/u013088062/article/details/50353202 1.什么是UML ...

  4. 微服务实战之春云与刀客(三)—— 面向接口调用代码结构实例

    2019独角兽企业重金招聘Python工程师标准>>> 概述 在上一篇中提到了spring cloud 面向接口调用的开发风格,这一篇会举一个简单的但完整的例子来说明整个代码结构. ...

  5. Python外壳:代码结构!(IF WHILE FOR RANGE...)

    #:octothorpe 书中说它是八脚怪物!哈哈! 注释就要在前面加上一个#符号! 在print语句里,恢复正常的符号功能! \连接符号: 这个样子就不会一行输入很多的东西,读起来不舒服!功能也是一 ...

  6. [转]VSTO Office二次开发RibbonX代码结构

    前段时间,碰到对于PPT中控制一些命令的问题,也是很是查找了不少的资料,最后使用的是RibbonX的形式解决的,发现RibbonX也是如此的高效. 文章来自:<细品RibbonX(9):层次分明 ...

  7. 解读eXtremeComponents代码结构--转载

    原文地址:http://blog.csdn.net/lark3/article/details/1937466 大致整理了去年写的东西,罗列如下: ec是一系列提供高级显示的开源JSP定制标签,当前的 ...

  8. storm源码之storm代码结构【译】

    说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于Storm进行源码级学习和研究的朋友有所帮助 ...

  9. c++服务器开发学习--02--MySQL,Redis,ASIO,iocp,TrinityCore代码结构,c++对象模型

    c++服务器开发学习--02--MySQL,Redis,ASIO,iocp,TrinityCore代码结构,c++对象模型 MySQL 问题 Redis Asio iocp TrinityCore代码 ...

  10. spring cloud云服务架构 - particle云架构代码结构讲解

    上一篇我们介绍了spring cloud云服务架构 - particle云架构代码结构,简单的按照几个大的部分去构建代码模块,让我们来回顾一下: 第一部分: 针对于普通服务的基础框架封装(entity ...

最新文章

  1. Apache启用mod_expires模块
  2. python爬虫小说代码示例-中文编程,用python编写小说网站爬虫
  3. Hibernate 关系映射
  4. Magento 2数据库EAV模型结构
  5. 如何使用第三方日志记录提供程序替代.NET Core中的内置程序
  6. 每天一个linux命令-curl命令
  7. sh文件进行qsub提交任务到远程服务器训练
  8. 2021年中国船用燃气发动机市场趋势报告、技术动态创新及2027年市场预测
  9. python 延时运行命令_使用子进程延迟执行命令
  10. Mac上IDA报错/:Permission denied Please specify another file path for the database
  11. PDMS管道设计基础到精通视频教程
  12. mysql字段命名_数据库表及字段命名规范
  13. 临时邮箱email网址收集
  14. 如何提高自身数学分析水平?
  15. 做Android开发摸鱼是要付出代价的,被主管劝退,我后悔了!
  16. 晶体(crystal)和晶振(oscillator)的区别
  17. Java工程师只要掌握这些知识点,就能给面试官一个满意的答案,挑战高薪
  18. 为什么越来越多的企业选择智能客服系统?
  19. Oracle 分析函数(Analytic Functions) 说明
  20. 一年成为Emacs高手(像神一样使用编辑器)

热门文章

  1. 我的天哪我有博客了!
  2. .Net快速获取网络文本文件最后一段文字-小应用
  3. 老男孩linux高级架构 百度云盘下载
  4. 为22-29岁的人解释一下什么叫工作(转)
  5. [转载] 老友记——潘石屹 任志强《天台论道》(下)
  6. WordPress精美免费主题分享系列全集
  7. 【贪心】LeetCode 55. Jump Game
  8. Leetcode 129. 根到叶子结点数字之和
  9. 由通项为In(1+1\n)的级数引申...
  10. symbol lookup error: undefined symbol:PySlice_Unpack