光线追踪<1-1> 超详解《Ray Tracing in One Weekend》

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,图像就清晰多了

由于今日天色已晚,咱们明天继续

感谢您的阅读,晚安~

猜你喜欢

转载自www.cnblogs.com/lv-anchoret/p/10163205.html