3D 渲染中使用 Accumulation Buffer 實現景深(Depth of Field)效果?
在 3D 渲染中,最精確的模擬景深的方法就是:使用 Accumulation Buffer。通過微動 View 的位置,多次渲染同一場景到 A Buffer 中;然後,對 A Buffer 裡面的同一位置上的色素進行混合,得到最終圖像。給出示意圖如下:
提出問題:哪個大神可以幫我證明下上面講的這個方法的正確性。最好可以給出比較嚴密的數學推導公式(我自己太愚笨沒有推出來)。謝謝啦 :)
我一般是用固定相機、根據depth決定CoC的思路來做DOF的...(其實就是固定人眼、然後根據光線在透鏡上不同位置,折射出來的範圍來做)
剛查了下 GPU Gems - Chapter 23. Depth of Field: A Survey of Techniques 裡面的描述(23.3),順藤摸瓜找了sig90的論文 The accumulation buffer: hardware support for high-quality rendering 然後繼續找到更早的82的論文 Synthetic Image Generation with a Lens and Aperture Camera Model _(:з」∠)_
大概讀了下,感覺這個方法就是一個單純的近似...論文作者都沒講為啥(╯‵□′)╯︵┻━┻ 82年的論文主要是將透鏡模型替換掉pinhole,然後提出了計算CoC的方法;90年的論文直接就說,本文通過擾動視點,模擬從不同離散點透過透鏡觀察來觀察,這個採樣點圖怎麼看都是不科學……
附錄B里還帶代碼真是業界良心(我絕不是吐槽最近有些siggraph要不到可執行程序,恩...)剛我還試了下虛光軸,結果推不出來...做不到通過移動視點來模擬同故宮透鏡的光線(自己太菜了-.-)總之我覺的這個方法就是為了使用accumulated buffer搞出的,DoF只是作為一個application~嘛ray tracing才是正道!
計算機圖形學為啥需要正確性?它是為了看起來爽的。你將來再看看工作在屏幕空間的技術,比如SSAO什麼的,使用的信息都是不完整的,正確個毛啊。看起來差不多就行了。
DoF效果是對透鏡積分產生,題主所描述的這種方法就是對透鏡上的點進行採樣來對積分進行估計(蒙特卡羅積分法),這個估計是「一致估計」,也即是隨著採樣數加大會無限接近被估計的積分的真實值,所以這種方法是很精確的。這也是Ray trace類方法最基本的思路。
大概說下這張圖,圖裡viewer的位置就是透鏡(加上光圈限制)上各點的位置,所以它們都在同一個與focal plane平行的平面內,然後關鍵在於viewer投影矩陣的計算,考慮到focal plane是對焦的平面,所以focal plane上的點不管從透鏡哪個點通過都會折射到感光面同一個位置,換成圖形學的語言就是會投影到屏幕上同一個位置,據此應該可以推導投影矩陣(我做離線的,實時不熟)。圖中就只取了一個點作參照,虛線是相機朝向,對應屏幕中心點的方向,不同位置的viewer都對準了focal plane上的同一點,也即是那個點投射到不同的viewer上都是屏幕中心點。然後我看他意思似乎是只改變了viewer的位置和朝向,不用管視角什麼的,不過光圈半徑一般都不大,大致就是厘米級別(焦距÷光圈數值),所以其他參數近似不變可能也可以。寫一個我自己的想法。其實,我想證明的就是為什麼這個方法能夠比較好的模擬出 DOF 效果。
首先想說的是前面貼的那張示意圖中的 Focal Plane,我完全不知道他出現的意義何在。當 View 的位置都改變了,為什麼 Focal Plane 不變?於是我重新畫了一張圖。從圖中可以看到,當 View 改變位置後,不變的是 Look Vector 上的點在 Screen 上投影的位置。有等式如下:
a0 = ( dnear * d(p, p0) ) / ( dtarget + d(t, p0) ) (1)
a1 = ( dnear * d(p, p1) ) / ( dtarget + d(t, p1) ) (2) 得到 a0 和 a1 的等式後,a0 - a1 其實也就是 CoC 了。那麼,只要找到 a0 - a1 同角 α 和向量 pt 之間的關係,應該就能說明到底是為什麼能很好的模擬 DOF 效果了。 上面是我想到的一個思路,具體怎麼推導還在思考中……推薦閱讀:
※如何評價國產3D動畫《墓王之王》?
※如何在WPF程序中調試C++ dll?
※keyshot渲染燈具怎麼才能做到光線自然發出?
※如何評價酷家樂?