光线追踪初探

身为一个计算机图形学领域的小白,最近由于课程的缘故学习了一些光线追踪方面的知识,并实现了基本的代码,现在分享给大家。希望读者能从一无所知到稍稍理解光线追踪的原理和意义,我的目的就达到了。

光线追踪的效果是生成一幅与真实世界高度相似的图片,先上结果图:

光线追踪效果

图中包含4个球体、1个正方体和地面。其中,绿球具有光滑表面,可以看到上面反射的其它物体的图案;红球具有光滑表面而且透明,可以透过它看到后面的蓝球;青球、黄色正方体和地面的表面是粗糙的,既没有反射也没有透射。另外,根据阴影的方向可以判断出光源位于屏幕的左上方。

以上就是图中包含的所有信息。接下来,我们将一步步揭开它的神秘面纱。

渲染

我们常常听到“渲染”这个词,却很少人清楚它的真正含义。当我们想要看到一个三维场景时,第一步要建立它的三维模型。这个模型存储在计算机中,它是真正的三维场景,但是我们看不到效果。要想从各个视角来观察这个三维模型,就要把它渲染成二维图片。就好像我们所处的世界是一个巨大的三维场景,无论你看或不看,它就在那里。当我们用眼睛来观察这个世界时,三维世界在视网膜上形成二维的像,这个像就是渲染的结果。

全局光照

对人来说,射入眼睛的光自动拼合成一幅完整的图像,这是自然而然是事情。但是计算机只有三维场景没有光,怎么办?

我们自己创造光。

我们完全仿照真实世界的物理规律,让三维场景中的光源向四面八方发出无数条光线,根据反射、折射、散射等等光学定律追踪每一条光线的轨迹。这样得到的效果称为全局光照,相对于局部光照,全局光照中任何一个物体都受到直接的光源照射和间接的来自其它物体反射光的照射。可以想象的是,这样追踪的结果是无穷无尽的,最初发出的每一条光线都会进一步衍生出无数条光线。在真实世界中,它们可以按照物理规律安静的发生,可是在计算机中我们实在无法处理如此大的计算量。

幸运的是,对于旨在渲染一幅图片的我们来说,大部分光线都是毫不相干的,我们只要追踪那些汇聚入摄像机镜头的光线就可以了。这种方法就是本文所讲的光线追踪

光线追踪

与上一段提到方法恰好相反,我们让光线从摄像机镜头出发,而且只发出特定角度的光线。这些光线恰好每一条对应最后生成的二维图片中的一个像素,这样的话,生成一幅640x480的位图就只需要307200条光线。

下图展示了生成一个9x8的位图的光线追踪原理。在一个三维笛卡尔坐标系中(图中没有画出坐标轴的位置,可以任意选定),相机(Camera)和图像(Image)的位置一旦确定,图像中所能呈现的三维场景的范围也就随之确定。从相机发出72条光线,穿过图像中每个小方格的中心。对每一条光线,找到场景中与之最近的交点。在本例中,一些光线会与球面相交,如果该球体既能反射又能透射(这些性质作为物体的固有属性事先已在场景中定义),光线在交点处将会生成两条新的反射光线和折射光线。于是,这些新的光线将按照与最初的光线相同的处理办法,一直递归处理下去。但是,递归总要有结束条件的,当光线不与任何物体相交,即射向了无穷远处,递归就可以结束了。然而总有可能出现无论如何总有物体与之相交的情况,那么我们就设置一个最大递归深度,一旦超过了这个深度就强制停止递归。

光线追踪原理

递归了半天不要忘记我们的初衷,我们是为了在图像上成像而做的光线追踪。图像上每个点代表一个像素,它的RGB分量决定了该点的颜色。而我们做光线追踪的目的就是得到最初穿过这个像素的光线的真实RGB分量。在整个递归过程中,考虑真实世界的物理规律,入射光线的颜色与入射角、物体颜色、反射光线颜色和透射光线颜色有关,它们之间的关系可以用菲涅尔公式来描述,在此不做具体解释。最终,我们递归的结果相当于把所有反射和折射的效果都融合到了最初穿过图像的光线上,因此,把这些光线的颜色存入位图的相应位置就得到了一幅图像。

这就是光线追踪的基本原理。

然而,懂得了这些原理并不代表你就能写出一套光线追踪的程序。因为实际实现过程中存在的问题很多很多,绝不是百十行代码就能搞定的。我也不是做计算机图形学方面研究的,对光线追踪的理解还很是肤浅。因此本文不再详细讲解具体的实现过程,想要更进一步了解的可以访问参考资料中列出的前两篇文章,这两位作者是计算机图形学领域的专家,我从他们那里受益颇多。

另外,需要指出的是,虽然光线追踪已经尽可能地降低了计算量,但目前的计算机硬件并不支持对其加速,因此做不到实时渲染,只能用于离线渲染。

代码实现

无论如何还是应该提一下实现代码,不然对读者来说本文就太过空洞了。

首先,我们用Solid类来表示三维场景中的物体,这是一个物体的基类,特定的形状如球体、正方体通过继承该类并覆写必要的方法来定义。在本例中,我们定义了球体Sphere和立方体Cube两个派生类。它们需要重写Solid中的intersectnhit方法。intersect方法用于判断给定光线是否与本物体相交,且给出两个交点(射入和射出)的距离。nhit方法用于计算给定交点处的法线方向。球体和立方体分别重新实现了这两个方法。

有了三维场景之后,我们就可以开始光线追踪。调用render函数完成整个光线追踪的过程,并生成一幅图片。可以通过render函数的参数调整相机和图像所处位置,以达到变换视角的效果。在render中,对每一条光线递归调用trace函数,返回值为该光线的颜色。在trace中遍历场景中的所有物体,找到交点并计算反射和折射光线,进入下一次递归。

我把完整代码上传到了GitHub上,大家可以前往下载。渲染结果是一个ppm格式的文件,为了直接显示该文件,我使用了opencv库。因此,如果你的电脑中没有安装opencv,代码可能会报错。那么你只需要删除showpicture这个文件,并在主函数中去掉showpicture(file)这一行代码即可。运行结束后在工程目录中找到生成的1.ppm文件,使用Photoshop打开,或到https://www.coolutils.com/online/PPM-to-PNG 上面在线转换成其它图片格式就可以看到效果了。

其它效果展示

如果我们想让画面动起来,有两种方式,让场景中的物体移动或让观察视角移动。像连拍照片一样在移动的同时不断地执行光线跟踪,生成一帧帧图片,再将它们连接起来就形成了一段视频。下面给出两个使用该场景制作出的视频片段。

视频1:视角移动

光线追踪-视角移动

视频2:光源移动

光线追踪-光源移动

需要改进的地方

相对于其它成功的光线跟踪作品来说,本文展示的效果有些相形见绌,尚有许多需要改进的地方。

粗糙物体表面受到光照的部分亮度完全一致,区分不开。比如正方体的左表面和上表面颜色完全一样,根本看不到棱的存在。这是因为我们对粗糙表面的处理太简单,只考虑被遮挡和不被遮挡两种情况。然而现实世界中,粗糙表面的颜色和亮度不光与光源有关,还与其他物体反射过来的光线颜色和亮度有关。改进方法是使用一种称为Path Tracing的技术,这会产生比光线追踪更好的效果。感兴趣的读者可以参考《Path Tracing介绍》这篇文章。

给物体表面添加纹理是个常见的话题。这需要做一些额外的工作,在参考资料的第二篇中讲解了如何添加纹理。

最后,我想说计算机图形学是一个非常大的学科,而且非常难。但它又极其重要,现在我们看到的屏幕上各种炫丽的画面都要归功于计算机图形学的贡献。因此感兴趣的同学可以深入研究,这里面大有可以施展才华之处。

参考资料

光线追踪算法综述 Manster
用JavaScript玩转计算机图形学(一)光线追踪入门 Milo Yip
Path Tracing介绍 Manster

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容