前言:前段时间在学习C++ primer的同时,我还有幸接触到了一本非常有趣的书,它通过我们的vs写出的代码直接模拟光线追踪生成图像。地址:Ray Tracing in One Weekend。它非常的有趣也具有很高的学习价值,所以我想把学习的过程记录下来,也欢迎大家来一起学习并找出其中的错误,废话不多说,直接开始!
图片格式
首先明确我们这里使用的是ppm格式的图片格式,它是通过类似于vector<vector<int>>
的方式记录下每个色素的RGB值。
此外在开头还需要做一些说明:
- P3#代表颜色使用ASCII码表示
- 3 2#代表3行两列,它使得我们接下来的数字不需要按照行列摆放工整,而是可以
- 255#表示使用0-255来表示一个通道的颜色
可以试着通过代码来生成一张这样的图片:
1 |
|
写完代码之后,我们以release方式运行,之所以不选择debug模式,主要还是因为太耗费时间,在保证代码不出现错误的情况下,使用release可以节省一些时间。
命令行
以上代码只能让信息输出到控制台,而我们希望将其输出到一个文件内,所以我们可以使用命令行实现:
- 打开命令行输入项目所在硬盘加冒号之后回车,如:
D:
- 接着输入,cd+空格+项目文件下的release文件夹地址后回车,如:
cd D:\C++\RayTracing\x64\Release
同时还要注意是X86还是X64。 - 之后输入
raycast.exe > image.ppm
,raycast.exe为我们的程序,使用>
重定向将数据输出到文件名为image1.1的文件中,同时指定文件格式为ppm
最后依次回车之后我们就可以在release文件夹下看到一个image的图片文件,如果打不开,可以下载一个极速看图软件。
一张非常绚丽的图,正如我们代码中的那样,从左到右越来越红,从下到上越来越绿。
加载进度
现在我们并不知道图片能够多久加载完成,当所需要的图片像素点非常多时,这个问题会更加明显,所以我们使用std::cerr来显式加载的进度,它主要用于显示错误消息,且不被缓冲,可以发送到显示器,并且不被重定向。
1 | for (int j = image_height-1; j >= 0; --j) { |
同时使用“\r”可以把光标强行移回本行开头,这样这次输出的内容就会覆盖掉这一行原本的内容,就好像每次到来的新东西会“冲洗”掉之前输出的东西。
注意这一行的结尾是std::flush,它表示再输出完这一行之后,会强行把内存中缓冲区内的数据打出到错误输出流里(清空缓冲区)。endl、ends和flush的区别
再次使用命令行就可以看到
参考文献
https://raytracing.github.io/books/RayTracingInOneWeekend.html
参考自《RayTracingInOneWeekend》第2节。