games101 – 4 – Ray Tracing

games101 – 4 – Ray Tracing

對應的Lecture 13 ~ 17

為什麼需要Ray Tracing

光柵化無法處理全局效果

  • 軟陰影;
  • 光反彈次數超過一次的情況,如glossy reflection,indirection illumination;
  • 光柵化的很快,但是品質比較低;
  • raytracing,很準確,但是很慢;

Recursive (Whitted-Style) Ray Tracing

An improved Illumination model for shaded display」 T. Whitted, CACM 1980

Ray-Surface Intersection

射線的定義:\(r(t) = o + td, 0 \le t \lt \infty\),一個起始點,和方向構成了一個射線。

對於射線和方程隱式表示的表面,可以通過求解方程式得到交點。更常見的場景是射線和三角網格模型進行求交計算。對於射線和三角形求交計算,可以先和平面進行求交,然後再判斷交點是不是位於三角形內部。

(23條消息) Möller-Trumbore演算法-射線三角形相交演算法_zhanxi1992的專欄-CSDN部落格

\[O + tD = (1 – b_1 – b_2)P_0 + b_1P_1 + b_2P_2 \\
O – P_0 = (P_1 – P_0)b_1 + (P_2 – P_0)b_2 – tD \\
S = E_1b_1 + E_2b_2 -tD
\]

矩陣的形式表示如下:

\[\begin{bmatrix}
-D & E_1 & E_2
\end{bmatrix}
\begin{bmatrix}
t \\
b_1 \\
b_2
\end{bmatrix} = S
\]

然後利用克萊姆法則(\(Ax = c=>x_i = detA_i/detA\))求解,

如果遍歷三角網格中的所有三角形,對每個三角形進行相交計算,並找到最近的交點,整個過程是非常耗時的。需要的開銷為#pixels x #triangles (x #bounces).

Bounding Volumes

可以利用包圍盒,進行加速。針對複雜物體,構建出包圍盒,然後如果射線不和包圍盒相交,那麼射線就不和包圍盒內部的物體相交,如果相交,然後再進行內部物體的相交測試,而包圍盒相交監測速度非常快。常見的包圍盒有:包圍球,軸對⻬包圍盒,非軸對齊包圍盒。更常用的是使用軸對齊包圍盒,因為針對它的相交計算很簡單。

在計算直線和Axis-Aligned Box相交的時候(此處允許t<0),分別針對每個維度,計算出\(t_{min}\)\(t_{max}\),那麼\(t_{enter}\)等於各個維度\(t_{min}\)的最大值,\(t_{exit}\)等於各個維度\(t_{max}\)的最小值。如果\(t_{enter} < t_{exit}\),那麼相交。

但是ray並不是一條直線需要對負值的情況進行額外判斷:

  • 如果\(t_{exit} < 0\),那麼不相交;
  • 如果\(t_{exit} \ge 0\)並且\(t_{enter} < 0\),那麼射線的原點位於box內部,相交;
  • 那麼ray和AABB相交,當且僅當\(t_{enter} < t_{exit}\ \&\& \ t_{exit} \ge 0\)

Spatial Partitions

  • Uniform Spatial Partitions (Grids) 適用於很多對象均勻的分布在空間中的場景。

更常用的是不均勻空間劃分。

常見的分法如下:

K-D Tree – OI Wiki (oi-wiki.org)

Bounding Volume Hierarchy (BVH)

構建一個BVHs,需要進行如下操作:

  • 找到包圍盒;
  • 將包圍盒中的對象分成兩個部分(細分的時候需要選擇維度最大的方向進行劃分,這裡通常選擇當前node軸長最大的軸,切分的位置通常位於中間);
  • 重新計運算元集的包圍盒;
  • 達到某種條件後中斷,通常是node中的對象少於一定數量;
  • 將對象存儲到各個節點中;

BVH的數據結構主要分為兩類:內部節點和葉子節點。內部節點包括:包圍盒,子節點;葉子節點包括:包圍盒,對象集合;

BVH樹的遍歷:

Intersect(Ray ray, BVH node) {
	if (ray misses node.bbox) return;
	if (node is a leaf node)
		test intersection with all objects;
		return closest intersection;
	
	hit1 = Intersect(ray, node.child1);
	hit2 = Intersect(ray, node.child2);
	
	return the closer of hit1, hit2;
}

Radiometry

radiant energy: the energy of electromagnetic radiation. \(Q\ [J=Joule]\); 能量整體

