88.1 引入(Introduction)

截至当前,回忆一下我们学过的针对直接光照和间接光照的不同反射模型。

直接光照:

Phong反射模型。包含漫反射部分和高光反射部分。

间接光照:

对于镜面材料,有镜面反射模型;

对于高光材料,有高光反射模型;

但是,对于粗糙表面(matte,漫射材料)呢?截至当前,除了ambient,我们尚未考虑漫射材料的其他间接光照。

漫射材料的其他间接光照有两种情况:

1,间接光照来自其他漫射材料的漫反射;

2,间接光照来自其他反射镜面(或高光)材料的镜面(或高光)反射。

如下图示意:

很明显,对于Matte材料的物体,这些间接光照是不能被忽略的。

所谓“全局光照算法”,即是模拟图形中所有对图形产生效果的光线。我们这里将要学习的Path Tracing则是其中一种“全局光照算法”。

88.2 Path Tracing

Path Tracing是一种计算有面积光源的场景中的直接光照和间接光照的简单粗暴的概念上理想的技术。

之所以说其“简单”,是因为“原理简单”。

之所以说其“粗暴”,是因为“如要消除图形中可见的噪音,需要耗费的时间特别长”。

之所以说其“概念上理想”,是因为“其一,能够模拟所有光线,所以‘理想’;其二,费时,所以只能停留在‘概念上’”。

另外,先声明一点。

其中提到“面积光源”指的是发光材质的几何物体,在Path Tracing的过程中考虑的不是“光源”,而是“发光材质”。

这里的发光材质可以是任何几何物体,不必限制于球面、矩形、圆之类。

因为Path Tracing过程中用到的只是“发光材质”的特性,而不是“面积光源”的概念,所以不需要对其对应的几何物体进行采样。

Path Tracing的过程:

一条光线进入场景(如上图中黄色起点的光线),然后开始追踪这条光线。过程中光线会因为撞击到场景中的物体而发生反射(可能是任何BRDF)。一直追踪,一直追踪,直到:

光线撞击到发光材质的物体(如a图所示);

或者:达到最大反射次数(如b图所示);

或者:离开了场景(如c图所示)。

如上三种情况,只有“撞击到发光材质的物体”情况,返回的是发光材质的光;其他两种情况返回的是背景色(黑色)。

追踪过程中,光线在所有撞击点处是怎么反射的呢?

这个是根据撞击点处的材质的BRDF来确定的。所有的材质类中都需要添加一个sample_f()函数来计算发生撞击后反射光线的方向和相应的概率。(这里的“所有材质”不包括“发光材质”,因为当光线撞击到发光材质物体时,返回的是发光材质的光)。

我们再看看之前贴的那张图:

如左图。

原始光线和Matte材质物体相撞于a点,接下来,我们需要对a点进行着色。怎么着色?根据a点的Matte材质颜色、a点的直接光照、a点的间接光照。对于Path Tracing算法,是不考虑“直接光照”的。因为在Path Tracing算法中只有“发光材质的物体”,没有“光源”。或者说Path Tracing算法将“直接光照”也当作“间接光照”来处理。怎么处理?在撞击点a处,由于该处是Matte材质,所以会依据Matte的BRDF对a点处的上半球进行采样。然后根据采样点来确定反射光线的方向和概率。则有可能出现三种情况:1,反射光线离开了场景;2,反射光线如r1直接撞击到了发光材质物体;3,反射光线如r2撞击到了Reflective材质的物体。前面两种情况,返回的是背景色或者发光材质的光,追踪结束。对于第三种情况,当光线撞击到Reflective材质的物体时,接下来则会依据Reflective的BRDF确定后续的反射光线的方向和概率(Reflective反射的方向是确定的)。

如右图。

如果撞击点a处的反射光线撞击到的是Matte材质的物体,后续的的处理方式和a点处的处理方式一样的:撞击点处的上半球进行采样,然后根据采样点来确定后续反射光线的方向和概率。

88.3 C++代码实现

新建一个叫做“PathTrace”的Tracer子类。该类的trace_ray()方法如下:

接下来则是需要在各种材质中添加相应的path_shade()方法。(在这里,我们只添加Emissive、Matte、Reflective三种材质的path_shade())

88.4 测试图形

我们这里的测试图形是Cornell Box。

相关代码:

