《一週學完光線追蹤》學習 三 光線相機和背景

蒙特卡洛光線追蹤技術系列 見 蒙特卡洛光線追蹤技術

所有光線跟蹤器都有一個光線類,以及計算沿光線看到的顏色。讓我們把射線看作一個函數,p(t)=A+t*B,這裏p是3D中沿直線的3D位置,a是射線的原點,B是射線的方向。射線參數t是實數(代碼中的浮點數)。插入不同的t和p(t)沿射線移動點。

加上負t,你就可以得到3D線上的任何地方。對於正t,你只得到A前面的部分,這就是通常所說的半線或射線。示例C=p(2)如下所示:

現在我們準備好轉彎,做一個光線跟蹤器。光線跟蹤器的核心是通過像素髮送光線,並計算在光線方向上看到的顏色。它的形式是計算從眼睛到像素的光線,計算光線與像素相交的部分,並計算該相交點的顏色。在第一次開發光線跟蹤器時,我總是用一個簡單的相機來啓動和運行代碼。我還做了一個簡單的顏色(光線)函數,返回背景的顏色(一個簡單的漸變)。

我經常在使用正方形圖像進行調試時遇到麻煩,因爲我經常轉換x和y,所以我將堅持使用200x100圖像(這裏我還是用的512*512的圖像)。我將把“眼睛”(或者相機中心,如果你想到相機的話)設爲(0,0,0)。我讓y軸向上,x軸向右。爲了尊重右手座標系的對流,進入屏幕的是負z軸。我將從左下角遍歷屏幕,並使用沿屏幕邊的兩個偏移向量來移動屏幕上的光線端點。請注意,我沒有將光線方向設置爲單位長度向量,因爲我認爲不這樣做會使代碼更簡單、速度略快。

在下面的代碼中,光線r接近像素中心(我現在不擔心精確性,因爲我們稍後將添加抗鋸齒):

#ifndef RAY_H
#define RAY_H

#include "Vector3.h"

class Ray  {
public:
    
    Ray() {}
    Ray(const Vector3& a, const Vector3& b) 
    { 
       data[0] = a; data[1] = b; 
       data[2] = Vector3(1.0f / b.x(), 1.0f / b.y(), 1.0f / b.z());
       
       posneg[0] =  (data[1].x() > 0 ? 0 : 1);
       posneg[1] = posneg[0] ^ 1;
       
       posneg[2] =  (data[1].y() > 0 ? 0 : 1);
       posneg[3] = posneg[2] ^ 1;  
       
       posneg[4] =  (data[1].z() > 0 ? 0 : 1);
       posneg[5] = posneg[4] ^ 1;  
    }
    
    Ray(const Ray& r) {*this = r;}
    Vector3 origin() const {return data[0];}
    Vector3 direction() const {return data[1];}
    Vector3 invDirection() const {return data[2];}
    void setOrigin(const Vector3& v) {data[0] = v;}
    void setDirection(const Vector3& v) 
    {
       data[1] = v;
       data[2] = Vector3(1.0f / v.x(), 1.0f / v.y(), 1.0f / v.z());
       
       posneg[0] =  (data[1].x() > 0 ? 0 : 1);
       posneg[1] = posneg[0] ^ 1;
       
       posneg[2] =  (data[1].y() > 0 ? 0 : 1);
       posneg[3] = posneg[2] ^ 1;  
       
       posneg[4] =  (data[1].z() > 0 ? 0 : 1);
       posneg[5] = posneg[4] ^ 1;  
    }
    Vector3 pointAtParameter(float t) const { return data[0] + t*data[1]; }

    Vector3 data[3];
    int posneg[6]; 
};


#endif

寫個程序測試一下:

	Vector3 lower_left_corner(-2.0, -1.0, -1.0);
	Vector3 horizontal(4.0,0.0,0.0);
	Vector3 vertical(0.0,2.0,0.0);
	Vector3 origin(0.0, 0.0, 0.0);
	for (int j = HEIGHT-1;j >= 0;j--) {
		for (int i = 0;i < WIDTH;i++) {
			int offset = (WIDTH*i + j) * 4;
			float u = float(i) / float(WIDTH);
			float v = float(j) / float(HEIGHT);
			Ray r(origin, lower_left_corner+u*horizontal+v*vertical);
			Vector3 col((u-0.5)*(u-0.5)+(v-0.5)*(v-0.5),0.0,0.0);
			Pixels[offset + 0] = (unsigned char)255.99*col[0];
			Pixels[offset + 1] = (unsigned char)255.99*col[1];
			Pixels[offset + 2] = (unsigned char)255.99*col[2];
			Pixels[offset + 3] = 255;
		}
	}

得到效果如圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章