我们需要什么前置知识?

C++编码知识还有3d数学知识,如果你连线性代数都没有学过,那右上角叉掉吧,去学习,至少得把和图形学相关的线性代数知识学会才行,这里指路GAMES101的3D数学课。
https://www.bilibili.com/video/BV1X7411F744?p=2
把第二节课到第四节课看完。

我们要做什么?

一个光追器。具体来说是使用纯粹的C++编写一个离线渲染的软件光追器。接下来我来解释“纯粹的C++编写一个离线渲染的软件光追器”到底是什么玩意。

“纯粹的C++”

指的是只用到了C++语言本身,嗯。。或许会在纹理采样的时候用到一些用于导入png/rpg格式的库。但绝大多数情况下,就只是C++而已。所以,通过这系列文章,你可能会学到更多关于C++编码的知识。

“离线渲染”

肯定得是离线渲染,我们要求低一点,因为实时渲染对于性能的要求太过苛刻了,要求一秒钟能生成30张以上的图像。第一次开始,我们还是以描述光追的具体实现过程为主,况且咱们还是在没有GPU的支持下,能30秒生成一张图片就不错了。

“软光追”

对,我们没有GPU支持。每一个像素的处理都是在一个嵌套for循环里面,这很慢,但很清楚。我相信对于每一个语言初学者来说,都比较喜欢看到自己熟悉的for循环,而不是看那些着色器。

要怎么渲染?

学过OpenGL的同学知道,我们一般会通过GLFW开启一个窗口,然后在这个窗口中绘制图形。那C++怎么办?难道也需要某个库么?不需要,我们把图形绘制在一张图片里,它就躺在你的项目目录下或者任何你指定的地方,比如说,某个jpg文件,然后你只要打开看这个文件就可以看到渲染的结果了。
但是,jpg还不够简单,它使用了某种编码,导致我们并不能很好的理解它。比如我想拿到某个jpg图像的第三行第五个像素,这可能非常困难。或者我想把这个像素改成绿色,这也是需要对jpg进行解码才能得到。
有没有这么一种文件格式,能把我在C++里面的数组直接转换成图片的呢?比如数组里面存了(255,255,255)且它是这个数组的第一个元素,我就可以明确的了解到——“嘿,这张图像最左上角那个像素的红绿蓝三个通道的值都是满的欸,哦,它是白色的!”
这就是ppm文件。它是我能想到,最好理解的一种图片格式。image.png
第一行是“P3”,你可以理解为这是固定要写的两个字符。它表示颜色都是ASCII码表示的。
第二行‘#’开头的是注释,不要管。
第四行是“3 2” 表示这个图像是3×2的大小。
第五行是 “255”,表示我们用0-255这个区间来表示颜色,这也是理想的颜色表示区间——每个通道256阶。如果你非想用0-1000表示颜色也未必不可以,但是如果某一天你在其他地方看见一个漂亮的颜色并且得知它的值是(145,163,25),你想用这个ppm文件表示这个颜色,你可能就得自己去换算了。
接下来的每一行,都表示实际图像中的每一行像素,比如这里写到 “255 0 0 0 255 0 0 0 255”一共九个值,显然就是三个为一组表示三个颜色的。
一行放多少个像素都是随便的,ppm文件不要求玩家把输出字符串中的行和实际图片中的行对应,比如我可以每一行只写三个数字,即一个颜色,也可以把一切都写在同一行。因为图片的行列我们已经在前面指定过了,所以这里无论怎么去排列,系统都能知道图片到底长什么样子——总结来说,你想怎么换行就怎么换行,但也别太过火,至少让每一行的数字的个数是3的倍数,毕竟你的代码也是写给人看的。
得到的图像可以从上图右侧看出,三列两行,一切都非常合理。

在哪里编码?

哪里都可以。笔者是WIndows环境-VS2019里面,如果你是Linux或者mac,都无所谓,只要能找到写C++的地方即可,当然我们还会用到命令行。

具体可以学到什么?

我们将分初级中级和高级三个大篇章介绍这个项目,其中初级篇包括15篇文章,通过它们你会学到:
一个底层的数学类。通过它你会学会数学工具类的制作方法。
光线追踪的本质。光线追踪是什么?什么是光线?光线又是如何和场景碰撞的。
如何绘制物体。我们会以自然界中最简单的物体——球,来举例说明光线追踪模型下,球是如何被相机捕捉到。
相机。一开始我们的相机是一台固定的相机,后面我们会给它装上翅膀,并且允许你改装它。
多种材质。我们会学习漫反射、金属和玻璃材质的光线交互原理,并且制作逼真的反射效果。
抗锯齿。学习反走样知识让你的图像更加清晰。
在学完这一切之后,我们的渲染器将有能力渲染出下面的图片:
image.png
嗯,我们的项目不超过十个文件,每个文件几十行代码。你就可以得到图中的效果了,这不令人心动么!那么,开始吧。

参考文献

https://raytracing.github.io/books/RayTracingInOneWeekend.html
参考自《RayTracingInOneWeekend》第1节和第2-1节。