【Ray Tracing in One Weekend 超詳解】 光線追蹤1-1


 

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

 

 

由於今日天色已晚,咱們明天繼續

 

感謝您的閱讀,晚安~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM