基于物理的渲染和光線追蹤算法
基于物理模型的渲染的目的是為了渲染出一張跟某個真實的3D場景一模一樣的圖片恼琼,就仿佛你站在什么地方對這現(xiàn)實場景拍了一張照片一樣屏富。
然而實際上狠半,在這里說渲染出一張跟真實的3D場景一模一樣的畫面是不夠精確的照激,因為在每個人的眼睛里痕钢,世界本來就是不一樣的双霍。有的人心里只有妹子瓶珊,有的人心里只有代碼艾扮。基于物理的渲染實際上只是在做在確定參數(shù)下甫恩,進行魯棒性比較高的現(xiàn)實世界的模擬。魯棒性這個詞可能一般的工人階層很少接觸奖慌,如果你是讀了碩士或者博士的简僧,應該很熟悉雕欺。我們需要根據(jù)物理光和與物理光反應的物質棉姐,基于我們知道的顯示技術伞矩,來呈現(xiàn)出最好的視覺效果乃坤。
基本上大部分基于物理渲染的系統(tǒng)都是基于光線追蹤算法的。為什么大家都這么偏好光線追蹤湿诊,是因為光線追蹤是最簡單的算法厅须,所以不要拋出一個光線追蹤就覺得自己很牛逼宇色,這沒什么值得驕傲的,你掌握的只是一個最簡單的算法例隆。光線追蹤算法主要依據(jù)的是光線在場景中與物體產(chǎn)生交互然后反射出來的路徑來對整個畫面進行渲染抢蚀。
雖然我們有很多種方式可以去實現(xiàn)光線追蹤器皿曲,但無論你怎么實現(xiàn),至少都會需要處理一下幾個主題:攝像機屋休、射線相交劫樟、光源、可見性檢測奶陈、表面散射附较、間接的光線照射、光線的傳播徐勃。
攝像機
跟著我們擼完了OpenGL知識點的人,肯定都是接觸了攝像機的很魂,攝像機的目的就是在你想拍照的位置用你最想看的角度去看一個東西檐涝。基本上各大計算機圖形學的書籍一說到攝像機都會提到小孔成像的概念幅聘,其實我們也不知道他們提這種古董出來是個什么意思帝蒿。我們現(xiàn)在都是用手機拍照的好嗎巷怜。很多書籍引出小孔成像原理來企圖使得對攝像機的說明變得更加清晰,但我們要說的是绣张,時代變了关带,我們這代人壓根不知道小孔成像的那些東西宋雏,我們見過的更多的是腎6。所以你完全可以忽略掉小孔成像這一段磨总。
攝像機最重要的功能就是定義一個你看3D場景的視野蚪燕,也就是定義了什么東西能被你看到。當別人跟你說小孔成像的時候,你想起來我們的視椎體就可以了厕诡,他說了半天不過是想告訴你那些顯而易見的東西灵嫌。我們非常確認壹罚,直接畫出視椎體猖凛,比講一大堆小孔成像更能讓人理解辨泳。
攝像機的一個重要作用就是計算在你所看到的一個畫面中的某一個像素點,所有光線對這一點的亮度所作出的貢獻菠红。當然我們目前只是在的鏡頭只有一個的情況下试溯。實際上我們的拍照的時候郊酒,鏡頭可能是多層的,有可能是多個的燎窘。不過這些都不關我們的事荠耽。我們只考慮一個,因為一個就非常耗時了倘屹。當有超過1個鏡頭(凸透鏡什么的)纽匙,你再去想小孔成像的問題拍谐。不過那時候你肯定碰到的是具體的現(xiàn)實問題,所以也不需要去考慮小孔成像践瓷。你只需要想起來視椎體就夠了晕翠。
我們將在后面再介紹關于攝像機的更多信息淋肾,你實現(xiàn)一個攝像機的時候,就可以支持多個攝像機拿愧。
我們現(xiàn)在應該知道的是浇辜,我們通過攝像機可以獲得一個畫面中的某個點與為這個貢獻了顏色的光線之間的關系七扰。剩下的就是光線如何在場景中傳播和衰減,最后到達這個像素點的時候膳灶,它到底是個什么顏色轧钓,能量有多強的問題毕箍。
寫代碼就是要邏輯清晰道盏,要不然就是亂七八糟的。
射線與物體的相交檢測
當我們去計算光線的時候媒咳,我們需要解決的第一個問題就是:光線與哪個物體第一次相交涩澡,交點在哪里坠敷。此時的這個交點對于光線來說就可以可見的一個點膝迎,此時我們就需要去模擬光線與物體在那一點的交互粥帚。為了找到誰與光線產(chǎn)生了交互芒涡,我們必須使用射線相交檢測拖陆,來看看誰是第一個與我們的光線產(chǎn)生相交的那個依啰。
這樣一來我們就需要一些幾何庫速警,幾何庫的目的主要是定義基本的幾何形體闷旧,比如:射線钧唐、球钝侠、包圍盒帅韧、膠囊、三角形等等双妨。然后我們還需要實現(xiàn)射線與各種基本幾何形體的相交檢測算法叮阅,如果相交刁品,則返回相交的點的坐標。這里為什么只需要和基本的幾何形體進行相交檢測就可以了呢帘饶?因為復雜的物體就是由這些簡單的物體組成的嘛哑诊。當然,當射線與某個乖乖相交之后及刻,你只知道交點的坐標是不夠的镀裤,一般的渲染算法還需要知道這個點的法線以及材質,才能知道該點最終的亮度缴饭。在我們基于物理的渲染算法里暑劝,我們還需要更多的信息,比如說颗搂,我們還需要知道這個點的各種偏導數(shù)(偏導數(shù)宏觀上來說是描述了某一點的變化的速度)担猛、局部參數(shù)描述下的表面法線。(法克傅联,全是一些晦澀的概念)
最后,我們的場景當然是有很多個物體構成的该溯,不是一個。所以到這時候氯庆,那些小學沒讀完的寫代碼就已經(jīng)寫不下去了粒督,因為他們不會組織描述一套復雜系統(tǒng)魯棒性較高的代碼。不過即便你能寫出來正確的代碼锐墙,比如我們要知道哪個點是光線射出去后夺脾,第一個相交的點蚀乔,我們最屌絲的做法是用光纖跟場景里的物體全部玩一遍,然后找出離光源最近的相交點终吼。但你的場景稍微復雜一點,你的這套系統(tǒng)就頂不住了出牧。當然,如果你是做電影渲染的,沒問題啸如。如果你是做實時渲染妇汗,那么你就麻煩大了寞焙。當然擒悬,我們介紹的方法豈能如此屌絲尊勿。我們知道即便我們說出方法,仍然有大量的玩家看不懂。
光照強度
在上一個階段,我們已經(jīng)得到了某一個被著色的點的幾何信息以及如何去著色的一些附加信息。但我們的最終任務是計算在某一個視角下,某一點有多少光線跟它發(fā)生了關系,并且我們還要調查處梳猪,光線與這個點到底發(fā)生了什么關系惕稻,到底見不見的人俺祠。這樣我們就需要觸及兩個概念蔫缸,第一個就是光源的幾何描述信息,另一個就是光在這一點作用后是如何輻射出來的。比如對于簡單的光源,光源的幾何描述信息是比較簡單的,比如說點光源喝噪,現(xiàn)實世界是沒有這家伙的,誰跟我說有點光源的平项!所以我們通常使用其他的幾何模型去模擬缺猛。(那我們進階課學的點光源是啥?)婉商。我們在物理渲染里的光源稍微會復雜一點,我們的光源不僅具備幾何模型匠童,而且光源通過幾何模型的表面往外輻射光線竖独。
我們假設一個光源的光照強度為I,我們假設有個球套在點光源上章办,點光源剛好位于球的中心,假設球的半徑是1,那么球表面某一點的光照強度是多少呢?答案是:I/4PI。其實你只要知道這一點睡雇,就可以大致知道后面光照怎么算了。俗話說撮珠,萬事就差一個帶你入門的饼酿。
可見性檢測
在我們之前介紹的那些奇奇怪怪的玩意里,我們其實沒有講一個東西肢础,那就是:陰影。每一個光線只對點亮物體做了貢獻,那么那些沒被點亮的東西咋辦呢廷区?我們在后面的內容中會詳細介紹這部分玩法隙轻。實際上是非常簡單的敛瓷。
表面的反射
現(xiàn)在我們已經(jīng)算出了兩個對于著色來說非常重要的信息了:被著色點的位置和光照強度。現(xiàn)在我們需要知道贪惹,光線射完了之后显蝌,會有多少倍反射出來肴裙,因為這些光線最終是要進入我們的氪金狗眼的涌乳。沒有進入我們的眼鏡的光線蜻懦,我們是看不見的。所以我們還需要之后夕晓,反射的時候有多少能量被反射出來了宛乃。每個物體都有一個材質,用來描述所有點的光照反射方面的屬性蒸辆。實際上就是BRDF征炼。這個算法告訴我們,有多少能量被反射出來了」保現(xiàn)在我們計算一個光線L有多少能量被反射出來就變得明鳥了谆奥。這里計算出來的這個強度跟我們之前講的那個輻射強度有一點點區(qū)別,我們后面再說拂玻。
在我們的基于物理渲染的光照反射算法里酸些,其實可以用的有很多種,比如:BRDF檐蚜、BTDF魄懂、BSDF,最復雜的可能是:BSSRDF了熬甚,我們同學里有很多變態(tài)一定會去研究BSSRDF逢渔,因為這些人是抖M傾向的肋坚。
間接的光線照射
間接的光線照射就是那些通過其他物體反射過來照亮了某一點的光線乡括。我們在opengl課程里面只介紹了被光直接照亮如何計算,如果是被間接照亮的該怎么辦呢智厌?所以這個部分主要是來計算間接光線照射對某一個像素點最終產(chǎn)生了多少顏色貢獻诲泌。這里介紹的技術還可以用來渲染透明物體。
光線的傳播
目前铣鹏,我們所討論的所有東西都是假設我們的光線在真空中傳播的狀態(tài)敷扫,但是事實上,大部分情況下,我們的光線不是在真空中傳播葵第,除非你模仿宇宙中的東西绘迁。所以我們還需要根據(jù)光線所處的環(huán)境,來讓光的傳播變得更真實卒密,比如說有霧的時候缀台,該怎么模擬光線,光線的穿透力如何哮奇。
總結
我們在這里講完了基于物理渲染的整個大的邏輯主干膛腐,以及要處理的問題大致有哪些。這每個系統(tǒng)中又涉及到很多細節(jié)鼎俘,所以不要以為我們講的很多東西沒有用哲身,我們只是沒介紹怎么用她們而已,隨著你的實踐的增多贸伐,會發(fā)現(xiàn)他們的用處勘天。如果你沒什么經(jīng)歷,或許永遠不會發(fā)現(xiàn)棍丐,我們opengl基礎課中那些例子是用來干嘛的误辑。最簡單的邊緣檢測,這是我們在每個進階課里都講了的歌逢。它是干哈的呢巾钉?舉個例子:FXAA就是基于邊緣檢測的算法。所以說秘案,我們介紹的很多知識點都是關鍵知識點砰苍。我們?yōu)橥瑢W們掰開了一個縫,同學們能走多遠看同學們自己了阱高。不是我們不講赚导,是因為每個縫里面的東西都太復雜,都是綜合實力的體現(xiàn)赤惊。所以那些抖M的差不多都已經(jīng)進到縫隙里面去了吼旧。