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