radiant flux: the energy emitted, reflected, transmitted or received, per unit time. \(\Phi = dQ/dt\),單位是[W=Watt],或者是[lm = lumen]。單位時間的能量

另外幾個關鍵概念,示意圖如下:

Radiant intensity: the power per unit solid angle emitted by a point light source. \(I(\omega) = d\Phi/d\omega\),單位是[W/sr],或者是[lm/sr = candela]。單位時間單位立體角的能量;立體角的概念,微分,積分,如下:

Irradiance:the power per (perpendicular projected) unit area incident on a surface point.\(E(x) = d\Phi(x)/dA\)單位面積單位時間的能量(面積為垂直於光線方向);面積理解的示意圖如下:

Radiance: the power emitted, reflected, transmitted or received by a surface, per unit solid angle, per projected unit area. 示意圖及公式如下:

irradiance和radiance概念對比,irradiance表示的是單位面積接收到的所有能量,radiance表示,從某一個單位立體角看過去的單位面積上接收的能量。

Bidirectional Reflectance Distribution Function (BRDF)

BRDF: 用來表示從每個方向過來的光線,有多少會貢獻到每個outgoing方向。represents how much light is reflected into each outgoing direction \(\omega_r\) from each incoming direction. 對應的公式如下:

上面的公式中為什麼需要對Lr做微分,對Ei做微分呢?具體解釋可以參見:關於BRDF公式理解的筆記_fatever的部落格-CSDN部落格,摘錄關鍵內容如下:

反射方程

表示的不同方向的irradiance對出射方向上的貢獻的積分。

渲染方程

在反射方程的基礎上再加上emission項,得到渲染方程。

Understanding the rendering equation

圖中,當一個光源的時候,用間接反射光取代了入射光。

Probability Review

隨機變數的概率密度函數:\(P(a\le x\lt b) = \int_a^b p(x) dx\)。p(x)即為概率密度函數。從負無窮到正無窮的圖形對應的面積為1。對應的期望為\(E(X) = \int xp(x)dx\).

Monte Carlo Integration

蒙特卡羅方法(Monte Carlo Method)概述——概念、起源、思路、應用、特點、計算程式、計算舉例和文獻資料(21k) (sohu.com)

蒙特卡洛光線追蹤技術_Dezeming的部落格-CSDN部落格

如果需要求解定積分,\(\int_a^bf(x) dx\),首先需要知道x的概率分布,那麼可以轉換成求解積分,\(\int_a^bf(x)/p(x)\cdot p(x) dx\),那麼用蒙特卡洛進行期望估計,得到:

Path Tracing

Whitted-Style Ray Tracing的條件是:總是執行鏡面反射和折射;碰到漫反射表面停止。這種近似對於一些場景會存在問題:1)對於glossy reflection表面;2)在diffuse材質,不會有反射;

之前給出的rendering equation是正確的,那麼如何求解呢?

A Simple Monte Carlo Solution

問題:假設我們需要渲染下面場景中一個點(僅考慮直接光照):

那麼可以得到如下的反射方程:

\[L_o(p,\omega_o)=\int_{\Omega^+}L_i(p,\omega_i)f_r(p,\omega_i, \omega_o)(n\cdot\omega_i)\mathrm{d}\omega_i
\]

要求解這樣的積分,我們利用蒙特卡洛積分,構建「f(x)”,為:\(L_i(p,\omega_i)f_r(p,\omega_i, \omega_o)(n\cdot\omega_i)\),並且先假設\(\omega_i\)的概率密度函數為\(p(\omega_i)=1/(2\pi)\),半球上均勻分布,那麼可以得到:

如果在光線追蹤的時候,一條光線hit到了物體,而沒有hit到light,需要怎麼處理呢?那麼首先需要計算hit到物體的位置,貢獻的光是多少。如下:

shade(p, wo)
	Randomly choose N directions wi~pdf
	Lo = 0.0
	For each wi
		Trace a ray r(p, wi)
		If ray r hit the light
			Lo += (1/N) * L_i * f_r * cosine / pdf(wi)
		Else If ray r hit an object at q
			Lo += (1/N) * shade(q, -wi) * f_r * cosine / pdf(wi)
	Return Lo

這樣就ok了么,並不然。上述的處理方式還存在什麼問題呢?

問題1:光線次數隨著碰撞次數的增多而指數增長

問題1:光線次數隨著碰撞次數的增多而指數增長。如下圖所示:

為了避免光線數量的暴增。隨機只選擇一條光線進行處理。如下:

shade(p, wo)
	Randomly choose 1 directions wi~pdf
	Lo = 0.0
	Trace a ray r(p, wi)
	If ray r hit the light
		Lo += L_i * f_r * cosine / pdf(wi)
	Else If ray r hit an object at q
		Lo += shade(q, -wi) * f_r * cosine / pdf(wi)
	Return Lo

這種方式的話,如果一個像素上只有一條光線穿過,那麼得到的結果雜訊會很大,因此需要多條射線穿過一個像素位置,然後對結果進行平均。這樣針對一個像素位置的偽程式碼如下:

ray_generation(camPos, pixel)
	Uniformly choose N sample positions within the pixel
	pixel_radiance = 0
	For each sample in the pixel
		Shoot a ray r(camPos, cam_to_sample)
		If ray hit the screen at p
			pixel_radiance += 1 / N * shade(p, sample_to_cam)
	Return pixel_radiance

問題2:此時shade函數如何終止

問題2:此時shade函數中還存在一個問題,就是函數進行無限循環。解決方案是提供輪盤賭的方式(Russian Roulette)。假設我們手動設置一個概率值,P,在發射一條光線的時候,給出一個隨機值,如果範圍在P~1,那麼返回:0,否則返回:Lo/P。這樣得到的Lo的期望為:E = P * (Lo/P) + (1-P)*0 = Lo。將這部分內容加到shader偽程式碼中如下:

shade(p, wo)
	Manully specify a probability P_RR
	Randomly select ksi in a uniform dist. in [0, 1]
	If (ksi > P_RR) return 0.0
	
	Randomly choose ONE direction wi-pdf(w)
	Trace a ray r(p, wi)
	If ray r hit the light
		Return L_i * f_r * cosine / pdf(wi) / P_RR
	Else If ray r hit an object at q
		Return shade(q,-wi) * f_r * cosine / pdf(wi) / P_RR

問題3:如何提高取樣效率

上述的實現並不是很高效,如下圖所示:

如果光源面積比較大,那麼發射較少數量的光線,就可以碰撞到光源,如果光源面積比較小,那麼需要發生很多的光線才行。這樣如果我們在半球表面進行均勻取樣,那麼會有大量的光線是wasted的。那麼怎麼解決呢?

可以將取樣分為兩部分,1)針對光源進行取樣,2)針對非直接光照場景進行取樣;

從渲染方程得知,接收到的光照資訊,是針對立體角進行積分的,那麼怎麼轉換到,通過光源面積進行積分呢?從立體角的定義得到:

\[dw = \frac{dA\cos\theta’}{||x’-x||^2}
\]

那麼渲染方程可以重寫為:

此時shade偽程式碼可以寫為:

shade(p, wo)
	# Contribute from the light source
	Uniformly sample the light at x' (pdf_light = 1/A)
	# test blocked
	Shoot a ray from p to x'
	If the ray is not blocked in the middle
		L_dir = L_i * f_r * costheta * costheta' / |x' - p|^2 / pdf_light
	
	# Contribute from other reflectors
	L_indir = 0.0
	Test Russian Roulette with probability P_RR
	Uniformly sample the hemisphere toward Wi (pdf_hemi = 1/2pi)
	Trace a ray r(p, wi)
	If ray hit a non-emitting object at q
		L_indir = shade(q, -wi) * f_r * costheta / pdf_hemi / P_RR

Materials and Appearances

Materials == BRDF。BRDF用來表示從每個方向過來的光線,有多少會貢獻到每個outgoing方向。

Snell’s Law

傳輸方向從i到t,那麼如果\(\eta_i/\eta_t > 1\)可能發生完全內反射(即,沒有折射的現象)。

Fresnel Reflection

用來解釋:視線垂直於表面時,反射較弱,而當視線非垂直表面時,夾角越小,反射越明顯,這一種現象。

Fresnel Reflection – 菲涅爾反射 – Tekkaman – 部落格園 (cnblogs.com)

準確解和近似解分別如下:

微表面

微表面,針對每一個元素都可以視為mirror。

沒有覆蓋到的內容

  • uniformly sampling the hemisphere; How?
  • Monte carlo integration allows arbitrary pdfs. What’s the best choice?
  • Do random numbers matter ? Yes! (low discrepancy sequences)
  • I can sample the hemisphere and the light. Can I combine them? Yes! (multiple imp. sampling)
  • The radiance of a pixel is the average of radiance on all paths passing through it. Why? (pixel reconstruction filter)
  • Is the radiance of a pixel the color of a pixel? No. (gamma correction, curves, color space)
  • deeper path tracing.