void
World::build(void) {
//      int num_samples = 1;                // for Figure 26.7(a)
//      int num_samples = 100;           // for Figure 26.7(b)int num_samples =1024;                  // for Figure26.7(c)
//      int num_samples =10000;      // for Figure 26.7(d)vp.set_hres(300);vp.set_vres(300);vp.set_samples(num_samples);vp.set_max_depth(10);background_color =black;tracer_ptr = newPathTrace(this);Pinhole* pinhole_ptr =new Pinhole;pinhole_ptr->set_eye(27.6,27.4, -80.0);pinhole_ptr->set_lookat(27.6,27.4, 0.0);pinhole_ptr->set_view_distance(400);pinhole_ptr->compute_uvw();set_camera(pinhole_ptr);Point3D p0;Vector3D a, b;Normal normal;// box dimensionsdouble width = 55.28;        // x directiondouble height          = 54.88;          //y directiondouble depth = 55.92;   //z direction// the ceiling light -doesn't need samplesEmissive* emissive_ptr= new Emissive;emissive_ptr->set_ce(1.0,0.73, 0.4);emissive_ptr->scale_radiance(100);p0 = Point3D(21.3,height - 0.001, 22.7);a = Vector3D(0.0, 0.0,10.5);b = Vector3D(13.0, 0.0,0.0);normal = Normal(0.0,-1.0, 0.0);Rectangle* light_ptr =new Rectangle(p0, a, b, normal);light_ptr->set_material(emissive_ptr);add_object(light_ptr);// left wallMatte* matte_ptr1 =new Matte;matte_ptr1->set_ka(0.0);matte_ptr1->set_kd(0.6);matte_ptr1->set_cd(0.57,0.025, 0.025);       // redmatte_ptr1->set_sampler(newMultiJittered(num_samples));p0 = Point3D(width,0.0, 0.0);a = Vector3D(0.0, 0.0,depth);b = Vector3D(0.0,height, 0.0);normal = Normal(-1.0,0.0, 0.0);Rectangle*left_wall_ptr = new Rectangle(p0, a, b, normal);left_wall_ptr->set_material(matte_ptr1);add_object(left_wall_ptr);// right wallMatte* matte_ptr2 =new Matte;matte_ptr2->set_ka(0.0);matte_ptr2->set_kd(0.6);matte_ptr2->set_cd(0.37,0.59, 0.2);     // green   from Photoshopmatte_ptr2->set_sampler(newMultiJittered(num_samples));p0 = Point3D(0.0, 0.0,0.0);a = Vector3D(0.0, 0.0,depth);b = Vector3D(0.0,height, 0.0);normal = Normal(1.0,0.0, 0.0);Rectangle*right_wall_ptr = new Rectangle(p0, a, b, normal);right_wall_ptr->set_material(matte_ptr2);add_object(right_wall_ptr);// back wallMatte* matte_ptr3 =new Matte;matte_ptr3->set_ka(0.0);matte_ptr3->set_kd(0.6);matte_ptr3->set_cd(1.0);        // whitematte_ptr3->set_sampler(newMultiJittered(num_samples));p0 = Point3D(0.0, 0.0,depth);a = Vector3D(width,0.0, 0.0);b = Vector3D(0.0,height, 0.0);normal = Normal(0.0,0.0, -1.0);Rectangle*back_wall_ptr = new Rectangle(p0, a, b, normal);back_wall_ptr->set_material(matte_ptr3);add_object(back_wall_ptr);// floorp0 = Point3D(0.0, 0.0,0.0);a = Vector3D(0.0, 0.0,depth);b = Vector3D(width,0.0, 0.0);normal = Normal(0.0,1.0, 0.0);Rectangle* floor_ptr =new Rectangle(p0, a, b, normal);floor_ptr->set_material(matte_ptr3);add_object(floor_ptr);// ceilingp0 = Point3D(0.0,height, 0.0);a = Vector3D(0.0, 0.0,depth);b = Vector3D(width,0.0, 0.0);normal = Normal(0.0,-1.0, 0.0);Rectangle* ceiling_ptr= new Rectangle(p0, a, b, normal);ceiling_ptr->set_material(matte_ptr3);add_object(ceiling_ptr);// the two boxesdefined as 5 rectangles each// short box// topp0 = Point3D(13.0,16.5, 6.5);a = Vector3D(-4.8,0.0, 16.0);b = Vector3D(16.0,0.0, 4.9);normal = Normal(0.0,1.0, 0.0);Rectangle*short_top_ptr = new Rectangle(p0, a, b, normal);short_top_ptr->set_material(matte_ptr3);add_object(short_top_ptr);// side 1p0 = Point3D(13.0,0.0, 6.5);a = Vector3D(-4.8,0.0, 16.0);b = Vector3D(0.0,16.5, 0.0);Rectangle*short_side_ptr1 = new Rectangle(p0, a, b);short_side_ptr1->set_material(matte_ptr3);add_object(short_side_ptr1);// side 2p0 = Point3D(8.2, 0.0,22.5);a = Vector3D(15.8,0.0, 4.7);Rectangle*short_side_ptr2 = new Rectangle(p0, a, b);short_side_ptr2->set_material(matte_ptr3);add_object(short_side_ptr2);// side 3p0 = Point3D(24.2,0.0, 27.4);a = Vector3D(4.8, 0.0,-16.0);Rectangle* short_side_ptr3= new Rectangle(p0, a, b);short_side_ptr3->set_material(matte_ptr3);add_object(short_side_ptr3);// side 4p0 = Point3D(29.0,0.0, 11.4);a = Vector3D(-16.0,0.0, -4.9);Rectangle*short_side_ptr4 = new Rectangle(p0, a, b);short_side_ptr4->set_material(matte_ptr3);add_object(short_side_ptr4);// tall box// topp0 = Point3D(42.3,33.0, 24.7);a = Vector3D(-15.8,0.0, 4.9);b = Vector3D(4.9, 0.0,15.9);normal = Normal(0.0,1.0, 0.0);Rectangle*tall_top_ptr = new Rectangle(p0, a, b, normal);tall_top_ptr->set_material(matte_ptr3);add_object(tall_top_ptr);// side 1p0 = Point3D(42.3,0.0, 24.7);a = Vector3D(-15.8,0.0, 4.9);b = Vector3D(0.0,33.0, 0.0);Rectangle* tall_side_ptr1= new Rectangle(p0, a, b);tall_side_ptr1->set_material(matte_ptr3);add_object(tall_side_ptr1);// side 2p0 = Point3D(26.5,0.0, 29.6);a = Vector3D(4.9, 0.0,15.9);Rectangle*tall_side_ptr2 = new Rectangle(p0, a, b);tall_side_ptr2->set_material(matte_ptr3);add_object(tall_side_ptr2);// side 3p0 = Point3D(31.4,0.0, 45.5);a = Vector3D(15.8,0.0, -4.9);Rectangle*tall_side_ptr3 = new Rectangle(p0, a, b);tall_side_ptr3->set_material(matte_ptr3);add_object(tall_side_ptr3);// side 4p0 = Point3D(47.2,0.0, 40.6);a = Vector3D(-4.9,0.0, -15.9);Rectangle*tall_side_ptr4 = new Rectangle(p0, a, b);tall_side_ptr4->set_material(matte_ptr3);add_object(tall_side_ptr4);
}

