Atmospheric Scattering
??? 以前由于硬件限制,很多游戲的天空和地面顏色主要是用貼圖模擬,近來硬件的發展,越來越多的游戲開始采用基于比較真實的大氣散射模型來實時計算。很多文章的計算最終都將眼睛高度和角度作為參數,這里主要按照Sean O’Neil系列的方法來(其實它也是Nishita的改進)。
??? 原理可以簡單歸結為:光從大氣外圈,散射之后進入眼睛。散射本身是一種衰減行為,由于星球通常離太陽比較遠,所以我們近似認為在大氣的"頂端"光照相等,這是一個重要的近似,讓相機在任何地方的時候,都可以用同樣的方式來計算,所以只要是往地面的路徑,則散射增加,只要是玩天空的路徑,則散射減少。
特定波長的光的亮度散射公式是:
?????? Iv(λ) = Is(λ) * K(λ) * F(θ,g) * ∫PbPa(exp(-b/H0) * exp(-t(PPc, λ) – t(PPa, λ)))ds;
波長的影響主要由散射系數K(λ)表現,其中Is(λ)是太陽亮度,F(θ,g)是散射函數,主要有Rayleigh散射和Mie散射兩種,Rayleigh散射主要是對空氣中較小的粒子,主要散射較小波長的波,散射的能量對于光的入射比較對稱,Mie散射主要散射空氣中較大的粒子,主要散射較長的波,散射的能量在逆光部分比較少。
??? Rayleigh散射的近似能量分布
?
?? 較大波長的Mie散射的能量分布
一般可以用Henyey-Greenstein函數來近似以上兩種散射公式,即:
?????? F(θ,g) = (3 * (1 – g2) * (1 + cos2θ)) / (2 * (2 + g2) * (1 + g2 – 2 * g * cosθ))3/2;
角度θ為入射光與觀察點之間的夾角。g是取值常量,當為0時公式近似為Reyleigh散射,當取-0.99左右時近似為Mie散射。
??? 亮度公式中的積分部分
∫PbPa(exp(-b/H0) * exp(-t(PPc, λ) – t(PPa, λ)))ds;
屬于比較麻煩的地方,后面的-t(PPc, λ) – t(PPa, λ)表示的是光從大氣頂部到眼睛的路徑的衰減的和。積分曲線變化不是很大,所以對于積分用分段計算再取和來逼近積分的值,對于這里來說,并不是簡單的求和,而是計算分段的中點(SamplePoint)的整個路徑的optical depth,然后求通過這個點的路徑的散射,再求根據長度比例求和。其中b是觀察點高度在大氣層中的比例,H0是大氣中平均空氣強度的那個高度在大氣層中的比例,一般取0.25即可。t(PaPb, λ)即是表示單獨在P1P2這條路徑上的能量衰減。公式是
?????? t(PaPb, λ) = 4 * π * K(λ) * ∫PbPaexp(-b/H0)ds;
Pa和Pb分別為觀察點和太陽離計算的采樣點最近的大氣位置,如果觀察點在大氣中則Pa就是觀察點的位置。公式中的積分稱為空氣的視覺深度(optical depth),以前一般用預計算查找表來進行,這樣不利于在GPU計算,gpugems2中Sean O’Neil通過圖形曲線發現在觀察角度固定的時候,每個高度上(從0到1)的積分值可以用地面的值(高度為0時候的值)乘于exp(-b/H0)來近似表示,但對于不同角度的縮放量曲線是一條類似指數函數的曲線,沒有很好的表示方式,Sean O’Neil自己根據圖形曲線用了一條逼近的公式來計算
Scale(ξ) = H0 * exp(-0.00287 + (1 - cos *ξ)(0.459 + (1 - cos *ξ)
(3.83 + (1 - cos *ξ)(-6.80 +(1 - cos *ξ)5.25))));
式中ξ表示觀察角度,0為正上方,1為正下方,不過只有星球大氣比例跟平均密度高度固定的時候才可以(0.25、0.25)。
??? 這樣全部問題就可以放到GPU中解決了,對于每個頂點首先從camera到該點(即Pa到Pb)做一些采樣(次數越多越能逼近,但計算量也越大),然后對每個采樣點根據角度計算Scale(ξ),再根據高度計算optical depth以及t(PaPb, λ),然后根據各段采樣長度就可以計算最終的強度。
??? 地面顏色的計算與此類似,不過增加了一次與原顏色的混合。
?????????? Ig(λ) = Iv(λ) + Isrc(λ) * exp(-t(PaPb, λ));
??? 另外說下這個方法的問題,最大的問題是沒有考慮多重散射,因此天空正上方的顏色實在太暗了,天空正中央看起來像是晚上,除非將hdr曝光調的極大,但這是不正確的,因此我自己在輸出顏色的時候,對rayleigh散射輸出的顏色乘了一個1+cos(cameradir,upvetor)*K(取2左右),看起來才正常一些,用這個因子來模擬多重散射。另外由于這個問題所以mie散射的影響太小了,在這里面僅僅只是對太陽產生一個光暈,導致太陽在天空中很大范圍內移動的時候,天空的顏色幾乎不變,如果有多重mie散射,太陽附近的亮度應該亮一些,而且會產生大小不一的光暈,目前也可以用角度差別來近似。
轉載于:https://www.cnblogs.com/linyizsh/archive/2007/04/01/696270.html
總結
以上是生活随笔為你收集整理的Atmospheric Scattering的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年第十七届中国研究生数学建模竞赛
- 下一篇: 计算收益复利的小例子