從玩具總動員到汽車總動員2
蓄積了好久,這一系列主要是針對計算機圖形學中真實感渲染分支方向的文章,其中也會包含涉及到的圖像處理,深度學習方面的內容。
本文是最近半年來對一些重點概念和知識結構較為粗糙的梳理, 之後會陸續寫關於不同細節的研究文章。我通常習慣於 top-down approach 而非bottom-up的方法來建立技能體系。希望對大家有所參考。
真實感渲染的電影業發展史
脫離應用光談理論是耍流氓。 先來看看電影比很多大部頭從開始細談openGL實現細節或者render pipeline要生動很多。 很久之前看高曉松的《曉松奇談》,他在 探訪星戰聖地天行者莊園 那兩期里,從星球大戰談到極具創造力的大導演喬治盧卡斯,再談到與這些科幻大作相輔相成的電影技術團隊 工業光魔公司。有句話大概是這樣說的,當時很多非常先進的技術都是由好萊塢的電影催生的。
那麼說到真實感渲染其實是一樣的, 最優秀的離線渲染技術也離不開這麼多年迪士尼和皮克斯動畫的推動研發,其實到如今他們的團隊也在學術界和工業界佔有無比重要的地位。
從幾張圖裡可以感受到這些年來伴隨我們成長的動畫電影水平的進步。
到底是什麼決定了它們的效果差別
我們眼睛看到的是屏幕上一個個pixel(像素),一個屏幕如果有幾個million,billion個像素,那就足以構成一個不錯的複雜的場景了。那麼一個3維空間怎麼呈現在二維平面上,並且通過一個個pixel的顏色顯示出來,就是渲染要做的事。
上面這些3D動畫效果差這麼多我總結為主要是因為三個方面,一個是global illumination(即全局光照)的效果,也就是你看到各種物體之間相互輝映或者在光照上通過反射/折射相互影響的效果,另一個是對於材質的模擬好壞,最後是一些特殊效果,比如depth of fields (景深),motion blur(運動模糊)。
OK,當這些都解決了之後,比如說我們對光線傳播過程,物體表面材質的物理結構都有了很優秀的建模之後,問題就都解決了嗎? 沒有。還有一個很重要而且很實際的問題,真實感渲染的速度。。。 渲染是一個無比computation-intensive 的過程,想像你所在的空間中同時在進行多少條光線的傳播或者碰撞。一部電影花幾個月去渲染的情況不足為奇, 所以為了提升渲染速度,學術界和工業界無論在硬體上(CPU/GPU,SIMD)還是演算法上都在不停進行優化。這也是真實感渲染要解決的終極問題,怎麼樣在更加短的時間內,通過更少的計算,獲得更好的渲染效果。
Path tracing,Ray tracing 傻傻分不清楚
在圖形學上稍有些基礎的朋友都聽過Path tracing (路徑追蹤),Ray tracing(光線追蹤)這些術語,但很容易高不清楚關係,我當初就是,下面是我自己的一些理解。很多大學包括我大學在HKU上圖形學第一課的時候,最後的大作業都是從頭實現一個儘可能包含多種高級效果的 ray tracer,那會兒還沒太聽說path tracing這個詞。
本質上Ray tracing 是說從視點和image pixel出發,生髮光線,然後去和場景中物體相互作用,再到達光源獲得luminance,逆向於直覺性從光源出發,最終到達視點的過程(forward tracing)。
所以Path tracing 和Ray tracing並不是並列關係,而是Ray tracing相當於一種方法論或者演算法框架,而path tracing相當於一種更加具體的實現。Path tracing 也是現在大部分流行離線渲染器都基於的演算法,即依賴於渲染方程理論和蒙特卡洛隨機方法 對路徑進行積分,最終得到每一個pixel的顏色。當然傳統的path tracing要最終收斂非常慢,所以也衍生出了各種優化手段(包括利用硬體優化,演算法先驗或後驗優化,其中又包括是基於統計還是基於物理法則,也有一些研究團隊開始用現在比較熱的萬金油式的 Deep learning來攻城略地),這個之後具體聊。
而整個rendering的過程可以拆解為兩個部分,visibility test 和shading,一個用來決定你在每一點上看到的是什麼,一個用來決定你看到的它是什麼樣子的。這裡無論離線還是實時渲染(很多遊戲或者漸進式VR效果都是通過實時渲染獲得的),都頻繁提到的一些詞,比如 shader啊,BRDF啊,illumination model啊,就都是在說shading相關的問題。Shading是很大一塊,這個具體之後再聊。
渲染框架
其實真實感渲染還包含其他很多方法,比如Photo mapping,radiosity 等等,但大部分先進渲染引擎比較普遍的採用Monte Carlo based path tracing, 我之前的學習也主要集中在在這裡。所以這裡先談Path tracing。
Path tracing 本質是一個簡單的遞歸演算法,為了計算某個pixel的值,從眼睛出發,在pixel上進行很多採樣,然後生髮出很多條光線,當光線交於場景中的一個物體時,需要根據存在的光源去計算交點處的direct lighting(直接光), 然後需要繼續生髮光線去探求場景中的indirect lighting(間接光),這裡你這條光線怎麼生髮就要看這個表面交點處的材質性質了,是漫反射呢還是鏡面反射呢還是折射呢,當然通常材質是很複雜的,同時包含很多屬性(所謂 Everything is shiny! Everything has fresnel! ),當光線繼續行進,在場景中和物體產生下一個交點的時候,繼續計算direct lighting,並且繼續生髮光線。 打個比方就好象你派出一隻軍隊,到了一個據點留下一部分軍隊進行駐守,同時剩餘的人員繼續前進完成(貌似亞歷山大東征。。。),當然你通常還需要從本地招募很多新的戰士,或者說你和本地人通婚,通過繁殖產生擁有自己血統的軍隊(這個繁殖過程,就可以看作BRDF的作用了)。
這個征戰的過程直到你無法找到一個新的領地(和場景中物體不再有交點),或者亞歷山大告訴你夠了,就到這裡吧(即path depth受到限制來保持速度)。
而且通常情況下,為了求indirect illumination,你所生髮的ray遠遠不只一條,而也是基於Monte Carlo隨機方法進行採樣,來使自己獲得一個更加科學的結果。這樣也就可以理解說為什麼渲染這麼慢了,你從pixel上拿16個sample,在第一個交點處再拿16個sample,,,,,16*16*16…. BAM ! 恭喜你獲得了指數增長。這樣還快的起來嗎?
這裡應該上代碼,但由於是第一篇文章就不上了,之後會出更加詳細的文章說明。
一切從渲染方程說起
奠定這一切基礎的,還是要追溯到1986年Kajiya 提出的Render Eqation。
對於經典,當然要去paper裡面直接抓公式。它自己也足夠自我解釋了。
基於這張圖, g(x』,x)相當於一個可見性測試,即看x』,x兩個點是否被遮擋,e表示自身發光,pho函數就是之後會大篇幅談得BRDF,即表面的一個光線作用性質。
所以總的來說這個是一個遞歸和積分的過程,通常在自然界中遞歸到第七個bounce的時候,亮度就已經收斂,之後的光強足以小到可以忽略不計了。
採樣和重建
自然界是一個相對連續的過程,然而計算機的本質是離散的,我們當然也是離散的去計算光線傳輸。那麼在整個遞歸的過程中,怎麼樣合理的採樣,又怎麼樣合理的重建是一個很大的問題,有很多前沿的基於這個方向的Research,比如近來很多的 Adaptive sampling&Reconstruction的方法,基於頻率分析,或者梯度分析,或者通過深度學習去利用大數據的已有信息。這些在之後出額外的文章論述。
這裡提到的一些問題也都只是浮光掠影,每個點都值得深入的探究下去,之後也會對一些了解過或者實踐過的點進行更加詳細的分享。
To be continued...
有什麼問題 , 歡迎大家指摘。
References:
Path to path traced Movies.
Recent Advances in Adaptive Sampling and Reconstruction for Monte Carlo Rendering
Rendering Equation by JT Kajiya - ?1986
推薦閱讀:
※Lens Matched Shading and Unreal Engine 4 Integration (Part 1)
※教堂的聖禮
※第八屆CSFF短片節,瑞雲又要放大招,你敢接嗎?
※藍海創意雲獨家渲染《巴霍巴利王2》
※【《Real-Time Rendering 3rd》 提煉總結】(一) 全書知識點總覽