输出图形:

单像素点的采样次数为1,耗时248s:

单像素点的采样次数为100,耗时976s:

单像素点的采样次数为1024,耗时6763s:

88.5 其他说明

如上测试图形,图形中很多噪声(黑点),这是因为原始光线撞击到该点后的反射光线没能撞击到发光材质。由于发光材质的面积有限,所以用Path Tracing算法生成的图形噪声较多,而且耗时较长。但是,Path Tracing算法模拟了场景中所有的光线传播机制,所以,只要采样次数足够多,时间足够长,Path Tracing算法生成的图形则是最接近现实的。所以,一般用Path Tracing算法所生成的图形作为参考图形,以用于验证其他算法的有效性。

完整的代码,参考:http://download.csdn.net/detail/libing_zeng/9783680

Referrance

[1]. Kevin Suffern, Ray Tracing from theGround Up, A K Peters Ltd, 2007.

[2]. https://en.wikipedia.org/wiki/Path_tracing

Q88:全局光照(Global Illumination)——Path Tracing相关推荐

  1. (中文详解篇)smallpt: 99行代码完成全局光照Path Tracing

    目录 0. 什么是SmallPT Features 1. 光线追踪需要了解知识 1.1 什么是全局光照? 1.2 渲染方程 2. SmallPT代码分析 2.1 代码块1 2.2 代码块2 2.2.1 ...

  2. 全局光照技术解析Global Illumination Explained

    解析全局光照Global Illumination Explained 前言:Global Illumination全局光照技术是实时渲染的必然发展方向.我参考了一些研究成果,琢磨了一下,让更多的人可 ...

  3. GAMES101课程学习笔记—Lec 14(2)~16:Ray Tracing(2) BRDF、渲染方程、全局光照、路径追踪

    GAMES101课程学习笔记-Lec 14(2)~16:Ray Tracing(2) BRDF.渲染方程.全局光照.路径追踪 0 引入--辐射度量学概述 1 相关概念 1.1 Radiant Ener ...

  4. (六)unity自带的着色器源码剖析之——————Unity3D的全局光照和阴影:上篇(全局照明GI和局部照明)

    一.全局照明和局部照明 全局照明(global illumination,GI)是用于向三维场景中添加更为逼真的光照效果的一组算法总称.全局算法不仅考虑光源发出的光与被照亮物体之间的关系,即直接照明( ...

  5. Q89:全局光照(Global Illumination)——Path Tracing(只用于间接光照)

    89.1 Path Tracing只用于间接光照 根据Path Trace的算法,只有当最终的反射光线撞击到发光材质物体时,才会对最初的撞击点进行"有效"着色,否则着色为" ...

  6. 实时高清渲染:全局光照(Global Illumination)[1]

    目录 基础知识: Radiance: Irradiance: Radiant flux: Radiant Intensity: Solid Angle: Lambertian surface: Lam ...

  7. Unity Global Illumination(Unity 全局光照 ) 官方手册笔记系列之Enlighten

    Enlighten 本文档主要是对Unity官方手册的个人理解与总结(其实以翻译记录为主:>) 仅作为个人学习使用,不得作为商业用途,欢迎转载,并请注明出处. 文章中涉及到的操作都是基于Unit ...

  8. 实时全局光照(Real-time Global Illumination)与Reflective Shadow Maps(RSM)

    文章目录 1 概述 1.1 什么是全局光照(GI)? 1.2 光照模型处理间接光照的方法 1.3 实时全局光照的思想 2 GI的主要问题 3 方法一:Reflective Shadow Maps(RS ...

  9. 【技术美术图形部分】PBR全局光照:理论知识补充

    写在前面 最近做东西的流程是这样的,想实现一个风格化森林小场景,场景体现的主体是风格化树和交互草 --> 于是用了两天时间学SpeedTree做树模型 --> 用了两天时间SD做了树干贴图 ...

最新文章

  1. 信息安全系统设计基础 实验四:外社驱动程序设计 20135327郭皓 20135329 李海空...
  2. python-- Image 模块
  3. 了解一下MongoDB中的写关注(write concern)
  4. Ubuntu18.04安装常用软件
  5. webpack使用插件将css抽取出来
  6. java面试题二十一 异常
  7. 快应用quickapp快速入门教程 by五个半柠檬
  8. jQuery (二)
  9. 华侨大学计算机学院2019,华侨大学计算机科学与技术学院2019年非全日制研究生复试成绩(第四批)...
  10. ssh无密码登录设置方法以及出现问题 ECDSA host key 和IP地址对应的key不同的解决...
  11. java-第十一章-类的无参方法-模拟ATM机进行账户余额查询
  12. Photoshop cc 2019安装与破解(附资源)
  13. require smarty.class.php 报错,Smarty SSTI
  14. python图像缺陷检测_python OpenCV 实现缺陷检测
  15. TDSQL携手金蝶云·苍穹,发布“国产数据库联合解决方案”
  16. 运用卫星数据及AI技术 微软推出新一代模拟飞行游戏
  17. 解析SWD协议,烧写程序
  18. 基于亨利气体溶解度优化算法的函数寻优算法
  19. DevExpress 设置DateEdit显示年月
  20. Mysql数据库常用的词汇,新手必备

热门文章

  1. 51Nod 1046 A^B Mod C(日常复习快速幂)
  2. 排序总结---常用的排序算法总结,java和js实现
  3. sqlserver自动备份脚本
  4. jQuery开发之windows边栏小工具开发(Gadget development)- wi...
  5. Leetcode 111.二叉树的最小深度
  6. 图像超分工具,在线工具
  7. tensorflow 中的 array_ops
  8. hdu4417(Super Mario)—— 二分+划分树
  9. 【bzoj1951】【古代猪文】Lucas定理+欧拉定理+孙子定理
  10. select模型的原理、优点、缺点