转pbr随笔
1 在一個要渲染的場景中,我們認為光能由預先指定的光源發出,然后我們以光線來描述光能的傳遞過程,當整個場景中的光能信息被我們計算出來后,我們收集這些信息轉化為頂點的亮度。
2 光線經過物體表面可以產生反射和漫反射,光線透過物體可以產生折射和散射。具體產生哪種出射效果,依據物體的表面屬性而定。物體的表面一般不會是理想的某種單一屬性的表面,表面可以同時存在反射,折射,漫反射等多種屬性,各種屬性按一定比例混合之后才是其表面反射模型。
3 一點的在某一個視線方向上的光亮度=該點在該方向的自身發光亮度+半球入射光能在該方向所產生的反射光亮度.
4 關于散射,高度真實的散射是一個很難模擬的物理過程,一般在渲染中都不會采用過于復雜的物理模型來表示散射,而是采用一些取巧的辦法來計算散射。
5 在常見的渲染中,有兩種效果很難模擬,但是它們會使人眼覺得場景更真實。
[1]color bleeding :入射光為漫反射,受光表面屬性為漫反射,出射光是漫反射。比如把一本藍色的紙制的書靠近白色的墻,墻上會有淺淺的藍暈。
[2]caustics:入射光為鏡面反射或折射,受光表面屬性為漫反射,出射光是漫反射。比如把一個裝了紅色葡萄酒的酒杯放在木桌上面,會有光透過杯中的酒在桌上形成一塊很亮的紅色區域。
[傳統的陰影算法]:
游戲中傳統的光照算法,是利用公式法來計算特定類型光源的直接光照在物體表面所產生的反射和漫反射顏色,然后再使用陰影算法做陰影補償。標準的陰影算法不能計算面光源,改進以后的陰影算法通過對面光源采樣,可以模擬出軟陰影的效果。但是這些方法計算的光照都是來自直接光源的,忽略了光的傳播過程,也就無法計算出由光的傳播所產生的效果。通過特定的修正,我們也可以計算特定的反射折射或漫反射過程,但是無法給出一種通用并且物理正確的方法。目前游戲中大多是采用改進的陰影算法來進行渲染,它的優點是效率比較高,結合預計算的話,還是可以產生比較生動可信的效果。
[傳統的逆向光線追蹤]
正如前面描述的那樣,要想計算光能在場景中產生的顏色,最自然的考慮就是,從光源出發,正向跟蹤每一根光線在場景中的傳遞過程,然后收集信息。然而這個想法在被提出的來的那個時代的計算機硬件上是不可能實現的,當時人們認為,正向光線追蹤計算了大量對當前屏幕顏色不產生貢獻的信息,而且它把看不見的物體也計算在內,極大的浪費了效率。
于是人們想出的另一個方法是:只計算有用的,從人眼出發,逆向跟蹤光線。
逆向光線追蹤從視點出發,向投影屏幕發出光線,然后追蹤這個光線的傳遞過程。如果這個光線經過若干次反射折射后打到了光源上,則認為該光線是有用的,遞歸的計算顏色,否則就拋棄它。很顯然,這個過程是真實光線投射的逆過程,它同樣會產生浪費(那些被拋棄的逆向光線),而且只適用于靜態渲染。
逆向光線追蹤算法中的頂點亮度主要包括三個方面:
1由光源直接照射而引起的光亮度
2來自環境中其它景物的反射折射光在表面產生的鏡面反射光亮度
3來自環境中其它景物的反射折射光在表面產生的規則透射光亮度
4預設定的頂點漫反射顏色
顯然,這一過程僅跟蹤景物間的鏡面反射光線和規則透射光線,忽略了至少經過一次漫反射之后光能傳遞,而且該算法中的物體表面屬性只能是單一的,因而它僅模擬了理想表面的光能傳遞。
對于該算法的具體描述:
1從視點出發,經過投影屏幕上的每一個像素向場景發射一根虛擬的光線。
2求光線與場景最近的交點。
3遞歸跟蹤:
(1)如果當前交點所在的景物表面為理想鏡面,光線沿其鏡面反射方向繼續跟蹤。
(2)如果當前交點所在的景物表面為規則投射表面,光線沿其規則投射方向繼續跟蹤。
4遞歸異常結束:
(1)光線與場景中的景物沒有交點
(2)當前交點所在的景物表面為漫反射表面
(3)跟蹤層次已經超過用戶設定的最大跟蹤層數
(4)所跟蹤的光線對顯示像素的光亮度的貢獻小于一預先設定的閥值
5遞歸正常結束:
(1)光線于光源相交,取得光亮度值,按遞歸層次反饋。
傳統的光線追蹤技術可以較好的表現出反射折射效果,也可以生成真實度比較高的陰影。但是他的光照都比較硬,無法模擬出非常細膩的柔化效果。
光線追蹤需要對大量的光線進行多次與場景中物體的求交計算。如何避免這些求交計算成為光線追蹤追求效率的本質。早期的光線追蹤算法都是通過各種空間劃分技術來避免無謂的求交檢測,這些方法對于之后的理論同樣有效,常見的空間劃分方法分為兩類,一類是基于網格的平均空間劃分,一類是基于軸平行的二分空間劃分。
[蒙特卡羅光線追蹤]
1對傳統的逆向光線追蹤的改進
傳統的逆向光線追蹤算法有兩個突出的缺點,就是表面屬性的單一,和不考慮漫反射。我們不難通過模型的修正來緩解這兩個問題。我們首先認為一個表面的屬性可以是混合的,比如它有20%的成分是反射,30%的成分是折射,50%的成分是漫反射。這里的百分比可以這樣理解,當一根光線打在該表面后,它有20%的概率發生反射,30%的概率發生折射,50%的概率發生漫反射。然后我們通過多次計算光線跟蹤,每次按照概率決定光線的反射屬性,這樣在就把漫反射也考慮了進去。具體的算法如下:
(1)從視點出發,經過投影屏幕上的每一個像素向場景發射一根虛擬的光線。
(2)當光線與景物相交時按照俄羅斯輪盤賭規則決定他的反射屬性。
(3)根據不同的反射屬性繼續跟蹤計算,直到正常結束或者異常結束。如果反射的屬性為漫反射,則隨機選擇一個反射方向進行跟蹤。
(4)重復前面的過程,把每次渲染出來的貼圖逐像素疊加混合,直到渲染出的結果達到滿意程度。
該方法是一種比較簡易的基于物理模型的渲染,其本質就是通過大量的隨機采樣來模擬半球積分。這種方法在光照細節上可以產生真實度很高的圖像,但是圖像質量有比較嚴重的走樣,而且效率極其低下。
2蒙特卡羅光線追蹤-采樣
蒙特卡羅光線追蹤的本質就是通過概率理論,把半球積分方程進行近似簡化,使之可以通過少量相對重要的采樣來模擬積分。蒙特卡羅光線追蹤理論中的采樣方案有很多,有時候還要混合使用這些采樣方案。
蒙特卡羅光線追蹤已經是一個比較完備的渲染方案,他極大的解決了光線追蹤的模型缺陷和效率問題,使得在家用圖形硬件上做基于物理的渲染成為一種可能。但是我們仍然無法實時的進行計算,而且如何解決圖像走樣的問題也是蒙特卡羅光線追蹤的一大難點。
相對于普通光線追蹤,蒙特卡羅光線追蹤引入了更復雜的漫反射模型,從而增加了需要跟蹤的光線數量。但是他又通過采樣算法減少了需要跟蹤光線,所以其核心效率取決于采樣模型。
與普通光線追蹤一樣,為了減少不必要的求交檢測,蒙特卡羅光線追蹤也需要使用空間劃分技術,最常用的是平衡kdtree。蒙特卡羅光線追蹤雖然是一種逆向光線追蹤算法,但是其采樣的理論卻與光線追蹤的方向無關,可以用于任何一種渲染方案。
此外,使用蒙特卡羅光線追蹤不容易計算caustics現象。也就是說它不容易計算由鏡面反射或者規則透射引起的漫反射。(但是很容易計算由漫反射引起的鏡面反射或者規則透射;)
蒙特卡羅光線追蹤本身也是一種逆向光線跟蹤。逆向光線追蹤最初被設計出來是為了只計算那些會影響最終屏幕像素的光能傳遞過程,這一思想在早期硬件并不發達,對最終影響要求也不高的年代是非常實用的。但是我認為由于對屏幕上每個像素的跟蹤都是無關的,即每兩次跟蹤之間都不會建立通信說哪些是計算過的,哪些是沒計算過的,所以這里面必然會包含大量的重復計算的中間過程。當我們對圖像所表現效果的真實度非常高的時候,必然會產生巨量的采樣,然后重復計算的問題就會被放大,而由逆向追蹤思想帶來的那些優勢也將蕩然無存。而且,對場景中光能貢獻越大的光源應該被越多的采樣跟蹤覆蓋到,但是逆向光線跟蹤只是對屏幕上每個像素反復遍歷追蹤,其結果應該趨向于采樣平均覆蓋各個光源,如果要想對高亮度光源采很多的樣本,必然也會導致對其它光源也過多的采了樣本,這會非常浪費效率。重新考慮正向光線追蹤,光由光源發出,打在場景之中,每一次光能轉化都被記錄下來,最后只要收集這些信息就可以知道任意點上面的亮度,這個方法的描述非常的貼近真實的自然,關鍵在于如何保證速度。
另外,完全的逆向光線追蹤根本就不應該作為實時渲染的算法,道理很簡單,光能的傳遞過程不變,只要視點一變,就要重新計算。
[輻射度算法]
輻射度的算法分為三個步驟
1先把場景中的面劃分為一個個小的patch,然后計算兩個patch之間的形式因子。兩個patch之間的形式因子表示了一個patch出射的光有多少比例會被另一個patch接收。對于任意一個有n個patch的場景來說,總有n*(n-1)個形式因子。
2通過迭代法來找到一個光能傳遞的平衡狀態
3把第二步所產生的亮度值作為頂點色渲染
輻射度算法會非常的慢,而且如果不考慮額外的復雜度,輻射度算法很難計算鏡面反射,改進的輻射度算法可以緩解這一問題。很多研究者都試圖結合光線追蹤和輻射度這兩種方法,以期達到各自的優勢。
?[photonmaping+final Gathering]:
前面談到,正向光線追蹤才是最自然的光能傳遞的描述,由此,在1994年,有人提出了photonmaping算法。photonmaping是一個兩步的算法,第一步通過正向光線跟蹤來構建光子圖,第二步通過光子圖中的信息來渲染整個場景。它的核心思想是從光源開始追蹤光能的傳遞,把每一個傳遞中間過程都記錄下來,最后按照投影或者逆向光線追蹤來收集這些信息,以達到渲染的目的。由于中間每一個光線和場景的相交都被記錄下來,所以他很自然的避免了逆向光線追蹤中重復計算的問題。
具體的,這兩步算法又可以分為下面四步。
1從光源發射出N根采樣光線。光線的方向和光源的類型有關。采樣光線的數目選擇與光源自身的亮度有關,越亮的光源應該選擇越多的采樣。
2光子打到場景中,一步步傳遞,把光能傳遞的過程記錄下來,結果放在kdtree中
3用逆向光線追蹤或者反投影的方法找到可視點
4使用逆向光線追蹤和半球積分(比如最終聚集)方法收集光子圖中的信息,從而計算可視點的光亮度。
首先要選擇一個光源,然后才能發射一個光子。對于場景中的多個光源,每次做發射一個光子采樣的時候,不能完全的隨機選擇光源,一個光源被選中的概率要正相關于他的在該場景中的能量
典型的,光源一般被分為:
(1)點光源:
點光源的數據結構僅僅是三維空間中的一個坐標。對點光源所發出的光線進行采樣時,可以在包圍該點的單位球上任選一點,然后以球心到該點的射線作為采樣光線。也有人建議用單位立方體包圍盒采樣來代替單位球。
(2)方形面光源:
方形面光源上的每一個點都可以看做一個只能從靠近面法向量一側發射光線的點光源。
(3)其它光源:
任意空間形狀和物理特性的光源,只能具體問題具體分析。
一旦選好了初始要追蹤的光子向量的位置和方向,我們就可以開始一次正向追蹤。
一般的,光子在與場景中景物的相交的情況可以分為三類
(1)如果光子打到了鏡面反射表面或者規則折射表面,不用做任何記錄,繼續追蹤。
(2)如果光子打到了漫反射表面,則把光子所攜帶的能量和入射方向記錄下來。
如果入射光是折射或者反射光,則把光子記入caustics map,否則就記入全局map;
其實,對于每一次相交,我們即可以記錄入射光子,也可以記錄出射光子。但是我們選擇了記錄入射光子。
我們記錄鏡面反射與規則折射的光子信息是沒有意義的,因為我們不可能把所有的鏡面反射和規則折射過程都記錄下來,所以這一類亮度還是要通過逆向光線追蹤或其它方法來計算。但是我們記錄漫反射過程中的采樣信息是有用的。因為我們可以通過某一點的部分入射采樣光子來近似的模擬該點的全部入射光子。然后我們可以計算該點任意方向上的出射光子。這也決定了我們只能記錄入射光子信息而不是出射光子信息。記錄入射光子還可以讓我們通過選擇不同的brdf甚至不同的簡化模型來重構每一次反射過程,這樣我們就可以隨心所欲的計算。
那么我們后面如何通過一點的入射光子來計算該點的出射光子呢,我們選擇一個包圍該點的范圍很小的球空間,把這個空間里所有的入射光子按照半球積分模型計算,就可以算出該點的出射光子。
(3)如果光子打到的表面既有一定的鏡面反射屬性,又有一定的漫反射屬性,則依據兩種屬性各自所占的百分比,使用俄羅斯輪盤賭原則來決定該次的反射屬性。
(4)光子再決定了反射屬性之后,還要依據反射屬性再隨機一次,以判定其是被表面吸收還是發射出去。
構造好光子貼圖之后,我們就可以在第二步收集這些信息來計算頂點亮度。
我們首先來看一個對光能半球積分簡化過了的公式:
L*f = ( L(l)+L(c)+L(d) )*( f(s)+f(d) )
這個公式中,L表示入射光的集合,f表示該點的表面反射屬性集合。
L(l)表示直接光照,L(c)表示純粹的反射折射光,L(d)表示至少經歷了一次漫反射的入射光
f(s)表示鏡面反射或者規則透射brdf,f(d)表示漫反射brdf。
L*f的結果就是出射光的亮度,我們要做的就是如何快速的計算L*f。
我們把上面的等式分化一下:
L*f = L(l)*( f(s)+f(d) )
??? + f(s)*L(c) + f(s)*L(d)
??? + f(d)*L(c)
??? + f(d)*L(d)
如果直接采用半球積分方程進行計算,需要大量的采樣,我們這種分化把半球積分分化為四部分,對不同的部分采用不同的辦法計算,這樣每一種都不會產生大量的采樣,合起來的計算復雜度遠遠低于原來不分開計算的。
(1)直接光源照射,反射屬性為所有。
(2)入射光源為鏡面反射或者規則透射或者漫反射,反射屬性為鏡面反射或者規則透射。
(3)入射光源為純反射或透射,反射屬性為漫反射。
(4)入射光源為至少經過一次漫反射的,反射屬性為漫反射。
對于(1),我們采用shadow ray的方法計算直接光照。
對于(2),我們采用經典Monte Carlo光線追蹤來計算。
對于(3),我們收集來自caustics map中的光子信息。
對于(4),我們收集來自全局map中的光子信息。
這樣,一次典型的正向光線追蹤的計算就完成了。即使是photon map算法,對于普通硬件,暫時也只能用于靜態渲染。但是我們依然可以把它用在游戲中,比如在地圖編輯器中對靜態光源和大型靜態場景進行預渲染,如果光源是變化的,那么對光源變化的過程采樣,渲染后在通過插值計算來模擬光源變化。通過基于光線追蹤計算出的圖像,具有很高的光真實感,可以令用戶產生賞心悅目的感受。
?[photonmap實時渲染方案的想法]
1 區別于靜態渲染,不是一次發射所有必須的光子,而是只產生少量的光子,把相關信息保存在光子圖中,然后每楨逐步遞加光子,過了一定時間以后,就拋棄舊的光子信息。
2 構造類似于windows臟矩形思想的臟光線算法。
轉載于:https://www.cnblogs.com/cloudseawang/archive/2007/03/31/695246.html
總結
- 上一篇: python 小说 云_python小说
- 下一篇: raidrive安装失败_记一次RaiD