Just My Life & My Work

[C++] 光線追蹤 (Ray Tracing)

關於【Ray Tracing】是一門很值得研究的學問,
在實做過程我遇到幾個瓶頸:
遞迴、折射、反射、鏡射光、散射光等,
尤其是【遞迴】如果沒有清楚的腦袋,
很難將後四者給兜起來。
首先我們來看一條「主光線」如何遞迴:

光線的遞迴

一條主光線產生2的冪次條次光線。

我實做時遞迴函式原型為:

Primitive* Raytrace(Ray& a_Ray, Color& a_Acc, int a_Depth, float a_RIndex, float& a_Dist)

這是一個raytrace的函式,透過它來做光線的遞迴,回傳圖元指標。
Ray& a_Ray:主要光線
Color& a_Acc:累積的顏色
int a_Depth:遞迴的深度
float a_RIndex:介質的折射率
float& a_Dist:光的距離

整體遞迴結構如下:

  • 1判斷遞迴深度,若遞迴深度超過最大遞迴深度
  • 1.1則傳回0指標
  • 1.2反之則繼續。
  • 2搜尋場景中的物體
  • 2.1比較打中的最短距離
  • 2.2紀錄最短距離該物體的指標以及光線打中物體的狀況
  • 3判斷該物體指標是否為0指標
  • 3.1若是則傳回0指標,表示光線沒有打中任何物體
  • 3.2若不是則繼續。
  • 4判斷物體是否為光點。
  • 4.1若是,則累積為光的顏色[1]
  • 4.2若不是,則繼續
  • 4.2.1決定在交點上的顏色,計算交點座標4.2.2搜尋場景中的物體,若為光點,則追溯光點接下來是calculate diffuse shading

    4.2.2.1判斷該物體的Diffuse是否大於0

    4.2.2.1.1若是,且DOT(L, N)大於0,則累積散射光(Diffuse)的顏色[2]

    接下來是calculate specular shading

    4.2.2.2判斷該物體的Specular是否大於0

    4.2.2.2.1若是,且DOT(H, N)大於0,則累積鏡射光(Specular)的顏色[3]

    接下來是calculate reflection

    4.2.3判斷該物體的Reflection是否大於0

    4.2.3.1若是,則計算反射光向量R,開始遞迴光線

    4.2.3.2累積遞迴光線的顏色[4]

    接下來是calculate refraction

    4.2.4判斷該物體的Refraction是否大於0

    4.2.4.1若是,則計算折射光向量T,開始遞迴光線

    4.2.4.2累積遞迴光線的顏色[5]

  • 回傳該物體的指標

以上累積顏色的方式稍有不同:

[1]:a_Acc = Color(1, 1, 1);

[2]:a_Acc += diff * prim->GetMaterial()->GetColor() [* light->GetMaterial()->GetColor()];

[3]:a_Acc += spec * light->GetMaterial()->GetColor();

[4]:a_Acc += refl * rcol * prim->GetMaterial()->GetColor();

[5]:a_Acc += refr [* rcol * prim->GetMaterial()->GetColor()];

累積的定義可仔細調整。

遞迴的次數會影響Screen的成像,
我實際跑出結果:

遞迴1次

遞迴1次的成像。

遞迴2次

遞迴2次的成像。

遞迴3次

遞迴3次的成像。

遞迴4次

遞迴4次的成像。

遞迴5次

遞迴5次的成像。

遞迴10次

遞迴10次的成像。

可以從以上影像觀察到:
第一次只有【主光線】,
第二次多了【次光線】反射和折射,
第四次有……(不會講XD自己看~),
第五次之後成像就定型了,
第十次是前幾次較大的亮度。
遞迴需要花很長的時間,
512*512像素來說,
總共有262144條主光線,
遞迴次數為3的話,
每一條主光線會產生(2^3-1)-1=6條次光線,
那麼整個程式一共會產生262144*7條光線,
大概是180萬條光線
短時間內可以運算完畢,
即使遞迴深度只有5次也可以得到不錯的效果。
當然剛才計算的是最差的結果,
因為並不是每一條光線都會產生「反射」和「折射」,
這必須端視光線擊中的物體特質來決定,
也就是說若場景中所有物體都有反射和折射性質,
那麼物體數量一多就會跑得相當吃力!
總之,玩過就知道:)~

Comments on: "[C++] 光線追蹤 (Ray Tracing)" (1)

  1. 未知 的大頭貼

    […] 在這呢~我想要將我去年所做的成果貼上來,這回合是光線追蹤動畫 (Ray Tracing Animation),想要知道動畫如何被製作出來,首先必須先參考我去年寫的光線追蹤 (Ray Tracing)。 […]

隨意留個言吧:)~

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

標籤雲