Preface
从这一篇起,我们开始学光线追踪这门牛逼的技术。读了几天,一个字:强!
这一篇我们主要讲述技术入门和一些简单的案例。
我们先学这本:
Ready
这本书需要ppmview这个软件帮忙看效果图,不过下载也非常快。
其次,需要你会C/C++读写文件
最后需要你具备三维空间想象能力以及我对书中公式的讲述
Chapter1: Output an image
先看一张图,秒懂一下它如何设置像素
话说,有这么一个文件,叫做.ppm文件。它以水平向右为x正方向,以垂直向下为y正方向。
它的文件存储内容解读如上,关于第一行的P3是指文件的type
P3下面那两个数指的是列数和行数,或者你可以理解为x轴的长度和y轴的长度,或者理解为图像的宽和高。
再下面一行有一个数为像素的最大值
之后有x*y个(r,g,b)三元组,它会按照顺序读取,并且在图像的左上角开始一行一行扫描设置像素值
所以我们现在开始写代码实现上面那个图像,但是我按照上面的输入到文件中,由于只有6个像素点,我几乎看不到任何图像,我不知道你们的情况,所以我自己设定一个例子:
我设定上面那个图像的每一个颜色方格为20*20尺寸的。然后每个方格对应自己的像素值。
代码如下:
#define stds std:: void build_1_1() { const stds string s1[3] = { "255 0 0","0 255 0","0 0 255" }; const stds string s2[3] = { "255 255 0","255 255 255","0 0 0" }; stds ofstream file("graph1-1.ppm"); if (file.is_open()) { file << "P3\n" << 60 << " " << 40 << "\n255\n"; for (int i = 0; i < 20; ++i) for (int j = 0; j < 60; ++j) file << s1[j / 20] << stds endl; for (int i = 0; i < 20; ++i) for (int j = 0; j < 60; ++j) file << s2[j / 20] << stds endl; file.close(); stds cout << "complished" << stds endl; } else stds cerr << "error" << stds endl; }
然后我们用ppmview打开就是这样的:
好了,大家估计明白了我们这个文件的使用
那我们来整一个好玩的。
这是书上的代码,如果你能够看懂,那固然很好,不过看不懂也没关系
它说了个啥意思呢?
它先设置三个量r,g,b,它们的值在[0,1),然后通过乘255.99将值映射到[0,255]
好了我们可以看第一个像素:(0,255,0.2),应该是绿色的,如果觉得blue的0.2有点干扰,你可以设为0(建议这么做),第一行扫完之后,也就是内部for第一次跳出的时候,那个像素是(255,255,0.2),差不多是r和g组合,接近黄色,那么第一行就是r从0到255,绿色到黄色渐变。用同样的方法,我们可以知道,左下角这个点应该是近黑色,右下角应该是近红色。中间的内容是线性插值得到的像素值。
Chapter 2:The vec3 class
此章节,以及后面的部分,数学部分直接引用现写的3D数学库
转到:https://www.cnblogs.com/lv-anchoret/p/10163085.html
这一章就是将上述rgb用三维向量表示:
#define LOWPRECISION #include <fstream> #include <lvgm\lvgm.h> using namespace lvgm; #define stds std:: void build_1_2() { int X = 400, Y = 200; stds ofstream file("graph2-1.ppm"); if (file.is_open()) { file << "P3\n" << X << " " << Y << "\n255\n"; for (int j = Y - 1; j >= 0; --j) for (int i = 0; i < X; ++i) { dvec3 col(double(i) / X, double(j) / Y, 0.0); int ir = int(255.99*col.r()); int ig = int(255.99*col.g()); int ib = int(255.99*col.b()); file << ir << " " << ig << " " << ib << stds endl; } file.close(); stds cout << "complished" << stds endl; } else stds cerr << "load file failed!" << stds endl; } int main() { build_1_2(); }
把blue改为0,图像就清晰多了
由于今日天色已晚,咱们明天继续
感谢您的阅读,晚安~
原文地址:https://www.cnblogs.com/lv-anchoret/p/10163205.html